데이터 처리 : flow control

조혜준·2023년 10월 20일

[0] flow control의 개요

1) flow control의 이해

컴퓨터의 기본 동작 : 개발자는 컴퓨터에게 명령하고, 컴퓨터는 수행

  • 특정 trigger로 시작~종료되기까지의 흐름 존재
  • 컴퓨터는 이 흐름을 상황별로 제어해야 함

Flow Control(제어 흐름, 흐름 제어)
: 명령형 프로그램의 개별 명령문, 명령 또는 함수 호출이 실행되거나 평가되는 순서

  • 5가지 제어 흐름의 종류
    • goto : 다른 구문에서 시작
    • choice : 일부 조건이 충족되는 경우에만 일련의 명령문 실행
    • loop : 어떤 조건이 충족될 때까지 일련의 명령문을 0회 이상 실행
    • continue : 현재 실행 구문에서 떨어진 한 구문의 집합을 실행
    • break : 프로그램 실행을 중단

Flow control의 종류

  • goto : 다른 구문에서 시작 <- 오류를 발생시킬수도 있음(권장x)
  • choice : If-else, switch
  • loop : Collection loop, General loop
  • continue : Loop continuation
  • break : Loop early exit, 함수 실행 정지

2) 표현식과 문의 개념

표현식 expression
: 어떤 값으로 이행되는 임의의 유효한 코드 단위

  • 표현식이 평가되면, 새로운 값을 생성하거나 기존 값을 참조
  • 값으로 평가될 수 있는 문은 모두 표현식
  • 리터럴 표현식, 함수 표현식, ...

문 statement
: 프로그램을 구성하는 기본 단위, 최소 실행 단위 (== 명령문)

  • 선언문, 할당문, 제어문, 반복문, 블럭문, ...
  • 블럭문 (block statement)
    • 명령문들을 그룹으로 묶을 수 있는 블럭문
    • 한 쌍의 중괄호로 묶어서 표현
{
	123;
    const foo = 'apple';
    function 함수() {
    	return 1;
    }
}

  • 제어문 (control flow statement)
제어문
choiceIf...else, switch
Loop (iterations)
- Loop early exitbreak
- Loop continuationcontinue
Subroutine exitreturn
Non-local control flowtry...catch, throw, generator, async

  • 반복문 (iteration statement)
반복문
Conditional loopwhile, do...while
General loopfor
Collection loopfor...in, for...of


[1] choice - 조건문

조건문
: 일부 조건이 충족되는 경우에만 일련의 명령문 실행

1) if...else 문

  • 논리조건의 참/거짓에 따라 명령문을 실행해야 할 경우 사용
  • if문의 논리조건에는 true, false로 평가할 수 있는 표현식을 대입 가능
  • 논리조건이 참인 경우, if 블럭문 실행. 거짓인 경우, else 블럭문을 실행
  • 해당 값은 false로 평가(Falsy)
    • false, undefined, null, 0, NaN, ""(empty string)
      -> if...else문

  • else if절을 사용하여, 다수의 조건을 순차적으로 검사할 수 있음

if...else문 - Nested Conditional

  • 실제 로직을 구현할 때, 중첩 if문을 사용할 수도 있음
  • 마틴 파울러의 리팩토링 자료
    • nested conditional지양
    • Guard Clauses 형태로 구현

2) switch 문

  • switch에 명시된 표현식을 평가한 후, 평가된 값과 case 라벨 값을 비교하여 일치하는 case의 명령문을 실행
  • default 작성 - 평가된 값에 해당하는 case문이 없을 경우, default의 명령문이 실행되도록
    ->switch문
  • switch 표현식을 작성, 라벨이 포함된 case절을 작성
  • default문은 라벨없이 작성
const foo = (parameter) => {
	switch (parameter) {
    	case 1:
        	return 1;
        case 2:
        case 3:
        	return 23;
        case 4:
        	return 4;
        default:
        	return 0;
    }
};

foo(3);


[2] Loop - 반복문

1) Conditional loop

조건부 loop

  • 대부분의 프로그래밍 언어에는 일부 조건이 변경될 때까지 루프를 반복하는 구조가 있음
    -> 시작할 때 조건을 평가하는 타입 - 본문 생략가능

  • while문
while (표현식) {
	...명령문...
}

-> 마지막에 조건을 평가하는 타입 - 본문은 한번 이상 실행

  • do...while문
do {
	...명령문...
} while(표현식);

ㅁ 조건부 loop - 주의사항※

  • 종료될 수 있는 조건이 아닌경우, 무한 루프에 빠질 수 있음
  • 조건문 작성시 주의

2) For loop

전통적인 for loop

  • 특정 부분의 코드가 반복적으로 수행될 수 있도록 함
  • 언어별로 지원하는 형식이 있음

(1) [초기화-조건식-증감문]의 형식

  • C언어에서 유래한 문법
  • while문과는 다르게, 해당 루프와 관련된 loop 변수 존재
    • loop 변수의 비교 및 증감을 위한 별도 문법을 명시 필요
    • ==loop 변수를 활용하여 명시적으로 카운트를 관리 필수
for([초기문]; [조건문]; [증감문]) {  //세미콜론으로 구분
	...
}
    • 초기문 : loop 내에서 사용할 loop변수를 초기화
    • 조건문 : loop 내 코드 실행 전, 조건을 평가하여 loop를 지속할지 판단
    • 증감문 : loop 내 코드 실행 후, 실행되는 문장 (루프변수 증감 용도)



(2) Collection loop (Foreach 루프)

  • 컬렉션 안의 항목들을 횡단하는 제어흐름문
  • For 문과 다르게, 명시적으로 카운터(루프변수)를 관리하지 않음
  • 잠재적인 순환 횟수 오류를 예방 (off-by-one error)
    • 코드를 더 단순하게 읽힐 수 있게 해줌
  • 자바스크립트 collection loop
  • for...of문
    • 반복 가능한 객체(iterator)를 통해 반복하는 루프를 만듦
for([변수] of [object]) {
 	... 
 }

-> 변수는 반복 가능한 객체의 값을 반환
-> 반복 가능한 객체 : Array, Set, String, ...


  • for...in문
    • 객체의 열거속성(enumerable)을 통해 지정된 변수를 반복
for([변수] in [object]) {
 	... 
 }

-> 변수는 객체의 key값을 반환



3) break문, continue문

break문

  • 제어흐름의 종류 중 프로그램 실행 중단 종료
  • 반복문, switch문을 종료시킬 때 사용
  • 가장 가까운 while, do-while, for, switch문을 종료하고, 다음 명령어로 넘어감
const foo = () => {
	for (let count = 0; count < 3; count++) {
    	console.log(count);
        break;
    }
};

foo();

continue문

  • 제어흐름의 종류 중 현재 실행 구문에서 떨어진 한 구문의 집합을 실행 종류에 속함
  • while, do...while, for문을 다시 시작하기 위해 사용
  • 가장 안쪽의 while, do-while, for문을 둘러싼 반복을 종료하고, 다음 loop를 실행
  • 전체 루프 실행을 종료하지 않음
    • while : 조건문으로 이동
    • for : 증감문으로 이동
const foo = () => {
	for (let count = 0; count < 3; count++) {
    	console.log(count);
        continue;
        console.log('여기');
    }
};

foo();


[3] 예외 처리하기

1) 예외 상황의 종류

예외 상황 Exception

  • 런타임 때 발생할 수 있는 의도치 않은 상황을 뜻
  • 흐름 제어 시 발생할 수 있는 예외 상황이므로, 이를 이해하여 코드 레벨에서 대응해야 함
    • handling : 대응한다는 의미
    • control : 예상하고 직접 조작한다는 의미
  • 예외 상황을 핸들링하지 않는다면, 기능이 동작하지 않거나, 어플리케이션이 shout down될 수 있음

예외의 원인
: 언어 레벨 ~ 외부 요인에 의한 예외 상황까지 다양

  • 코드 레벨에서의 문제
  • 하드웨어, 디바이스의 문제
  • 라이브러리 손상
  • 사용자의 입력 실수
  • ...

예외의 종류

  • ECMAScript Error : 자바스크립트 언어에서 발생하는 Error Type

    • RangeError : 값이 집합에 없거나, 허용 범위가 아닐 때
    • ReferenceError : 존재하지 않는 변수 참조 시
    • SyntaxError : 문법을 지키지 않았을 때
    • TypeError : 값이 기대한 자료형이 아니여서 연산이 불가능할 때
    • ...
  • DOMException : Web API 레벨에서 발생하는 Error Type

    • NetworkError : 네트워크 에러 발생 시
    • AbortError : 작업이 중단되었을 때
    • TimeoutError : 작업 시간이 초과되었을 때
    • ...
  • 그 외의 예외의 종류

    • 개발자도 예상치 못한 예외 상황
    • 개발자가 직접 예외 상황을 예상하여 핸들링할 수 있음
    • 자바스크립트의 Error 객체를 사용하여 직접 에러를 정의내리고 핸들링할 수 있음

2) throw와 Error 객체

throw문
: 예외를 발생시킬 때 사용
-> catch 블럭에서 에러 객체 핸들링

  • 예외를 발생시키기 위해 throw문을 사용
  • throw문 이후의 명령문은 실행되지 않음
const foo = () => {
	console.log(1);
    throw : 여기
    console.log(2);
};

foo();
//  출력은  |  Error: 여기
//         |  1

예외가 발생하면,
1. 현재 함수의 실행이 중지
2. 에러객체와 함께 에러가 throw
3. 제어흐름은
-> 호출자 사이에 catch블록이 있으면, catch블록으로 전달
-> 호출자 사이에 catch블록이 없으면, 프로그램 종료


Error객체

  • 사용자가 직접 Error객체를 정의하여 사용할 수 있음
new Error('에러 메시지')
Error.message
Error.name
  • ECMAScript 표준 내장 오류 유형이 있음

3) try...catch문

에러 catch

예외가 발생하면,

  1. 현재 함수의 실행이 중지
  2. 에러객체와 함께 에러가 throw
  3. 제어흐름은
    -> 호출자 사이에 catch블록이 있으면, catch블록으로 전달
    -> 호출자 사이에 catch블록이 없으면, 프로그램 종료
    • 에러를 catch하여 프로그램이 종료되지 않도록 해야 함
    • 예외 처리를 담당하는 핸들러를 찾기 위해, 순서대로 콜 스택(call stack)을 거슬러 올라가 올바른 핸들러를 찾아내 그 곳에서 처리되도록 함

콜 스택 call stack

  • 스택 자료구조 : 출입구가 하나인 데이터 구조 (First In Last Out)
  • Call stack
    • 자바스크립트 코드가 실행되며 생성되는 실행 컨텍스트를 저장하는 자료구조
    • 함수를 호출할 때마다 스택이 쌓이고, 함수의 실행이 종료되면 콜스택에서 스택을 제거하는 원리
  • 에러 throw되면 콜 스택을 확인하여, 핸들링하고 있는 catch문이 있는 스택에서 처리

try...catch문

  • 블록문 내에서 예외가 발생할 경우, 예외 처리를 맡을 하나 이상의 반응 명령문을 지정
    • try 블록의 명령문 중 하나가 실패하면, catch로 제어권이 넘어감
    • try 블록의 명령문 중 하나가 성공하면, catch로 제어권이 넘어가지 않음
  • catch블럭에서 인자로 throw된 catchID를 참조할 수 있음
try {
	...
}catch(catchID) {
	...
}

-> 콜스택 중 하나에서 catch문에서 예외가 처리된다면, 더 상위의 콜 스택에서는 더 이상 예외가 타고 올라오지 않음


try...catch문의 finally블록

  • finally블록은 try블록에서 예외 상황이 발생하지 않더라도, 실행됨
  • 예외상황이 발생되면: try → catch → finally
  • 예외상황이 발생되지 않으면: try → finally
const foo = (value) => {
	if (value < 3) throw value;
    else console.log(value);
};

const bar = (value) => {
	try {
    	foo(value);
    } catch (catchID) {
    	console.log('catch', catchID);
    	return catchID;
    } finally {
    	console.log('finally');
    }
};

bar(2);

//  출력은  |  'catch' 2
//         |  'finally'

try...catch문 - 사례

  • 외부에서 의존되어 구현된 로직에서 사용 (예기치 못한 상황 대응)
    • network 에러 발생 시
    • 에러를 감지해야 하는 비지니스 로직
      • 비지니스 데이터가 유효하지 않는 경우
    • 유저가 잘못된 데이터를 입력한 경우
    • ...
profile
안녕하세요

0개의 댓글