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

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

왜 Go에서는 반복문이 단 하나뿐일까요?

터미널에 숫자가 끝없이 출력되는 것을 보고 당황한 적이 있나요? 혹은 파이썬의 for나 자바의 while을 기대하며 코드를 작성하다가 Go의 단순한 구조에 멈칫했을지도 몰라요. Go 언어는 다른 언어와 달리 반복문을 위한 키워드가 오직 for 하나뿐이에요.

단순해 보이지만, 이 하나의 키워드가 모든 상황을 해결해야 한다는 뜻이에요. 조건문만 쓰는 방식, 숫자를 세는 방식, 리스트를 순회하는 방식이 모두 하나의 문법 안에서 이루어져요. 처음 접하면 이 유연함이 오히려 혼란을 줄 수 있지만, 원리만 제대로 파악하면 코드가 훨씬 간결해지는 경험을 하게 될 거예요.

이 글은 Go를 처음 배우는 분들이 반복문 때문에 겪는 시행착오를 줄이기 위해 준비했어요. 복잡한 이론보다는 실제 현업에서 바로 써먹을 수 있는 패턴 위주로 구성했으니, 이 치트시트를 옆에 띄워두고 코딩해 보세요.

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

  • 기본적인 C-style 반복문 작성법
  • while문을 대체하는 조건부 반복문
  • 슬라이스와 맵을 위한 range 활용법
  • 실전에서 자주 발생하는 실수와 해결책

반복문은 프로그램의 심장과 같아요. 효율적인 반복문을 작성하는 법을 배우면, 데이터가 수만 개로 늘어나도 당황하지 않고 안정적인 코드를 짤 수 있어요. 이제 본격적으로 Go의 반복문 세계로 들어가 볼게요.

Go 반복문을 시작하기 전 꼭 알아야 할 기본 개념

Go 언어의 설계 철학은 단순함(Simplicity)이에요. 반복문 역시 이 철학을 그대로 따르고 있어요. 다른 언어처럼 while이나 do-while 같은 별도의 키워드를 두지 않아요. 대신 for 키워드 하나에 모든 기능을 담았어요.

이 방식이 왜 효율적인지 이해하려면, 우선 우리가 구현하려는 반복의 형태를 먼저 분류할 줄 알아야 해요. 어떤 상황에서 어떤 문법 형식을 선택해야 할지 기준을 세우는 것이 첫걸음이에요.

반복문 형태별 선택 기준

상황에 따라 가장 적합한 문법이 달라져요. 아래 표를 통해 어떤 경우에 어떤 방식을 사용하는지 확인해 보세요.

반복 형태 Go 문법 형태 주요 사용 사례
횟수 지정형 for [초기값]; [조건]; [증감] 정해진 횟수만큼 반복할 때
조건 중심형 for [조건] 특정 조건이 만족될 때까지 (while 대체)
무한 루프형 for 종료 조건을 내부에서 직접 관리할 때
컬렉션 순회형 for [변수] := range [컬렉션] 슬라이스, 맵, 문자열 탐색 시

이 표를 눈에 익혀두면 코드를 설계할 때 고민하는 시간이 훨씬 줄어들 거예요. 예를 들어,

Go 반복문 실전 활용 가이드: 단계별 문법과 패턴

이제 실전이에요. 이론으로 배운 내용을 실제 코드로 구현해 보면서 Go의 반복문이 얼마나 강력한지 느껴보세요. 각 단계별로 가장 자주 쓰이는 핵심 패턴들만 모았어요.

STEP 1. 전통적인 횟수 제어형 반복문

C언어나 Java를 써본 적이 있다면 가장 익숙할 형태예요. 초기화, 조건식, 증감식을 한 줄에 작성하여 루프의 흐름을 명확하게 보여줘요.

예를 들어, 1부터 5까지 출력하는 코드는 다음과 같아요. for i := 1; i <= 5; i++ { fmt.Println(i) } 이 구조에서 i := 1은 시작점, i <= 5는 멈출 기준, i++는 다음 단계로 넘어가는 규칙을 의미해요. 이 세 가지 요소가 모두 조화롭게 맞아야 무한 루프에 빠지지 않아요.

STEP 2. 조건만 사용하는 while 스타일 반복문

Go에는 while 키워드가 없어요. 대신 for 뒤에 조건식만 남겨두면 똑같은 역할을 수행해요. 어떤 상태가 바뀔 때까지 계속 실행해야 하는 작업에 아주 유용해요.

예를 들어, 사용자로부터 특정 값을 입력받을 때까지 반복하거나, 큐(Queue)에 데이터가 남아 있는 동안 계속 처리하는 로직을 짤 때 사용해요. for count < 10 { count++ } 처럼 작성하면, count가 10이 되는 순간 루프가 자연스럽게 종료돼요. 조건을 관리하는 변수가 루프 외부에서 정의되어야 한다는 점을 꼭 기억하세요.

STEP 3. 컬렉션 정복을 위한 range 활용법

Go 프로그래밍에서 가장 많이 쓰이는 패턴이에요. 슬라이스(Slice), 맵(Map), 문자열(String)을 순회할 때 range를 사용하면 인덱스와 값을 매우 편하게 가져올 수 있어요.

1) 슬라이스 순회: 슬라이스를 돌 때는 인덱스와 값을 모두 받을 수 있고, 인덱스만 필요하다면 값 부분은 생략할 수 있어요. for i, v := range mySlice { ... }

2) 맵 순회: 맵에서는 인덱스 대신 '키(Key)'를 가져와요. for key, value := range myMap { ... } 이 방식은 데이터 셋을 전체적으로 훑으며 값을 수정하거나 검색할 때 최적이에요. 단, 맵의 순회 순서는 매번 달라질 수 있다는 점을 주의해야 해요.

3) 문자열 순회: 문자열을 range로 돌리면 바이트(byte) 단위가 아니라 룬(rune, 유니코드 코드포인트) 단위로 처리해요. 한글처럼 한 글자가 여러 바이트를 차지하는 경우에도 깨지지 않고 정확하게 한 글자씩 읽어올 수 있는 아주 중요한 특징이에요.

STEP 4. 흐름 제어: break와 continue

반복문을 실행하다가 중간에 멈추거나, 특정 조건에서만 건너뛰고 싶을 때가 있죠? 이때 사용하는 것이 breakcontinue예요.

break는 루프를 즉시 완전히 빠져나가는 명령이에요. 예를 들어, 수만 개의 데이터 중 내가 찾는 것을 발견했다면 더 이상 돌 필요가 없으니 break를 써서 종료하면 효율적이에요. 반면, continue는 이번 차례만 건너뛰고 다음 반복으로 넘어가는 명령이에요. 짝수만 출력하고 싶을 때 홀수 번호에서 continue를 사용하면 코드가 훨씬 깔끔해져요.

STEP 5. 실전 응용: 중첩 루프와 복잡한 패턴

2차원 배열을 다루거나 복잡한 로직을 짤 때는 반복문 안에 반복문을 넣는 중첩 루프를 사용해요. 이때는 break가 가장 가까운 루프 하나만 탈출한다는 점을 조심해야 해요. 만약 바깥쪽 루프까지 한꺼번에 탈출하고 싶다면 라벨(Label)을 활용하는 고급 기술이 필요해요.

💡 알아두기
실무에서는 단순한 반복보다 for-range를 통해 데이터의 의도를 명확히 드러내는 코드를 더 선호해요. 코드가 읽기 쉬워야 유지보수가 편하기 때문이에요.

실제 업무에서 흔히 볼 수 있는 시나리오를 하나 만들어 볼게요. 사용자 목록(슬라이스)에서 특정 권한을 가진 사용자만 골라내는 로직이에요. for _, user := range users { if user.Role == "admin" { admins = append(admins, user) } } 이처럼 rangeif를 조합하는 방식이 Go의 가장 기본적인 프로그래밍 스타일이에요.

자주 하는 실수와 해결법 및 궁금한 점 정리

반복문을 작성하다 보면 누구나 한 번쯤은 꼬이기 마련이에요. 특히 Go에서는 초보자가 자주 빠지는 함정들이 몇 가지 있어요. 이를 미리 알고 있으면 디버깅 시간을 획기적으로 줄일 수 있어요.

자주 하는 실수와 해결법

실수: 반복문 변수를 고루틴(Goroutine) 내부에서 직접 사용하기
왜 발생하는가: Go의 반복문 변수는 매 반복마다 값이 바뀌는 게 아니라, 루프가 도는 동안 메모리 주소가 유지되는 경우가 많아요. 그래서 고루틴이 실행될 시점에는 이미 변수 값이 마지막 값으로 바뀌어 있을 수 있어요.
✅ 해결법: 고루틴을 호출할 때 함수 인자로 현재의 값을 전달하거나, 루프 안에서 변수를 새로 선언해서 값을 복사해 사용하세요.

실수: 맵(Map)을 순회하는 동안 맵의 요소를 삭제하거나 추가하기
왜 발생하는가: 맵의 구조가 변경되면 반복자(Iterator)의 상태가 불안정해져서 예상치 못한 동작을 유발할 수 있어요.
✅ 해결법: 삭제할 키들을 별도의 슬라이스에 먼저 모아둔 다음, 그 슬라이스를 순회하면서 맵에서 삭제하는 방식을 사용하세요.

실수: 슬라이스를 순회하면서 요소를 삭제할 때 인덱스 오류 발생
왜 발생하는가: 요소를 삭제하면 슬라이스의 길이가 줄어드는데, 인덱스는 그대로 증가하기 때문에 다음 요소를 건너뛰거나 범위를 벗어나게 돼요.
✅ 해결법: 슬라이스를 뒤에서부터 거꾸로 순회(for i := len(s) - 1; i >= 0; i--)하면 삭제해도 앞쪽 인덱스에 영향을 주지 않아요.

실수: 무한 루프 조건 설정 오류
왜 발생하는가: 조건식을 잘못 설정하거나 루프 내부에서 조건을 변화시키는 코드를 빼먹었을 때 발생해요.
✅ 해결법: 루프를 설계할 때 break 조건을 명확히 작성하고, 디버깅 시 출력 로그를 통해 조건 변수가 어떻게 변하는지 반드시 확인하세요.

실수: 문자열을 바이트 단위로만 처리하기
왜 발생하는가: 한글 같은 멀티바이트 문자를 단순히 string[i]로 접근하면 글자가 깨져 보여요.
✅ 해결법: 반드시 for range를 사용하여 룬(rune) 단위로 안전하게 순회하세요.

자주 묻는 질문

Q. for와 range 중 언제 무엇을 써야 하나요?

단순히 숫자를 세거나 복잡한 조건이 필요하면 for를 쓰고, 슬라이스나 맵의 모든 요소를 순서대로 훑어야 한다면 range를 쓰는 것이 가장 깔끔하고 안전해요.

Q. 맵(Map)을 순회할 때 순서가 왜 매번 달라지나요?

Go 언어 설계 팀에서 맵의 순회 순서가 일정하면 개발자가 특정 순서에 의존하는 잘못된 코드를 짤 수 있다고 판단하여, 일부러 매번 랜덤하게 순서를 섞도록 설계했어요. 정렬된 순서가 필요하다면 키를 슬라이스에 담아 먼저 정렬한 뒤 순회해야 해요.

Q. 중첩된 반복문에서 한 번에 완전히 탈출하고 싶어요. 어떻게 하나요?

라벨을 사용하면 돼요. 루프 시작 전에 OuterLoop: 라고 이름을 붙인 뒤, 안쪽에서 break OuterLoop라고 쓰면 모든 루프가 종료돼요.

Q. continue를 쓰면 이번 루프만 건너뛰는 게 맞나요?

네, 맞아요. continue를 만나면 현재 진행 중인 코드 블록 아래쪽은 무시하고, 즉시 다음 반복 단계로 넘어가게 돼요.

Q. 슬라이스의 인덱스만 필요할 때는 어떻게 하나요?

for i := range mySlice { ... } 처럼 작성하면 값은 생략하고 인덱스만 깔끔하게 받아올 수 있어요.

성공적인 Go 코딩을 위한 마지막 체크리스트

Go의 반복문은 단순하지만 강력해요. 오늘 배운 내용을 잊지 않도록 핵심만 다시 한번 짚어볼게요. 코드를 작성한 뒤 스스로에게 이 질문들을 던져보세요.

✅ 핵심 요약

  • 모든 반복은 for 키워드 하나로 해결한다.
  • 컬렉션(슬라이스, 맵) 순회 시에는 range를 우선적으로 고려한다.
  • 문자열 처리는 반드시 룬(rune) 단위로 안전하게 한다.
  • 맵 순회는 순서가 보장되지 않음을 인지한다.
  • 고루틴 내에서 루프 변수를 쓸 때는 값을 복사해서 전달한다.
  • 슬라이스 요소를 삭제할 때는 역순으로 순회한다.

이제 이론은 충분해요. 직접 코드를 쳐보는 것만큼 확실한 공부는 없어요. 지금 바로 IDE를 켜고 아래 단계들을 차근차근 실행해 보세요.

다음 단계로 나아가기

  1. 오늘 할 일: 슬라이스에 숫자 10개를 넣고 for range를 사용해 모두 출력해 보세요.
  2. 이번 주 할 일: 맵(Map)을 만들고, 키와 값을 번갈아 출력하는 코드를 짜보세요. 이때 순서가 매번 바뀌는지 직접 확인해 보세요.
  3. 실행 직전 할 일: Go의 breakcontinue를 사용해 특정 조건에서 루프를 제어하는 작은 프로그램을 완성해 보세요.

Go 반복문 사용법을 익히는 과정에서 막히는 부분이 있다면 언제든 댓글로 질문을 남겨 주세요. 여러분의 고민에 함께 답해 드릴게요. 함께 성장하는 즐거움을 느껴보시길 바라요!

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

댓글 남기기