[모던 자바스크립트 Deep Dive] - 8장 정리

2026. 4. 1. 23:53Book Review

반응형

 

자바스크립트를 사용하다보면 어느 순간 "코드가 위에서 아래로 그냥 실행되는 게 아니네"를 체감하게 된다.

조건에 따라 다르게 실행하고, 특정 작업을 반복하고, 중간에 흐름을 끊거나 건너뛰는 것들이 흐름 제어에 영향을 주기 때문이다.

저렇게 흐름 제어를 변경할 수 있도록 도와주는 것들을 제어문이라고 한다.

제어문이란?

코드는 기본적으로 위에서 아래로 순서대로 실행된다. 제어문은 그 흐름을 인위적으로 바꾸는 도구다.

조건에 따라 코드 블록을 실행하거나 특정 횟수만큼 반복하거나 중간에 빠져나오는 등 

블록문이란 { } 중괄호로 묶인 코드 뭉치를 말한다. 제어문은 대부분 이 블록문과 함께 쓰인다.
블록문 끝에는 세미콜론을 안 붙이는 게 원칙인데, 블록문 자체가 "여기서 끝"을 의미하기 때문이다.

 

한 가지 알아두면 좋은 건, 제어문이 많아질수록 코드 흐름이 복잡해진다는 점이다. 그래서 실무에서는 forEach, map, filter 같은 고차 함수를 활용해서 제어문 자체를 줄이려는 노력을 하기도 한다.

조건문

if / else if / else

조건식이 참인지 거짓인지에 따라 실행 블록을 결정한다.

const score = 75;

if (score >= 90) {
  console.log('A등급');
} else if (score >= 70) {
  console.log('B등급');  // ← 이게 실행됨
} else {
  console.log('C등급 이하');
}

 

조건식이 꼭 boolean일 필요는 없다. 자바스크립트는 조건식에 들어온 값을 알아서 boolean으로 강제 변환한다.

빈 문자열, 0, null, undefined, NaN은 false로, 나머지는 true로 변환된다.

 

if/else를 쓸 때랑 삼항 연산자를 쓸 때를 어떻게 구분해요?

 

핵심은 값이 필요한가다. 조건에 따라 변수에 값을 할당하는 상황이라면 삼항 연산자가 훨씬 간결하다.

if/else는 "표현식"이 아니라 "문"이기 때문에 변수에 직접 할당이 안 된다.

// if/else 방식
let grade;
if (score >= 90) {
  grade = 'A';
} else {
  grade = 'B';
}

// 삼항 연산자 방식 — 훨씬 깔끔하다
const grade = score >= 90 ? 'A' : 'B';

 

그런데 조건이 3개 이상으로 중첩되면 오히려 삼항 연산자가 가독성이 나쁘다. 그럴 땐 if/else를 쓰는 편이 좋다.

switch

switch는 하나의 값을 여러 case와 비교할 때 사용한다.

if/else보다 코드가 길어 보일 수 있고 경우의 수가 많은 경우에 오히려 가독성이 좋다.

const day = 'Tuesday';

switch (day) {
  case 'Monday':
    console.log('월요일');
    break;
  case 'Tuesday':
    console.log('화요일');  // ← 실행됨
    break;
  default:
    console.log('그 외 요일');
}

 

break를 쓰지 않으면 일치한 case 이후의 모든 case가 연달아 실행된다.

이걸 폴스루(fall-through)라고 하는데 버그가 될수도 있지만 의도적으로 활용할 방법도 있다.

// 폴스루 활용 예 — 주말을 하나로 묶기
switch (day) {
  case 'Saturday':
  case 'Sunday':
    console.log('주말이다!');
    break;
  default:
    console.log('평일');
}

Saturday와 Sunday 둘 다 같은 결과를 내야 할 때, 이렇게 case를 연달아 쓰고 break를 하나만 두면 된다.

default는 어차피 마지막에 실행되기 때문에 break가 필요 없다.

경우의 수가 5개 이상 넘어가면 if/else가 else if의 연속으로 너무 길어진다. 그런 경우에 switch가 훨씬 읽기 편하다.
반대로 조건이 단순하다면 if/else를 쓰는 게 낫다.

반복문

for

반복 횟수가 정해져 있을 때 주로 쓴다. 형태는 for(초기값; 조건식; 증감식)이다.

// 1부터 5까지 출력
for (let i = 1; i <= 5; i++) {
  console.log(i);
}
// 1, 2, 3, 4, 5

// 역방향도 가능
for (let i = 5; i >= 1; i--) {
  console.log(i);
}
// 5, 4, 3, 2, 1

 

초기값, 조건식, 증감식은 전부 생략할 수 있다. 전부 생략하면 무한 루프가 된다. for문 안에 for문을 중첩해서 쓸 수도 있다.

// 중첩 for문 — 구구단 2단 출력
for (let i = 1; i <= 9; i++) {
  console.log(`2 × ${i} = ${2 * i}`);
}

 

while

반복 횟수를 미리 알 수 없고 조건이 맞는 동안 계속 돌려야 할 때 쓴다.

let count = 0;

while (count < 5) {
  console.log(count);
  count++;
}
// 0, 1, 2, 3, 4

 

while의 조건식이 항상 true면 영원히 돌아간다. 그러니 내부에 탈출 조건을 만들어줘야 한다.

// break로 탈출하는 패턴
let x = 0;

while (true) {
  x++;
  if (x >= 5) break;  // 5가 되면 탈출
}

console.log(x);  // 5

 

do while

while과 비슷한데 한 가지 차이가 있다. 코드 블록을 먼저 실행하고 조건을 나중에 확인한다. 즉, 조건과 무관하게 최소 한 번은 실행된다.

let x = 100;

do {
  console.log('일단 한 번은 실행');
} while (x < 10);
// 조건이 false여도 위 블록은 이미 실행됨

 

실제로 do while을 쓸 일이 많진 않아도 처음에 무조건 뭔가를 보여줘야 하는 경우에 유용하다.

break와 continue

break

반복문이나 switch문에서 완전히 빠져나올 때 쓴다. 레이블과 함께 쓰면 중첩 반복문에서 바깥 루프까지 한 번에 탈출할 수 있다.

// 레이블을 활용한 중첩 for문 탈출
outer: for (let i = 0; i < 3; i++) {
  for (let j = 0; j < 3; j++) {
    if (j === 1) break outer;  // 바깥 for문까지 탈출
    console.log(i, j);
  }
}
// 0 0 만 출력됨

레이블은 중첩 반복문을 통째로 빠져나올 땐 유용하다. 하지만 남발하면 코드 흐름을 따라가기 어려워지고 버그도 생기기 쉬워서 꼭 필요한 경우에만 쓰는 게 좋다.

continue

break처럼 탈출하는 게 아니라, 현재 반복만 건너뛰고 다음 반복으로 넘어간다.

// 홀수만 출력하기
for (let i = 1; i <= 10; i++) {
  if (i % 2 === 0) continue;  // 짝수면 건너뜀
  console.log(i);
}
// 1, 3, 5, 7, 9

 

if문으로 감싸는 방식과 결과는 같지만 실행할 코드가 길어질수록 들여쓰기가 한 단계 더 깊어진다. 그럴 때 continue를 쓰면 깔끔하게 정리된다.

고차 함수로 제어문 줄이기

제어문이 많아질수록 코드 흐름이 복잡해진다. 그래서 요즘 자바스크립트에서는 forEach, map, filter 같은 고차 함수를 활용해서 제어문 사용을 줄이는 방식을 선호한다.

const numbers = [1, 2, 3, 4, 5];

// for문 버전
const evens = [];
for (let i = 0; i < numbers.length; i++) {
  if (numbers[i] % 2 === 0) {
    evens.push(numbers[i]);
  }
}

// filter 버전 — 훨씬 간결하다
const evens2 = numbers.filter(n => n % 2 === 0);
console.log(evens2);  // [2, 4]

배열을 순회하면서 변환하거나 필터링하는 작업이라면 고차 함수가 훨씬 읽기 편하다.

다만 모든 상황에서 고차 함수가 정답은 아니다. 복잡한 조건이나 흐름 제어가 필요할 때는 여전히 for문이 명확할 때도 있다.

반응형