[IT-정보] Go 반복문 치트시트: 핵심을 한눈에 – 초보 개발자를 위한 실전 문법과 패턴 정리

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

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

새로운 프로그래밍 언어를 배울 때 가장 당혹스러운 순간이 언제인지 아시나요? 아마도 다른 언어에서는 당연하게 쓰던 문법이 보이지 않을 때일 거예요. 파이썬의 while이나 자바스크립트의 다양한 반복문 구조를 기대하며 코드를 작성하다가, Go(Golang)의 문서에서 오직 for 하나만 발견하면 누구나 당황하기 마련이에요.

처음 Go를 접하는 개발자들은 “정말 반복문이 하나뿐이라고?”라며 의구심을 갖기도 해요. 하지만 이는 Go가 추구하는 철학인 단순함과 명확성을 보여주는 아주 멋진 설계예요. 불필요한 키워드를 줄이고 하나의 강력한 도구를 여러 방식으로 활용하게 함으로써, 코드의 복잡도를 낮추고 가독성을 높인 것이죠.

반복문을 제대로 다루지 못하면 데이터 리스트를 순회하거나, 조건이 충족될 때까지 작업을 수행하는 기본적인 로직조차 작성하기 어려워요. 특히 Go는 슬라이스(Slice)나 맵(Map) 같은 자료구조를 다룰 일이 굉장히 많은데, 이때 반복문의 활용 능력은 개발자의 숙련도를 결정짓는 핵심 요소가 돼요.

이 글을 끝까지 읽고 나면 여러분은 더 이상 Go의 반복문 구조를 헤매지 않게 될 거예요. 단순한 문법 암기를 넘어, 어떤 상황에서 어떤 방식의 Go 반복문 치트시트 패턴을 적용해야 효율적인 코드를 짤 수 있는지 확실히 알게 됩니다.

💡 이 글에서 다루는 내용

  • Go의 유일한 반복문인 for의 기본 구조와 변형 유형
  • 슬라이스, 배열, 맵을 효율적으로 순회하는 range 활용법
  • 실전에서 바로 복사해서 쓸 수 있는 유용한 코드 스니펫
  • 초보 개발자가 가장 많이 저지르는 실수와 해결 방법

본격적인 시작 전, 필수 개념 정리

반복문을 배우기 전에 우리가 반드시 짚고 넘어가야 할 개념들이 있어요. Go의 반복문은 단순히 숫자를 세는 것을 넘어, 데이터의 흐름을 제어하는 아주 정교한 도구이기 때문이에요. 무작정 코드를 타이핑하기 전에, Go가 반복문을 설계한 의도를 먼저 이해하는 것이 중요해요.

가장 먼저 기억해야 할 점은 Go에는 while 키워드가 없다는 사실이에요. 다른 언어에서 조건문만 사용하던 while 루프는 Go에서 for 문법의 변형으로 모두 처리돼요. 즉, 하나의 키워드로 모든 상황을 커버하는 구조죠.

또한, 반복문을 다룰 때는 제어 변수의 생명 주기를 잘 파악해야 해요. 반복문 안에서 선언된 변수가 루프가 끝난 뒤에도 살아있는지, 아니면 매 루프마다 새로 생성되는지에 따라 프로그램의 동작이 완전히 달라질 수 있거든요.

반복문 유형별 선택 기준

상황에 맞는 적절한 반복 방식을 선택하는 것은 코드의 가독성과 성능에 큰 영향을 미쳐요. 아래 표를 통해 어떤 상황에서 어떤 형식을 써야 하는지 비교해 보세요.

사용 유형 주요 특징 권장 사용 상황
표준 for 문 초기값, 조건식, 증감식을 직접 제어 특정 횟수 반복 또는 인덱스 조작이 필요할 때
조건식 for 문 조건이 참인 동안 계속 실행 (while 대체) 종료 시점이 명확하지 않은 지속적 작업 시
range 기반 for 문 슬라이스, 배열, 맵의 요소를 자동 순회 자료구조의 모든 요소를 하나씩 꺼내 쓸 때
무한 루프 조건 없이 계속 실행 내부에서 break로 탈출할 조건이 따로 있을 때

이처럼 Go의 반복문은 형태는 하나지만, 어떻게 작성하느냐에 따라 그 성격이 완전히 달라져요. 이제 이 기본 지식을 바탕으로 실제 코드가 어떻게 작성되는지 단계별로 살펴볼게요.

💡 알아두기
Go의 반복문 성능은 매우 뛰어납니다. 컴파일러가 루프 구조를 최적화하기 때문에, 복잡한 로직에서도 다른 인터프리터 언어보다 훨씬 빠른 속도를 보장해요.

실전에서 바로 쓰는 Go 반복문 마스터 가이드

이제 본격적으로 코드를 작성하며 감을 익혀볼까요? 단순한 이론보다는 직접 보고 이해할 수 있는 Go 반복문 예제를 중심으로 단계별 가이드를 구성했어요. 각 단계는 실무에서 가장 빈번하게 사용되는 패턴들이에요.

STEP 1. 가장 기본적인 C 스타일의 for 문

가장 클래식한 형태예요. 반복 횟수를 명확하게 제어하고 싶을 때 사용해요. 세 가지 구성 요소인 초기화, 조건식, 증감식이 한 줄에 들어가는 것이 특징이에요.

이 방식은 인덱스 번호를 직접 다루어야 하거나, 숫자를 1씩 증가시키는 것이 아니라 2씩 혹은 3씩 건너뛰며 순회해야 할 때 아주 강력한 힘을 발휘해요.

💡 알아두기
초기화 식에서 변수를 선언하면, 그 변수의 범위(Scope)는 해당 for 루프 블록 내부로 제한돼요. 루프가 끝나면 더 이상 사용할 수 없으니 메모리 관리 측면에서도 효율적이에요.

예를 들어, 1부터 10까지 짝수만 출력하고 싶다면 다음과 같이 작성할 수 있어요.
for i := 1; i <= 10; i += 2 { fmt.Println(i) }
이처럼 조건과 증감 로직을 한눈에 파악할 수 있다는 게 큰 장점이에요.

STEP 2. 데이터 집합을 위한 range 문법 활용하기

Go 개발자가 가장 많이 사용하는 패턴이 바로 range 키워드예요. 슬라이스(Slice)나 배열(Array)에 담긴 데이터를 하나씩 꺼낼 때, 인덱스를 직접 계산하는 번거로움을 없애줘요.

range를 사용하면 루프가 돌 때마다 현재 요소의 인덱스을 동시에 반환해 줘요. 만약 인덱스가 필요 없고 값만 필요하다면, 언더바(\_)를 사용하는 '공백 식별자(Blank Identifier)'를 써야 해요. Go는 사용하지 않는 변수가 있으면 컴파일 에러를 발생시키기 때문이죠.

슬라이스 순회 예시를 살펴볼까요?
nums := []int{10, 20, 30}
for i, v := range nums { fmt.Printf("인덱스: %d, 값: %d\n", i, v) }

이 코드는 슬라이스의 길이를 몰라도 알아서 끝까지 안전하게 돌아가요. 인덱스 실수를 방지할 수 있는 아주 안전한 방법이에요.

STEP 3. 맵(Map) 자료구조의 불규칙한 순회

맵(Map)은 키(Key)와 값(Value)의 쌍으로 이루어진 자료구조죠. 맵을 range로 순회할 때는 슬라이스와는 다른 아주 중요한 특징이 있어요. 바로 순서가 보장되지 않는다는 점이에요.

동일한 맵을 대상으로 루프를 두 번 돌려도, 첫 번째 루프와 두 번째 루프의 출력 순서가 다를 수 있어요. 이는 Go 언어 설계상 맵의 순회 순서가 무작위(Random)로 결정되기 때문이에요. 만약 일정한 순서로 데이터를 처리해야 한다면, 먼저 키들을 슬라이스에 담아 정렬한 뒤 그 슬라이스를 순회하는 전략을 써야 해요.

맵 순회 예시를 확인해 보세요.
m := map[string]int{"apple": 1, "banana": 2}
for k, v := range m { fmt.Printf("%s: %d\n", k, v) }

여기서 출력되는 apple과 banana의 순서는 실행할 때마다 달라질 수 있다는 점을 꼭 기억하세요.

STEP 4. 루프 제어의 핵심: break와 continue

반복문을 실행하다 보면 특정 조건에서 멈추거나, 이번 차례만 건너뛰고 싶을 때가 있어요. 이때 사용하는 것이 breakcontinue예요.

break는 루프를 즉시 종료하고 빠져나오게 해요. 특정 값을 찾았을 때 더 이상 검색할 필요가 없다면 break를 써서 자원을 아껴야 해요. 반면, continue는 현재 진행 중인 반복 단계만 스킵하고 다음 반복으로 바로 넘어가게 만들어요. 예를 들어, 리스트에서 특정 조건에 맞지 않는 데이터는 무시하고 넘어가고 싶을 때 아주 유용해요.

실제 상황을 가정해 볼게요. 1부터 100까지 숫자 중 7의 배수만 출력하다가, 40이 나오면 멈추고 싶다면 어떻게 할까요?
for i := 1; i <= 100; i++ {
if i == 40 { break }
if i % 7 != 0 { continue }
fmt.Println(i)
}

이 코드는 40에 도달하면 멈추고, 7의 배수가 아닌 숫자는 그냥 넘어갑니다.

STEP 5. 실전 스니펫: 데이터 필터링과 합계 구하기

이 모든 개념을 종합한 실전 코드를 하나 준비했어요. 슬라이스에 담긴 점수 데이터에서 60점 이상인 학생들의 평균 점수를 구하는 시나리오예요.

이 코드는 단순한 반복을 넘어, 실제 프로덕션 환경에서 조건부 데이터 처리 로직을 짤 때 사용하는 전형적인 패턴이에요.

💡 실전 시나리오 코드
scores := []int{45, 88, 92, 55, 76, 30, 95}
sum := 0
count := 0

for _, score := range scores {
if score >= 60 {
sum += score
count++
}
}

if count > 0 {
avg := float64(sum) / float64(count)
fmt.Printf("합격자 수: %d, 평균 점수: %.2f\n", count, avg)
} else {
fmt.Println("합격자가 없습니다.")
}

위 코드에서 보듯, range로 데이터를 하나씩 꺼내고, if 문으로 조건을 검사하며, 필요한 변수에 값을 누적하는 과정은 모든 백엔드 로직의 기초가 됩니다.

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

반복문은 논리적으로 단순해 보이지만, 작은 실수 하나가 무한 루프를 만들거나 프로그램의 성능을 갉아먹을 수 있어요. 입문자들이 가장 많이 겪는 문제들을 모아봤어요.

자주 하는 실수와 해결법

실수: 조건식 오류로 인한 무한 루프 발생
왜 발생하는가: for 문의 종료 조건을 잘못 설정하거나, 루프 내부에서 종료 조건을 충족시키는 변수의 변화를 주지 않았을 때 발생해요. 프로그램이 멈추지 않고 CPU 점유율이 치솟는 주범이죠.
해결법: 루프가 돌 때마다 조건식에 사용되는 변수가 반드시 변화하는지 확인하세요. 또한, 반드시 탈출할 수 있는 break 경로를 명시적으로 설계하는 습관을 들이는 것이 좋아요.

실수: 슬라이스 인덱스 초과(Out of Bounds) 에러
왜 발생하는가: 표준 for 문에서 조건식을 i <= len(slice)와 같이 작성할 때 발생해요. 슬라이스의 인덱스는 0부터 시작하기 때문에, 길이를 그대로 사용하면 마지막 인덱스를 넘어선 위치를 참조하게 됩니다.
해결법: 인덱스 기반 루프를 쓸 때는 항상 i < len(slice) (작다) 조건을 사용하거나, 가급적 인덱스 계산이 필요 없는 range 문법을 사용하세요.

실수: range 변수의 포인터 참조 문제
왜 발생하는가: range 문법은 루프가 돌 때마다 새로운 복사본을 변수에 할당해요. 만약 루프 안에서 해당 변수의 주소값을 가져와 슬라이스에 저장하면, 모든 요소가 루프의 마지막 값만을 가리키게 되는 심각한 논리 오류가 생겨요.
해결법: 루프 내부에서 요소의 주소를 가져와야 한다면, 인덱스를 사용하여 원본 슬라이스에 직접 접근하세요. 예: &slice[i]

실수: 맵 순회 중 데이터 수정
왜 발생하는가: 맵을 순회하는 도중에 맵의 크기를 변경(요소 추가 또는 삭제)하려고 하면 예기치 못한 동작이 발생할 수 있어요.
해결법: 순회 중에 요소를 삭제해야 한다면, 삭제할 키들을 별도의 슬라이스에 모아두었다가 루프가 완전히 끝난 뒤에 따로 처리하는 것이 가장 안전해요.

자주 묻는 질문

Q. Go 언어에는 while 문이 정말 없나요?
네, 맞아요. 대신 for 키워드를 활용해 모든 형태의 반복을 수행해요. 조건식만 적으면 while처럼 동작하고, 조건 없이 적으면 무한 루프가 됩니다.

Q. range에서 인덱스가 필요 없을 때는 어떻게 하나요?
변수 이름 자리에 언더바(\_)를 사용하면 돼요. 예를 들어 for _, value := range slice라고 쓰면 인덱스는 무시하고 값만 가져올 수 있어요.

Q. 루프를 중첩해서 사용할 때 안쪽 루프를 한 번에 탈출하고 싶어요.
이럴 때는 레이블(Label)을 사용하세요. 루프 앞에 이름을 붙이고 break 레이블이름이라고 호출하면 중첩된 루프를 한 번에 빠져나갈 수 있어요.

Q. 슬라이스를 역순으로 순회하려면 어떻게 해야 하나요?
표준 for 문을 사용해야 해요. 인덱스를 len(slice)-1부터 시작해서 0까지 감소시키는 방식으로 작성하면 됩니다.

반복문 정복을 위한 마지막 정리

지금까지 Go 프로그래밍의 핵심인 반복문에 대해 깊이 있게 살펴보았어요. 처음에는 for 하나뿐이라는 사실이 낯설 수 있지만, 익숙해지면 이보다 더 명료하고 강력한 도구는 없다는 것을 느끼실 거예요. 오늘 배운 내용을 잊지 않도록 아래 요약을 꼭 확인해 보세요.

✅ 핵심 요약

  • Go는 단 하나의 for 키워드로 모든 반복을 처리해요.
  • 전통적인 제어가 필요할 땐 표준 for 문을, 데이터 순회 시엔 range를 쓰세요.
  • range 사용 시 인덱스가 필요 없다면 반드시 _를 사용해야 해요.
  • 맵(Map) 순회는 항상 순서가 무작위라는 점을 주의하세요.
  • 중첩 루프 탈출은 레이블(Label) 기능을 활용하면 편리해요.
  • 무한 루프를 방지하기 위해 종료 조건을 항상 설계하세요.

이제 이론은 충분해요. 이제 직접 코드를 쳐볼 시간입니다. 오늘 바로 다음의 작은 미션을 수행해 보세요.

🚀 오늘 할 일: 1부터 50까지 숫자 중 소수(Prime Number)만 출력하는 코드를 직접 작성해 보세요.

📅 이번 주 목표: 슬라이스에 담긴 문자열 데이터를 정렬하고, 특정 단어가 포함된 항목만 필터링하는 실전 함수를 만들어 보세요.

🛠 실행 직전 체크: 작성한 코드에 인덱스 초과 에러나 무한 루프의 위험이 없는지 다시 한번 눈으로 확인해 보세요.

Go 프로그래밍의 길은 이제 시작이에요. 공부하다가 막히는 부분이나 이해가 안 가는 패턴이 있다면 언제든 댓글로 남겨 주세요. 여러분의 성장을 진심으로 응원하며, 함께 고민하고 답변드릴게요!

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

댓글 남기기