[js] 모듈

·2022년 10월 24일
0

개발 기록

목록 보기
36/68

모듈이란?

애플리케이션을 구성하는 개별적 요소로서 재사용 가능한 코드 조각

모듈을 사용하면 다음의 장점을 얻을 수 있다.

1. 유지 보수성
관련된 기능끼리 모듈화시키면 다른 코드와의 결합도를 줄일 수 있다. 기능을 유지 보수할 때 다른 코드에 영향을 덜 미치기 때문에 훨씬 편하게 할 수 있다.

2. 네임스페이스화
모듈은 모듈만의 네임스페이스(모듈 스코프)를 가진다. 전역 공간을 사용하며 전역 변수가 중복되는 등의 문제를 해결할 수 있다.

3. 재사용성
모듈로 분리하면 반복되는 코드를 제거하고 재사용할 수 있다.

  • 결합도
    소프트웨어 코드의 한 요소가 다른 것과 얼마나 강력하게 연결되어 있는지, 얼마나 의존적인지를 나타내는 정도
  • 응집도
    프로그램의 한 요소가 해당 기능을 수행하기 위해 얼마만큼의 연관된 책임과 아이디어가 뭉쳐있는지를 나타내는 정도

IIFE

즉시 실행 함수 표현
Immediately Invoked Function Expression

var math = math || {}; // math 네임스페이스

(function () {
  function sum(a, b) {
    return a + b
  }
  math.sum = sum // 네이스페이스에 추가
})()

이렇게 즉시 실행 함수를 사용해 math에 sum 메서드를 등록했다. 즉시 실행 함수는 선언과 동시에 실행되고 사라졌기 때문에 더 이상 참조할 수 없다. sum 함수를 더 이상 참조할 수 없게 된 것이다. 하지만 math에 등록되어 있으므로 math.sum()으로 사용할 수 있다.
이렇게 즉시 실행 함수를 사용해 전역 공간에 변수, 함수를 선언하는 것을 방지할 수 있다.

CommonJS, AMD, UMD

자바스크립트를 브라우저 환경 밖에서 범용적으로 사용하기 위해 제안된 모듈 시스템이 CommonJS와 AMD이다.
node.js는 사실상 표준인 CommonJS를 채택했고 현재는 동일하진 않지만 기본적으로 CommonJS 사양을 따르고 있다.
AMD는 CommonJS 그룹에서 의견이 맞지 않아 나온 사람들이 만든 그룹으로 비동기 모듈에 대한 표준안을 다루는 그룹이다. AMD는 브라우저 쪽에서 더 큰 효과를 발휘한다.
UMD는 CommnJS와 AMD를 통합하기 위한 하나의 패턴이라고 볼 수 있다.

나는 아래에 얘기할 ESM을 사용하기 때문에 사실 위 모듈 방식들은 잘 모르겠다. 특히 AMD와 UMD는 쓰는 곳을 본 적이 없다. CommonJS의 경우에는 node.js를 사용할 때 사용해 본 적이 있어 기본적으로 require, export.moudules를 사용한다는 것까지 알고 있다.

ESM(ES6 module)

exportimport 구문을 사용하는 방식으로 script 태그에 type="module"어트리뷰트를 추가하면 로드된 자바스크립트 파일은 모듈로서 동작한다. 기본적으로 strict mode가 적용된다.

named export

  • 모듈이 export 한 이름으로 동일하게 import 해야 한다.
  • import 시에 {}를 적어줘야 한다.
export class User {...}	
...	
import {User} from 

default export

  • '해당 모듈엔 개체가 하나만 있다'라는 사실을 명확히 나타낼 수 있다.
  • import 시에 {}를 적지 않아도 된다.
  • default 키워드는 var, let, const 키워드와 함께 사용할 수 없다.
  • import 시에 원하는 대로 이름을 정해 줄 수 있다.
export default class User {...}
...
import User from
  • default로 내보낼 개체엔 이름이 없어도 괜찮다.
export default class { // 클래스 이름이 없음
  constructor() { ... }
}
  
export default function(user) { // 함수 이름이 없음
  alert(`Hello, ${user}!`);
}

named export와 default export를 같은 모듈에서 사용

사용할 순 있지만 이렇게는 잘 사용하지 않는다.

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

export function sayHi(user) {
  alert(`Hello, ${user}!`);
}
...
import {default as User, sayHi} from './user.js';
  • 함께 써도 *을 이용해 한 번에 가져올 수 있다. 이 경우에 default 프로퍼티를 통해 default 키워드로 export 한 개체를 사용할 수 있다.
import * as user from './user.js';

let User = user.default; // default export
new User('John');

모듈 다시 내보내기

가져온 개체를 즉시 다시 내보내기 할 수 있다.

export {sayHi} from './say.js'; // sayHi를 다시 내보내기 함

export {default as User} from './user.js'; // default export를 다시 내보내기 함

index.js 사용

진입점 역할을 하는 index.js를 사용하면 경로에 디렉터리 명만 적어도 자동으로 index.js를 찾는다. auth/index.js로 적지 않고 auth만 적어도 동일하게 동작한다. 때문에 index.js를 통해 다시 내보내기를 하면 사용하는 곳에서는 디렉터리 내부 구조를 몰라도 import를 할 수 있게 된다.

import {login} from "./auth/index.js";
import {login} from "./auth"; //위와 동일함

default export 다시 내보내기

default export를 다시 내보낼 때 주의사항이 있다.

  • export {default as User}를 사용해야 한다.
export {default as User} from './user.js';
  • *을 사용할 경우에는 named export만 다시 내보내진다. default export도 따로 내보내기 해줘야 한다.
export * from './user.js'; // named export를 다시 내보내기
export {default} from './user.js'; // default export를 다시 내보내기

참고자료

0개의 댓글