
Go 반복문, 왜 제대로 배워야 할까요?
개발 환경에서 서버 CPU 점유율이 갑자기 100%를 찍으며 시스템이 멈춰버리는 아찔한 경험을 해본 적이 있나요? 대부분의 경우, 범인은 통제력을 잃고 무한히 돌아가는 반복문이에요. 특히 조건식을 잘못 설정하거나 탈출 조건을 놓치면 프로그램은 순식간에 먹통이 되고 말아요.
Go 언어(Golang)는 다른 언어와 달리 반복문 키워드가 오직 for 하나뿐이에요. while이나 do-while 같은 별도의 키워드가 없어서 처음 접하는 입문자들은 “이거 하나로 어떻게 모든 반복을 다 한다는 거지?”라는 의문을 갖기 쉬워요. 하지만 이 단순함이야말로 Go의 강력한 설계 철학이며, 제대로 익히기만 하면 어떤 복잡한 로직도 간결하게 구현할 수 있는 무기가 돼요.
이 글을 끝까지 읽고 나면, 여러분은 단순히 코드를 따라 치는 수준을 넘어 상황에 맞는 가장 효율적인 루프 패턴을 선택할 수 있게 돼요. 슬라이스를 빠르게 순회하는 방법부터 맵(Map)의 불규칙한 순서를 다루는 법, 그리고 실전에서 자주 발생하는 무한 루프의 함정을 피하는 기술까지 모두 가져가실 수 있어요.
- Go의 유일한 반복문 for의 기본 구조와 변형 패턴
- range를 활용하여 슬라이스, 맵, 문자열을 다루는 기술
- 실무에서 반드시 마주치는 제어문(break, continue) 활용법
- 초보자가 가장 많이 저지르는 반복문 실수와 해결책
Go 반복문 시작 전 꼭 알아야 할 기본 개념
반복문을 작성하기 전에 반드시 머릿속에 정리해두어야 할 개념들이 있어요. Go의 반복문은 매우 유연하기 때문에, 내가 지금 어떤 방식으로 데이터를 꺼내올 것인지에 따라 문법의 모양이 완전히 달라져요. 무작정 코드를 쓰기 전에 아래의 기준들을 먼저 살펴봐 주세요.
반복문 패턴 선택 기준
상황에 따라 어떤 for 문을 사용할지 결정하는 것이 코드의 가독성과 성능을 결정해요. 아래 표를 통해 기준을 명확히 잡아보세요.
| 구분 방식 | 주요 용도 | 핵심 특징 |
|---|---|---|
| 표준 3요소 방식 | 정해진 횟수만큼 반복할 때 | 초기값, 조건식, 증감식을 직접 제어 |
| 조건식 전용 방식 | 특정 조건이 충족될 때까지 반복 | 다른 언어의 while 문과 유사한 역할 |
| range 활용 방식 | 컬렉션(슬라이스, 맵 등) 순회 | 인덱스와 값을 한 번에 안전하게 추출 |
| 무한 루프 방식 | 서버 대기, 이벤트 루프 구현 | 내부에서 break를 통한 탈출이 필수 |
사전 준비 체크리스트
반복문을 다루기 위해 최소한 다음의 개념들은 이해하고 있어야 해요. 만약 이 개념들이 낯설다면, 반복문을 배우기 전에 먼저 가볍게 훑어보는 것을 추천드려요.
- 슬라이스(Slice): 데이터를 순차적으로 담는 Go의 핵심 자료구조예요.
- 맵(Map): 키와 값의 쌍으로 이루어진 자료구조로, 순서가 보장되지 않는다는 점을 기억해야 해요.
- 루나(Rune): 문자열을 다룰 때 바이트 단위가 아닌 글자 단위로 처리하기 위한 개념이에요.
Go의 반복문은 매우 강력해서, 종료 조건을 명확히 설정하지 않으면 프로그램이 끝없이 실행되는 무한 루프에 빠지기 쉬워요. 항상 탈출 조건을 먼저 설계하는 습관을 들이세요.
Go 반복문 실전 활용 가이드
이제 본격적으로 실무에서 바로 사용할 수 있는 Go 반복문의 5가지 핵심 패턴을 단계별로 살펴볼게요. 각 패턴은 용도가 명확히 다르니, 상황에 맞춰 골라 쓰는 연습이 필요해요.
STEP 1. 표준 3요소로 제어하는 for 루프
가장 기본적인 형태예요. C나 Java에서 사용하는 방식과 매우 흡사하며, 반복의 시작, 끝나는 조건, 그리고 한 번 돌 때마다 수행할 행동을 한 줄에 정의할 수 있어요. 숫자를 셀 때나 특정 간격으로 건너뛰며 반복해야 할 때 가장 유용해요.
예를 들어, 0부터 9까지 2씩 증가하며 숫자를 출력하고 싶다면 다음과 같이 작성할 수 있어요.
for i := 0; i < 10; i += 2 {
fmt.Println(i)
}
여기서 i := 0은 시작점, i < 10은 언제까지 돌 것인지에 대한 조건, 그리고 i += 2는 한 번 돌 때마다 어떻게 변할지를 의미해요. 이 구조를 완벽히 이해하면 반복의 흐름을 완벽하게 통제할 수 있어요.
STEP 2. 조건식만 사용하는 while 스타일 루프
Go에는 while이라는 키워드가 없지만, for 문에 조건식 하나만 적어줌으로써 똑같은 기능을 수행할 수 있어요. 특정 값이 변할 때까지, 혹은 어떤 작업이 완료될 때까지 반복해야 하는 경우에 사용해요. 이는 주로 외부 파일의 끝(EOF)을 읽거나, 채널(Channel)에서 데이터가 들어올 때까지 대기하는 로직에서 자주 보여요.
예를 들어, 어떤 변수 active가 true인 동안 계속해서 작업을 수행하는 코드는 다음과 같아요.
for active {
// 반복할 작업 수행
if 작업완료 {
active = false
}
}
이 방식은 조건의 상태가 핵심이에요. 조건이 거짓이 되는 순간 루프는 자연스럽게 종료돼요. 다만, 루프 내부에서 조건이 변하지 않으면 무한 루프에 빠진다는 점을 항상 명심해야 해요.
STEP 3. range를 이용한 컬렉션 순회하기
실무에서 가장 많이 쓰이는 패턴이에요. 슬라이스나 맵 같은 데이터 집합을 하나씩 꺼낼 때 사용해요. range 키워드를 사용하면 인덱스와 값을 동시에 안전하게 얻을 수 있어 실수를 줄여줘요.
1) 슬라이스(Slice) 순회: 슬라이스의 인덱스와 실제 값을 가져와요.
2) 맵(Map) 순회: 맵에서는 키(Key)와 값(Value)을 가져와요. 여기서 주의할 점은 맵의 순회 순서는 매번 랜덤하다는 것이에요. 데이터가 들어간 순서대로 나오지 않으므로, 순서가 중요하다면 별도의 정렬 과정이 필요해요.
만약 인덱스나 키가 필요 없다면, 언더스코어(
_)를 사용하여 무시할 수 있어요. 이는 불필요한 변수 선언을 막아 코드를 훨씬 깔끔하게 만들어줘요.STEP 4. 문자열을 안전하게 다루는 방법
문자열을 반복문으로 돌릴 때 초보자들이 가장 많이 하는 실수가 있어요. 바로 문자열을 단순한 바이트(byte) 배열로 생각하고 인덱스로 접근하는 것이에요. 한글과 같은 멀티바이트 문자는 한 글자가 여러 바이트로 구성되어 있어서, 단순히 바이트 단위로 자르면 글자가 깨져버려요.
이때 해결책이 바로 range를 사용한 문자열 순회예요. range를 쓰면 Go가 내부적으로 글자 단위인 룬(rune) 타입으로 변환해서 안전하게 하나씩 꺼내줘요.
위 코드를 실행하면 한글이 깨지지 않고 정확한 위치와 글자를 출력할 수 있어요. 문자열을 다룰 때는 반드시 range를 사용하는 습관을 들여야 해요.
STEP 5. 제어 흐름을 결정하는 break와 continue
반복문 중간에 흐름을 끊거나 건너뛰어야 할 때가 있죠? 이럴 때 사용하는 것이 제어문이에요.
- break: 반복문을 즉시 완전히 종료하고 빠져나와요. 특정 조건을 만족했을 때 더 이상의 연산이 불필요한 경우 사용해요.
- continue: 현재 차례의 작업을 건너뛰고 바로 다음 반복 단계로 넘어가요. 특정 조건인 데이터만 제외하고 처리하고 싶을 때 유용해요.
예를 들어, 리스트에서 짝수만 출력하고 싶다면 if value % 2 != 0 { continue }를 사용하여 홀수를 건너뛸 수 있어요.
사용자 목록(슬라이스)에서 성인(age >= 19)만 추출하여 새로운 리스트를 만드는 로직을 작성해 보세요. 이때
range로 순회하며 if문과 continue를 조합하면 매우 간결한 코드가 완성됩니다.자주 하는 실수와 해결법
Go 반복문을 작성하다 보면 문법적으로는 틀리지 않았지만, 논리적으로 큰 문제를 일으키는 경우가 많아요. 실전에서 자주 마주치는 실수들을 정리했으니 꼭 체크해 보세요.
자주 하는 실수와 해결법
- ❌ 실수: 고루틴(Goroutine) 안에서 루프 변수 직접 사용
왜 발생할까요? Go의 루프 변수는 매 반복마다 값이 새로 생기는 게 아니라, 같은 메모리 주소를 재사용해요. 그래서 고루틴이 실행되는 시점에 변수 값이 이미 마지막 값으로 바뀌어 있을 수 있어요.
✅ 해결법: 루프 내부에서 변수를 인자로 전달하거나, 새로운 지역 변수에 값을 복사해서 사용하세요. - ❌ 실수: 슬라이스 순회 중 요소 삭제
왜 발생할까요? 반복문이 돌고 있는 도중에 슬라이스의 길이를 줄여버리면, 인덱스가 꼬이면서 범위를 벗어나거나(out of bounds) 일부 요소를 건너뛰게 돼요.
✅ 해결법: 요소를 삭제해야 한다면 역순으로 루프를 돌거나, 삭제할 요소를 따로 모아둔 뒤 한꺼번에 처리하세요. - ❌ 실수: 증감식 누락으로 인한 무한 루프
왜 발생할까요?for i := 0; i < 10;처럼 증감식(i++)을 빼먹으면 조건이 영원히 참이 되어 CPU를 점유하게 돼요.
✅ 해결법: 루프 구조를 작성한 직후, 조건식이 언젠가 거짓이 되는지 반드시 눈으로 검증하세요. - ❌ 실수: 맵(Map) 순회 시 순서 의존
왜 발생할까요? 맵은 설계상 순서가 보장되지 않아요. 테스트 코드를 짤 때 매번 결과 순서가 달라져 실패할 수 있어요.
✅ 해결법: 순서가 중요하다면 키들을 슬라이스에 담아 정렬한 뒤, 그 슬라이스를 기준으로 맵에 접근하세요.
자주 묻는 질문
Q. Go에서 while 문을 어떻게 쓰나요?
Go에는 while 키워드가 따로 없어요. 대신 for 조건식 { ... } 형태로 작성하면 우리가 아는 while 문과 완전히 똑같이 동작해요.
Q. range를 쓰면 인덱스가 왜 안 나오나요?
for _, value := range slice처럼 작성하셨나요? 첫 번째 반환값인 인덱스를 무시하기 위해 언더스코어(_)를 사용했기 때문이에요. 인덱스가 필요하다면 for i, v := range slice로 작성해 주세요.
Q. 중첩된 루프(Nested Loop)에서 바깥쪽 루프를 탈출하고 싶어요.
<
break는 자신을 감싸고 있는 가장 가까운 루프 하나만 탈출해요. 바깥쪽 루프까지 한 번에 나가려면 'Label'을 사용해야 해요. OuterLoop: for ... { for ... { break OuterLoop } } 형식을 사용하면 됩니다.
Q. 문자열 길이를 잴 때 len()을 써도 되나요?
한글이 포함된 경우 주의해야 해요! len()은 글자 수가 아니라 바이트 수를 반환해요. 글자 수를 알고 싶다면 utf8.RuneCountInString()을 사용하거나, range로 순회하며 카운트하는 것이 정확해요.
Go 반복문 마스터를 위한 요약
오늘 배운 내용을 잊지 않도록 핵심만 다시 한번 짚어볼게요. 이 내용만 기억해도 Go 반복문 때문에 고생하는 일은 절반 이상 줄어들 거예요.
- Go의 반복문은 for 하나로 모든 것을 해결한다.
- 횟수가 정해진 경우 표준 3요소 방식을 사용한다.
- 컬렉션 순회에는 안전하고 간결한 range가 최고다.
- 문자열을 다룰 때는 글자 깨짐 방지를 위해 반드시 range를 쓴다.
- 맵(Map) 순회 시에는 순서가 매번 바뀐다는 점을 잊지 않는다.
- 무한 루프를 방지하기 위해 항상 탈출 조건을 먼저 설계한다.
자, 이제 이론은 충분해요. 눈으로만 보는 것보다 직접 코드를 입력해 보는 것이 훨씬 빠르게 실력을 키우는 방법이에요. 지금 바로 IDE를 켜고 슬라이스에 담긴 숫자들을 range로 출력하는 것부터 시작해 보세요.
혹시 코드를 작성하다가 예상치 못한 오류가 발생하거나, 더 궁금한 패턴이 있다면 주저하지 말고 댓글로 남겨 주세요. 여러분의 고민이 다음 글의 주제가 될 수도 있어요! 오늘 배운 내용이 도움이 되었다면 주변 동료들에게도 공유해 주세요.
다음 단계로 넘어가고 싶다면, Go의 핵심 자료구조를 더 깊게 다루는 Go 반복문 완전 정복 가이드 글과 함께 읽어보시는 것을 강력히 추천드려요.