Named Export와 Default Export의 이해

MacJavaScript

Named Export

Named Export는 모듈에서 여러 개의 변수, 함수, 클래스를 내보낼 때 사용한다. 각각의 내보낸 요소들은 이름을 가지고 있으며, 이를 통해 선택적으로 필요한 부분만 가져올 수 있다.

예를 들면, 다음과 같이 코드를 작성한다.

// utils.js
export const PI = 3.14;

export function add(a, b) {
  return a + b;
}

export class Calculator {
  subtract(a, b) {
    return a - b;
  }
}

위와 같이 export를 하면, 사용하는 곳에서는 아래와 같이 import 할 수 있다.

// main.js
import { PI, add, Calculator } from './utils.js';

console.log(PI); // 3.14
console.log(add(2, 3)); // 5

const calc = new Calculator();
console.log(calc.subtract(5, 2)); // 3

Default Export

Default Export는 모듈에서 단 하나의 기본값을 내보낼 때 사용한다. 모듈당 하나의 Default Export만 가질 수 있으며, 가져올 때 이름을 지정할 수 있다.

아래 처럼 export 하고,

// logger.js
export default function log(message) {
  console.log(message);
}

다음과 같이 import 한다.

// app.js
import log from './logger.js';

log('안녕하세요!'); // 안녕하세요!

주요 차이점

  1. export 개수
    • Named Export: 여러 개 가능
    • Default Export: 모듈 당 하나만 가능
  2. import 문법
    • Named Export: import { name1, name2 } from './module';
    • Default Export: import anyName from './module';
  3. 이름 변경
    • Named Export: import { originalName as newName } from './module';
    • Default Export: 가져올 때 자유롭게 이름 지정 가능
  4. 전체 가져오기
    • Named Export: import * as moduleName from './module';
    • Default Export: 이미 하나의 객체로 취급되므로 전체 가져오기 불필요
  5. 동적 가져오기
    • Named Export: import('./module').then(module => module.namedExport)
    • Default Export: import('./module').then(module => module.default)

언제 어떤 것을 사용해야 할까?

  • Named Export: 모듈에서 여러 개의 유틸리티 함수나 변수를 내보내고, 이를 선택적으로 가져와 사용하고 싶을 때 유용하다.
  • Default Export: 모듈의 주요 기능이나 클래스를 내보낼 때 사용하면 좋다.

index.js 활용

아래와 같이 폴더 구조를 가지고 있는 프로젝트를 살펴보자

Image.png

각 컴포넌트는 아래와 같이 Named Export 되어 있다.

const TestComponent = () => {
  return <div></div>;
};

export { TestComponent };

이를 쓰기 위해서는 다음과 같이 import 해올 것이다.

import { TestComponent } from '@/components/ui/TestComponent.tsx';
import { TestComponent2 } from '@/components/ui/TestComponent2.tsx';

function App() {
  return (
    <div>
      <TestComponent />
      <TestComponent2 />
    </div>
  );
}

export default App;

아래와 같이 index.js(ts) 파일을 만든 뒤 재 export 해보자.

// Named Export
export { TestComponent } from './TestComponent';
export { TestComponent2 } from './TestComponent2';

// Default Export
export { default as TestComponent } from './TestComponent';
export { default as TestComponent2 } from './TestComponent2';

그럼 import 하는 곳에서는 아래와 같이 조금 더 깔끔하게 import 할 수 있다.

import { TestComponent, TestComponent2 } from '@/components/ui';

function App() {
  return (
    <div>
      <TestComponent />
      <TestComponent2 />
    </div>
  );
}

export default App;

index.js 사용시 장단점

장점

  • 디렉토리의 진입점 역할을 하여 모듈 구조를 간단하게 만들 수 있다.
  • 여러 파일의 내용을 하나로 모아 내보낼 수 있어 import 문을 간결하게 만들 수 있다.
  • 디렉토리 구조를 변경하더라도 외부 코드에 영향을 주지 않는다.

단점

  • 너무 많은 내용을 index.js에 모으면 파일이 복잡해질 수 있다.

Avoid Export Default

해당 문서에서는 Export Default를 사용하는 것을 지양하라고 한다. (적어도 타입스크립트 프로젝트에서는?) 주요 이유는 아래와 같다.

이름 변경 미지원

IDE에서 리팩토링 기능을 통해 이름을 변경할 때, 자동으로 변경해주지 않는다. 예를 들어, TestComponent의 이름을 TestComponent2 로 바꿔도, import 하는 부분에서는 바뀌지 않는다. 그러나 Named Export를 사용할 경우는 잘 바꿔준다.

이름 변경의 자유로움으로 인한 일관성 부족

  • default export를 사용하면 가져올 때 아무 이름이나 사용할 수 있어, 같은 모듈을 다른 파일에서 다른 이름으로 사용할 수 있다.
  • 이는 코드의 일관성을 해치고 혼란을 야기할 수 있다.

타입 정보의 부족:

  • default export는 타입 정보를 제공하지 않아, 어떤 타입의 객체나 함수가 내보내지는지 명확하지 않을 수 있다.