본문으로 건너뛰기
yceffort
PostsSeriesTagsAbout🧪 Research
EN

Tweaks

theme
accent palette
film grain
minimal mode
BACK TO INDEX
◆ ESSAY
--min
--year
KOoriginal

mailMail icongithubtwitter
yceffort
•
© 2026
•
https://yceffort.kr
BACK TO INDEX
◆ ESSAY

export default를 쓰지 말아야 할 이유

avatar
yceffort
2020-11-09 · 4분
4min
2020year
KOoriginal
typescriptjavascript

export default 구문은 보통 파일 내에서 한개만 export하거나, 대표로 export할 것이 있을 때 많이 쓴다.

function Foo {
  // ...
}

export default Foo
export default function Foo {
  // ...
}

그리고 쓰는 쪽에서는 이렇게 import할 것이다.

import Foo from './foo'

그런데 왜 이것을 않으면 좋은지 몇 가지 이유를 들어서 설득해보자.

Table of Contents

  • 예제
  • 검색이 어렵다.
  • commonjs
  • re-export
  • 다이나믹 import
  • 클래스나 함수가 아니면 한줄이 더 필요함.
  • 리팩토링의 어려움
  • 트리 쉐이킹
  • 결론

예제

foo.ts

export default function Foo() {
  console.log('foo')
}

bar.ts

export function hello() {
  console.log('hello')
}

export function hi() {
  console.log('hi')
}

검색이 어렵다.

import {h} from './bar'

default export를 하게 되면 내보내기가 있는지 여부가 불투명하다.

import {Foo} from 'something'

그러나 기본값이 없으면 코드 intellisense로 내부에 어떤 것을 import 할 수 있는지 쉽게 알 수 있다.

commonjs

default는 commonjs를 쓰는 사람들에게는 혼동을 준다. 위의 default export를 commonjs로 바꾸면

export default function Foo() {
  console.log('foo')
}

module.exports = {
  Foo,
  default: Foo,
}

방식으로 해야하는 어려움이 있다.

re-export

export {default as Foo} from './foo'
export * from './bar'

named export 쪽이 다시 export 하는데 있어서 훨씬 편하다.

다이나믹 import

const foo = await import('./foo')
foo.default()
const {hello} = await import('./bar')
hello()

default 한단계를 더 거쳐야 한다.

클래스나 함수가 아니면 한줄이 더 필요함.

// 이건 안된다
export default const hello = 'hello'

// 이건 가능
export const hi = "hi";
// 이렇게 해야한다.
const hello = 'hello'

export default hello

리팩토링의 어려움

default export는 가져다 쓰는 곳에서 네이밍을 제멋대로 할 수 있으므로, 리팩토링 하기가 어렵다.

import Foo from './foo'
import Wow from './foo'
import Bye from './foo'

위 세개는 모두 동일하게 동작하기 때문에, 오타를 수정하는 등의 작업이 어려워 진다.

트리 쉐이킹

만약 여러개의 object를 하나의 default export로 내보내는 코드가 있다고 가정해보자.

foo.ts

export default {
  foo1: 'foo1',
  bar1: 'bar1',
}

bar.ts

export const bar2 = 'bar2'
export const foo2 = 'foo2'

index.ts

import Foo from './foo'
import {foo2} from './bar'

console.log(Foo.foo1)
console.log(foo2)

이를 트리쉐이킹을 거치게 되면 아래와 같은 결과가 나온다.

var Foo = {
  foo1: 'foo1',
  bar1: 'bar1',
}

const foo2 = 'foo2'

console.log(Foo.foo1)
console.log(foo2)

named exports를 하는게 번들 사이즈를 더 줄이는데 도움을 준다.

결론

그럼에도 불구하고 default export를 쓰는 것을 그만두지는 않을 것 같다. eslint-config-airbnb 만 보더라도 내보낼 것이 한개인 경우에는 default를 쓰는 것을 권장하고 있고 nextjs 등의 라이브러리에서도 default export를 하지 않고서는 할 수 없는 기능들이 더러 있다.

물론 여전히 두 export 방식에 대해서는 논란이 많지만 아무래도 default 가 깔끔한 건 기분 탓일까, 습관 탓일까 🤔

그래도 가급적이면 named exports를 하는 방향으로 코드를 써보자. 그럼에도 default는 죄가 없는 것 같다.

관련 글

  • #javascript#typescript

    ECMAScript 명세 읽어보기 (1)

    가끔 문서를 볼 때 마다 도망쳤던 그 곳

    2020-09-24·10분
  • #typescript#javascript

    자바스크립트 데코레이터

    ## 데코레이터 ### 0. 설명자 데코레이터에 대해 시작하기 전에, 설명자(Descriptor)에 대해 알아보자. 설명자란, 객체의 프로퍼티가 쓰기가 가능한지, 그리고 열거가 가능한지 여부를 나타낸다. 그리고 설명자를 구현하기 위해서는, [Object.getOwnPropertyDescriptor(obj, propName)](https://develo...

    2020-05-20·4분
  • #turbopack#nextjs#bundler

    Next.js turbopack에서 싱글톤이 두 개가 됐다: scope hoisting 버그와 순환 import

    Next.js 16 turbopack 프로덕션 빌드에서 모듈 스코프 싱글톤이 런타임에 두 개가 됐다. 같은 동기 구간에서 조건 판정이 뒤집히고, 응답이 도착해도 타임아웃이 나는 증상을 번들 산출물로 추적한 기록. scope hoisting의 부분 병합, 순환 import, 이미 고쳐져 있던 upstream 버그, 그리고 뒤늦게 돌린 단일 변수 실험까지.

    2026-08-19·28분
  • #javascript#animation#web-animations-api

    number-flow를 구형 브라우저로 이식하기: 다섯 가지 결정과 두 가지 번복

    number-flow가 애니메이션을 켜는 최소 버전은 Chrome 125, Safari 17.2다. 이 하한을 Chrome 66과 WebKit 16.4까지 내리는 포크를 만들면서 내린 결정들과, 뒤집게 된 판단 두 가지, 그리고 자동 강등을 포기한 Safari 버그 조사의 기록.

    2026-08-11·44분

새 글을 놓치고 싶지 않으시다면 RSS로 구독해 주세요.

RSS 구독 →

yceffort — 프론트엔드 엔지니어입니다. 발표·기술 자문·기고 문의는 이곳에서 받고 있습니다.

← Back to the blogIssue on GitHub →