본문으로 건너뛰기

모던 javascript - 제어문

· 약 6분
Seung hyo, Lee
Front End Engineer @ Assistfit

❤️‍🔥 TIL : Today I Learned

노트

제어문을 사용하면 코드의 실행 흐름을 인위적으로 제어할 수 있다.

제어문(control flow statement)​

조건에 따라 코드 블록을 실행(조건문)하거나, 반복실행(반복문)할 때 사용한다.

블록문(block statement)​

0개 이상의 문을 중괄호로 묶은 것으로, 코드 블록 또는 블록이라고 부르기도 한다. { }

문의 끝에는 세미콜론을 붙이는 것이 일반적이다. 하지만 블록문은 언제나 문의 종료를 의미하는 자체 종결성을 갖기 때문에 블록문의 끝에는 세미콜론을 붙이지 않는다.

// 블록문
{
var foo = 10;
}

// 제어문
var x = 1;
if (x < 10) {
x++;
}

// 함수 선언문
function sum(a, b) {
return a + b;
}

조건문(conditional statement)​

if...else 문

주어진 조건식의 평가 결과에 따라 코드를 블록(블록문)의 실행을 결정한다. 조건식은 불리언 값으로 평가될 수 있는 표현식이다.

자바스크립트는 if...else 문과 switch 문으로 두가지 조건문을 제공한다. 또한 조건식을 추가해 실행될 코드블록을 늘리고 싶으면 else if 문을 사용한다.

if (조건식1) {
// 조건식1이 참이면 이 코드 블록이 실행된다.
} else if (조건식2) {
// 조건식2가 참이면 이 코드블록이 실행된다.
} else {
// 조건식1과 조건식2가 모두 거짓이면 이 코드 블록이 실행된다.
}

하지만 여기서 else if 문과 else 문은 옵션이다. 즉, 사용할 수도 있고 사용하지 않을 수 있다. 또 if 문과 else 문은 2번 이상 사용할 수 없지만, else if 문은 여러 번 사용할 수 있다.

대부분의 if...else 문은 삼항 조건 연산자로 바꿔 쓸 수 있다.

이 포스팅중 가장 핵심이 되는 제어문이 될 것 같다.

우리가 제목만 다른 내용의 문서를 2개 작성한다고 가정해 보자. 아니 더 극단적으로 필기노트라고 가정 해 보자.

오늘 기분 안좋음
그래도 공부 열심히 해보자
오늘 공부할 내용은
.
.
.
// 동일한 내용
오늘 기분 좋음
그러니 공부 열심히 해보자
오늘 공부할 내용은
.
.
.
// 동일한 내용

이 상태에서는 천줄, 만줄로 아무리 길어도 내용은 같지만 서로다른 2개의 노트를 일일히 수기로 작성해야 한다...

만약 코드에도 이런 상황이 벌어진다면 어떨까?.. 생산성이 극도로 저하된다.. 단순하게 파일 2개로 나눈다고 해결 될 문제가 아니다. 오타를 수정해도 2개의 파일을 수정해야 하고, 컴퓨터는 2개의 파일을 읽어내 메모리공간을 2번이나 차지하게 되어 성능면에서도 상당히 비효율적인 코드가 된다. 혹여나 2, 3... 번 이상 반복해야 한다면? 생각만 해도 끔찍하다.

이를 해결하고자 제어문을 사용하는데 그 중에서 가장 자주 쓰이는 제어문은 삼항 조건 연산자 라고 생각한다.

// x가 짝수이면. result 변수에 문자열 '짝수'를 할당하고, 홀수이면 문자열 '홀수'를 할당한다.
var x = 2;
var result;

if (x % 2) {
// 2 % 2는 0이다. 이때 0은 false로 암묵적 강제 변환된다.
result = "홀수";
} else {
result = "짝수";
}
console.log(result); // 짝수

// 삼항 조건 연산자 변환

var x = 2;

// 0은 false로 취급된다.
var result = x % 2 ? "홀수" : "짝수";
console.log(result); // 짝수

삼항 조건 연산자는 값으로 평가되는 표현식을 만든다. 하지만 if...else 문은 표현식이 아닌 문이다. 따라서 if...else문은 값처럼 사용할 수 없기 때문에 변수에 할당할 수 없다.

조건에 따라 값을 결정하여 변수에 할당하는 경우 if...else문 보다 삼항조건 연산자를 사용하는 편이 가독성이 좋다. 다만, 여러 줄의 문이 필요 하다면, if...else문을 사용하는 편이 가독성이 좋다.

switch문

switch (표현식) {
case 표현식1:
// switch 문의 표현식과 표현식1이 일치하면 실행될 문;
break;
case 표현식2:
// switch 문의 표현식과 표현식2가 일치하면 실행될 문;
break;
default:
// switch 문의 표현식과 일치하는 case 문이 없을 때 실행될 문;
}

if...else문은 논리적 참, 거짓으로 실행할 코드 블록을 결정하지만, switch문은 다양한 상황(case)에 따라 실행할 코드 블록을 결정할 때 사용한다.

위에서 break를 사용하지 않는다면 어떻게 될까.. switch문을 탈출하지 않고, switch 문이 끝날 때까지 이후의 모든 case문과 default문을 실행한다. 이를 폴스루(fall through) 라고 한다.

그래서 case 에 맞는 표현식을 실행하고 switch 문을 빠져나가기 위해 break를 작성한다. 하지만 default문에는 break 문을 생략하는 것이 일반적이다. 왜냐하면 default문의 실행이 종료되면 switch문을 빠져나간다. 따라서 별도로 break문이 필요 없다.

팁

해결할 수 있다면 switch 문보다 if...else문을 사용하는 편이 좋다. 하지만 조건이 너무 많아서 if...else 문보다 switch문을 사용했을 때 가독성이 더 좋다면 switch문을 사용하는 편이 좋다.

반복문(loop statement)​

조건식의 평가 결과가 참(true)인 경우 코드 블록을 실행한다. 이는 조건식이 거짓(false)일 때까지 반복된다. for문, while문, do...while문을 제공한다.

for문

for (변수 선언문 또는 할당문; 조건식; 증감식) {
// 조건식이 참인 경우 반복 실행될 문;
}

for (var i = 0; i < 2; i++) {
console.log(i);
} // 0 1

for문의 변수 선언문, 조건식, 증감식은 모두 옵션이므로 반드시 사용할 필요는 없다. 단, 어떤 식도 선언하지 않으면 무한루프가 된다. (코드 블록을 무한히 반복 실행)

주사위 하나를 던졌을 때의 경우의 수를 6가지라고 할 수 있겠으나, 여기서 주사위가 2개가 되었을 경우.. 우리는 이중 중첩 for 문을 사용할 수 있다.

예제는 주사위 두개를 던졌을 때 두 눈의 합이 6이 되는 모든 경우의 수를 출력하기 위해 흔히 말하는 '이중 for문'을 사용한 예다.

for (var i = 1; i <= 6; i++) {
for (var j = 1; j <= 6; j++) {
if (i + j === 6) console.log(`[${i}, ${j}]`);
}
}

while문

for 문은 반복 횟수가 명확할 때 주로 사용하고, while문은 반복 횟수가 불명확할 때 주로 사용한다.

var count = 0;

// 무한 루프
while (true) {
console.log(count);
count++;
// count가 3이면 코드 블록을 탈출한다.
if (count === 3) break;
} // 0 1 2

do...while문

do...while문은 코드 블록을 먼저 실행하고 조건식을 평가한다.

var count = 0;

// count가 3보다 작을 때까지 코드 블록을 계속 반복 실행한다.
do {
console.log(count); // 0 1 2
count++;
} while (count < 3);

break 문​

switch 문과 while 문에서 살펴보았듯이 break 문은 레이블 문, 반복문 또는 switch문의 코드 블록을 탈출한다.

위 문의 코드블록 외에 break문을 사용하면 SyntaxError(문법에러)가 발생한다.

var string = "Hello World";
var search = "l";
var index;

// 문자열은 유사 배열이므로 for 문으로 순회할 수 있다.
for (var i = 0; i < string.length; i++) {
// 문자열의 개별 문자가 'l'이면
if (string[i] === search) {
index = i;
break; // 반복문을 탈출한다.
}
}

console.log(index); // 2

레이블 문

outer: for (...) {...}

식별자를 붙여 레이블 for문을 사용할 수 있는데 일반적으로 권장하지 않는다. 프로그램 흐름이 복잡하고 가독성이 나빠져 오류를 발생시킬 가능성이 높아지기 때문이다.

continue 문​

continue 문은 반복문의 코드 블록 실행을 현 지점에서 중단하고 반복문의 증감식으로 실행흐름을 이동시킨다. break 문처럼 반복문을 탈출하지는 않는다.

노트
  • break = 코드블럭을 완전 빠져나와, 다음 문을 실행
  • continue = 코드블럭을 끝까지 실행시키지 않고 다시 반복
var string = "Hello World.";
var search = "l";
var count = 0;

// continue 문을 사용하지 않으면 if문 내에 코드를 작성해야 한다.
for (var i = 0; i < string.length; i++) {
// 'l'이면 카운트를 증가시킨다.
if (string[i] === search) {
count++;
// code
// code
// code
}
}

// continue 문을 사용하면 if문 밖에 코드를 작성할 수 있다.
for (var i = 0; i < string.length; i++) {
// 'l'이 아니면 카운트를 증가시키지 않는다.
if (string[i] !== search) continue;

count++;
// code
// code
// code
}
최종 정리
  • 제어문 : 조건문, 반복문 으로 코드의 실행을 인위적으로 제어
  • 블록문 : 중괄호로 묶은 코드, 코드블록
  • 조건문 : (조건식)의 평가결과에 따라 코드블록의 실행을 결정 true, false [if...else문, switch문]
  • 반복문 : 조건식의 평가 결과가 거짓일 때 까지 반복한다. [for문, while문, do...while문]
  • break문 : 레이블 문, 반복문, 또는 switch문의 코드블록을 탈출하고 다음 코드로 넘어간다.
  • continue문 : break문과 다르게 코드블록을 탈출하지 않지만 현 지점에서 중단하고 다시 코드블록을 실행한다.