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

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

반복문 제어 실패로 멈춰버린 코드, 해결할 수 있어요

새벽 두 시, 코드를 실행했는데 터미널에 아무것도 찍히지 않고 CPU 점유율만 치솟는 경험을 해보셨나요? 분명히 조건문을 잘 썼다고 생각했는데, 프로그램은 무한 루프의 늪에 빠져 한 발짝도 나아가지 못해요. 이런 문제는 대부분 반복문의 종료 조건을 잘못 설정했거나, 반복 내부의 변수 변화를 놓쳤을 때 발생해요.

Go 언어는 다른 언어와 달리 for 하나로 모든 반복 구조를 처리하는 독특한 철학을 가지고 있어요. while 문이나 do-while 문이 따로 없기 때문에, 처음 접하는 입문자에게는 이 단순함이 오히려 혼란으로 다가올 수 있어요. 하지만 이 규칙을 정확히 이해하면 코드는 훨씬 간결하고 강력해져요.

오늘 이 글에서는 Go 반복문 치트시트를 통해 여러분이 더 이상 무한 루프에 빠지지 않도록 도와드릴게요. 복잡한 이론보다는 실제 현업에서 바로 쓸 수 있는 코드 패턴 위주로 준비했어요.

이 가이드를 다 읽고 나면 다음과 같은 능력을 갖추게 돼요.

  • 기본 for 문법부터 range를 활용한 고급 패턴까지 완벽히 이해해요.
  • 상황에 맞는 최적의 반복문 형태를 즉시 선택할 수 있어요.
  • 초보자가 흔히 저지르는 논리 오류를 사전에 방지해요.
  • 실전 프로젝트에서 바로 복사해서 쓸 수 있는 코드 스니펫을 확보해요.

효율적인 루프 작성을 위한 사전 준비

반복문을 무작정 작성하기 전에, 우리가 어떤 도구를 사용할 수 있는지 명확히 구분해야 해요. Go의 반복문은 구조가 매우 단순하지만, 그 단순함 속에 담긴 의도를 파악하는 것이 중요해요. 무턱대고 모든 곳에 for range를 쓰거나, 모든 곳에 기본 for 문을 쓰면 코드의 가독성이 떨어지고 성능 손실이 발생할 수 있어요.

반복문 선택을 위한 판단 기준

어떤 상황에서 어떤 형태의 반복문을 써야 할지 고민될 때, 아래 표를 기준으로 판단해 보세요. 상황에 맞는 도구를 고르는 것만으로도 코드 리뷰에서 좋은 점수를 받을 수 있어요.

반복문 유형 주요 특징 추천 사용 상황
기본 for 문 초기값, 조건, 증감식 제어 인덱스 계산이 복잡할 때
조건식 for 문 특정 조건이 참인 동안 실행 while 문이 필요할 때
for range 문 요소와 인덱스를 자동으로 추출 슬라이스, 맵 순회 시
무한 루프 조건 없이 계속 실행 서버 대기, 이벤트 루프
💡 알아두기
Go에는 별도의 while 문이 없다는 사실을 기억하세요. 모든 조건부 반복은 for 키워드로 통합되어 처리됩니다. 이는 언어의 문법을 단순하게 유지하려는 Go의 설계 철학이에요.

반복문 작성 전 체크리스트

코드를 작성하기 전, 다음 세 가지 질문을 스스로에게 던져보세요. 이 질문들에 답할 수 있다면 실수할 확률이 급격히 줄어들어요.

  1. 종료 조건이 명확한가?: 루프가 반드시 멈추는 지점이 계산되어 있어야 해요.
  2. 반복 변수가 매 단계 변화하는가?: 인덱스나 조건 변수가 업데이트되지 않으면 무한 루프에 빠져요.
  3. 데이터 구조에 최적인가?: 슬라이스를 하나씩 꺼내야 한다면 range가 훨씬 안전하고 편해요.

Go 반복문의 모든 패턴: 기초부터 실전 스니펫까지

이제 본격적으로 Golang의 반복문 문법을 단계별로 파헤쳐 볼게요. 각 패턴은 저마다의 강력한 무기가 있으니, 상황에 맞춰 적절히 꺼내 쓰는 연습이 필요해요.

STEP 1. 가장 기본이 되는 C-스타일 for 문

가장 전통적인 방식이에요. 초기화, 조건식, 증감식을 한 줄에 적어 제어할 수 있어요. 인덱스를 세밀하게 조정해야 할 때 유용해요.

💡 알아두기
for i := 0; i < 10; i++ 형태에서 세 요소 중 하나라도 생략할 수 있어요. 생략된 부분은 기본적으로 빈 상태로 간주됩니다.

예를 들어, 1부터 10까지 합계를 구하는 코드는 다음과 같아요.

for i := 1; i <= 10; i++ {
  sum += i
}

여기서 주의할 점은 조건식의 경계값이에요. 10까지 포함하고 싶다면 i <= 10을 써야 하고, 10 미만까지라면 i < 10을 써야 해요. 이 작은 차이가 로직의 성패를 결정해요.

STEP 2. while 문을 대체하는 조건식 루프

Go에는 while 키워드가 없어요. 대신 for 뒤에 조건식만 적으면 우리가 아는 while 문과 똑같이 동작해요. 조건이 참(true)인 동안 계속해서 블록 내부를 실행하죠.

for n < 100 {
  n *= 2
}

이 방식은 인덱스보다는 특정 상태나 변수의 값이 목표치에 도달할 때까지 반복해야 하는 상황에 아주 적합해요. 데이터 스트림을 처리하거나, 특정 버퍼가 가득 찰 때까지 데이터를 넣는 시나리오에서 자주 사용돼요.

STEP 3. 강력한 for range: 슬라이스와 맵 순회

실무에서 가장 많이 쓰게 될 패턴이에요. for range를 사용하면 데이터 구조의 인덱스와 값을 아주 쉽게 가져올 수 있어요. 슬라이스, 배열, 맵, 문자열, 채널 등 거의 모든 데이터 타입에 적용 가능해요.

슬라이스(Slice) 순회하기

슬라이스의 요소를 하나씩 꺼낼 때 사용해요. 인덱스가 필요 없다면 언더바(_)를 사용하여 무시할 수 있어요.

numbers := []int{10, 20, 30}
for index, value := range numbers {
  fmt.Printf("%d번째 값은 %d예요\n", index, value)
}

맵(Map) 순회하기

맵은 순서가 없다는 점이 중요해요. range를 사용해 맵을 돌 때마다 결과의 순서가 달라질 수 있으니, 순서가 중요한 로직에는 주의가 필요해요.

userAges := map[string]int{"Alice": 25, "Bob": 30}
for name, age := range userAges {
  fmt.Printf("%s의 나이는 %d살이에요\n", name, age)
}

STEP 4. 흐름을 제어하는 break와 continue

반복문 도중에 특정 상황에서 빠져나가거나, 다음 차례로 건너뛰어야 할 때가 있죠. 이때 사용하는 것이 breakcontinue예요.

  • break: 루프를 즉시 종료하고 반복문 밖으로 탈출해요.
  • continue: 현재 단계의 남은 코드를 건너뛰고 다음 반복으로 바로 넘어가요.

예를 들어, 리스트에서 특정 숫자를 찾으면 즉시 멈추고 싶을 때는 break를, 홀수만 처리하고 싶을 때는 continue를 사용하면 돼요.

STEP 5. 실전 시나리오: 데이터 필터링 패턴

실제로 프로젝트를 진행할 때 자주 마주하는 시나리오를 하나 만들어 볼게요. 사용자 목록 중에서 특정 조건(예: 성인)을 만족하는 사람만 골라내는 로직이에요.

type User struct {
  Name string
  Age int  var adults []string
  for _, user := range users {
    if user.Age >= 19 {
      adults = append(adults, user.Name)
    }
  }
  return adults

이 코드는 for rangeif 문을 결합한 전형적인 필터링 패턴이에요. 가독성이 높고, 인덱스 실수로 인한 에러를 원천 봉쇄할 수 있는 아주 안전한 방식이죠.

⚠️ 주의
range 문에서 값을 복사해서 사용할 때, 값이 매우 큰 구조체라면 성능 저하가 발생할 수 있어요. 그럴 때는 인덱스를 이용해 포인터로 접근하는 방식을 고려해 보세요.

자주 하는 실수와 해결법

Go 프로그래밍을 하다 보면 누구나 한 번쯤은 겪게 되는 실수들이 있어요. 미리 알고 있다면 당황하지 않고 대처할 수 있겠죠?

  • 인덱스 범위를 벗어나는 에러 (Out of Bounds)
    왜 발생하는가: i <= len(slice) 처럼 조건식에 등호를 잘못 포함했을 때 발생해요.
    ✅ 해결법: 슬라이스의 마지막 인덱스는 항상 len(slice) - 1임을 명심하고, i < len(slice)를 사용하세요.
  • 무한 루프의 늪
    왜 발생하는가: for n < 10이라고 썼는데, 루프 안에서 n의 값을 변화시키지 않았을 때 발생해요.
    ✅ 해결법: 반복문 내부에서 탈출 조건에 영향을 주는 변수가 반드시 업데이트되는지 확인하세요.
  • for range 변수 재사용 문제 (Go 1.22 이전 버전)
    왜 발생하는가: 루프 안에서 생성된 인덱스나 값 변수의 메모리 주소가 공유되어, 고루틴(Goroutine) 실행 시 예상치 못한 값을 참조할 수 있어요.
    ✅ 해결법: Go 1.22 이상을 사용하거나, 루프 내부에서 변수를 새로 선언하여 스코프를 분리하세요.
  • 맵(Map) 순회 순서 의존
    왜 발생하는가: 맵은 저장 순서를 보장하지 않는데, 순서가 중요하다고 가정하고 코드를 짰을 때 로직이 깨져요.
    ✅ 해결법: 순서가 필요하다면 키들을 별도의 슬라이스에 담아 정렬한 뒤, 그 슬라이스로 맵을 순회하세요.
  • 빈 슬라이스에 대한 range 사용
    왜 발생하는가: 에러는 나지 않지만, 로직상 데이터가 반드시 있어야 한다고 가정하면 문제가 생겨요.
    ✅ 해결법: 루프를 돌기 전 len(slice) == 0인 경우를 먼저 체크하여 예외 처리를 해주세요.

자주 묻는 질문

Q. Go에서 while 문을 쓰고 싶은데 어떻게 하나요?

Go에는 별도의 while 문이 없어요. 대신 for condition { ... } 형식을 사용하면 완벽하게 같은 동작을 수행할 수 있어요.

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

언더바(_)를 사용하여 인덱스 자리를 비워두면 돼요. 예를 들어 for _, value := range slice라고 쓰면 값만 깔끔하게 가져올 수 있어요.

Q. 무한 루프를 안전하게 멈추는 방법이 있나요?

가장 일반적인 방법은 break 키워드를 사용하는 것이에요. 혹은 특정 조건이 만족되었을 때 함수 자체를 종료시키는 return을 사용할 수도 있어요.

Q. 슬라이스를 반복문 안에서 삭제해도 안전한가요?

반복문 도중에 슬라이스 요소를 삭제하면 인덱스가 밀려서 다음 요소를 건너뛰게 될 수 있어요. 이런 경우에는 역순(뒤에서부터 앞으로)으로 반복문을 돌리는 것이 가장 안전한 방법이에요.

Q. 성능 면에서 for 문과 for range 중 어떤 것이 더 빠른가요?
대부분의 경우 차이는 미미해요. 하지만 슬라이스의 인덱스만 필요하다면 기본 for 문이 아주 약간 더 빠를 수 있고, 전체 요소의 값이 필요하다면 range가 훨씬 직관적이고 안전해요.

반복문 마스터를 위한 마지막 정리

오늘 배운 내용들을 잊지 않도록 핵심만 콕 집어 정리해 드릴게요. 이 체크리스트만 기억해도 여러분의 Go 코드는 훨씬 견고해질 거예요.

✅ 핵심 요약

  • 모든 반복은 for 키워드로 통일해서 사용해요.
  • 인덱스 조절이 필요할 땐 기본 for 문을, 데이터 순회는 for range를 활용해요.
  • 종료 조건과 변수 업데이트 여부를 반드시 확인하여 무한 루프를 방지해요.
  • 맵(Map)을 순회할 때는 데이터 순서가 매번 달라질 수 있음을 인지하세요.
  • 중간 탈출은 break, 다음 차례는 continue를 사용해요.
  • 대량의 데이터를 다룰 땐 값의 복사 비용을 고려해 포인터 접근을 검토하세요.

자, 이제 이론은 충분해요. 이제 직접 키보드를 잡고 코드를 짜볼 시간이에요!

오늘 바로 실천할 일

  • 자신이 작성 중인 코드에서 for 문이 종료 조건을 명확히 가지고 있는지 검토해 보세요.
  • 기존에 인덱스로 복잡하게 짰던 루프를 for range로 바꿔서 더 간결하게 만들어 보세요.

Go 프로그래밍의 세계는 무궁무진해요. 반복문을 정복했다면 이제는 구조체와 인터페이스로 나아갈 준비가 된 거예요. 공부하시다가 막히는 부분이 생기면 언제든 댓글로 질문 남겨 주세요. 함께 고민하고 해결해 드릴게요!

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

댓글 남기기