JavaScript의 export가 가지는 진짜 의미
JavaScript의 export는 종종 이렇게 이해된다.
다른 파일에서 쓰기 위해 붙이는 키워드
하지만 이 설명만으로는 왜 export라는 개념이 필요한지, 왜 어떤 것은 외부로 드러내고 어떤 것은 내부에 남겨두는지, 그리고 왜 때로는 파일을 굳이 쪼개지 않는 선택이 나오는지를 충분히 설명하기 어렵다.
이 글은 문법 사용법을 정리하려는 목적이 아니다. JavaScript의 export를 하나의 기능이 아니라 설계 의사결정의 결과로 바라보는 관점에 대해 이야기해보려 한다.
접근 제어자는 왜 존재하는가
대부분의 프로그래밍 언어에는 접근 제어자가 존재한다.
public
private
protected
이 키워드들은 단순히 보이게 하거나 숨기기 위한 장치가 아니다. 핵심은 누가 이 코드에 의존해도 되는지를 명확히 하는 데 있다. 조금 더 풀어 말하면, 무엇은 비교적 자유롭게 바뀔 수 있고 무엇은 신중하게 다뤄져야 하는지를 구분하기 위한 장치다.
public으로 선언된 요소는 외부 코드가 의존해도 괜찮다는 의미를 가진다. 반대로 private은 내부 구현으로, 언제든 변경될 수 있다는 전제를 담고 있다. 결국 접근 제어자는 가시성의 문제가 아니라 변경 가능성을 통제하기 위한 도구라고 볼 수 있다.
JavaScript에는 접근 제어자가 없다, 대신 export가 있다
JavaScript에는 public이나 private와 같은 키워드가 없다. 대신 모듈 시스템이 있고, 그 중심에 export가 있다.
export function foo() {}
이 선언은 단순히 다른 파일에서 사용할 수 있다는 의미로 끝나지 않는다. 이 함수는 외부에 대해 책임지는 API이며, 외부 코드가 의존해도 되는 안정적인 경계라는 신호에 가깝다.
반대로 다음과 같은 함수는 전혀 다른 성격을 가진다.
function internalFoo() {}
이 함수는 외부에서 알 필요가 없는 내부 구현이다. 언제든 변경될 수 있고, 그 변경에 대해 외부 코드는 기대를 가져서는 안 된다. JavaScript에서 모듈은 하나의 캡슐화 단위가 되며, export는 그 경계를 드러내는 역할을 한다.
export는 계약이다
다음 두 코드는 문법적으로는 동일하지만, 전달하는 설계적 의미는 다르다.
export function process() {}
export function normalizeUserPayload() {}
process라는 이름은 내부 구현처럼 느껴진다. 이 함수가 무엇을 처리하는지, 외부에서 어떤 기대를 가져야 하는지가 명확하지 않다. 반면 normalizeUserPayload는 함수의 역할과 책임을 비교적 분명하게 드러낸다.
이 차이는 export된 이름이 단순한 식별자가 아니라 공개된 언어(public vocabulary)라는 점에서 비롯된다. 외부와 공유되는 개념이기 때문에, export된 식별자는 자연스럽게 설계 문서와 비슷한 역할을 하게 된다.
그래서 내부 변수나 함수는 비교적 자유로운 이름을 가져도 되지만, 외부로 노출되는 이름만큼은 길어지더라도 의도가 충분히 드러나는 편이 좋다. 이는 스타일의 문제가 아니라 계약을 명확히 하기 위한 선택에 가깝다.
파일을 나누는 기준에 대해
기능이 늘어날수록 파일을 계속 쪼개는 구조를 흔히 볼 수 있다. 하지만 파일 분리는 그 자체가 목적이 될 수 없다. 설계 관점에서 더 중요한 것은 변경이 함께 일어나는 단위가 무엇인지다.
여러 함수가 항상 함께 수정되고, 외부에서는 하나의 개념으로 사용된다면 한 파일에 남겨두는 편이 오히려 더 안정적인 구조가 된다. 파일을 나누지 않는 선택 역시, export를 최소화하는 선택과 마찬가지로 의도적인 경계 설정의 결과다.
소프트웨어 설계 원칙과의 연결: Information Hiding
이 관점은 새로운 개념은 아니다. 소프트웨어 설계 원칙 중에는 Information Hiding(정보 은닉)이라는 오래된 원칙이 있다. 구현의 세부사항을 숨기고, 외부에는 안정적인 인터페이스만을 노출하라는 생각이다.
JavaScript의 export는 이 Information Hiding을 모듈 단위에서 실천할 수 있게 해주는 수단이라고 볼 수 있다. export되지 않은 코드는 자연스럽게 숨겨진 구현이 되고, export된 요소만이 외부와의 인터페이스로 남는다.
다만 JavaScript에서는 이 경계가 문법적으로 강제되지 않기 때문에, 무엇을 노출하고 무엇을 숨길지에 대한 판단이 설계자의 몫으로 남는다. 어떤 요소를 export할지 결정하는 과정 자체가, 어떤 부분을 안정적인 계약으로 삼을지를 정하는 일과 맞닿아 있다.
정리
JavaScript의 export는 파일 간 코드를 공유하기 위한 문법을 넘어, 설계자가 의도적으로 그은 경계에 가깝다. 모듈은 캡슐화 단위가 되고, export는 외부와의 인터페이스를 정의하며, 네이밍은 그 의도를 설명하는 언어가 된다.
이 관점은 코드를 평가하거나 비교하기 위한 기준이 아니라, 코드를 어떻게 바라보고 유지해 나갈지에 대한 하나의 참고점으로 작용할 수 있다.