Menu

자바스크립트 for문 완벽 정리: 문법부터 break/continue까지

자바스크립트 for문의 기본 구조부터 배열 순회, break와 continue, 중첩 반복문, 자주 하는 실수까지 예제로 정리합니다.

기본 for문 사용법

반복 횟수가 정해져 있을 때 가장 먼저 떠올리게 되는 것이 바로 자바스크립트 for문입니다. 시작값, 종료 조건, 증감식까지 반복에 필요한 세 가지 요소를 한 줄에 깔끔하게 담을 수 있다는 게 for문의 가장 큰 매력이죠.

index.js
Output
Click Run to see the output here.

다섯 번 반복되어 다섯 줄이 출력됩니다. 헤더를 하나씩 뜯어보면 이렇습니다.

  • let i = 0은 루프가 시작되기 전에 딱 한 번만 실행됩니다. 카운터를 초기화하는 부분이죠.
  • i < 5는 매 반복마다 실행 전에 먼저 검사합니다. true면 본문이 실행되고, false면 루프가 종료됩니다.
  • i++는 매 반복이 끝난 뒤, 다음 조건 검사 직전에 실행됩니다.

세 부분은 쉼표가 아니라 세미콜론으로 구분한다는 점에 주의하세요. 셋 다 생략할 수는 있지만 실제로 그렇게 쓰는 경우는 거의 없습니다. 그럴 땐 보통 while문을 쓰는 게 더 자연스럽거든요.

for문 실행 순서 한눈에 보기

순서를 확실히 익히려면 직접 한 번 손으로 따라가 보는 게 제일 좋습니다.

index.js
Output
Click Run to see the output here.

동작 순서를 하나씩 따라가 보겠습니다.

  1. let i = 1 — 카운터 변수가 만들어지고 1로 초기화됩니다.
  2. i <= 3 확인 — 참이므로 본문을 실행합니다. 1을 출력합니다.
  3. i++ 실행 — i는 이제 2입니다.
  4. i <= 3 확인 — 참. 2를 출력합니다.
  5. i++ 실행 — i는 이제 3입니다.
  6. i <= 3 확인 — 참. 3을 출력합니다.
  7. i++ 실행 — i는 이제 4입니다.
  8. i <= 3 확인 — 거짓. 반복문을 빠져나옵니다.

여기서 헷갈리기 쉬운 포인트는, 증감식이 본문보다 먼저 실행되는 게 아니라 본문이 끝난 뒤에 실행된다는 점입니다.

for문으로 배열 순회하기

자바스크립트 for문이 가장 많이 쓰이는 상황은 역시 배열을 순회할 때입니다. 이때는 카운터 변수가 그대로 인덱스 역할을 합니다.

index.js
Output
Click Run to see the output here.

몇 가지 짚고 넘어갈 포인트입니다.

  • 배열의 인덱스는 0부터 시작합니다. 첫 번째 요소는 인덱스 0, 마지막 요소는 length - 1에 있습니다.
  • 조건은 i <= fruits.length가 아니라 i < fruits.length입니다. <=를 쓰면 마지막 인덱스를 넘어서 undefined가 출력돼요.
  • ilet으로 선언했기 때문에 for문 안에서만 유효합니다. 루프 바깥에서는 존재하지 않아요.

인덱스가 필요 없고 값만 쓰면 된다면 for...of 문법이 훨씬 간결하고 읽기 좋습니다. 이건 따로 문서에서 다룰 예정이에요.

break: 반복을 도중에 멈추기

break는 루프를 즉시 빠져나옵니다. 찾던 값을 발견해서 더 이상 돌 필요가 없을 때 유용하죠.

index.js
Output
Click Run to see the output here.

break가 실행되는 순간, 제어 흐름은 반복문의 닫는 중괄호 바깥으로 바로 점프합니다. 업데이트 단계도 건너뛰고, 조건도 다시 확인하지 않습니다. 반복문은 그대로 끝입니다.

continue: 이번 회차만 건너뛰기

continue는 현재 회차의 남은 코드를 건너뛰고 곧장 업데이트 단계로 넘어갑니다. 반복문 자체는 계속 돌아가며, 단지 이번 한 바퀴만 마저 실행하지 않을 뿐입니다.

index.js
Output
Click Run to see the output here.

짝수일 때는 continue를 만나서 console.log를 건너뛰고, 홀수만 출력됩니다. 특정 반복만 걸러내고 싶은데 나머지 본문을 if 블록 안에 들여쓰기 하기 싫을 때 continue가 유용합니다.

+1 말고 다른 증가 값 사용하기

증감식은 그냥 하나의 표현식일 뿐이라 꼭 i++일 필요는 없습니다. 2씩 건너뛰며 세어볼까요?

index.js
Output
Click Run to see the output here.

카운트다운:

index.js
Output
Click Run to see the output here.

배열을 역순으로 순회할 때도 있는데, 순회하면서 요소를 제거할 때 특히 유용합니다:

index.js
Output
Click Run to see the output here.

어떤 방식을 택하든 규칙은 똑같습니다. 조건식과 증감식이 맞물려 돌아가면서 언젠가는 조건이 false가 되도록 만들어야 해요. 그렇지 않으면 루프는 영원히 돌아갑니다. for (let i = 0; i < 10; i--) 같은 코드가 바로 무한루프예요. i가 엉뚱한 방향으로 움직이고 있으니까요.

중첩 for문

for문 안에 또 다른 for문을 넣을 수도 있습니다. 바깥쪽 루프가 한 번 돌 때마다 안쪽 루프는 끝까지 전부 실행됩니다.

index.js
Output
Click Run to see the output here.

출력은 총 9줄이 찍힙니다. 바깥 루프 3번, 안쪽 루프가 각각 3번씩 돌기 때문이죠. 카운터 변수는 row/col이나 i/j처럼 역할이 드러나는 이름을 쓰는 게 좋습니다. 같은 변수를 돌려쓰지 마세요.

한 가지 주의할 점: breakcontinue는 자기가 속한 가장 안쪽 루프에만 영향을 줍니다. 안쪽 루프에서 break를 걸어도 바깥 루프는 멈추지 않아요. 바깥까지 빠져나가고 싶다면 플래그 변수를 하나 두고 바깥 루프에서 체크하거나, 중첩된 로직을 함수로 빼서 return으로 탈출하는 방식을 쓰면 됩니다.

자주 하는 실수들

자바스크립트 for문에서 초보자가 흔히 걸려 넘어지는 지점 몇 가지입니다:

하나 차이(off-by-one) 오류. i <= arr.length로 쓰면 한 칸 더 돌아서 범위를 벗어나고, i < arr.length - 1로 쓰면 마지막 요소를 빠뜨립니다. 정석은 i < arr.length예요.

증감식 빼먹기. i++(또는 이에 해당하는 식)을 빼먹으면 카운터 값이 그대로라서 루프가 영원히 돌아갑니다. 자바스크립트 무한루프의 대표적인 원인이죠:

for (let i = 0; i < 10; ) {
    console.log(i); // 끝나지 않음
}

카운터 변수로 var를 쓰는 경우. var는 함수 스코프라서 카운터가 반복문 밖으로 새어나가고, 클로저 안에서 예상치 못한 동작을 일으킬 수 있습니다. 그냥 let을 쓰세요.

순회 중에 배열을 수정하는 경우. 중간에 요소를 제거하면 인덱스가 밀려서 일부 요소를 건너뛰게 됩니다. 요소를 지워야 한다면 역순으로 반복하거나, filter로 새 배열을 만드세요.

언제 다른 문법을 써야 할까

고전적인 for문은 언제든 쓸 수 있지만, 자주 쓰는 패턴에는 자바스크립트에 더 짧은 대안이 있습니다:

  • 배열 값을 순회할 때: for (const item of array)가 더 깔끔합니다.
  • 배열을 변환할 때: array.map(fn)이 새 배열을 돌려줍니다.
  • 걸러낼 때: array.filter(fn).
  • 합계를 내거나 누적할 때: array.reduce(fn, start).
  • 각 요소마다 뭔가 실행만 할 때: array.forEach(fn).

전통적인 for문은 인덱스가 실제로 필요하거나, 중간에 건너뛰거나 break로 빠져나와야 하거나, 역순 반복이나 2씩 증가처럼 변칙적인 step이 필요할 때 쓰면 됩니다.

다음: while문

for문은 반복 범위를 미리 알고 있을 때 진가를 발휘합니다. 반대로 범위를 모르는 상황 — 어떤 조건이 바뀔 때까지 계속 돌려야 하는 경우 — 에는 whiledo...while이 더 잘 어울립니다. 다음 페이지에서 이어서 살펴보겠습니다.

자주 묻는 질문

자바스크립트 for문 문법은 어떻게 되나요?

괄호 안에 세미콜론으로 구분된 세 부분이 들어갑니다: for (초기화; 조건; 업데이트) { ... }. 초기화는 딱 한 번 실행되고, 조건은 매 반복마다 검사하며, 업데이트는 각 반복이 끝난 뒤에 실행됩니다. 가장 흔한 형태는 for (let i = 0; i < 10; i++) { ... } 이런 식이에요.

배열을 for문으로 어떻게 순회하나요?

인덱스를 쓰는 고전적인 for문으로 충분합니다: for (let i = 0; i < arr.length; i++) { console.log(arr[i]); }. 인덱스가 굳이 필요 없다면 for...of가 훨씬 깔끔해요: for (const item of arr) { ... }. 값을 변형하거나 걸러내는 작업이라면 map, filter 같은 배열 메서드를 쓰는 편이 자연스럽습니다.

for문 안에서 break와 continue는 어떻게 동작하나요?

break는 반복문을 즉시 빠져나갑니다. 실행 흐름이 반복문 바로 뒤 코드로 넘어가요. continue는 현재 반복의 남은 부분을 건너뛰고 바로 업데이트 단계로 가서 조건을 다시 검사합니다. 둘 다 기본적으로 가장 안쪽 반복문에만 영향을 주고, 바깥 루프까지 제어하려면 라벨(label)을 써야 해요.

for문이 무한 루프에 빠지는 이유가 뭔가요?

대부분 업데이트 식이 조건을 false에 가깝게 만들지 못하기 때문입니다. 예를 들어 for (let i = 0; i < 10; i--)i가 0에서 시작해 계속 작아지니까 영원히 끝나지 않아요. 조건과 업데이트가 같은 방향을 보고 있는지, 언젠가는 조건이 false가 되는지 반드시 확인하세요.

Coddy로 코딩 배우기

시작하기