표현식 expression
표현식(Expression)은 자바스크립트에서 값으로 평가되는 코드의 일부입니다. 즉, 표현식은 어떤 값으로 평가될 수 있는 모든 코드 단위를 말합니다. 예를 들어, 숫자, 문자열, 연산자의 조합, 함수 호출, 객체 접근 등이 표현식이 될 수 있습니다.
// 리터럴 표현식
const number = 42; // 여기서 42는 숫자 리터럴 표현식입니다.
// 문자열 리터럴 표현식
const greeting = "Hello, World!"; // "Hello, World!"는 문자열 리터럴 표현식입니다.
// 산술 표현식
const sum = 10 + 32; // 10 + 32는 두 숫자를 더하는 산술 표현식입니다.
// 함수 표현식
const square = function(x) {
return x * x;
}; // function(x) { return x * x; }는 함수 표현식입니다.
// 함수 표현식을 사용한 호출
const squaredValue = square(5); // square(5)는 표현식이며, 여기서 5는 함수 square에 전달됩니다.
// 객체 리터럴 표현식
const book = {
title: "1984",
author: "George Orwell"
}; // { title: "1984", author: "George Orwell" }는 객체 리터럴 표현식입니다.
// 배열 리터럴 표현식
const array = [1, 2, 3, 4, 5]; // [1, 2, 3, 4, 5]는 배열 리터럴 표현식입니다.
// 조건 표현식
const eligibility = age > 18 ? 'Adult' : 'Minor'; // age > 18 ? 'Adult' : 'Minor'는 조건 표현식입니다.
문 statement
- 문이란, 프로그램을 구성하는 기본 단위이며, 최소 실행 단위입니다.
- 예로는 명령문, 할당문, 제어문, 반복문, 반환문 등이 있습니다.
choice - 조건문
일부 조건이 충족되는 경우에만 일련의 명령문 실행
- if...else문 - Nested Conditional
- 실제 조건은 구현할 때, 중첩 if문을 사용할 수 있다.
- 미터 파라다임의 리팩토링 자료
- nested conditional 지양
- Guard Clauses 형태로 구현
코드 예시
Before
- 중첩된 if...else 문을 사용하여 조건에 따라 다른 값을 반환합니다.
const 조건1 = (입력) => 입력 === 1;
const 조건2 = (입력) => 입력 === 2;
const 함수 = (입력) => {
if (조건1(입력)) {
return 1;
} else if (조건2(입력)) {
return 2;
} else {
return 3;
}
};
함수(2); // 반환값은 2
After
- Guard Clauses를 사용하여 보다 간결하게 표현된 코드입니다.
const 조건1 = (입력) => 입력 === 1;
const 조건2 = (입력) => 입력 === 2;
const 함수 = (입력) => {
if (조건1(입력)) return 1;
if (조건2(입력)) return 2;
return 3;
};
함수(2); // 반환값은 2
이와 같은 리팩토링은 코드의 가독성을 향상시키고, 유지보수를 용이하게 하는 데 도움을 줍니다. if...else문을 중첩하지 않고 각 조건을 명확하게 분리하여 처리하는 것이 좋은 패턴 중 하나입니다.
switch문
- switch와 평가식을 작성하고,
- 라벨이 포함된 case절을 작성
- switch ( 평가식 ) {
- case 라벨:
- 명령문...
- default:
- 명령문...
- case 라벨:
- }
- switch ( 평가식 ) {
- default문은 라벨에 없이 실행한다.
코드 예시는 switch 문을 사용하여 parameter에 따라 다른 값을 반환하는 함수 foo를 보여줍니다. foo(3)을 호출했을 때 23이 반환되는 것을 볼 수 있습니다.
주의사항: 라벨별로 return이나 break를 작성하지 않으면 switch 문은 종료되지 않습니다. 예를 들어, case 2: 다음에는 명령문이 없으므로, 바로 case 3:의 명령문이 실행되어 23을 반환합니다. 이를 통해 switch 문 안에서 특정 case 절이 실행된 후에 다음 case 절로 넘어가지 않도록 하려면, 명시적으로 case 명령문의 마지막에 return 또는 break 문을 작성해줘야 합니다. 이러한 동작은 "fall through"라고 하며, 때로는 의도적으로 사용되기도 하지만, 실수로 인해 버그가 발생할 수도 있으므로 주의가 필요합니다.
조건부 loop
- 시작할 때 조건을 평가하는 타입
- 루프를 실행하기 전에 조건을 검사합니다.
- 이러한 루프는 보통 while 루프로 알려져 있습니다.
- 흐름도는 시작 지점에서 조건을 평가하고, 조건이 true일 경우 명령문을 실행한 후 다시 조건을 평가하는 과정을 반복합니다. 만약 조건이 false가 되면 루프를 종료합니다.
마지막에 조건을 평가하는 타입
- 루프를 한 번 실행한 이후 실행
- 루프 내부의 명령문을 먼저 실행하고, 그 후에 조건을 검사합니다.
- 이러한 루프는 do...while 루프에 해당합니다.
- 흐름도는 루프가 시작될 때 바로 명령문을 실행하고, 그 다음 조건을 평가하여 true일 경우 루프를 계속하고, false일 경우 루프를 종료합니다.
두 루프의 주된 차이점은 루프의 명령문이 최소 한 번 실행될지 여부입니다. while 루프는 조건이 처음부터 거짓이면 내부 명령문이 단 한 번도 실행되지 않을 수 있지만, do...while 루프는 조건의 참/거짓 여부와 상관없이 최소 한 번은 실행됩니다.
*Collection loop - for...of
- 반복 가능한 객체(iterator)를 통해 반복하는 루프를 모델링한다.
- for ([변수] of [object]) { ... }
- 반복하는 변수는 반복 가능한 객체의 값을 반복한다.
- 반복 가능한 객체: Array, Set, String 등
for...of 문은 컬렉션의 각 요소에 대해 반복을 수행합니다. 이 구문은 배열, 문자열, 세트(Set) 등, Iterator 인터페이스를 구현하는 어떤 객체에 대해서도 사용할 수 있습니다.
코드 예시:
첫 번째 예시에서는 문자열 'apple'의 각 문자를 순회하며 출력합니다.
const foo = 'apple';
for (const i of foo) {
console.log(i); // 'a', 'p', 'p', 'l', 'e' 순서로 출력
}
두 번째 예시에서는 Set 객체에 'apple', 'banana'를 추가한 후 각 요소를 순회하며 출력합니다.
const foo = new Set();
foo.add('apple');
foo.add('banana');
for (const i of foo) {
console.log(i); // 'apple', 'banana' 순서로 출력
}
for...of 루프는 컬렉션의 각 요소를 쉽고 직관적으로 다룰 수 있게 해주는 효율적인 방법을 제공합니다.
*Collection loop - for...in
- 객체의 열거 가능한(enumerable) 속성에 대해 지정된 변수로 반복한다.
- for ([변수] in [object]) { ... }
- 반복하는 변수는 객체의 key값을 반복한다.
for...in 루프는 객체의 모든 열거 가능한 속성을 통해 반복하며, 각 반복에서 객체의 키(key)를 변수로 사용합니다. 이는 객체의 속성을 통해 반복적인 작업을 수행할 때 유용합니다.
코드 예시:
- 객체 foo에는 'apple'과 'banana'라는 키가 있으며, 각각의 키에는 각각의 이모지가 값으로 할당되어 있습니다.
const foo = {
apple: '🍎',
banana: '🍌'
};
for (let key in foo) {
console.log(key); // 'apple', 'banana' 순서로 출력됩니다.
}
break문,continue문
break문
제어흐름의 종류 중 프로그램 실행 중단
반목문,switch문을 종료시킬 때 사용
가장 가까운 while,do-while,for,switch문을 종료하고 다음명령어로 넘어간다.
continue문
제어흐름의 종류중 현재 실행 구문에서 떨어진 한 구문의 집합을 실행
while,do...while,for문을 다시 시작하기 위해 사용한다.
가장 안쪽의 while,do...while,for문을 둘러싼 반복을 종료하구, 다음 loop를 실행한다.
전체 루프 실행을 종료하지 않는다.
while : 조건문으로 이동
for : 증감문으로 이동
예외의 종류
예외 상황 Exception
런타임 때 발생할 수 있는 의도치 않는 상황을 뜻한다.
*예외 처리
외부에 의존되어 구현된 로직에서 사용(예기치 못한 상황 대응)
ex) network 에러 발생
ex) 에러를 감지해야 하는 비즈니스 로직 (비즈니스 데이터가 유효하지 않는 경우)
ex) 유저가 잘못된 데이터를 입력한 경우
ECMAScript Error
- RangeError: 정해진 범위를 벗어난 값을 사용할 때 발생합니다. 예를 들어, 유효 범위를 초과하는 배열 길이 등을 지정했을 때 발생합니다. (new Array(-1); 예시에서는 유효하지 않은 배열 길이 때문에 발생합니다.)
- ReferenceError: 존재하지 않는 변수를 참조할 때 발생합니다. (foo; 예시에서 foo가 정의되지 않았기 때문에 발생합니다.)
- SyntaxError: 코드 구문이 잘못되었을 때 발생합니다. 예를 들어, 코드 작성 시 구문 규칙을 따르지 않았을 때 발생합니다. (const a = 예시에서는 구문이 완성되지 않아 발생합니다.)
- TypeError: 변수나 매개변수가 예상한 타입이 아닐 때 발생합니다. 예를 들어, 상수에 값을 재할당하려고 할 때 발생합니다. (const a = 1; a = 2; 예시에서 상수 a에 새 값을 할당하려 했기 때문에 발생합니다.)
DOMException
- NetworkError: 네트워크와 관련된 에러 발생 시. 예를 들어, 요청이 네트워크 문제로 인해 도달할 수 없을 때 발생합니다.
- AbortError: 작업이 강제로 중단될 때. 예를 들어, 사용자가 파일 다운로드를 중단하거나 요청을 취소했을 경우 발생합니다.
- TimeoutError: 작업 시간이 초과되었을 때. 서버로부터 응답을 받는 데 필요한 시간이 설정된 시간을 초과할 때 발생합니다.
*throw문
- 예외를 발생시키기 위하여 throw 문을 사용한다.
- throw 표현식
- throw문은 이후의 명령문을 실행하지 않는다.
코드 예시 설명:
const foo = () => {
console.log(1); // '1'을 출력
throw '에러'; // '에러'라는 예외를 발생시키고, 이후 코드는 실행되지 않음
console.log(2); // 이 코드는 실행되지 않음
};
foo(); // 함수 호출 시 '1' 출력 후 '에러' 예외 발생
throw 문을 사용하면 개발자가 의도적으로 오류 상황을 만들어 예외 처리 로직을 테스트하거나 필요한 시점에 프로그램의 실행 흐름을 중단시킬 수 있습니다. 이는 오류 처리와 프로그램의 안정성 관리에 매우 중요한 기능입니다.
*Error 객체
- 사용자가 직접 Error 객체를 생성하여 사용할 수 있다.
- new Error('에러 메시지'): 새로운 에러 객체를 생성하며, 에러 메시지를 지정할 수 있습니다.
- Error.message: 에러 객체의 메시지를 저장하는 속성입니다.
- Error.name: 에러 객체의 이름을 저장하는 속성입니다.
- ECMAScript 표준 내장 오류 유형 외에 사용할 수 있다.
코드 예시 설명:
const foo = () => {
console.log(1); // '1'을 출력
const customError = new Error(); // 새로운 Error 객체 생성
customError.name = 'ErrorName'; // 에러 이름 설정
customError.message = '에러메시지'; // 에러 메시지 설정
throw customError; // 설정한 에러 객체를 throw하여 예외 발생
console.log(2); // 이 코드는 실행되지 않음
};
foo(); // 함수 호출 시 '1' 출력 후 '에러메시지'가 포함된 에러 발생
*try...catch문
- 예외가 발생하면:
- 현재 함수의 실행이 중지되며,
- 예외처리와 함께 예외가 throw 됩니다.
- 시스템은:
- 호출 스택에 catch 블록이 있으면, catch 블록으로 진행합니다.
- 호출 스택에 catch 블록이 없으면, 프로그램 종료.
- 예외를 catch 하여 프로그램이 종료되지 않도록 해야 합니다.
- 예외 처리를 담당하는 핸들러는 호출 스택을 거슬러 올라가 모든 관련 호출을 찾아내고 그 과정에서 처리되도록 합니다.
try...catch의 중요성: try...catch 구문은 예외 상황에서 프로그램의 안정성을 유지할 수 있게 해줍니다. 예외가 발생했을 때 적절한 에러 처리를 통해 사용자에게 오류 정보를 제공하거나, 프로그램이 완전히 중단되는 것을 방지할 수 있습니다. 예외 처리는 예상치 못한 에러에서부터 프로그램을 보호하고, 데이터 손실을 방지하며, 사용자 경험을 개선하는 데 필수적인 요소입니다.
콜 스택(call stack)
- 스택 자료구조:
- 후입선출(FILO, First In Last Out) 방식을 따르는 데이터 구조입니다. 마지막에 들어간 것이 가장 먼저 나오는 방식으로 동작합니다.
- Call stack:
- 자바스크립트 엔진은 코딩된 함수를 실행할 때 콜 스택을 사용하여 함수 호출들을 관리합니다.
- 함수 호출은 스택에 "푸시(push)"되어 기록되고, 함수의 실행이 완료되면 "팝(pop)"되어 스택에서 제거됩니다.
- 예외가 발생하면, 콜 스택은 현재 실행 중인 함수에서 시작하여 예외를 처리할 수 있는 catch 블록을 찾기 위해 스택을 거슬러 올라갑니다.
- 예외 throw 시:
- 콜 스택을 확인하고, 핸들링할 수 있는 catch 블록이 있는 스택에서 찾기 시작합니다.
- 적절한 catch 블록을 찾으면, 그 지점에서 예외 처리를 시작하고, 찾지 못하면 프로그램은 오류를 발생시키고 종료됩니다.
try...catch문의 finally 블록
- finally 블록은 try 블록에서 예외가 발생하든 발생하지 않든, 실행됩니다.
- 예외가 발생한 경우: try → catch → finally
- 예외가 발생하지 않은 경우: try → finally
finally 블록은 주로 자원을 해제하거나, 실행해야 할 필수적인 정리 작업을 보장하기 위해 사용됩니다. 예외 처리가 끝난 후에도 반드시 실행되어야 하는 코드를 포함시키기에 적합합니다.
코드 예시 설명:
const foo = (value) => {
if (value < 3) throw value; // 3 미만의 값에서는 예외 발생
else console.log(value); // 그 외의 값에서는 값을 출력
};
const bar = (value) => {
try {
foo(value); // foo 함수를 호출
} catch (catchId) {
console.log('catch', catchId); // 예외 발생 시 catch 블록 실행
return catchId; // 예외 발생한 값 반환
} finally {
console.log('finally'); // 최종적으로 항상 실행
}
};
bar(2); // 'catch 2'와 'finally'가 출력되며, 최종 반환값은 2
'클라우딩 어플리케이션 엔지니어링 TIL > 4주차' 카테고리의 다른 글
[파트07] 언어가 갖고 있는 매커니즘 (0) | 2024.05.02 |
---|---|
[파트06]데이터처리 > 객체와빌트인객체 (0) | 2024.05.02 |
[파트3] 데이터와 형태 (0) | 2024.04.29 |
[파트2] JavaScript 입문 (0) | 2024.04.29 |