
Go 반복문 하나로 모든 것을 해결하는 법
파이썬(Python)이나 자바(Java)를 공부하다가 Golang(Go)의 세계로 넘어오면 가장 먼저 당황하는 순간이 있어요. 바로 반복문을 돌리려고 할 때 while이나 foreach 같은 키워드가 보이지 않는다는 점이에요. 분명히 반복을 해야 하는데, 도대체 어떤 키워드를 써야 할지 몰라 코드 창을 멍하니 바라본 경험이 한 번쯤은 있으실 거예요.
Go 언어는 철학 자체가 굉장히 간결해요. 복잡한 문법을 여러 개 만드는 대신, for라는 단 하나의 키워드에 모든 반복 로직을 담아버렸거든요. 처음에는 이게 불편하게 느껴질 수 있지만, 익숙해지면 오히려 코드가 훨씬 깔끔해지고 읽기 편해져요. 반복문의 종류가 하나뿐이라서 공부해야 할 양이 줄어드는 셈이니까요.
이 글을 끝까지 읽고 나면, Go의 유일한 반복문인 for를 자유자재로 다루게 돼요. 단순히 문법을 외우는 수준을 넘어, 슬라이스(Slice)나 맵(Map) 같은 복잡한 자료구조를 어떻게 효율적으로 순회하는지, 그리고 실무에서 흔히 저지르는 실수들은 무엇인지 정확히 알게 될 거예요.
이 글에서 배우게 될 내용
- Go 반복문의 기본 3요소와 표준 사용법
- while 문과 무한 루프를 for로 구현하는 기술
- 슬라이스와 맵을 위한 range 문법 완전 정복
- 중첩 루프를 탈출하는 라벨(Label) 활용법
- 실전에서 바로 쓰는 반복문 패턴과 주의사항
Go 반복문 시작 전 반드시 알아야 할 기본기
Go의 반복문을 제대로 활용하려면 먼저 for 문이 가진 구조적 유연성을 이해해야 해요. 다른 언어에서는 상황에 따라 문법을 바꿔 써야 했지만, Go에서는 단 하나의 틀 안에서 세 가지 형태를 오가며 사용해요. 이 구조를 머릿속에 그려두지 않으면 코드를 볼 때마다 헷갈릴 수 있어요.
가장 먼저 기억해야 할 점은 Go의 반복문은 세 가지 구성 요소를 가질 수 있다는 거예요. 첫째는 루프를 시작하기 전 변수를 설정하는 초기화 구문, 둘째는 루프를 계속할지 결정하는 조건식, 셋째는 한 번의 루프가 끝날 때마다 실행되는 후속 조치예요. 이 세 가지를 모두 적으면 우리가 흔히 아는 C 스타일의 반복문이 되고, 하나만 적으면 조건식만 있는 루프가 돼요.
Go에서는 세미콜론(;)을 사용하여 초기화, 조건, 후속 조치를 구분해요. 하지만 각 항목 사이에는 공백을 넣어 가독성을 높이는 것이 관례예요.
자신의 프로젝트 성격이나 다루려는 데이터 타입에 따라 어떤 형태의 반복문을 선택해야 할지 고민될 때가 있을 거예요. 아래 비교 표를 통해 상황별 최적의 선택 기준을 확인해 보세요.
| 반복 유형 | 적합한 상황 | 핵심 특징 |
|---|---|---|
| 표준 for 루프 | 횟수가 정해진 반복 | 인덱스 제어가 매우 정밀함 |
| 조건식 루프 (while형) | 특정 조건이 만족될 때까지 | 초기화와 증감식이 분리됨 |
| range 루프 | 슬라이스, 맵 순회 시 | 인덱스와 값을 한 번에 획득 |
| 무한 루프 | 서버 리스너, 채널 대기 | break 문으로 명시적 탈출 필수 |
무엇보다 중요한 건 무조건적으로 루프를 돌리는 것이 아니라, 데이터의 성격에 맞춰 선택하는 것이에요. 슬라이스의 모든 요소를 하나씩 꺼내야 한다면 range가 압도적으로 편하고, 3칸씩 건너뛰며 검사해야 한다면 표준 for 루프가 훨씬 효율적이에요. 이 판단 기준을 명확히 세워야 나중에 코드를 수정할 때 고생하지 않아요.
Go 반복문 완벽 마스터를 위한 5단계 실전 가이드
이제 이론은 충분해요. 직접 코드를 짜는 것처럼 단계별로 핵심 패턴을 하나씩 정복해 봐요. 각 단계는 실제 개발 환경에서 마주하게 될 구체적인 시나리오를 바탕으로 구성했어요.
STEP 1. 기본 3요소로 정밀하게 제어하기
가장 먼저 익혀야 할 것은 전통적인 방식의 표준 for 루프예요. 이 방식은 반복 횟수를 숫자로 정확히 제어해야 할 때 가장 강력한 힘을 발휘해요. 예를 들어, 배열의 특정 구간만 반복하거나, 숫자를 역순으로 줄여나가는 작업을 할 때 아주 유용해요.
표준 루프의 구조는 for 초기화; 조건식; 후속조치 { ... }로 이루어져요. 여기서 조건식이 false가 되는 순간 루프는 즉시 종료된다는 점을 꼭 기억하세요. 초보자들이 가장 많이 하는 실수가 조건식을 반대로 설정해서 무한 루프에 빠지는 것이니 주의해야 해요.
Go의 for 루프 안에서 선언된 변수는 루프가 끝나면 사라져요. 만약 루프 밖에서도 그 값이 필요하다면, 반드시 루프 시작 전에 미리 변수를 선언해 두어야 해요.
STEP 2. 조건이 만족될 때까지 도는 while 스타일 구현
Go에는 while이라는 키워드가 따로 없어요. 대신 for 문에서 초기화와 후속 조치 부분을 생략하면 자연스럽게 while 문처럼 동작하게 돼요. 이 방식은 반복 횟수가 정해져 있지 않고, 특정 상태가 변할 때까지 계속 실행해야 하는 경우에 아주 적합해요.
예를 들어, 네트워크에서 데이터를 가져올 때 데이터가 더 이상 없을 때까지 계속 읽어들이는 로직을 짠다고 가정해 볼게요. 이때는 for 데이터가있는가 { ... }와 같은 형태로 작성할 수 있어요. 이는 코드의 가독성을 높여줄 뿐만 아니라, 로직의 의도를 명확하게 전달해 줘요.
STEP 3. 무한 루프와 제어문(break, continue) 활용
때로는 조건 없이 무조건 루프를 시작해야 할 때가 있어요. 서버가 24시간 내내 클라이언트의 요청을 기다려야 하는 상황이 대표적이죠. 이때는 조건식 없이 for { ... }만 작성하여 무한 루프를 만들어요. 하지만 무한 루프는 매우 위험해요. 반드시 루프 내부에서 어떤 조건이 충족되었을 때 루프를 빠져나가는 break 문을 설계해야 해요.
또한, 특정 조건에서 이번 차례만 건너뛰고 다음 반복으로 넘어가고 싶다면 continue를 사용해요. 예를 들어, 리스트를 돌면서 짝수만 처리하고 홀수는 그냥 지나치고 싶을 때 continue를 쓰면 코드가 훨씬 깔끔해져요. if-else를 길게 늘어뜨리는 것보다 훨씬 직관적이죠.
STEP 4. range를 이용한 컬렉션 순회 마스터하기
실무 개발에서 가장 많이 쓰게 될 패턴은 바로 for range 문이에요. 슬라이스(Slice), 배열(Array), 맵(Map), 문자열(String) 등 Go의 주요 자료구조를 순회할 때 최적의 성능과 가독성을 제공해요. range를 쓰면 인덱스와 값을 동시에 받을 수 있어 코드가 매우 간결해져요.
슬라이스를 돌 때는 for index, value := range slice { ... } 형식을 사용해요. 만약 인덱스 정보는 필요 없고 값만 필요하다면, 인덱스 자리에 언더스코어(_)를 써서 무시할 수 있어요. 맵(Map)을 순회할 때는 인덱스 대신 키(Key)를 가져오게 된다는 점도 기억해 두세요. 맵은 순서가 보장되지 않기 때문에, 실행할 때마다 결과가 달라질 수 있다는 독특한 특징이 있어요.
range 문에서 가져오는 값은 원본의 복사본이에요. 루프 안에서 value 값을 수정한다고 해서 원본 슬라이스의 요소가 바뀌지는 않아요. 원본을 수정하려면 반드시 인덱스를 사용하여
slice[index] = newValue와 같이 직접 접근해야 해요.STEP 5. 중첩 루프 탈출을 위한 라벨(Label) 사용법
루프 안에 또 다른 루프가 들어있는 중첩 루프 상황에서, 가장 안쪽 루프의 break가 가장 바깥쪽 루프까지 멈추게 하고 싶을 때가 있죠? 일반적인 break는 자신을 감싸고 있는 가장 가까운 루프만 탈출해요. 이때 사용하는 마법 같은 기능이 바로 라벨(Label)이에요.
<
루프 시작 전에 OuterLoop:와 같이 이름을 붙여주고, break 시 break OuterLoop라고 명시하면 한 번에 모든 루프를 탈출할 수 있어요. 2차원 배열을 탐색하다가 원하는 값을 찾는 순간 전체 탐색을 종료해야 하는 복잡한 로직에서 이 라벨 기능은 필수적인 역할을 수행해요.
[실전 시나리오 예시: 2차원 그리드 탐색]
사용자가 지정한 좌표(x, y)를 찾는 로직을 짠다고 해볼게요. 2차원 슬라이스를 돌면서 좌표를 찾으면 즉시 전체 루프를 끝내야 하므로 라벨이 아주 유용해요.
// 라벨을 사용한 중첩 루프 탈출 예시
TargetLoop:
for i := 0; i < rows; i++ {
for j := 0; j < cols; j++ {
if grid[i][j] == target {
fmt.Println("찾았습니다!")
break TargetLoop // Outer loop까지 한 번에 탈출!
}
}
}
자주 하는 실수와 해결법 + FAQ
반복문을 작성하다 보면 문법적으로는 틀리지 않았지만, 프로그램이 예상과 다르게 동작하거나 성능이 떨어지는 경우가 생겨요. 실전에서 자주 마주치는 5가지 실수와 해결책을 정리했어요.
- ❌ 실수: 슬라이스 순회 중 원본 요소를 수정하려고 함 (value 값만 바뀜) → ✅ 해결:
slice[i] = newValue처럼 인덱스를 사용해 직접 접근하세요. - ❌ 실수: 조건식을 잘못 설정하여 무한 루프에 빠짐 → ✅ 해결: 루프를 돌기 전, 반드시 어떤 조건에서 루프가 끝날지 종이 위에 써보고 코드를 작성하세요.
- ❌ 실수: range 문에서 포인터 변수를 참조할 때 모든 요소가 마지막 값만 가짐 → ✅ 해결: Go 1.22 버전 이전이라면 루프 안에서 변수를 새로 생성하여 값을 복사해야 해요.
- ❌ 실수: 맵(Map)을 순회하면서 맵의 크기를 변경함 → ✅ 해결: 순회 중에 맵을 수정하는 것은 안전하지만, 결과가 예측 불가능하므로 별도의 슬라이스에 수정할 키를 모아두었다가 나중에 처리하세요.
- ❌ 실수: 인덱스 범위를 벗어난 접근 (Index out of range) → ✅ 해결 hard: 루프의 종료 조건이
i < len(slice)인지 반드시 확인하세요.
자주 묻는 질문
Q. Go에는 왜 while 문이 따로 없나요?
Go 설계자들은 언어를 최대한 단순하게 유지하고 싶어 했어요. for 문 하나만 잘 설계하면 while 문, do-while 문, 무한 루프를 모두 표현할 수 있기 때문에, 불필요한 키워드를 늘리지 않고 for 하나로 통합한 것이에요.
Q. range를 쓸 때 인덱스가 필요 없으면 어떻게 하나요?
언더스코어(_)를 사용하면 돼요. for _, value := range slice라고 쓰면 인덱스는 무시하고 값만 깔끔하게 가져올 수 있어요. 이는 Go의 매우 중요한 관례 중 하나예요.
Q. for 루프 성능이 다른 언어보다 느린가요?
아니요, 전혀 그렇지 않아요. Go의 for 루프는 컴파일 시점에 매우 효율적인 기계어로 변환되기 때문에 매우 빠릅니다. 오히려 언어의 단순함 덕분에 컴파일러가 최적화하기 더 좋은 구조를 가지고 있어요.
Q. 무한 루프를 방지하는 가장 좋은 습관은 무엇인가요?
루프 내부에 반드시 탈출 조건(break)을 명시적으로 작성하고, 가능하다면 루프가 돌아야 하는 최대 횟수를 제한하는 카운터 변수를 함께 사용하는 것이 가장 안전해요.
반복문 정복을 위한 마지막 체크리스트
오늘 배운 내용은 Go 프로그래밍의 가장 기본이면서도 가장 강력한 무기예요. 반복문을 제대로 다루지 못하면 복잡한 데이터를 처리하는 로직을 짤 수 없거든요. 마지막으로 핵심 내용을 정리해 드릴게요.
- Go에는 for 문 하나로 모든 반복을 처리해요.
- 표준 for 루프는 정밀한 인덱스 제어가 필요할 때 사용해요.
- while 문처럼 쓰고 싶다면 조건식만 남긴 for를 활용하세요.
- 슬라이스나 맵은 range 문을 쓰는 것이 가장 안전하고 편해요.
- range의 값은 복사본이므로, 원본 수정 시 인덱스를 직접 써야 해요.
- 중첩 루프를 한 번에 탈출하려면 라벨(Label) 기능을 활용하세요.
이제 이론은 끝났어요. 바로 코드 에디터를 켜고 직접 타이핑해 보세요. 눈으로 보는 것과 직접 에러를 겪으며 고치는 것은 하늘과 땅 차이예요. 오늘 배운 패턴들을 하나씩 직접 구현해 보면서 자신의 것으로 만드시길 바라요.
오늘 바로 실천할 수 있는 단계
- 오늘 할 일: 슬라이스를 만들고 range 문을 사용해 모든 요소를 출력해 보기
- 이번 주 할 일: 2차원 배열을 만들고 라벨을 사용해 특정 값을 찾는 로직 구현하기
- 실행 직전 할 일: Go 공식 문서의 for 문 예제를 한 번 더 정독하기
이 가이드가 여러분의 Go 학습 여정에 큰 도움이 되었기를 바라요. 혹시 코드를 작성하다가 막히는 부분이 있거나, 이해가 잘 안 되는 패턴이 있다면 언제든 댓글로 질문을 남겨 주세요. 제가 아는 선에서 최대한 자세히 답변드릴게요!
관련해서 더 깊이 있는 Go 문법이 궁금하시다면 Go 반복문 완전 정복 가이드 글도 함께 읽어 보시는 것을 추천해요.