프론트엔드/Javascript

조건문(If)

syleemomo 2021. 10. 9. 06:35
728x90

* 조건문의 기본작성법 

if (조건){
	// 코드블록
}

조건문은 if 라는 키워드를 사용하고 조건을 검사한 다음 조건이 참(true)이면 코드블록을 실행한다. 

let year = prompt('ECMAScript-2015 명세는 몇 년도에 출판되었을까요?', '');

if (year == 2015) alert( '정답입니다!' );

해당 조건문은 사용자로부터 입력을 받아 year 변수에 저장한다. 조건문의 조건을 검사하여 year 변수값이 2015이면 경고창을 띄워준다. 해당 조건문은 코드블록이 한줄이므로 중괄호({})를 생략할 수 있다. 

if (year == 2015) {
  alert( "정답입니다!" );
  alert( "아주 똑똑하시네요!" );
}

해당 조건문은 복수의 코드문이 들어가 있으며 경고창도 2번 실행된다. 조건문을 사용할때는 코드블록이 한줄이라도 중괄호로 감싸주는 것이 코드 가독성에 좋다. 

 

* 불린형으로의 변환

조건문은 괄호안의 표현식을 평가하여 불린형으로 변환한다. 괄호안의 표현식이 참(true)이면 코드블록이 실행되고, 그렇지 않으면 코드블록이 실행되지 않는다.

if (0) { // 0은 falsy입니다.
  ...
}

 숫자 0, 빈 문자열(" "), null, undefined, Null 과 같은 falsy 값이 조건의 결과이면 코드블록은 실행되지 않는다. 

if (1) { // 1은 truthy입니다.
  ...
}

해당 조건문은 truthy 이므로 항상 실행된다.

let cond = (year == 2015); // 동등 비교를 통해 true/false 여부를 결정합니다.

if (cond) {
  ...
}

위와 같이 조건의 반환값(결과값)을 변수(cond)에 저장한 다음에 조건문에 사용할 수 있다. 

let cond = (year == 2015); // 동등 비교를 통해 true/false 여부를 결정합니다.

if (cond) {
  ...
}

cond = cond && isWeekend
if(cond){
	...
}

조건의 반환값을 저장하는 이유는 위와 같이 반환값이 프로그램의 다양한 위치에서 사용되기 때문이다. 

 

* else 구문

if(조건){
	// 코드블록 (truthy 일때 실행)
}else{
	// 코드블록 (falsy 일때 실행)
}

조건문에는 else 구문을 포함할 수 있다. else 구문의 코드블록은 조건이 거짓(falsy)일때 실행된다.

let year = prompt('ECMAScript-2015 명세는 몇 년도에 출판되었을까요?', '');

if (year == 2015) {
  alert( '정답입니다!' );
} else {
  alert( '오답입니다!' ); // 2015 이외의 값을 입력한 경우
}

해당 조건문은 year 변수값이 2015가 아닌 경우 else 구문이 실행된다.

 

* else if ~ else 구문 

else if ~ else 구문을 사용하면 여러가지 조건에 대한 처리가 가능하다. 

let year = prompt('ECMAScript-2015 명세는 몇 년도에 출판되었을까요?', '');

if (year < 2015) {
  alert( '숫자를 좀 더 올려보세요.' );
} else if (year > 2015) {
  alert( '숫자를 좀 더 내려보세요.' );
} else {
  alert( '정답입니다!' );
}

해당 조건문은 year 변수값이 2015보다 작지 않은 경우 else if 구문의 조건을 검사한다. 또한, year 변수값이 2015보다 작지 않고, 크지도 않은 경우 마지막 else 구문의 코드블록을 실행한다. 즉, 마지막 else 구문은 앞의 모든 조건들이 거짓(falsy)인 경우에 디폴트값으로 실행된다. 

 

* 조건부 연산자 (삼항 연산자)

아래와 같이 조건에 따라 다른 값을 변수에 할당해야 하는 경우가 있다.

let accessAllowed;
let age = prompt('나이를 입력해 주세요.', '');

if (age > 18) {
  accessAllowed = true;
} else {
  accessAllowed = false;
}

alert(accessAllowed);

조건부 연산자(삼항 연산자)를 사용하면 아래와 같이 더 간결한 문장으로 코드를 작성할 수 있다. 물음표 연산자는 우선순위가 낮으므로 부등호(>)가 실행되고 나서 평가한다. 

let accessAllowed = (age > 18) ? true : false;

조건을 감싸는 괄호는 생략이 가능하다. 하지만 코드 가독성을 위하여 괄호를 사용하는 것이 좋다.

// 연산자 우선순위 규칙에 따라, 비교 연산 'age > 18'이 먼저 실행됩니다.
// (조건문을 괄호로 감쌀 필요가 없습니다.)
let accessAllowed = age > 18 ? true : false;

해당 코드는 아래와 같이 더 짧게도 작성할 수 있다. 

let accessAllowed = (age > 18)

조건부 연산자(삼항 연산자)는 물음표(?) 기호를 사용하여 조건이 참이면 value1 값을 변수 result 에 저장하고, 조건이 거짓이면 value2 값을 변수 result 에 저장한다. 

let result = condition ? value1 : value2;

 

물음표(?) 연산자를 여러개 사용하면 if ~ else if 처럼 여러가지의 조건을 처리할 수 있다. 

let age = prompt('나이를 입력해주세요.', 18);

let message = (age < 3) ? '아기야 안녕?' :
  (age < 18) ? '안녕!' :
  (age < 100) ? '환영합니다!' :
  '나이가 아주 많으시거나, 나이가 아닌 값을 입력 하셨군요!';

alert( message );

해당 코드는 아래와 같이 동작한다.

첫 번째 물음표에선 조건문 age < 3을 검사합니다.
그 결과가 참이면 '아기야 안녕?'를 반환합니다. 그렇지 않다면 첫 번째 콜론 ":"에 이어지는 조건문 age < 18을 검사합니다.
그 결과가 참이면 '안녕!'를 반환합니다. 그렇지 않다면 다음 콜론 ":"에 이어지는 조건문 age < 100을 검사합니다.
그 결과가 참이면 '환영합니다!'를 반환합니다. 그렇지 않다면 마지막 콜론 ":" 이후의 표현식인 
'나이가 아주 많으시거나, 나이가 아닌 값을 입력 하셨군요!'를 반환합니다.

해당 코드는 if ~ else if 구문을 사용하여 아래와 같이 작성할 수 있다. 

if (age < 3) {
  message = '아기야 안녕?';
} else if (age < 18) {
  message = '안녕!';
} else if (age < 100) {
  message = '환영합니다!';
} else {
  message = '나이가 아주 많으시거나, 나이가 아닌 값을 입력 하셨군요!';
}

age 가 3보다 작으면 "아기야 안녕?"이 출력된다. age 가 3보다 크거나 같고, 18보다 작은 경우에는 "안녕!"이 출력된다. age 가 18보다 크거나 같고, 100보다 작은 경우에는 "환영합니다!"를 출력한다. age 가 100보다 크거나 같은 경우에는 "나이가 아주 많으시거나, 나이가 아닌 값을 입력하셨군요!"를 출력한다. 

age = parseInt(age) // 명시적인 형변환

if (age < 3) {
  message = '아기야 안녕?';
} else if (age < 18) {
  message = '안녕!';
} else if (age < 100) {
  message = '환영합니다!';
} else {
  message = '나이가 아주 많으시거나, 나이가 아닌 값을 입력 하셨군요!';
}

해당 코드는 숫자를 비교하기 위하여 parseInt 나 Number 함수를 이용하여 명시적인 형변환을 먼저 해주는 것이 코드 무결성에 도움이 된다. 

let company = prompt('자바스크립트는 어떤 회사가 만들었을까요?', '');

(company == 'Netscape') ?
   alert('정답입니다!') : alert('오답입니다!');

어떤 개발자는 위와 같이 삼항 연산자를 조건문 대신 사용하는 경우가 있다. 코드가 짧아진다는 장점은 있지만, 코드 가독성이 떨어지고 유지보수에 좋지 않다. 이런걸 두고 겉멋 들었다고 한다. 첫번째 줄에 세미콜론이 없으면 에러가 발생한다.

let company = prompt('자바스크립트는 어떤 회사가 만들었을까요?', '');

if (company == 'Netscape') {
  alert('정답입니다!');
} else {
  alert('오답입니다!');
}

조건을 판단하는 경우에는 조건문을 사용하는 것이 올바른 사용법이며, 코드 가독성도 더 낫다. 코드를 읽을때 우리의 눈은 수평이 아니라 수직으로 빠르게 읽어내려가기 때문이다. 

 

* switch ~ case 문

switch ~ case 문은 다양한 조건에 대한 일치여부를 검사하고 조건이 일치하는 코드블록을 실행한다. switch 문은 하나 이상의 case 문으로 구성되며, default 구문은 옵션이다. 

switch(x) {
  case 'value1':  // if (x === 'value1')
    ...
    [break]

  case 'value2':  // if (x === 'value2')
    ...
    [break]

  default:
    ...
    [break]
}

변수 x 의 값과 첫번째 case 문의 'value1'값이 일치하면 해당 case 문의 코드블록이 실행된다. 이후 변수 x의 값과 두번째 case 문의 'value2' 값이 일치하면 해당 case 문의 코드블록이 실행된다. 이후 같은 과정을 반복한다. 만약 중간에 break 를 만나면 switch ~ case 문은 종료된다. 또는 switch ~ case 문이 전부 실행되면 코드실행은 멈춘다. 변수 x의 값과 일치하는 case 가 없으면 default 문의 코드블럭이 실행된다. 

let a = 2 + 2;

switch (a) {
  case 3:
    alert( '비교하려는 값보다 작습니다.' );
    break;
  case 4:
    alert( '비교하려는 값과 일치합니다.' );
    break;
  case 5:
    alert( '비교하려는 값보다 큽니다.' );
    break;
  default:
    alert( "어떤 값인지 파악이 되지 않습니다." );
}

switch 문은 a 의 변수값과 첫번째 case 문의 3을 비교한다. 조건이 거짓이므로 그다음 case 문으로 건너띄어서 4와 비교한다. 조건이 참이므로 해당 코드블럭의 경고창이 실행된다. 그런 다음 break 문을 만나므로 switch ~ case 문은 종료된다.

let a = 2 + 2;

switch (a) {
  case 3:
    alert( '비교하려는 값보다 작습니다.' );
  case 4:
    alert( '비교하려는 값과 일치합니다.' );
  case 5:
    alert( '비교하려는 값보다 큽니다.' );
  default:
    alert( "어떤 값인지 파악이 되지 않습니다." );
}

case 문의 코드블럭에 break 문이 없으면 아래의 경고창이 모두 화면에 출력된다.

alert( '비교하려는 값과 일치합니다.' );
alert( '비교하려는 값보다 큽니다.' );
alert( "어떤 값인지 파악이 되지 않습니다." );

 이유는 두번째 case 문에서 조건의 일치여부를 검사하여 일치가 되면 해당 코드블럭을 실행하고 나머지 case 문의 조건은 검사하지 않고 곧바로 코드블럭을 실행하기 때문이다. 

let a = "1";
let b = 0;

switch (+a) {
  case b + 1:
    alert("표현식 +a는 1, 표현식 b+1는 1이므로 이 코드가 실행됩니다.");
    break;

  default:
    alert("이 코드는 실행되지 않습니다.");
}

switch ~ case 문의 조건에는 모든 형태의 표현식이 가능하다. +a 값은 숫자 1이다. 그리고 첫번째 case 문의 조건식(표현식) b + 1도 1이다. 조건이 일치하므로 첫번째 case 문의 코드블럭이 실행된다. 

let a = 3;

switch (a) {
  case 4:
    alert('계산이 맞습니다!');
    break;

  case 3: // (*) 두 case문을 묶음
  case 5:
    alert('계산이 틀립니다!');
    alert("수학 수업을 다시 들어보는걸 권유 드립니다.");
    break;

  default:
    alert('계산 결과가 이상하네요.');
}

여러 case 에서 실행될 코드가 동일한 경우에는 이와 같이 묶을수 있다. a 가 3 이나 5인 경우 동일한 코드블럭이 실행된다. a가 3인 경우 break 문이 없기 때문에 아래쪽에 있는 case 5 조건은 검사하지 않고 곧바로 case 5의 코드블럭을 실행한다.

let a = 4;

switch (a) {
  case 4:
    alert('계산이 맞습니다!');

  case 3: // (*) 두 case문을 묶음
  case 5:
    alert('계산이 틀립니다!');
    alert("수학 수업을 다시 들어보는걸 권유 드립니다.");
    break;

  default:
    alert('계산 결과가 이상하네요.');
}

코드를 위와 같이 변경하면 어떻게 동작할까?

첫번째 case 와 a 변수값이 일치하므로 첫번째 case 문의 코드블럭이 실행된다. 첫번째 case 문의 코드블럭에는 break 문이 없으므로 break 문을 만날때까지 조건검사는 건너띄고 코드블럭만 연속으로 실행한다.  

let weather = '맑음';

switch (weather) {
  case '구름':
    alert('조퇴한다.')
    break

  case '눈': 
    alert('결석한다.')
    break 

  case '맑음':
    alert('학원 나온다.')
    break 

  case '비':
    alert('결석한다.')
    break
    
  default:
    alert('조퇴한다.')
}

조건식(표현식)에는 당연히 문자열도 검사할 수 있다. 위 코드는 어떤 학생의 날씨에 따른 출석여부를 판단하는 로직이다.

let weather = '장마';

switch (weather) {
    case '맑음':
        alert('학원 나온다.')
        break 

    case '구름':
        alert('조퇴한다.')
        break

    case '눈': 
    case '비':
        alert('결석한다.')
        break 
        
    default:
        alert('조퇴한다.')
}

해당 코드도 마찬가지로 위와 같이 같은 케이스를 묶어서 코드를 다시 작성할 수 있다. 

let arg = prompt("값을 입력해주세요.");
switch (arg) {
  case '0':
  case '1':
    alert( '0이나 1을 입력하셨습니다.' );
    break;

  case '2':
    alert( '2를 입력하셨습니다.' );
    break;

  case 3:
    alert( '이 코드는 절대 실행되지 않습니다!' );
    break;
  default:
    alert( '알 수 없는 값을 입력하셨습니다.' );
}

위 코드에서 사용자로부터 받은 입력값 arg 는 문자열 타입이므로 사용자가 숫자 3을 입력하더라도 case 3 은 절대 실행되지 않는다. 즉, 자료형 자체가 다르기 때문에 case 3 의 코드블럭은 실행되지 않는다. 그 대신에 숫자 3을 입력하면 arg 는 문자열 "3"이므로 default 구문의 코드블럭이 실행된다. 

let a = 5;

switch (a) {
  case (a > 3):
    alert('3보다 크다!')
    break 

  case (a > 10): 
    alert('10보다 크다!')
    break 

  default:
    alert('3보다 작거나 같다.')
}

switch 문에서 부등호 조건을 사용할 수 있는지 테스트하기 위하여 위와 같이 작성하였으나 예상대로 동작하지 않는다. default 구문만 계속 실행된다. 왜냐하면 swtch ~ case 문은 조건과 일치하는 경우에 대하여 실행이 되는데 a 는 5이고, a (5) > 3 은 true 이므로 5와 true 는 일치하지 않는다. 물론 두번째 case 에서 5와 a > 10 도 일치하지 않는다. a (5) > 10 은 false 이므로 5와 false 는 일치하지 않는다.  즉, a 는 정수이고, 부등호 연산의 반환값은 true 나 false 이므로 일치하지 않는다. 

let a = 5;

switch (true) {
  case (a > 3):
    alert('3보다 크다!')
    break 

  case (a > 10): 
    alert('10보다 크다!')
    break 

  default:
    alert('3보다 작거나 같다.')
}

부등호의 반환값은 true 나 false 이므로 switch 문의 조건으로 true 나 false 를 넣어주면 만족하는 케이스가 분명히 존재한다. 첫번째 case 문의 조건 a (5) > 3 은 true 이므로 해당 조건문은 항상 첫번째 케이스의 코드블럭만 실행한다.  

let a = 3;

switch (true) {
  case (a > 3):
    alert('3보다 크다!')
    break 

  case (a > 10): 
    alert('10보다 크다!')
    break 

  default:
    alert('3보다 작거나 같다.')
}

a = 3인 경우에는 a(3) > 3 과 a(3) > 10 의 경우 모두 false 이므로 모든 조건을 만족하지 못하고 default 구문만 실행된다. 

 

* 중첩조건문

조건문은 상황에 따라 얼마든지 중첩이 가능하다.  

let username = 'sunrise'
let password = '12345'

if(username === 'sunrise'){
  if(password === '12345'){
    console.log('로그인에 성공하였습니다.')
  }else{
    console.log('비밀번호가 일치하지 않습니다.')
  }
}else{
  console.log('올바른 사용자가 아닙니다.')
}

해당 조건문은 사용자 이름과 비밀번호에 따라 로그인 정보가 올바른지 검사하는 간단한 프로그램이다. 먼저 조건문으로 사용자가 올바른지 검사하여 상황에 따라 다른 작업을 수행하도록 한다. 사용자가 올바르다면, 안쪽에 조건문을 첨가하여 비밀번호가 일치하는지 검사하고, 다시 상황에 따라 다른 작업을 수행하도록 한다. 사용자가 올바르지 않으면, 비밀번호 검사는 하지 않는다. 

let username = 'sunrise'
let password = '12345'
let confirmPassword = '12345'

if(username === 'sunrise'){
  if(password === '12345'){
    if(password === confirmPassword){
      console.log('로그인에 성공하였습니다.')
    }else{
      console.log('비밀번호 확인에 실패하였습니다.')
    }
  }else{
    console.log('비밀번호가 일치하지 않습니다.')
  }
}else{
  console.log('올바른 사용자가 아닙니다.')
}

비밀번호 확인 절차가 포함되어 있다면 상황은 더 복잡해진다. 비밀번호가 일치하더라도 비밀번호와 비밀번호 확인을 위한 번호가 일치하지 않으면 로그인은 성공하지 못하도록 위와 같이 삼중 조건문으로 작성하였다. 

let username = 'sunrise'
let password = '12345'
let confirmPassword = '12345'

if(username !== 'sunrise'){ 
  console.log('올바른 사용자가 아닙니다.')
}else if(password !== '12345'){ // 사용자가 올바른 경우
  console.log('비밀번호가 일치하지 않습니다.')
}else if(password !== confirmPassword){ // 사용자와 비밀번호 모두 일치하는 경우
  console.log('비밀번호 확인에 실패하였습니다.')
}else{ // 사용자와 비밀번호가 모두 일치하고 비밀번호 확인도 된 경우
  console.log('로그인에 성공하였습니다.')
}

하지만 실제 프로그램을 작성할때는 최대한 중첩이 되지 않도록 작성하는 것이 좋다. 해당 조건문은 앞서 봤던 로그인 프로그램과 동일한 기능을 수행하지만, if ~ else 구문을 이용하여 중첩을 피하고, 훨씬 더 좋은 가독성을 보여준다. 

 

 

 

연습과제 1

prompt 함수로 평점에 대한 사용자 입력을 받고, if 조건문을 사용하여 평점만들기 과제 1~5점 사이의 평점을 콘솔창에 별표로 보여주세요.

1. 평점은 1, 2, 3, 4, 5의 정수라고 가정한다.
2. 평점이 1의 경우가 아니면 "잘못된 평점입니다"라는 문구를 경고창에 띄운다.

연습과제 2

prompt 함수로 평점에 대한 사용자 입력을 받고, switch 조건문을 사용하여 평점만들기 과제 1~5점 사이의 평점을 콘솔창에 별표로 보여주세요. 

1. 평점은 1, 2, 3, 4, 5의 정수라고 가정한다.
2. 평점이 1의 경우가 아니면 "잘못된 평점입니다"라는 문구를 경고창에 띄운다.

연습과제 3

let a = 3;

switch (true) {
  case (a > 3):
    alert('3보다 크다!')
    break 

  case (a > 10): 
    alert('10보다 크다!')
    break 

  default:
    alert('3보다 작거나 같다.')
}

해당 코드는 a 가 3보다 작거나 같은 경우에는 default 구문만 실행되고, a 가 3보다 큰 경우에는 첫번째 case 문의 코드블럭만 실행된다. 만약 a 가 10보다 큰 경우 두번째 case 문의 코드블럭이 실행되려면 코드를 어떻게 변경하면 될까?

연습과제 4

점수 60점 미만 60~69점 70~79점 80~89점 90~100점
성취기준 Fail 2 3 4 5

prompt 함수로 점수에 대한 사용자 입력을 받고, 점수환산 기준 테이블을 참고하여 점수에 대한 성취기준을 콘솔창에 출력하세요! 

1. 입력한 점수가 정수가 아닌 실수이거나 문자열, 특수문자인 경우
2. 입력한 점수가 100보다 큰 경우
3. 입력한 점수가 0보다 작은 경우

단, 위의 세가지 경우에는 점수환산을 하지 않고, 경고창을 띄워서 "잘못된 점수입니다" 를 화면에 보여준다. 

 

연습과제 5

중첩 조건문을 이용하여 두 플레이어에 대한 가위, 바위, 보 게임을 만들어보세요!

let player1 = '가위'
let player2 = '바위'

// 코드 작성하기

콘솔창 출력결과

 

연습과제 6

프롬프트(prompt) 대화상자를 이용해 간이 로그인 창을 구현해보세요.

사용자가 "Admin"를 입력하면 비밀번호를 물어보는 프롬프트 대화상자를 띄워주세요. 이때 아무런 입력도 하지 않거나 Esc를 누르면 "취소되었습니다."라는 메시지를 보여주세요. 틀린 비밀번호를 입력했다면 "인증에 실패하였습니다."라는 메시지를 보여주세요.

비밀번호 확인 절차는 다음과 같습니다.

1. 맞는 비밀번호 "TheMaster"를 입력했다면 "환영합니다!"라는 메시지를 보여주세요.
2. 틀린 비밀번호를 입력했다면 "인증에 실패하였습니다."라는 메시지를 보여주세요.
3. 빈 문자열을 입력하거나 입력을 취소했다면 "취소되었습니다."라는 메시지를 보여주세요.

 

연습과제 7

연습과제 5에서 player1과 player2의 변수에 값을 할당할때 아래와 같은 랜덤함수를 사용하여 새로고침할때마다 다른 결과가 나오게 코드를 변경해보세요!

Math.random()

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random

 

Math.random() - JavaScript | MDN

The Math.random() static method returns a floating-point, pseudo-random number that's greater than or equal to 0 and less than 1, with approximately uniform distribution over that range — which you can then scale to your desired range. The implementation

developer.mozilla.org

Math 객체의 random 메서드는 0보다 크거나 같고 1보다 작은 랜덤한 실수값을 반환합니다. 예를 들면, 0.123, 5.65656, 9.9999 등이다. 해당 메서드를 이용하여 player1과 player2의 변수값을 0, 1, 2 세 값 중 하나로 랜덤하게 저장한다. 그리고 조건문을 사용하여 0은 "가위", 1은 "바위", 2는 "보"로 환산해서 게임을 실행하도록 한다.  

 

 

control flow

 

728x90