[IT-정보] Go 반복문 치트시트: 핵심을 한눈에 – 입문자를 위한 문법 요약부터 실전 패턴까지

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

반복문 때문에 멈춰버린 개발 흐름, 어떻게 해결할까요?

새로운 프로그래밍 언어를 배울 때 가장 당혹스러운 순간 중 하나는 익숙했던 문법이 보이지 않을 때예요. 다른 언어에서는 당연하게 사용하던 while 문이나 do-while 문이 Go(Golang) 언어에는 아예 존재하지 않는다는 사실을 처음 마주하면 당황하기 마련이죠. 코드를 짜다가 루프를 돌려야 하는데 어떻게 시작해야 할지 몰라 빈 화면만 바라보고 있는 경험, 분명히 해보셨을 거예요.

특히 슬라이스(Slice)나 맵(Map) 같은 자료구조를 다룰 때, 인덱스를 잘못 계산해서 프로그램이 갑자기 종료되거나 무한 루프에 빠져 CPU 점유율이 치솟는 상황은 입문 단계에서 매우 흔한 실수예요. 단순한 문법 오류를 넘어, 성능 저하나 논리적 결함으로 이어지기 때문에 반복문은 대충 넘어가서는 안 되는 핵심 영역이에요.

이 글은 단순히 문법을 나열하는 사전식 설명서가 아니에요. Go 반복문 치트시트로서, 여러분이 실제 업무나 프로젝트에서 바로 꺼내 쓸 수 있는 실전적인 코드 패턴을 제공하는 데 집중했어요. 이 글을 끝까지 읽고 나면, Go의 유일한 반복문인 for 하나만으로도 모든 반복 로직을 자유자재로 제어할 수 있게 될 거예요.

💡 이 글에서 다루는 핵심 내용

  • Go 반복문의 기본 3가지 구조와 사용 조건
  • range 키워드를 활용한 효율적인 컬렉션 순회법
  • 실무에서 바로 복사해 쓰는 단계별 코드 스니펫
  • 입문자가 반드시 피해야 할 흔한 실수와 해결책

Go 반복문을 시작하기 전 반드시 알아야 할 기초 지식

Go 언어의 반복문을 제대로 다루려면 먼저 Go가 설계된 철학을 이해해야 해요. Go는 복잡성을 줄이고 가독성을 높이기 위해 문법을 매우 간결하게 유지해요. 그래서 다른 언어에서 보던 다양한 반복문 종류를 과감히 삭제하고, 오직 for 하나로 모든 상황을 해결하도록 설계되었어요. 이것은 언어의 일관성을 높여주지만, 반대로 생각하면 for 하나의 용법을 완벽히 숙지해야 한다는 뜻이기도 해요.

반복문을 작성하기 전에 여러분의 머릿속에 정리되어 있어야 할 핵심 개념은 조건식의 평가 시점변수의 생명 주기예요. 루프 내부에서 선언된 변수가 루프가 끝난 뒤에도 살아있는지, 아니면 매 회차마다 초기화되는지를 명확히 구분하지 못하면 데이터 오염 문제가 발생할 수 있어요.

또한, 반복문을 사용하기 전에 현재 다루고자 하는 자료구조가 무엇인지 먼저 판단해야 해요. 슬라이스인지, 맵인지, 혹은 단순한 정수 범위인지에 따라 가장 최적화된 반복 방식이 달라지기 때문이에요. 아래 표를 통해 상황별로 어떤 형태의 for 문을 선택하는 것이 유리한지 비교해 보세요.

반복 유형 주요 용도 특징 및 장점
기본 C-스타일 정해진 횟수 반복 초기값, 조건식, 증감식을 직접 제어 가능
range 활용형 슬라이스/맵 순회 인덱스와 값을 동시에 추출하여 코드 간결
조건 중심형 특정 조건 만족 시까지 while 문을 대체하며 조건식만으로 동작
무한 루프형 지속적인 이벤트 대기 break를 사용하여 명시적으로 탈출 필요

준비가 되셨나요? 이제 본격적으로 Go의 강력한 반복문 문법 속으로 들어가 볼게요. 각 패턴이 실제 코드에서 어떻게 구현되는지 하나씩 살펴봅시다.

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

이제 이론을 넘어 실제 코드를 작성할 시간이에요. Go의 반복문은 단순해 보이지만, 어떻게 조합하느냐에 따라 코드의 성능과 가독성이 극명하게 갈려요. 단계별로 가장 많이 쓰이는 패턴을 상세히 설명해 드릴게요.

STEP 1. 가장 기본이 되는 3요소 제어 루프

가장 전통적인 방식의 for 문이에요. 프로그래밍 언어의 기본인 초기화, 조건 검사, 증감 세 단계를 한 줄에 작성해요. 정해진 횟수만큼 반복하거나, 인덱스를 세밀하게 조정해야 할 때 가장 강력해요.

// 1부터 10까지 출력하는 예제
for i := 1; i <= 10; i++ {
    fmt.Println(i)
}

이 방식은 루프가 시작될 때 `i := 1`이 실행되고, 매 회차가 끝날 때마다 `i++`가 실행돼요. 조건을 검사하는 `i <= 10`은 루프의 시작 전에 매번 확인하죠. 인덱스를 역순으로 돌리거나 2씩 증가시키는 등 자유로운 변형이 가능하다는 것이 큰 장점이에요. 다만, 조건식을 잘못 작성하면 무한 루프에 빠질 수 있으니 주의가 필요해요.

STEP 2. 컬렉션 순회의 마법, range 키워드

슬라이스(Slice)나 배열(Array)을 다룰 때 가장 많이 사용하는 방식이에요. 인덱스를 직접 계산할 필요 없이, Go가 제공하는 `range`를 사용하면 코드의 가독성이 비약적으로 상승해요. `range`는 반복할 때마다 인덱스와 해당 요소의 값을 쌍으로 반환해 줘요.

// 슬라이스 순회 예제
fruits := []string{"사과", "바나나", "포도"}

for index, value := range fruits {
    fmt.Printf("%d번째 과일: %s\n", index, value)
}

// 인덱스가 필요 없을 때는 언더스코어(_) 사용
for _, value := range fruits {
    fmt.Println("과일 이름:", value)
}

여기서 중요한 팁이 있어요. 만약 인덱스 값이 필요 없다면 반드시 `_` (blank identifier)를 사용해 주세요. 사용하지 않는 변수를 선언만 하고 쓰지 않으면 Go 컴파일러는 에러를 발생시키기 때문이에요. 또한, `range`는 내부적으로 복사본을 생성하여 값을 전달하므로, 원본 데이터를 수정해야 한다면 인덱스를 사용해 직접 접근해야 한다는 점을 기억하세요.

STEP 3. Go 스타일의 While 문 구현하기

Go에는 별도의 while 키워드가 없어요. 대신 for 문에 조건식만 남겨서 동일한 기능을 수행해요. 특정 상태가 유지되는 동안 계속해서 로직을 실행해야 할 때 매우 유용해요.

// 조건 중심의 루프 (While 문 대체)
count := 0
for count < 5 {
    fmt.Println("현재 카운트:", count)
    count++
}

이 패턴은 조건이 참(true)인 동안 계속 실행돼요. 만약 조건이 아예 없는 for { ... } 형태를 사용하면 무한 루프가 되는데, 이는 서버의 이벤트 루프나 백그라운드 워커를 구현할 때 자주 쓰여요. 이럴 때는 반드시 내부에서 break를 통해 탈출 조건을 만들어 주어야 해요.

STEP 4. 맵(Map) 순회와 비결정적 순서

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

// 맵 순회 예제
scores := map[string]int{"철수": 90, "영희": 85, "민수": 95}

for name, score := range scores {
    fmt.Printf("%s의 점수: %d\n", name, score)
}

똑같은 코드를 실행하더라도 매번 출력되는 순서가 달라질 수 있어요. 이는 Go 설계자들이 맵의 순회 순서에 의존하는 코드를 짜지 못하도록 의도적으로 설계한 결과예요. 만약 맵을 순서대로 출력하고 싶다면, 먼저 키들을 슬라이스에 담아 정렬한 뒤 그 슬라이스를 다시 `range`로 돌리는 과정을 거쳐야 해요.

STEP 5. 복잡한 제어: break와 continue

루프의 흐름을 중간에 끊거나 건너뛰어야 할 때가 있죠. 이때 사용하는 것이 breakcontinue예요. break는 루프 전체를 즉시 종료하고 탈출하며, continue는 현재 회차의 남은 코드를 무시하고 다음 회차로 바로 넘어갑니다.

// 실전 시나리오: 특정 조건에서 건너뛰기 및 중단
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

for _, n := range numbers {
    if n%2 == 0 {
        continue // 짝수는 건너뜁니다
    }
    if n > 7 {
        break // 7보다 큰 홀수가 나오면 종료합니다
    }
    fmt.Println("홀수 출력:", n)
}
💡 실전 팁: 중첩 루프 탈출하기
중첩된 루프(루프 안에 루프가 있는 경우)에서 안쪽 루프를 탈출할 때 break를 쓰면 안쪽 루프만 빠져나가요. 바깥쪽 루프까지 한꺼번에 탈출하고 싶다면 Label을 사용해야 해요. OuterLoop: for ... { for ... { break OuterLoop } } 형식을 활용해 보세요.

자주 하는 실수와 해결법

개발 과정에서 반복문을 사용할 때 마주치는 대표적인 실수들을 정리했어요. 이 패턴들만 피해도 디버깅 시간이 절반으로 줄어들 거예요.

  • 인덱스 범위 초과(Index out of range)
    왜 발생하는가: 슬라이스의 길이를 계산할 때 < 대신 <=를 사용하거나, 인덱스 계산 로직이 잘못되었을 때 발생해요.
    ✅ 해결법: 항상 len(slice)를 기준으로 조건을 설정하고, 인덱스가 음수가 되거나 길이를 넘지 않는지 확인하세요.
  • 무한 루프 발생
    왜 발생하는가: for 문 내에서 조건을 변화시키는 증감식(예: `i++`)을 누락했거나, 탈출 조건에 도달할 수 없는 논리 오류가 있을 때 발생해요.
    ✅ 해결법: 루프가 종료되는 명확한 종료 조건을 항상 먼저 설계하고, 조건이 변하는 로직이 포함되었는지 검토하세요.
  • range 변수의 포인터 문제
    왜 발생하는가: `for i, v := range slice`에서 `v`는 슬라이스 요소의 복사본이에요. `v`의 값을 변경해도 원본 슬라이스는 변하지 않아요.
    ✅ 해결법: 원본을 수정하려면 `slice[i] = newValue`와 같이 인덱스를 직접 사용하세요.
  • 사용하지 않는 변수 에러
    왜 발생하는가: `range`가 인덱스와 값을 모두 반환하는데, 인덱스만 쓰고 값은 선언만 한 뒤 사용하지 않으면 컴파일 에러가 나요.
    ✅ 해결법: 값이 필요 없다면 `for _, v := range`처럼 언더스코어를 사용하세요.
  • 맵 순회 순서에 의존하는 로직
    왜 발생하는가: 맵은 순서가 없는데, 특정 키가 항상 먼저 나올 것이라고 가정하고 코드를 짜면 실행 환경에 따라 결과가 달라져요.
    ✅ 해결법: 순서가 중요하다면 키를 슬라이스에 담아 정렬한 뒤 순회하세요.

자주 묻는 질문

Q. Go에서 while 문은 정말 아예 없나요?
네, 맞아요. 하지만 걱정하실 필요 없어요. for 조건식 { ... } 형태를 사용하면 우리가 아는 모든 while 문 기능을 완벽하게 대체할 수 있답니다.

Q. range를 쓸 때 인덱스를 생략하고 값만 가져오고 싶어요.
그럴 때는 for _, value := range collection 처럼 첫 번째 반환값 자리에 언더스코어(`_`)를 넣어주면 돼요. Go에서는 선언 후 사용하지 않는 변수를 허용하지 않기 때문에 이 규칙을 꼭 지켜야 해요.

Q. 중첩된 for 문에서 한 번에 모두 빠져나가려면 어떻게 하나요?
앞서 언급했듯이 '라벨(Label)' 기능을 사용하면 돼요. 루프 시작 전에 `LoopName:` 처럼 이름을 붙이고, 안쪽에서 `break LoopName`이라고 명령하면 모든 루프가 종료돼요.

Q. 슬라이스를 순회하는 동안 요소를 삭제해도 안전한가요?
순회 중에 슬라이스의 길이를 변경하는 것은 매우 위험해요. 인덱스가 꼬여서 예상치 못한 요소를 건너뛰거나 에러가 날 수 있거든요. 요소를 삭제해야 한다면, 뒤에서부터 앞으로(역순으로) 순회하는 방식을 추천해요.

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

오늘 배운 Go 반복문의 핵심 패턴들을 머릿속에 잘 담아두셨나요? 복잡한 로직도 결국 기본 문법의 조합일 뿐이에요. 마지막으로 실전에서 코드를 작성하기 직전, 아래 체크리스트를 통해 스스로 점검해 보세요.

✅ 핵심 요약

  • 정해진 횟수는 C-스타일 for 문을 사용하세요.
  • 슬라이스/맵 순회는 range가 가장 깔끔하고 안전해요.
  • 값이 필요 없는 인덱스는 반드시 _로 처리하세요.
  • 맵 순회 시 결과 순서가 매번 달라질 수 있음을 명심하세요.
  • 원본 데이터를 수정할 때는 인덱스를 통해 직접 접근하세요.
  • 무한 루프를 방지하기 위해 탈출 조건을 항상 검토하세요.

이제 여러분은 Go의 유일한 반복문인 for를 자유롭게 다룰 준비가 되었어요. 이론을 읽는 것보다 직접 타이핑하며 에러를 마주해 보는 것이 가장 빠른 학습법이에요.

오늘 바로 해볼 일: 1부터 100 사이의 숫자 중 3의 배수만 출력하는 코드를 직접 작성해 보세요.
이번 주 목표: 슬라이스에 담긴 구조체(Struct) 데이터를 range로 순회하며 특정 조건의 데이터만 필터링하는 연습을 해보세요.

혹시 코드를 짜다가 막히거나, 이해가 가지 않는 부분이 있다면 언제든 댓글로 질문을 남겨 주세요. 여러분의 성장을 진심으로 응원하며, 제가 아는 선에서 최대한 친절하게 답변해 드릴게요!

함께 읽으면 좋은 글: Go 반복문 완벽 가이드 - 기초부터 심화까지

댓글 남기기