[IT-정보] Go 반복문 치트시트: 핵심 문법 정리 – Go 반복문 for 예제와 실전 패턴 완벽 가이드

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

반복문 for, Go 프로그래밍의 시작과 끝

다른 프로그래밍 언어를 공부하다가 Go(Golang)를 처음 접하면 당혹스러운 순간이 찾아와요. Python에는 forwhile이 있고, C 언어에서는 forwhile이 각각 존재하지만, Go에는 오직 for라는 단 하나의 반복문 키워드만 있기 때문이에요. 이 단순함이 처음에는 오히려 혼란을 주기도 하지만, 사실은 Go의 철학인 단순함과 명확성을 가장 잘 보여주는 대목이기도 해요.

슬라이스를 순회하다가 인덱스 범위를 넘겨서 프로그램이 갑자기 멈춰버린 경험이 있나요? 혹은 맵(Map)을 반복문으로 돌리는데 결과값이 매번 다르게 나와서 당황한 적은 없으신가요? 이러한 문제는 Go의 반복문 동작 방식을 정확히 이해하지 못했을 때 발생하는 아주 흔한 실수들이에요. 단순한 문법을 넘어, Go가 데이터를 어떻게 다루는지 그 원리를 파악하는 것이 중요해요.

이 글을 끝까지 읽고 나면, 여러분은 더 이상 반복문 앞에서 머뭇거리지 않게 될 거예요. 복잡한 데이터를 효율적으로 처리하는 방법부터, 실무에서 바로 쓸 수 있는 코드 패턴까지 모두 가져가실 수 있어요. Go 반복문 치트시트를 옆에 띄워두고 실전 코드를 작성해 보세요.

이 글에서 얻어갈 수 있는 핵심 내용

  • 기본적인 3요소 기반의 표준 for 문법 숙달
  • 슬라이스와 맵을 위한 range 키워드 완벽 활용법
  • 무한 루프를 제어하는 break와 continue 기술
  • 실무에서 자주 쓰이는 반복문 패턴과 주의사항

반복문 사용 전 반드시 알아야 할 기초 지식

Go의 반복문을 본격적으로 다루기 전에, 우리가 어떤 도구들을 사용할 수 있는지 명확히 정리할 필요가 있어요. Go의 for는 단순히 숫자를 세는 용도를 넘어, 조건에 따른 실행, 데이터 구조 순회, 그리고 무한 루프 생성까지 모든 역할을 수행해요. 언어의 단순함이 강력한 유연성으로 변하는 지점이라고 이해하시면 좋아요.

반복문을 작성할 때 가장 먼저 결정해야 하는 것은 “어떤 방식으로 데이터를 훑을 것인가”예요. 단순히 인덱스 번호가 필요한지, 아니면 데이터의 실제 값이 필요한지에 따라 선택할 문법이 달라지거든요. 만약 조건식만 가지고 루프를 돌리고 싶다면, 마치 다른 언어의 while 문처럼 동작하게 만들 수도 있어요.

아래 표를 통해 상황에 맞는 반복문 형태를 미리 비교해 보세요. 어떤 상황에서 어떤 문법을 선택해야 하는지 기준을 잡는 데 큰 도움이 될 거예요.

반복 형태 주요 용도 특징 및 장점
표준 for 문 인덱스 기반 제어 증감식과 조건을 직접 설정하여 정밀한 제어 가능
range 활용 문 컬렉션 순회 슬라이스, 맵, 채널의 요소를 인덱스와 값으로 추출
조건식 기반 loop 조건부 실행 특정 조건이 충족될 때까지 계속 실행 (while 역할)
무한 루프 지속적 작업 수행 내부 break 조건이 나올 때까지 무한히 반복

반복문을 설계할 때는 항상 종료 조건을 가장 먼저 생각해야 해요. 종료 조건이 모호하면 프로그램이 응답하지 않는 무한 루프에 빠지게 되고, 이는 서버 자원을 순식간에 고갈시키는 원인이 되거든요. 코드를 짜기 전, “이 루프는 언제 멈추는가?”라는 질문에 스스로 답할 수 있어야 해요.

💡 알아두기
Go에서는 별도의 while 키워드가 없어요. 대신 for condition { ... } 형식을 사용하면 우리가 흔히 아는 while 문과 똑같이 동작한답니다.

실전에서 바로 쓰는 Go 반복문 활용 패턴

이제 본격적으로 실전 코드로 들어가 볼게요. Go의 반복문은 단순하지만, 이를 조합하여 사용하는 방식은 매우 다양해요. 각 단계를 따라가며 문법이 실제 데이터 흐름을 어떻게 제어하는지 눈으로 확인해 보세요.

STEP 1. 표준 for 문으로 정밀하게 제어하기

가장 기초적인 형태는 C 언어 스타일의 3요소(초기화, 조건식, 증감식)를 사용하는 방식이에요. 이 방식은 인덱스를 직접 조작해야 하거나, 특정 간격으로 건너뛰어야 할 때 유용해요.

예를 들어, 숫자를 0부터 9까지 2씩 증가시키며 출력하고 싶다면 다음과 같이 작성할 수 있어요. 초기화 구문에서는 변수를 선언하고, 조건 구문에서는 반복 여부를 판단하며, 증감 구문에서는 매 루프마다 변수 값을 업데이트해요.

for i := 0; i < 10; i += 2 { fmt.Println(i) }

이 구조를 잘 활용하면 슬라이스의 특정 구간만 읽거나, 역순으로 순회하는 등 아주 세밀한 제어가 가능해져요. 하지만 인덱스 계산 실수가 잦을 수 있으니 주의가 필요해요.

STEP 2. range를 이용한 슬라이스 및 배열 순회

실무에서는 숫자를 세는 것보다 슬라이스(Slice) 안에 담긴 데이터를 하나씩 꺼내는 작업이 훨씬 많아요. 이때 가장 강력한 도구가 바로 range 키워드예요. range를 사용하면 인덱스와 값을 동시에 얻을 수 있어 코드가 매우 간결해져요.

슬라이스를 순회할 때 인덱스만 필요하다면, 값 부분에 언더스코어(_)를 사용하여 무시할 수 있어요. 이는 Go의 엄격한 변수 사용 규칙을 따르면서도 불필요한 코드를 줄이는 아주 깔끔한 방법이에요.

// 인덱스와 값을 모두 사용하는 경우
for i, v := range slice { fmt.Printf("인덱스: %d, 값: %v\n", i, v) }

// 값만 필요한 경우
for _, v := range slice { fmt.Println(v) }

여기서 주의할 점은 range가 반환하는 값은 복사본이라는 사실이에요. 루프 내부에서 받은 값을 수정한다고 해서 원본 슬라이스의 값이 바뀌지는 않아요. 원본을 바꾸고 싶다면 반드시 인덱스를 통해 직접 접근해야 해요.

STEP 3. 맵(Map) 데이터 순회와 무작위성 이해하기

Go의 맵은 키(Key)와 값(Value)의 쌍으로 이루어진 자료구조예요. range를 맵에 적용하면 키와 값을 아주 쉽게 추출할 수 있어요. 하지만 여기서 입문자들이 가장 많이 당황하는 포인트가 있어요.

Go의 맵은 순서가 보장되지 않아요. 즉, 똑같은 맵을 대상으로 range를 두 번 돌려도 첫 번째 루프와 두 번째 루프의 출력 순서가 다를 수 있어요. 이는 Go 설계 단계에서부터 의도된 사항이에요. 만약 일정한 순서가 필요하다면, 키들을 따로 슬라이스에 담아 정렬한 뒤 그 슬라이스를 기반으로 반복문을 돌려야 해요.

// 맵 순회 예시
m := map[string]int{"사과": 5, "바나나": 10, "포도": 3}
for key, value := range m { fmt.Printf("%s: %d개\n", key, value) }

STEP 4. 무한 루프와 제어 흐름(break, continue)

때로는 조건이 명확하지 않거나, 특정 상황이 발생할 때까지 계속 실행해야 하는 작업이 있어요. 이때는 아무런 조건식이 없는 for { ... } 형태를 사용하여 무한 루프를 만들어요. 무한 루프는 양날의 검과 같아서, 반드시 탈출구를 마련해야 해요.

탈출구 역할을 하는 것이 breakcontinue예요. break는 루프를 즉시 완전히 종료하고 빠져나가게 하며, continue는 현재 루프의 남은 코드를 건너뛰고 즉시 다음 반복으로 넘어가게 해요. 이 두 키워드를 적절히 조합하면 복잡한 비즈니스 로직도 우아하게 처리할 수 있어요.

⚠️ 주의
무한 루프 안에서 break 조건이 충족되지 않으면 프로그램은 영원히 멈추지 않아요. CPU 점유율이 100%로 치솟는 상황을 방지하기 위해, 루프 내에 적절한 타임아웃이나 종료 조건을 반드시 설계하세요.

STEP 5. 실전 시나리오: 데이터 필터링하기

이해를 돕기 위해 실제 업무에서 자주 쓰이는 상황을 가정해 볼게요. 슬라이스에 담긴 점수 데이터 중에서 60점 이상인 합격자만 골라내는 필터링 로직을 작성해 보겠습니다.

func filterPassers(scores []int) []int {
var passers []int
for _, score := range scores {
if score < 60 {
continue // 60점 미만은 건너뜁니다
}
passers = append(passers, score)
}
return passers
}

이 코드에서는 continue를 사용하여 불필요한 조건문을 중첩시키지 않고도 깔끔하게 로직을 분리했어요. 조건에 맞지 않는 데이터를 먼저 걸러내고(Guard Clause), 통과한 데이터만 처리하는 방식은 가독성을 높이는 아주 좋은 습관이에요.

자주 하는 실수와 해결법 및 FAQ

반복문을 작성하다 보면 누구나 실수를 합니다. 특히 Go의 독특한 동작 방식 때문에 발생하는 오류들은 디버깅을 어렵게 만들기도 하죠. 자주 발생하는 실수들을 정리했으니, 여러분의 코드와 비교해 보세요.

자주 하는 실수와 해결법

  • 무한 루프에 빠지는 경우: 루프를 종료하는 조건식이 잘못되었거나, 조건에 도달하기 전에 변수 값이 변하지 않는 경우예요.
    해결법: 루프 내부에서 제어 변수가 반드시 변화하는지, 탈출 조건이 모든 시나리오를 포함하는지 검토하세요.
  • range의 값 수정 시도: for _, v := range slice에서 v를 수정해도 원본 슬라이스는 변하지 않아요.
    해결법: 원본을 수정해야 한다면 반드시 slice[i] = newValue와 같이 인덱스를 사용하세요.
  • 맵 순회 순서에 의존하는 로직: 맵을 돌릴 때마다 결과 순서가 바뀌는데, 이를 고정된 순서라고 가정하면 버그가 생겨요.
    해결법: 정렬된 키 슬라이스를 먼저 만들고, 그 슬라이스를 range로 순회하며 맵의 값을 가져오세요.
  • 범위 초과(Out of Bounds) 에러: 인덱스 계산 중 i <= len(slice)처럼 범위를 잘못 설정하는 경우예요.
    해결법: 항상 조건식을 i < len(slice)로 설정하여 마지막 인덱스를 넘지 않도록 주의하세요.
  • 루프 변수 캡처 문제: (Go 1.22 이전 버전 기준) 고루틴(Goroutine) 내부에서 루프 변수의 주소를 사용할 때 모든 고루틴이 마지막 값만 참조하는 현상이에요.
    해결법: 루프 내부에서 변수를 지역 변수로 새로 선언하여 복사본을 전달하거나, 최신 Go 버전을 사용하세요.

자주 묻는 질문

Q. Go에는 while 문이 따로 없나요?

네, 따로 없습니다. 대신 for condition { ... } 형식을 사용하면 우리가 사용하는 while 문과 완벽하게 동일하게 동작해요.

Q. range를 쓸 때 인덱스가 필요 없으면 어떻게 하나요?

언더스코어(_)를 사용하면 돼요. for _, value := range slice와 같이 작성하면 인덱스를 무시하고 값만 깔끔하게 가져올 수 있습니다.

Q. for 루프 안에서 다른 루프를 돌리면 성능이 많이 떨어지나요?

중첩 루프(Nested Loop)는 데이터 양이 많아질수록 연산 횟수가 기하급수적으로 늘어나요(O(n^2)). 데이터 규모가 크다면 맵(Map)을 활용하여 연산 횟수를 줄이는 방안을 고민해야 합니다.

Q. break와 return의 차이는 무엇인가요?
break는 현재 실행 중인 루프만 탈출하지만, return은 루프를 포함한 현재 함수 자체를 종료하고 호출한 곳으로 돌아가요.

Q. 채널(Channel)을 반복문으로 읽을 수 있나요?
네, for range channel 형식을 사용하여 채널이 닫힐 때까지 데이터를 계속해서 받아올 수 있어요. 아주 강력한 패턴이에요.

반복문 마스터를 위한 마지막 체크리스트

지금까지 Go의 다양한 반복문 사용법을 살펴보았어요. 반복문은 단순해 보이지만, 데이터의 성격과 목적에 따라 적절한 도구를 선택하는 능력이 프로그래머의 숙련도를 결정해요. 오늘 배운 내용을 잊지 않도록 아래 핵심 요약을 다시 한번 확인해 보세요.

✅ 핵심 요약

  • Go의 반복문은 for 하나로 모든 상황을 해결할 수 있어요.
  • 정밀한 제어가 필요할 땐 표준 for 문을 사용하세요.
  • 슬라이스나 맵을 빠르게 훑을 땐 range가 가장 효율적이에요.
  • 맵(Map)을 순회할 때는 순서가 보장되지 않는다는 점을 명심하세요.
  • 무한 루프를 만들 때는 반드시 탈출 조건(break)을 설계하세요.
  • 원본 데이터를 수정하려면 반드시 인덱스를 통해 접근하세요.

이제 이론은 충분해요. 다음 단계로 넘어가 볼까요? 지금 바로 IDE를 켜고, 여러분이 가진 슬라이스 데이터를 range로 출력하는 코드부터 직접 작성해 보세요. 눈으로 보는 것과 직접 타이핑하는 것은 천지 차이랍니다.

혹시 코드를 작성하다가 막히는 부분이 있거나, 이해가 잘 되지 않는 패턴이 있다면 주저하지 말고 댓글로 남겨 주세요. 여러분의 질문이 다른 학습자들에게도 큰 도움이 될 수 있어요.

더 깊이 있는 Go 프로그래밍 학습을 원하신다면, Go 반복문 완전 정복 가이드 글도 함께 읽어 보시기를 추천드려요!

댓글 남기기