[IT-정보] Go 반복문 치트시트: 핵심 문법 5가지 – 초보 개발자를 위한 실전 예제 모음

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

반복문 for, 왜 제대로 알아야 할까요?

다른 프로그래밍 언어를 공부하다가 Golang(Go)의 세계로 넘어오면 가장 먼저 당황하는 순간이 있어요. 바로 반복문을 돌리려고 할 때 while 키워드가 보이지 않는다는 사실이에요. 파이썬이나 자바, C언어에서는 조건식만 넣어서 돌리는 while 문이 아주 익숙하잖아요? 하지만 Go는 오직 for 하나로 모든 반복 상황을 해결해요.

처음에는 이게 왜 불편할까 생각할 수도 있지만, 사실 이건 Go가 추구하는 단순함과 명확함을 보여주는 아주 멋진 설계예요. 문법이 하나로 통일되어 있으니 코드가 훨씬 깔끔해지고, 개발자가 어떤 상황에서 어떤 루프를 쓸지 고민하는 시간을 줄여주거든요. 하지만 이 단순함 뒤에는 꼭 익혀두어야 할 몇 가지 핵심 패턴이 숨어 있어요. 이걸 제대로 모르면 무한 루프에 빠져 프로그램이 멈추거나, 슬라이스의 인덱스를 잘못 건드려 에러를 뿜어내는 상황을 마주하게 돼요.

지금 이 글을 읽고 있는 여러분도 아마 비슷한 고민을 하고 있을 거예요. “Go에서는 while을 어떻게 흉내 내지?”, “배열을 돌릴 때 인덱스와 값을 동시에 가져오려면 어떻게 해야 하지?” 같은 질문들이 머릿속을 스쳐 지나가고 있을 거예요. 걱정하지 마세요. 이 글 하나만 완벽히 이해하면 여러분은 더 이상 Go의 반복문 앞에서 헤매지 않게 될 거예요.

이 가이드를 통해 우리는 다음 내용들을 완벽하게 내 것으로 만들 거예요.

  • Go의 유일한 반복문, for의 기본 구조와 작동 원리
  • while 문을 대체하는 Go만의 독특한 활용법
  • 슬라이스와 맵을 다룰 때 필수적인 range 문법
  • 실전에서 바로 써먹는 break와 continue 제어 기술
  • 초보자가 가장 많이 하는 실수와 이를 피하는 방법

Go 반복문 시작 전 반드시 확인해야 할 개념

본격적으로 코드를 작성하기 전에, Go의 반복문이 가진 철학을 먼저 이해하는 것이 중요해요. Go는 불필요한 키워드를 줄이는 데 진심인 언어예요. 그래서 우리는 for라는 키워드 하나만 가지고 세 가지 서로 다른 스타일의 반복을 구현해야 해요. 준비물은 따로 필요 없지만, 조건식(condition)증감식(post statement)의 개념을 머릿속에 다시 한번 그려보는 것이 큰 도움이 돼요.

💡 알아두기
Go의 for 문은 괄호()를 사용하지 않아요. C 계열 언어에 익숙하다면 `for (i=0; i<10; i++)` 처럼 쓰고 싶겠지만, Go에서는 `for i := 0; i < 10; i++` 처럼 괄호 없이 작성해야 한다는 점을 꼭 기억하세요!

반복문을 선택할 때는 어떤 상황인지에 따라 기준이 달라져요. 단순히 횟수를 정해놓고 돌리는지, 아니면 어떤 조건이 충족될 때까지 계속 돌릴 것인지, 혹은 데이터 꾸러미(슬라이스나 맵)를 하나씩 꺼내 볼 것인지를 먼저 결정해야 해요. 아래 표를 통해 상황별로 어떤 방식을 선택하면 좋을지 비교해 볼게요.

반복 방식 주요 특징 추천 상황
전통적 for 초기값, 조건, 증감을 한 줄에 작성 정확한 횟수가 정해진 반복 작업
조건식 for while 문처럼 조건만 사용 특정 상태가 될 때까지 반복할 때
range for 인덱스와 값을 자동으로 추출 슬라이스, 배열, 맵 순회 시
무한 루프 조건 없이 계속 실행 서버 리스너나 지속적인 모니터링

이 기준을 잘 세워두지 않으면, 굳이 복잡한 인덱스 계산을 직접 할 필요가 없는 상황에서도 어렵게 코드를 짜는 실수를 범하게 돼요. 예를 들어, 슬라이스의 모든 요소를 출력하고 싶은데 굳이 `i := 0; i < len(slice); i++`를 쓰는 것보다 `range`를 쓰는 것이 훨씬 읽기 쉽고 안전하거든요. 이제 준비가 되었다면, 실제 코드로 어떻게 구현하는지 단계별로 차근차근 살펴볼게요.

실전 Go 반복문 활용 가이드: 단계별 마스터하기

이제 이론을 넘어 실제 코드로 만져볼 시간이에요. Go의 반복문은 생각보다 훨씬 강력하고 유연해요. 각 단계별로 실무에서 가장 많이 쓰이는 패턴들을 하나씩 짚어 드릴게요. 코드를 눈으로만 보지 말고, 직접 타이핑하며 결과가 어떻게 나오는지 확인해 보세요!

STEP 1. 기본 3요소 구조 이해하기

가장 기본이 되는 형태는 초기화, 조건식, 그리고 증감식(후속 작업)을 세미콜론으로 구분하여 한 줄에 적는 방식이에요. 이 방식은 루프의 시작과 끝, 그리고 매 단계에서 일어날 일을 한눈에 보여주기 때문에 매우 명확해요.

// 1부터 5까지 출력하는 가장 기본적인 루프\nfor i := 1; i <= 5; i++ {
    fmt.Printf("현재 숫자는: %d\n", i)
}

여기서 i := 1은 루프가 시작될 때 딱 한 번 실행되는 초기화 단계예요. i <= 5는 매 루프 시작 전마다 검사하는 조건식이죠. 이 조건이 거짓(false)이 되는 순간 루프는 종료돼요. 마지막으로 i++는 한 번의 루프가 끝날 때마다 실행되는 증감식이에요. 이 세 가지 요소가 유기적으로 움직이며 반복의 흐름을 만들어내요.

STEP 2. 조건만 사용하는 While 스타일 활용

Go에는 `while`이라는 단어가 없다고 말씀드렸죠? 하지만 걱정 마세요. `for` 문에서 초기화와 증감식을 생략하면, 우리가 원하던 `while` 문이 완벽하게 구현돼요. 어떤 특정 조건이 만족되는 동안 계속 무언가를 실행해야 할 때 아주 유용해요.

count := 1\n// count가 10보다 작을 때까지 계속 반복 (while 스타일)\nfor count <= 10 {
    fmt.Println("카운트 진행 중:", count)\n    count++ // 반드시 내부에서 조건을 변화시켜줘야 해요!\n}

여기서 주의할 점은 조건을 변화시키는 코드(count++)가 루프 내부에서 반드시 실행되어야 한다는 거예요. 만약 이걸 깜빡하면 프로그램은 영원히 멈추지 않는 무한 루프에 빠지게 되고, 서버라면 CPU 점유율이 100%로 치솟는 대참사가 일어날 수 있어요.

STEP 3. 슬라이스와 맵을 위한 Range 문법

실무에서 가장 많이 쓰는 패턴은 단연 range 키워드를 사용하는 거예요. 슬라이스(Slice)나 맵(Map) 같은 데이터 꾸러미를 다룰 때, 인덱스를 직접 계산하는 것은 매우 번거롭고 실수하기 쉽거든요. `range`는 인덱스와 실제 값을 아주 우아하게 꺼내줍니다.

names := []string{"철수", "영희", "민수"}\n\n// 인덱스와 값을 모두 가져오기\nfor i, name := range names {
    fmt.Printf("%d번째 사람: %s\n", i, name)\n}\n\n// 인덱스는 필요 없고 값만 필요할 때 (Blank Identifier 사용)\nfor _, name := range names {
    fmt.Println("이름:", name)\n}

여기서 중요한 팁! 만약 인덱스는 필요 없고 값만 쓰고 싶다면, 반드시 언더바(_)를 사용해야 해요. Go는 사용하지 않는 변수가 있으면 컴파일 에러를 내뱉는 아주 엄격한 친구거든요. 맵(Map)에서도 똑같이 사용할 수 있는데, 맵의 경우 순서가 매번 랜덤하게 바뀔 수 있다는 점을 꼭 염두에 두어야 해요.

STEP 4. 루프 제어하기: Break와 Continue

반복문을 돌리다 보면 중간에 멈춰야 하거나, 특정 조건일 때 이번 차례만 건너뛰고 싶을 때가 있어요. 이때 사용하는 것이 바로 breakcontinue예요.

  • break: 루프를 즉시 탈출합니다. 원하는 데이터를 찾았을 때 사용하면 효율적이에요.
  • continue: 현재 루프의 남은 코드를 무시하고 바로 다음 반복 단계로 넘어갑니다. 잘못된 데이터를 스킵할 때 유용해요.
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}\n\nfor _, n := range numbers {
    if n%2 == 0 {\n        continue // 짝수는 건너뛰고 홀수만 출력해요\n    }\n    if n > 7 {\n        break // 7보다 큰 숫자가 나오면 루프를 완전히 종료해요\n    }\n    fmt.Println("홀수 발견:", n)\n}

STEP 5. 실전 시나리오: 사용자 데이터 처리하기

이 모든 것을 종합해서, 실제 서비스에서 발생할 법한 시나리오를 구성해 볼게요. 사용자들의 점수 슬라이스를 받아서, 80점 이상의 우수 사용자를 선별하고 그 이름만 출력하는 로직이에요.

type User struct {
    Name  string
    Score int
}\n\nfunc main() {
    users := []User{
        {"김철수", 75},
        {"이영희", 92},
        {"박민수", 88},
        {"최지우", 60},
        {"정다은", 95},
    }\n\n    fmt.Println("--- 우수 사용자 명단 ---")\n    for _, u := range users {
        if u.Score >= 80 {\n            fmt.Printf("축하합니다, %s님!\n", u.Name)\n        }\n    }\n}

이 예제처럼 구조체(Struct)와 슬라이스를 결합하여 사용하는 방식은 Go 프로그래밍의 핵심 중의 핵심이에요. 반복문을 통해 복잡한 데이터 구조를 하나씩 파고드는 감각을 익히는 것이 중요해요.

자주 하는 실수와 해결법

반복문을 완벽하게 이해했다고 생각해도, 막상 코드를 짜다 보면 예상치 못한 에러를 마주하곤 해요. Go 개발자들이 가장 흔히 겪는 실수 5가지를 정리해 드릴게요. 이것만 피해도 여러분의 코드는 훨씬 견고해질 거예요.

  • 인덱스 범위 초과 (Index out of range)
    왜 발생하는가: 슬라이스의 길이를 잘못 계산하거나, 반복문 조건에서 `<=`를 사용하여 마지막 인덱스를 넘어가는 경우예요.
    ✅ 해결법: 항상 len(slice)를 기준으로 조건을 설정하고, 인덱스는 0부터 시작한다는 사실을 명심하세요.
  • 무한 루프 발생
    왜 발생하는가: `while` 스타일의 반복문에서 조건을 거짓으로 만드는 증감식이나 탈출 조건을 누락했을 때 발생해요.
    ✅ 해결법: 루프 몸체 안에서 조건 변수가 확실히 변하고 있는지, 혹은 break가 도달할 수 있는 경로에 있는지 검토하세요.
  • 사용하지 않는 변수 에러
    왜 발생하는가: `for i, v := range`를 썼는데 정작 `i`를 코드에서 사용하지 않을 때 Go 컴파일러가 에러를 냅니다.
    ✅ 해결법: 사용하지 않는 변수는 반드시 _ (Blank Identifier)로 처리해 주세요.
  • 루프 변수의 포인터 문제 (Go 1.22 미만 버전)
    왜 발생하는가: `range`를 통해 가져온 변수의 주소값을 슬라이스에 담을 때, 모든 요소가 마지막 요소의 주소만 가리키는 현상이 생겨요.
    ✅ 해결법: 최신 Go 버전(1.22 이상)을 사용하거나, 루프 내부에서 변수를 복사해서 사용하세요.
  • 반복 중 슬라이스 수정
    왜 발생하는가: 슬라이스를 순회하는 도중에 해당 슬라이스의 요소를 삭제하거나 추가하면 인덱스가 꼬여버려요.
    ✅ 해결법: 원본을 수정하기보다, 필터링된 결과를 담을 새로운 슬라이스를 만들어 관리하는 것이 훨씬 안전해요.

자주 묻는 질문

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

Go 설계자들은 언어의 복잡성을 낮추기 위해 의도적으로 키워드를 줄였어요. for 하나만으로 모든 반복 상황을 표현할 수 있기 때문에, 굳이 별도의 키워드를 추가해 문법을 무겁게 만들 필요가 없다고 판단한 것이죠.

Q. range 문법을 쓸 때 성능 차이가 큰가요?
성능 차이는 아주 미미해요. 오히려 인덱스를 직접 계산하는 것보다 실수할 확률이 훨씬 낮기 때문에, 특수한 성능 최적화가 필요한 상황이 아니라면 무조건 range를 쓰는 것을 추천해요.

Q. 무한 루프를 안전하게 멈추는 가장 좋은 방법은 무엇인가요?
보통은 특정 조건이 충족되었을 때 break를 사용하는 것이 가장 깔끔해요. 만약 고루틴(Goroutine) 환경이라면 context를 이용해 외부에서 루프를 중단시키는 것이 정석입니다.

Q. 중첩 반복문(Nested Loop)을 써도 괜찮을까요?
가능은 하지만, 중첩이 깊어질수록 코드의 가독성이 떨어지고 시간 복잡도가 급격히 증가해요. 3단계 이상의 중첩은 가급적 피하고, 로직을 함수로 분리하여 단계별로 처리하는 것이 좋아요.

Go 반복문 마스터를 위한 마무리

오늘 우리는 Go의 유일한 반복문인 for를 통해 다양한 실전 패턴을 살펴보았어요. 처음에는 `while`이 없어서 어색했을지 몰라도, 익숙해지면 이 단순함이 얼마나 큰 힘을 발휘하는지 느끼게 될 거예요. 복잡한 문법 대신 명확한 로직에 집중할 수 있게 해주니까요.

✅ 핵심 요약

  • Go의 반복문은 오직 for 키워드 하나로 통일되어 있어요.
  • 전통적인 3요소 방식, While 스타일, Range 방식의 차이를 구분하세요.
  • 슬라이스 순회 시에는 rangeBlank Identifier(_)를 활용하면 안전해요.
  • 루프 제어를 위해 breakcontinue를 적절히 섞어 사용하세요.
  • 사용하지 않는 변수는 반드시 _로 처리해야 컴파일 에러를 피할 수 있어요.

이제 이론 공부는 충분해요. 직접 IDE를 켜고 위에서 배운 예제들을 하나씩 다시 타이핑해 보세요. 손 끝에서 익혀진 감각만이 진짜 여러분의 실력이 됩니다. 오늘 배운 내용을 바탕으로 직접 작은 프로그램을 만들어보는 건 어떨까요?

🚀 오늘 할 일: 위 예제 코드 중 하나를 골라 나만의 데이터로 바꿔서 실행해 보기
📅 이번 주 할 일: 슬라이스와 맵을 조합한 복잡한 구조를 range로 순회해 보기
🛠️ 실행 직전 할 일: Go 환경(Go SDK)이 제대로 설치되어 있는지 확인하기

혹시 코드를 짜다가 막히는 부분이 있거나, 이해가 잘 안 되는 패턴이 있다면 주저 말고 댓글로 남겨 주세요. 제가 확인하는 대로 친절하게 답변해 드릴게요! 함께 성장해 나갔으면 좋겠습니다.

함께 읽으면 도움이 되는 글: Go 반복문 완전 정복 가이드

댓글 남기기