[IT-정보] Go 반복문 치트시트: 핵심을 한눈에 – 입문자를 위한 필수 문법과 실전 예제 정리

반복문 for 개념을 시각화한 Go 프로그래밍 일러스트

Go 반복문 for, 왜 이것만 알면 될까요?

파이썬이나 자바 같은 다른 언어를 배우다가 Golang의 세계로 넘어오면 가장 먼저 마주하는 당혹감이 있어요. 바로 반복문의 종류가 너무나 단순하다는 점이에요. 보통의 언어들은 숫자를 세는 for 문, 조건이 참일 때까지 돌리는 while 문, 그리고 배열을 훑는 foreach 문이 따로 존재하죠. 하지만 Go는 이 모든 것을 오직 for 하나로 처리해요.

처음에는 이게 과연 가능한가 싶기도 하고, 오히려 복잡하게 느껴질 수도 있어요. “while 문은 어디 갔지?” 혹은 “배열을 돌릴 때 더 편한 방법은 없나?” 하는 의문이 드는 게 당연해요. 하지만 이 단순함이 바로 Go가 지향하는 철학이에요. 문법의 종류를 줄임으로써 프로그래머가 언어 자체의 규칙을 고민하기보다, 실제 비즈니스 로직을 어떻게 효율적으로 짤지에 더 집중하게 만들거든요.

지금 이 글을 보고 계신 여러분도 아마 반복문을 어떻게 써야 가장 Go다운 방식인지, 혹은 내가 짠 코드가 혹시 성능을 갉아먹고 있지는 않은지 걱정될 거예요. 무작정 코드를 복사해서 붙여넣는 것은 위험해요. 잘못된 반복문 사용은 무한 루프에 빠지게 하거나, 메모리 사용량을 급격히 늘리는 주범이 되기도 하니까요.

이 가이드를 끝까지 읽고 나면, 여러분은 더 이상 Go의 반복문 앞에서 망설이지 않게 될 거예요. 복잡한 조건문 없이도 깔끔하게 루프를 돌리고, range 키워드를 자유자재로 다루며, 실전 프로덕션 환경에서 안전한 코드를 작성하는 능력을 갖추게 될 거예요.

이 글에서 함께 알아볼 내용들

  • Go 반복문의 4가지 핵심 패턴 완벽 정리
  • 슬라이스, 맵, 채널을 다루는 실전 range 활용법
  • 반복문 사용 시 반드시 피해야 할 치명적인 실수와 해결책
  • 성능을 높이는 효율적인 루프 설계 팁

반복문 작성 전 반드시 확인해야 할 기초 지식

Go의 반복문을 본격적으로 다루기 전에, 우리가 어떤 도구를 사용하는지 정확히 이해할 필요가 있어요. Go는 문법을 단순화하는 대신, 하나의 키워드에 여러 가지 역할을 부여했어요. 따라서 우리가 어떤 상황에서 어떤 스타일의 for 문을 꺼내 써야 할지 판단하는 기준이 명확해야 해요.

가장 먼저 머릿속에 넣어두어야 할 개념은 제어 변수(Control Variable)조건식(Condition)의 관계예요. 반복문은 결국 “언제 시작해서, 어떤 조건이 만족될 때까지, 어떻게 변하며 돌아갈 것인가”를 결정하는 과정이에요. Go에서는 이 과정을 아주 유연하게 구성할 수 있어요.

💡 알아두기
Go에는 while 문이 따로 없어요. 대신 for condition { } 형태를 사용하면 기존의 while 문과 똑같이 동작해요. 즉, for 하나가 모든 반복의 역할을 수행한다는 뜻이에요.

또한, 반복문을 사용하기 전에 데이터의 형태를 먼저 파악하는 습관을 들여야 해요. 우리가 돌리려는 대상이 숫자인지, 아니면 데이터의 묶음인 슬라이스(Slice)인지, 아니면 키와 값이 쌍을 이루는 맵(Map)인지에 따라 사용하는 문법이 완전히 달라지기 때문이에요.

상황별 반복문 선택 가이드

아래 표를 통해 지금 여러분이 처한 상황에 어떤 문법이 가장 적합한지 한눈에 비교해 보세요.

반복 스타일 주요 용도 핵심 특징
C 스타일 (Classic) 횟수가 정해진 반복 초기화, 조건, 증감식을 한 줄에 작성
조건식 스타일 조건 만족 시까지 무한 반복 기존의 while 문과 동일한 역할
Range 스타일 컬렉션(슬라이스, 맵 등) 순회 인덱스와 값을 동시에 안전하게 추출
무한 루프 스타일 특정 조건에서 탈출할 때까지 조건식 없이 for { }만 사용

이 표를 머릿속에 넣어두면 코드를 짜기 전에 “아, 이번에는 range를 써야겠구나” 하는 판단이 훨씬 빨라질 거예요. 단순히 코드를 외우는 것보다, 상황에 맞는 도구를 선택하는 능력이 좋은 개발자를 만든다는 사실을 꼭 기억하세요.

실전에서 바로 쓰는 Go 반복문 핵심 패턴 5단계

이제 본격적으로 실전 코드를 통해 Go 반복문의 모든 것을 파헤쳐 볼게요. 단순히 문법을 나열하는 게 아니라, 실제 개발 현장에서 어떤 식으로 코드가 작성되는지 그 흐름을 따라가 봅시다.

STEP 1. 가장 기본이 되는 C 스타일 반복문

가장 전통적인 방식이에요. 숫자를 하나씩 증가시키거나 감소시키며 정해진 횟수만큼 실행할 때 사용해요. 이 방식의 핵심은 초기화(init); 조건(condition); 증감(post) 세 가지 요소를 한 줄에 관리한다는 점이에요.

예를 들어, 1부터 10까지 숫자를 출력하고 싶다면 이렇게 작성해요.
for i := 1; i <= 10; i++ { fmt.Println(i) }
여기서 i := 1은 시작점, i <= 10은 언제 멈출지, i++는 한 번 돌 때마다 어떻게 변할지를 나타내요. 이 형식을 지키기만 하면 어떤 숫자 범위든 자유자재로 다룰 수 있어요.

주의할 점은 조건식을 잘못 설정하면 무한 루프에 빠질 수 있다는 거예요. 예를 들어 i--를 써야 하는데 실수로 i++를 쓴다면, 조건이 영원히 참이 되어 프로그램이 멈추지 않을 거예요. 항상 조건이 언젠가는 거짓(false)이 될 수 있는 구조인지 확인하는 습관을 가져야 해요.

STEP 2. 조건에 집중하는 while 스타일 반복문

Go에는 별도의 while 키워드가 없지만, for 문에서 초기화와 증감식을 생략하면 완벽한 while 문이 돼요. 특정 변수의 상태가 변할 때까지 계속 실행해야 하는 로직에 아주 유합해요.

예를 들어, 어떤 사용자의 잔액이 0보다 큰 동안 계속해서 물건을 구매하는 로직을 짠다고 해볼게요.
for balance > 0 { purchaseItem(); balance -= cost }
이런 식으로 작성하면, balance라는 조건이 만족되는 동안에는 몇 번이고 루프가 돌아가요. 시작점이 명확하지 않거나, 루프 내부에서 조건이 복잡하게 변하는 경우에 이 방식을 선택하면 코드가 훨씬 읽기 편해져요.

STEP 3. 강력한 컬렉션 순회 도구, range

현대적인 프로그래밍에서 가장 많이 쓰이는 방식이에요. 슬라이스(Slice), 배열(Array), 맵(Map), 문자열(String), 채널(Channel) 같은 데이터 묶음을 하나씩 꺼내올 때 사용해요. range를 사용하면 인덱스와 값을 아주 안전하고 깔끔하게 가져올 수 있어요.

슬라이스를 순회할 때 가장 흔히 쓰는 패턴은 다음과 같아요.
for index, value := range mySlice { fmt.Printf("%d번째 값은 %v입니다\n", index, value) }
여기서 index는 위치를, value는 실제 데이터를 의미해요. 만약 위치 정보는 필요 없고 값만 필요하다면, 인덱스 자리에 언더스코어(_)를 써서 무시할 수 있어요.
for _, value := range mySlice { fmt.Println(value) }

맵(Map)을 순회할 때는 인덱스 대신 key를 가져와요.
for key, val := range myMap { fmt.Println(key, val) }
이때 주의할 점은 맵은 순회할 때마다 순서가 보장되지 않는다는 거예요. 매번 실행할 때마다 데이터가 나오는 순서가 달라질 수 있으니, 순서가 중요한 로직에는 맵을 직접 순회하면 안 돼요.

STEP 4. 흐름을 제어하는 break와 continue

반복문을 돌다가 특정 상황에서 멈추거나 건너뛰어야 할 때가 있죠? 이때 사용하는 것이 breakcontinue예요.

찾으려는 값을 발견했을 때 루프를 즉시 종료하고 싶다면 break를 사용하세요. 반대로, 특정 조건에 해당하는 데이터만 빼고 나머지는 계속 돌리고 싶다면 continue를 쓰면 돼요. 예를 들어, 슬라이스에서 짝수만 출력하고 싶다면 홀수일 때 continue를 실행하게 만들면 코드가 훨씬 간결해져요.

STEP 5. 복합적인 중첩 루프와 실전 시나리오

때로는 루프 안에 루프가 들어가는 중첩 루프가 필요해요. 2차원 배열(행렬)을 처리하거나, 복잡한 데이터 구조를 파고들 때 사용하죠. 하지만 중첩 루프는 조심해서 사용해야 해요. 루프가 깊어질수록 연산 횟수가 기하급수적으로 증가하기 때문이에요.

💡 알아두기
중첩 루프를 설계할 때는 항상 시간 복잡도를 고려하세요. $N imes N$ 형태의 루프는 데이터가 1,000개만 되어도 1,000,000번의 연산을 수행합니다. 가능한 한 루프의 깊이를 줄이는 방향으로 로직을 개선하는 것이 프로페셔널한 자세예요.

실전 시나리오 예시: 쇼핑몰의 주문 목록에서 각 주문(Order)마다 포함된 상품(Item)들의 총 가격을 계산하는 로직을 짠다고 가정해 봅시다.

  1. 바깥쪽 루프: 전체 주문 목록(Orders)을 하나씩 가져옵니다.
  2. 안쪽 루프: 현재 주문에 포함된 상품들(Items)을 하나씩 순회합니다.
  3. 계산: 상품 가격을 합산하여 주문 총액을 결정합니다.

이런 구조는 매우 일반적이지만, 만약 주문이 수백만 건이고 상품도 수백 개씩 들어있다면 성능 병목이 발생할 수 있어요. 이럴 때는 반복문을 돌리기 전에 데이터를 미리 필터링하거나, 병렬 처리를 고려해야 하죠. 이처럼 반복문은 단순한 문법을 넘어 시스템의 성능과 직결되는 설계 요소라는 점을 잊지 마세요.

자주 하는 실수와 해결법

코드를 짜다 보면 누구나 실수할 수 있어요. 하지만 Go 개발자라면 반드시 마주하게 되는 몇 가지 전형적인 실수들이 있죠. 이를 미리 알고 있으면 디버깅 시간을 획기적으로 줄일 수 있어요.

  • 실수: 루프 변수의 캡처 문제 (Closure Trap)
    가장 악명 높은 실수예요. 루프 안에서 고루틴(Goroutine)을 생성하면서 루프 변수를 그대로 사용하면, 모든 고루틴이 루프의 마지막 값만 참조하는 비극이 발생해요.
    해결법: 루프 내부에서 변수를 새로운 지역 변수로 복사해서 전달하거나, 함수 인자로 명시적으로 넘겨주어야 해요.
  • 실수: 슬라이스를 순회하며 요소를 삭제함
    반복문 도중에 슬라이스의 길이를 줄이는 작업을 하면, 인덱스가 꼬여서 데이터 일부를 건너뛰거나 범위를 벗어나는 에러가 발생해요.
    해결법: 삭제할 요소를 따로 모아두었다가 루프가 끝난 뒤 처리하거나, 역순(뒤에서부터 앞으로)으로 루프를 돌리세요.
  • 실수: 무한 루프와 조건식 누락
    for 조건식만 적고 내부에서 조건을 변화시키는 코드를 넣지 않으면 프로그램이 영원히 멈추지 않아요.
    해결법: 루프가 종료될 수 있는 탈출 조건이 반드시 코드 경로 상에 존재하는지 검토하세요.
  • 실수: range 사용 시 인덱스 실수
    값(value)이 필요한데 인덱스(index)를 사용하는 경우예요. 데이터 값이 아닌 0, 1, 2 같은 숫자가 출력되어 당황하는 일이 많죠.
    해결법: range 문법의 반환 순서(인덱스, 값)를 정확히 인지하고, 필요 없는 값은 _로 처리하세요.
  • 실수: 맵 순회 시 순서 의존적 로직 작성
    맵을 돌 때 데이터가 매번 다른 순서로 나오는데, 이를 순서가 있는 것처럼 코딩하면 결과가 들쭉날쭉해져요.
    해결법: 순서가 중요하다면 맵의 키를 별도의 슬라이스에 담아 정렬한 뒤, 그 슬라이스를 기준으로 맵을 참조하세요.

자주 묻는 질문

Q. Go에서 for 문을 쓸 때 성능상 가장 유리한 방법은 무엇인가요?

일반적으로 슬라이스를 순회할 때는 range를 사용하는 것이 코드 가독성과 안전성 측면에서 훨씬 유리해요. 성능 차이는 극히 미미하므로, 특별히 초고성능 최적화가 필요한 상황이 아니라면 range를 권장해요.

Q. range를 쓸 때 인덱스와 값을 모두 안 쓰면 에러가 나나요?
네, Go는 사용하지 않는 변수가 있으면 컴파일 에러를 발생시켜요. 따라서 인덱스가 필요 없다면 반드시 _ 기호를 사용해 명시적으로 무시해야 해요.

Q. 채널(Channel)도 for로 돌릴 수 있나요?
네, 아주 자주 쓰이는 패턴이에요. for range channel { } 문법을 사용하면 채널이 닫힐 때까지 계속해서 데이터를 하나씩 꺼내올 수 있어요.

Q. for 문 안에서 break를 쓰면 중첩된 루프 전체가 멈추나요?
아니요, 가장 가까운 루프 하나만 탈출해요. 만약 이중 루프 전체를 한 번에 빠져나가고 싶다면 Label을 사용해야 해요.

Q. map을 순회할 때 성능 저하가 심한가요?
데이터 양이 아주 많다면 맵 순회는 슬라이스 순회보다 느릴 수 있어요. 하지만 이는 맵 자체의 특성이지 for 문 때문은 아니에요. 대량의 데이터를 다룰 때는 데이터 구조 설계를 먼저 고민해 보세요.

Go 반복문 마스터를 위한 마지막 요약

오늘 우리는 Go 프로그래밍의 심장과도 같은 for 문법의 모든 것을 살펴보았어요. 단순해 보이지만 그 안에 담긴 유연함과 강력함은 Go를 최고의 언어로 만드는 핵심 요소 중 하나예요. 다시 한번 핵심 내용을 정리해 드릴게요.

✅ 핵심 요약

  • Go는 for 하나로 모든 반복을 처리하는 단순함을 지향해요.
  • 전통적인 카운팅은 C 스타일 for를, 조건 중심은 while 스타일을 사용하세요.
  • 슬라이스와 맵 순회에는 range가 가장 안전하고 효율적이에요.
  • 사용하지 않는 변수는 반드시 _로 명시하여 컴파일 에러를 방지하세요.
  • 고루틴과 함께 쓸 때는 변수 캡처 문제를 항상 경계해야 해요.

이제 이론은 충분해요. 코드는 눈으로 읽는 것이 아니라 직접 타이핑하며 익히는 것이 가장 빨라요. 오늘 배운 내용을 바탕으로 여러분의 프로젝트에 적용해 보세요.

다음 단계: 오늘 바로 실천하기

  • 오늘 할 일: Go Playground에서 4가지 반복문 패턴을 각각 한 번씩 직접 타이핑하고 실행해 보세요.
  • 이번 주 할 일: 기존에 작성했던 코드 중 반복문이 복잡한 부분을 range 문법으로 리팩토링해 보세요.
  • 실행 직전 할 할: 반복문 내부에서 고루틴을 사용할 계획이 있다면, 변수 복사 로직이 포함되었는지 다시 한번 점검하세요.

글을 읽으시면서 이해가 안 가거나, 더 궁금한 실전 사례가 있다면 언제든 댓글로 질문을 남겨 주세요. 여러분의 성장을 진심으로 응원합니다!

함께 읽으면 좋은 글: Go 반복문 for 완전 정복 가이드

댓글 남기기