티스토리 뷰

▶모듈

모듈은 외부로 공개한 API를 통해서 상태를 변경하고 내부 구현에 대한 캡슐화의 역할을 합니다.

각각의 모듈은 애플리케이션을 구성하는 단위가 하며, 모듈 단위로 재사용하여 불필요한 코드를 줄이고 유지 보수성을 높일 수 있습니다.

 

1) export, import

모듈 안에 선언한 식별자를 다른 모듈에서 접근할 수 있도록 하고 싶다면 export 키워드를 사용하여 내보내기를 하면 됩니다.

함수, 변수, 클래스 모두를 내보낼 수 있으며, 이들은 반드시 모듈의 최상위 위치(top-level)에 존재해야 합니다.

export const a = 1;
export function foo() {
	// ...
}

const b = 1;
function bar() {
	// ...
}

export { b, bar };

function baz() {
	export let c = 'oh'; // Uncaught SyntaxError: Unexpected token 'export'
}

변수 a와 foo() 함수를 개별적으로 내보낼 수도 있고 변수 b와 bar() 함수처럼 객체 형태로 한 번에 내보낼 수도 있습니다.

그리고 baz() 함수의 c처럼 모듈의 최상위 위치가 아닌 곳에서는 내보내기를 할 수 없습니다.

예제 코드처럼 export 키워드를 사용하여 개별 식별자를 내보내는 것은 named exports라고 부릅니다.

 

다른 모듈에서 내보낸 식별자들을 가져오기 위해서는 import 키워드를 사용하며 반드시 파일의 최상단에 위치해야 합니다.

named exports로 내보낸 식별자들은 import 키워드와 중괄호({})로 감싸 가져올 수 있습니다.

 

모듈에서 내보낸 식별자들을 어떻게 가져오는지 예제 코드를 보겠습니다.

/*
 * a.js
 */
 export const a = 1;
 export function foo() {
 	// ...
}

다른 모듈에서 가져올 수 있도록 a.js 모듈에서 변수 a와 foo() 함수를 named exports로 내보냅니다.

/*
 * b.js
 */
 import { a, foo } from './a.js';
 
 console.log(a); // 1

b.js 모듈에서는 중괄호로 감싸 a.js에서 가져올 항목들을 나열합니다.

가져올 항목들 다음에는 from과 모듈 경로를 작성하여 import 문을 작성합니다.

 

또한 모듈이 내보낸 식별자들을 하나의 이름으로 한 번에 가져올 수 있습니다.

이 경우 가져오는 모듈의 식별자들은 as 키워드 뒤에 지정한 객체의 프로퍼티로 할당됩니다.

/*
 * b.js
 */
 import * as all from './a.js';
 
 console.log(all.a); // 1

b.js 모듈에서는 a.js 모듈로 내보낸 식별자들을 all이라는 이름의 객체의 프로퍼티로 할당하여 가져왔습니다.

 

2) default export

모듈을 내보내는 또 다른 방식으로 default export라는 방식이 있습니다.

default export는 export 키워드와 default 키워드를 함께 사용하여 식별자를 내보냅니다.

또한 named exports와는 다르게 모듈에서 하나만 정의할 수 있습니다.

/*
 * a.js
 */
 function foo() {
 	// ...
}
export default foo;

default export로 내보낸 모듈을 다른 모듈에서 사용하는 경우, 중괄호({}) 없이 임의의 이름으로 가져와 사용합니다.

/*
 * b.js
 */
 import bar from './a.js';

a.js 모듈에서 default export로 내보낸 foo() 함수를 b.js모듈에서 bar라는 임의의 이름으로 가져왔습니다.

 

[NOTE]

여러 개의 식별자를 내보낼 때는 default export보단 named exports를 사용하는 것이 좋습니다.

named exports를 사용하면 가져오는 측에서 정적 타입 체크나 IDE의 자동 완성 기능과 같은 이점을 누릴 수 있기 때문에 오타나 잘못된 식별자에 접근하는 문제를 방지할 수 있습니다.

 

/*
 * a.js
 */
export const a = 1;
export const b = 2;

export default { a, b };

/*
 * b.js
 */
 import { a, b }, defaultModuleA from './a.js';
 
 // named exports로 내보낸 모듈은 명확하게 체크하여 가져올 수 있습니다.
 console.log(a, b); // 1, 2
 
 // default export 로 내보내는 경우 가져올 때 잘못된 식별자(defaultModuleA.c)에 접근하는 문제가 발생할 수 있습니다.
 console.log(defalutModuleA.a, defaultModuleA.c); // 1, undefined

 

3) 식별자 충돌 피하기

여러 모듈에서 필요한 식별자를 가져오는 경우 이름이 충돌할 수 있습니다.

이런 경우에는 as 키워드를 사용하여 가져오는 식별자의 이름을 변경할 수 있습니다.

/*
 * a.js
 */
export const a = 1;
export const b = 1;

/*
 * b.js
 */
export const a = 2;
export const b = 2;

/*
 * c.js
 */
import { a as a1 } from './a.js';
import { a as a2 } from './b.js';

c.js 모듈에서는 가져오는 식별자들의 충돌을 막기 위해 as 키워드를 사용하여 각각 a1, a2로 식별자의 이름을 변경하였습니다.

가져오기에서 식별자의 이름을 변경하여 문제를 해결할 수 도 있지만 아래 코드처럼 내보내기를 할 때 식별자의 이름을 변경하여 해결할 수도 있습니다.

/*
 * a.js
 */
export const a = 1;
export const b = 1;

/*
 * b.js
 */
 const a = 2;
 const b = 2;
 
 export { a as a1, b as b1 };
 
 /*
  * c.js
  */
import { a } from './a.js';
import { a1 } from './b.js';

b.js 모듈에서 as 키워드를 사용하여 내보내는 식별자의 이름을 변경하였기 때문에 c.js 모듈에서 이름의 충돌 없이 식별자를 가져올 수 있습니다.

 

4) <script type="module">

정의한 모듈을 브라우저 환경에서 사용하기 위해서는 어떻게 해야 할까요?

script 태그types="module" 속성을 설정하여 모듈임을 명시할 수 있습니다.

이렇게 정의된 파일은 모듈로 인식되어 전역 스코프를 공유하는 것이 아니라 모듈 스코프로 동작합니다.

그렇기 때문에 내보낸 식별자가 아니라면 외부에서 모듈 내의 식별자에 접근할 수 없습니다.

<!DOCTYPE html>
<html>
<body>
	<script type="module" src="a.mjs"></script>
   	<script type="module" src="b.mjs"></script>
</body>
</html>

a.mjs와 b.mjs는 각각 별도의 모듈 스코프로 동작합니다.

만약 type="module" 속성을 명시하지 않는다면 모든 코드는 전역 스코프로 동작하니 모듈로 사용하기 위해서는 해당 속성은 반드시 추가해야 합니다.

 

[NOTE]

mjs 확장자는 해당 자바스크립트 파일이 모듈임을 명시하기 위해 사용합니다.


여기까지 자바스크립트 모듈에 대해 알아보았습니다.

 

정리하자면,

프로토타입, 스코프와 같은 내용들은 자바스크립트 활용 능력을 한 단계 향상시키기 위해 반드시 알아야 할 개념입니다.

프로토타입을 이해해야 객체 프로퍼티에 어떻게 접근하고, 상속은 어떻게 구현할 수 있는지 알 수 있습니다.

나아가 모던 자바스크립트에서 널리 사용하고 있는 class 문법이 내부적으로 어떤 매커니즘을 사용하는지도 쉽게 이해할 수 있는 것입니다.

스코프도 마찬가지입니다.

렉시컬 스코프 규칙과 블록 스코프, 함수 스코프의 특징에 대해 이해해야 호이스팅, 클로저, 모듈 등 파생되는 개념들을 이해할 수 있습니다.

 

728x90
LIST
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함