안녕하세요, 개발자 여러분! 오늘은 정말 흥미로운 주제를 가지고 왔어요. 혹시 여러분은 웹팩, 롤업, 파셀 같은 번들러를 사용하면서 '스코프 호이스팅'이라는 최적화 기법에 대해 들어보신 적 있나요?
처음 들으면 뭔가 엄청 좋은 최적화처럼 느껴지는데... 정말 그럴까요? 사실 이 기법에는 우리가 모르는 큰 함정들이 숨어있답니다. 지금부터 하나씩 파헤쳐볼게요! 💡
🔍 스코프 호이스팅이 뭔데?
먼저 스코프 호이스팅이 무엇인지 간단히 알아볼까요?
예를 들어 이런 코드가 있다고 해봅시다:
// math.js
export function add(a, b) {
return a + b;
}
// main.js
import {add} from './math';
console.log(add(2, 3));
번들러가 스코프 호이스팅을 적용하면 이렇게 변해요:
function add(a, b) {
return a + b;
}
console.log(add(2, 3));
각 모듈을 함수로 감싸는 대신, 하나의 스코프에 모든 코드를 합쳐버리는 거죠. 얼핏 보면 번들 크기도 줄어들고 성능도 좋아질 것 같은데요...
💥 문제의 시작: 코드 스플리팅과의 충돌
여기서 문제가 시작돼요. 실제 프로젝트에서는 코드 스플리팅을 많이 사용하잖아요? 여러 페이지가 있고, 공통 라이브러리들(React, lodash 등)을 따로 번들로 분리하는 경우가 많죠.
예를 들어 이런 상황을 생각해보세요:
// entry-a.js
import React from 'react';
import './a1';
import './a2';
// entry-b.js
import React from 'react';
import './b1';
import './b2';
번들러는 똑똑하게 React 같은 공통 의존성을 별도 번들로 분리해줘요. 그런데 여기서 스코프 호이스팅이 문제를 일으켜요!
🚨 가장 심각한 문제: 실행 순서 꼬임
JavaScript 모듈의 가장 중요한 특징 중 하나가 바로 실행 순서예요. 모듈들이 올바른 순서로 실행되어야 하는데, 스코프 호이스팅이 이를 망가뜨리는 경우가 있어요.
실제 예시를 보여드릴게요:
// 원래 실행 순서 (번들링 전)
// shared1 → a1 → shared2 → a2
// 스코프 호이스팅 후
// shared1 → shared2 → a1 → a2
보시다시피 실행 순서가 완전히 바뀌어버려요! 이는 예상치 못한 버그를 일으킬 수 있어요. 특히 모듈에서 전역 상태를 변경하거나 부수 효과(side effect)가 있는 코드들은 심각한 문제가 생길 수 있답니다.
🎯 다른 숨겨진 문제들
this 값이 사라져요!
또 다른 문제는 this 값이 엉뚱하게 바뀌는 거예요:
// 원래 코드
import * as foo from './foo';
foo.bar(); // foo 객체가 this가 됨
// 스코프 호이스팅 후
function bar() {
console.log(this); // undefined가 됨!
}
bar();
모듈 시스템에서 this는 해당 모듈 객체를 가리켜야 하는데, 스코프 호이스팅 후에는 undefined가 되어버려요.
💡 해결책은 있어요!
그렇다면 어떻게 해결할까요?
Parcel의 접근 방식이 흥미로워요. 공유되는 모듈들을 함수로 감싸서 필요할 때 호출하는 방식이에요:
import modules from 'shared.bundle.js';
modules['shared1']();
console.log('a1');
modules['shared2']();
console.log('a2');
Webpack은 조건부 모듈 연결(module concatenation)을 구현해서, 같은 번들 내에서만 안전하게 합칠 수 있는 모듈들만 스코프 호이스팅을 적용해요.
🤔 정말 스코프 호이스팅이 필요할까?
솔직히 말하면... 글쎄요? 🤷♀️
초기에 Rollup이 등장했을 때는 코드 스플리팅이 없었어서 스코프 호이스팅이 유용했어요. 하지만 요즘처럼 복잡한 애플리케이션에서는:
- 실제로 스코프 호이스팅의 혜택을 받는 모듈이 5% 미만
- 대부분의 모듈은 결국 함수로 감싸져야 함
- 복잡성 대비 성능 향상이 미미함
🌟 앞으로의 방향
Parcel v3에서는 아예 스코프 호이스팅을 제거하는 것도 고려하고 있다고 해요. 대신 다른 최적화 기법들에 집중하는 거죠:
- 트리 셰이킹 (Tree shaking)
- 데드 코드 제거 (Dead code elimination)
- 상수 폴딩 (Constant folding)
🎉 마무리하며
개발하다 보면 '최신이고 좋아 보이는' 기술이 항상 정답은 아니라는 걸 느껴요. 스코프 호이스팅도 마찬가지죠. 이론적으로는 좋아 보이지만, 실제 사용해보면 예상치 못한 문제들이 많이 생겨요.
여러분도 새로운 기술을 도입할 때는 항상 신중하게 검토해보세요. 특히 번들러 설정을 만질 때는 더욱 조심스럽게! 🔧
오늘 포스팅이 도움이 되셨나요? 댓글로 여러분의 경험도 공유해주세요!
'기술의기록' 카테고리의 다른 글
Tailwind CSS에서 Grid Template Areas 사용하기 (3) | 2025.08.13 |
---|---|
React Suspense 완전 정복: 비동기 UI의 혁신적 해결책 (10) | 2025.08.09 |
GPT-5 드디어 출시! 🎉 AI의 새로운 전환점이 오다 (3) | 2025.08.08 |
JavaScript Promise, 이제 제대로 알아보자! (4) | 2025.08.07 |
개발자들의 새로운 파트너, Claude Opus 4.1이 드디어 등장했어요! (4) | 2025.08.06 |