[IT-비교] C# 반복문 방식 비교: 실무에서 바로 쓰는 4가지 패턴 – for, foreach, while, do-while의 성능과 활용법 총정리

반복문 선택 하나로 갈리는 코드의 질

어렵게 로직을 완성해서 코드를 제출했는데, 시니어 개발자에게 “이 부분은 foreach로 바꾸는 게 좋겠는데요?” 혹은 “왜 여기서 while을 썼나요?”라는 피드백을 받고 당황했던 적이 있나요? 기능이 돌아가는 것과 좋은 코드를 짜는 것 사이에는 생각보다 큰 간극이 존재해요.

단순히 데이터를 반복해서 보여주는 작업이라도 어떤 방식을 선택하느냐에 따라 코드의 읽기 쉬운 정도(Readability)가 완전히 달라져요. 심지어 대규모 데이터를 다루는 서비스라면 아주 미세한 성능 차이가 서버 비용이나 사용자 경험에 영향을 미치기도 하죠. 주니어 단계에서는 ‘작동하는 코드’에 집중하지만, 실무에서는 의도가 명확한 코드를 짜는 것이 핵심이에요.

오늘 이 글에서는 단순히 문법을 나열하는 것을 넘어, 실무 상황에서 어떤 반복문을 꺼내 들어야 할지 판단할 수 있는 기준을 세워드릴게요. 상황에 맞는 최적의 선택을 할 수 있다면 코드 리뷰 시간이 훨씬 즐거워질 거예요.

💡 알아두기
C# 반복문 방식 비교를 통해 여러분은 코드의 가독성과 성능이라는 두 마리 토끼를 잡는 법을 배우게 돼요.

이 글을 읽고 나면 다음과 같은 내용을 완벽히 이해하게 돼요.

  • for, foreach, while, do-while의 핵심 동작 원리
  • 각 반복문의 명확한 사용 목적과 적합한 상황
  • 실무에서 자주 발생하는 반복문 관련 실수와 해결법
  • 데이터 규모와 상황에 따른 성능 최적화 전략

반복문 선택을 위한 사전 준비와 기준

반복문을 사용하기 전에 스스로에게 던져야 할 질문이 있어요. 내가 지금 다루려는 데이터의 형태는 무엇인가? 그리고 반복을 제어하는 기준이 인덱스인가, 아니면 특정 조건인가? 이 두 질문에 답할 수 있다면 이미 절반은 성공한 셈이에요.

무작정 코드를 치기 전에, 어떤 상황에서 어떤 도구를 꺼낼지 결정하는 기준표를 먼저 머릿속에 넣어두는 게 좋아요. 모든 반복문은 각자의 ‘전공 분야’가 다르거든요.

선택 기준 for 문 foreach 문 while 문
인덱스 접근 매우 용이함 불가능 (직접 접근 불가) 직접 구현 필요
코드 가독성 보통 (수식이 복잡할 수 있음) 매우 높음 낮음 (조건식 의존)
컬렉션 수정 가능 (인덱스 제어) 불가능 (예외 발생) 조건에 따라 가능
주요 용도 정해진 횟수, 배열 처리 모든 요소 순회 조건 만족 시까지 반복

이 표를 보면 알 수 있듯이, 무조건 빠른 것이 좋은 것이 아니에요. 만약 리스트의 모든 요소를 단순히 읽기만 한다면 foreach가 가장 깔끔하고 안전한 선택이에요. 하지만 리스트의 요소를 건너뛰거나 특정 인덱스의 값을 조작해야 한다면 for를 사용해야 하죠. 이러한 판단 기준을 세우는 것이 C# 프로그래밍 실력을 한 단계 높이는 첫걸음이에요.

⚠️ 주의
반복문 내부에서 순회 중인 컬렉션(List, Dictionary 등)의 크기를 변경(Add, Remove)하는 것은 매우 위험해요. 특히 foreach 문에서는 즉시 예외가 발생하므로 주의해야 해요.

C# 반복문 4가지 패턴의 심층 분석

이제 본격적으로 각 반복문의 특징과 어떤 상황에서 빛을 발하는지 단계별로 살펴볼게요. 단순히 문법을 외우는 게 아니라, 각 문법이 내부적으로 어떻게 돌아가는지 상상하며 읽어보세요.

STEP 1. 인덱스 기반의 정밀 제어, for 문

for 문은 가장 고전적이면서도 강력한 도구예요. 반복 횟수가 명확하게 정해져 있거나, 인덱스 번호를 직접 활용해야 할 때 이보다 좋은 대안은 없어요. 예를 들어, 배열의 홀수 번째 요소만 골라내거나, 특정 간격으로 데이터를 건너뛰어야 할 때 for 문은 최고의 성능과 유연성을 제공해요.

for 문을 사용할 때는 초기화, 조건식, 증감식이라는 세 가지 요소가 유기적으로 맞물려 돌아가요. 이 구조 덕분에 개발자는 반복의 시작과 끝, 그리고 한 단계씩 어떻게 나아갈지를 아주 세밀하게 통제할 수 있어요.

💡 알아두기
배열(Array)처럼 메모리 상에 연속적으로 배치된 데이터를 다룰 때, for 문은 인덱스를 통해 직접 메모리 주소에 접근하는 것과 유사한 효율을 내기 때문에 매우 빨라요.

하지만 주의할 점도 있어요. 인덱스 범위를 잘못 계산해서 IndexOutOfRangeException을 발생시키는 실수는 주니어 개발자들이 가장 자주 하는 실수 중 하나예요. 항상 조건식의 경계값(Boundaries)을 확인하는 습관을 들여야 해요.

STEP 2. 가독성과 안전성의 끝판왕, foreach 문

현대적인 C# 프로그래밍에서 가장 권장되는 방식은 단연 foreach 문이에요. foreach 문은 컬렉션의 내부 구조를 몰라도 모든 요소를 하나씩 순차적으로 꺼내올 수 있게 해줘요. 코드가 매우 직관적이라서, 다른 사람이 내 코드를 읽을 때 “아, 이 컬렉션의 모든 데이터를 순회하고 있구나”라고 즉시 이해할 수 있죠.

foreach 문은 내부적으로 IEnumerator 인터페이스를 사용해요. 즉, 우리가 직접 인덱스를 올리거나 내리지 않아도, C# 엔진이 알아서 다음 요소를 찾아주는 방식이에요. 이 방식의 가장 큰 장점은 안전성이에요. 인덱스를 직접 조작하지 않으니 범위를 벗어날 위험이 아예 없거든요.

하지만 치명적인 제약이 하나 있어요. 순회 중인 컬렉션을 수정할 수 없다는 점이에요. 만약 리스트를 돌면서 특정 조건을 만족하는 아이템을 삭제하려고 시도한다면, 프로그램은 즉시 멈춰버려요. 이때는 리스트를 역순으로 for 문을 돌리거나, 삭제할 아이템을 별도의 리스트에 담아두었다가 나중에 처리하는 전략이 필요해요.

STEP 3. 조건이 충족될 때까지 무한 질주, while 문

while 문은 ‘횟수’보다 ‘상태’가 중요할 때 등장하는 주인공이에요. 반복을 시작하기 전에 특정 조건이 참(true)인지 확인하고, 그 조건이 거짓(false)이 될 때까지 계속해서 코드를 실행하죠. 데이터의 개수를 미리 알 수 없는 상황, 예를 들어 네트워크에서 데이터가 들어올 때까지 기다리거나 사용자의 입력이 특정 값일 때까지 대기해야 하는 상황에서 주로 사용돼요.

while 문을 사용할 때 가장 경계해야 할 것은 바로 무한 루프(Infinite Loop)예요. 조건식이 절대로 거짓이 되지 않는 상황을 만들면 프로그램은 CPU 점유율을 100%로 치솟게 만들며 멈춰버려요. 조건식 내부에서 반드시 조건을 거짓으로 만들 수 있는 로직(예: 카운터 증가, 플래그 변경 등)이 포함되어 있는지 반드시 확인해야 해요.

STEP 4. 최소 한 번의 실행은 보장한다, do-while 문

do-while 문은 while 문과 비슷하지만 결정적인 차이가 있어요. while 문은 시작부터 조건을 검사하지만, do-while 문은 일단 코드를 한 번 실행한 뒤에 조건을 검사해요. 즉, 조건이 처음부터 거짓이더라도 최소한 한 번은 반드시 실행된다는 특징이 있어요.

실무에서 어떤 상황에 쓰일까요? 대표적인 예가 사용자 메뉴 선택 시스템이에요. 사용자에게 메뉴를 보여주고 입력을 받아야 하는데, 입력받기 전에는 메뉴를 보여줄 수 없죠? 이때 do 블록 안에서 메뉴를 출력하고, while 조건문에서 사용자의 입력값이 ‘종료’가 아닌지를 체크하는 식으로 아주 자연스럽게 구현할 수 있어요.

STEP 5. 실무 시나리오: 대규모 데이터 처리 시 성능 비교

자, 그럼 이제 실제 상황을 가정해볼게요. 만약 여러분이 1,000,000개의 정수가 들어있는 리스트를 순회하며 합계를 구해야 한다면 어떤 것을 선택해야 할까요?

현대적인 .NET Framework 환경에서는 foreach 문과 for 문의 성능 차이가 매우 미미해요. 컴파일러가 foreach 문을 매우 효율적인 코드로 최적화해주기 때문이죠. 하지만 아주 극단적인 성능이 요구되는 게임 엔진의 메인 루프나 고빈도 트레이딩 시스템(HFT) 같은 환경이라면, 미세한 오버헤드조차 줄이기 위해 인덱스 기반의 for 문을 선호하는 경향이 있어요.

다음은 상황별 권장 패턴 요약이에요.

  • 데이터 양이 적고 가독성이 중요하다: foreach
  • 배열의 특정 위치를 조작하거나 건너뛰어야 한다: for
  • 특정 이벤트나 상태가 변할 때까지 기다려야 한다: while
  • 사용자 입력처럼 일단 한 번은 실행되어야 한다: do-while

결국 중요한 것은 의도를 명확히 드러내는 것이에요.

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

자주 하는 실수와 해결법

실수: foreach 문 안에서 리스트 아이템 삭제하기
왜 발생하는가: foreach는 내부적으로 반복자(Enumerator)를 사용하는데, 컬렉션의 구조가 바뀌면 반복자가 길을 잃기 때문이에요.
해결법: 삭제할 항목을 별도의 임시 리스트에 담아두었다가 반복문이 끝난 뒤 한꺼번에 지우거나, for 문을 사용하여 인덱스를 역순(count-1부터 0까지)으로 돌리며 삭제하세요.

실수: for 문에서 인덱스 범위 초과(IndexOutOfRangeException)
왜 발생하는가: 조건식에 i <= list.Count처럼 등호를 잘못 넣거나, 인덱스 계산 로직이 틀렸을 때 발생해요.
해결법: 배열이나 리스트의 마지막 인덱스는 항상 Count – 1이라는 점을 명심하고, 조건식에서 등호 사용을 주의 깊게 검토하세요.

실수: while 문에서 조건 업데이트 누락
왜 발생하는가: 반복을 멈추게 할 변수의 값을 업데이트하지 않아 조건이 영원히 참(true)으로 남기 때문이에요.
해결법: 반복문 블록 안에서 탈출 조건과 관련된 변수가 반드시 변하고 있는지 로직을 검증하세요.

실수: 중첩 반복문(Nested Loop)의 과도한 사용
왜 발생하는가: 문제를 풀기 위해 반복문 안에 반복문을 계속 넣다 보면 시간 복잡도가 기하급수적으로 증가해요.
해결법: 데이터 구조를 최적화하거나, LINQ(Language Integrated Query)를 사용하여 반복문을 단순화할 수 있는지 고민해보세요.

자주 묻는 질문

Q. for 문과 foreach 문 중 무엇이 더 빠른가요?
일반적인 비즈니스 로직에서는 차이를 체감하기 어려울 정도로 미세해요. 최신 .NET 버전은 foreach를 매우 효율적으로 처리합니다. 다만, 아주 빈번하게 호출되는 핵심 루프에서는 for 문이 아주 조금 더 빠를 수 있지만, 가독성을 포기할 만큼의 이득은 아닐 때가 많아요.

Q. break와 continue의 차이점은 무엇인가요?
break는 반복문 자체를 즉시 종료하고 빠져나가는 것이고, continue는 현재 차례의 남은 코드를 건너뛰고 다음 반복 단계로 바로 넘어가는 것이에요.

Q. foreach 문에서 인덱스 번호가 꼭 필요하면 어떻게 하나요?
가장 좋은 방법은 for 문을 쓰는 것이지만, 굳이 foreach를 쓰고 싶다면 외부 변수(int index = 0;)를 선언하여 루프 안에서 직접 증가시키는 방법이 있어요. 하지만 이 경우 코드가 지저분해질 수 있으니 주의하세요.

Q. LINQ를 쓰면 반복문을 아예 안 써도 되나요?
대부분의 단순 순회나 필터링은 LINQ로 대체 가능해요. 하지만 매우 복잡한 조건이나 성능이 극도로 중요한 구간에서는 명시적인 반복문이 더 유리할 수 있으니 상황에 맞춰 선택하세요.

완벽한 반복문 활용을 위한 마무리

지금까지 C#의 다양한 반복문 방식을 깊이 있게 살펴보았어요. 반복문은 단순해 보이지만, 어떤 상황에서 어떤 도구를 선택하느냐에 따라 여러분의 코드는 ‘돌아가기만 하는 코드’에서 ‘신뢰할 수 있는 프로페셔널의 코드’로 진화해요.

✅ 핵심 요약

  • 가독성과 안전성이 최우선이라면 foreach를 사용하세요.
  • 인덱스 제어나 데이터 수정이 필요하다면 for가 정답이에요.
  • 조건이 충족될 때까지 대기해야 한다면 while을 꺼내세요.
  • 최소 한 번의 실행이 보장되어야 한다면 do-while이 적합해요.
  • 컬렉션 수정 시에는 foreach 사용을 피하고 역순 for 문을 고려하세요.

오늘 배운 내용을 바탕으로 바로 여러분의 프로젝트 코드를 한 번 훑어보세요. 혹시 불필요하게 복잡한 for 문을 쓰고 있지는 않은지, 혹은 안전하지 않은 foreach 문을 쓰고 있지는 않은지 확인해보는 것만으로도 큰 공부가 될 거예요.

🚀 다음 단계로 나아가기

  • 오늘 할 일: 현재 작성 중인 코드에서 foreach를 쓸 수 있는 곳을 찾아 변경해보기
  • 이번 주 할 일: LINQ를 공부하여 반복문을 더 세련되게 대체하는 방법 익히기
  • 실행 직전 할 일: 반복문 사용 시 발생할 수 있는 예외 상황(IndexOutOfRangeException 등)을 직접 테스트해보기

반복문의 기초를 다졌다면, 이제 프로그램의 흐름을 결정짓는 조건문과 결합하여 더 복잡한 로직을 설계할 준비가 되셨어요. C# 조건문 관련 글도 함께 읽어보시면 논리적인 사고력을 키우는 데 큰 도움이 될 거예요. 다음 편에서 다룰 심화 주제도 놓치지 말고 확인해 보세요!

댓글 남기기