본문 바로가기

2022-2 웹개발 스터디

[모던 JS] CH47. 에러 처리, CH48. 모듈

CH47. 에러 처리

47.1 에러 처리의 필요성

- 프로그램이 강제 종료되지 않고 계속해서 코드를 실행시킬 수 있음

 

! 직접적으로 에러를 발생하지는 않는 예외적인 상황이 발생할 수도 있음

: 이 경우 예외적인 상황에 적절하게 대응하지 않으면 에러로 이어질 가능성

const $elem = document.querySelector('#1');
// DOMException
// 인수로 전달한 CSS 선택자 문자열로 DOM에서 요소 노드를 찾을 수 없는 경우
// 에러를 발생시키지 않고 null을 반환함

47.2 try...catch...finally 문

에러 처리를 구현하는 방법

1. querySelector나 Array#find 메서드처럼 예외적인 상황이 발생하면    

   반환값을 if 문이나 단축 평가 또는 옵셔널 체이닝 연산자를 통해 확인해서 처리하는 방법

2. 에러 처리 코드를 미리 등록해두고 에러가 발생하면 에러 처리 코드로 점프하도록 하는 방법

 

! try...catch...finally문은 두 번째 방법

try {
    // 실행할 코드 (에러가 발생할 가능성이 있는 코드)
} catch (err) {
    // try 코드 블록에서 에러가 발생하면 이 코드 블록의 코드가 실행됨
    // err에는 try 코드 블록에서 발생한 Error 객체가 전달됨
} finally {
    // 에러 발생과 상관없이 반드시 한 번 실행됨
}

47.3 Error 객체

- Error 생성자 함수는 에러 객체를 생성함

- 이 함수에는 에러를 상세히 설명하는 에러 메시지를 인수로 전달할 수 있음

 

1. message 프로퍼티

: Error 생성자 함수에 인수로 전달한 에러 메시지

2. stack 프로퍼티

: 에러를 발생시킨 콜스택의 호출 정보를 나타내는 문자열, 디버깅 목적으로 사용함

const error = new Error('invalid');

47.4 throw문

- 에러를 발생시키려면 try 코드 블록에서 throw 문으로 에러 객체를 던져야 함

try {
    // 에러 객체를 던지면 catch 코드 블록이 실행되기 시작함
    throw new Error('something wrong');
} catch (error) {
    console.log(error);
}

47.5 에러의 전파

- throw 된 에러를 캐치하지 않으면 호출자 방향으로 전파됨

- 이 에러를 어디에서도 캐치하지 않으면 프로그램은 강제 종료됨

CH48. 모듈

48.1 모듈의 일반적 의미

- 공개가 필요한 자산에 한정하여 명시적으로 선택적 공개가 가능함 (export)

- 모듈 사용자는 모듈이 공개한 자산 중 일부 또는 전체를 선택해 자신의 스코프 내로 불러들여 재사용할 수 있음 (import)

- 재사용성이 좋아서 개발 효율성과 유지보수성을 높일 수 있음

48.2 자바스크립트와 모듈

- 자바스크립트는 모듈이 성립하기 위해 필요한 파일 스코프와 import, export를 지원하지 않았음

- Node.js는 모듈 시스템을 지원함

48.3 ES6 모듈(ESM)

- 사용 방법: script 태그에 type="module" 어트리뷰트를 추가함

- ESM의 파일 확장자는 mjs 사용

<script type="module" src="app.mjs"></script>

48.3.1 모듈 스코프

- ESM은 독자적인 모듈 스코프를 가짐

// foo.js
// x는 전역 변수
var x = 'foo';
console.log(window.x); // foo

// bar.js
// x는 전역 변수, foo.js에서 선언한 전역 변수 x와 중복된 선언
var x = 'bar';
console.log(window.x); // bar

 

- 아래 예제의 HTML에서 script 태그로 분리되어 로드된 2개의 자바스크립트 파일은

  하나의 자바스크립트 파일 내에 있는 것처럼 동작함 (하나의 전역을 공유)

 

- ESM 모듈 내에서 var 키워드로 선언한 변수는 더는 전역 변수가 아니며 window 객체의 프로퍼티도 아님

- 모듈 내에서 선언한 식별자는 모듈 외부에서 참조할 수 없음( 모듈 스코프가 다름 )

// foo.mjs
var x = 'foo';
console.log(x); // foo
console.log(window.x); // undefined

// bar.mjs
var x = 'bar';
console.log(x); // bar
console.log(window.x); // undefined

48.3.2 export 키워드

- 모듈 내부에서 선언한 식별자를 외부에 공개하여 다른 모듈들이 재사용할 수 있게 하려면 export 키워드 사용

- 선언문 앞에 사용

// lib.mjs
export const pi = Math.PI;

export function square(x) {
    return x * x;
}

export class Person {
    constructor(name) {
        this.name = name;
    }
}


// export 할 대상을 하나의 객체로 구성하여 한 번에 export 하기
const pi = Math.PI;

function square(x) {
    return x * x;
}

class Person {
    constructor(name) {
        this.name = name;
    }
}

export {pi, square, Person};

48.3.3 import 키워드

- 다른 모듈에서 공개한 식별자를 자신의 모듈 스코프 내부로 로드하려면 import

- 다른 모듈이 export한 식별자 이름으로 import해야 하며 ESM의 경우 파일 확장자를 생략할 수 없음

// app.mjs
import {pi, square, Person} from './lib.mjs';


// 한 번에 import 하기
import * as lib from './lib.mjs';


// 식별자 이름 변경하여 import
import { pi as PI, square as sq, Person as P} from './lib.mjs';

 

모듈에서 하나의 값만 export 한다면 default 키워드 사용 가능

- 기본적으로 이름 없이 하나의 값을 export 함

- var, let, const 키워드 사용 불가

- {} 없이 임의의 이름으로 import

// lib.mjs
export default x => x * x;

// const, let, var 사용 불가
export default const foo = () => {}; // SyntaxError


// app.mjs
import square from './lib.mjs';
console.log(square(3)); // 9