Shim은 자바스크립트 실행 환경이 특정 기능이나 API를 기본적으로 지원하지 않을 때, 그 기능을 흉내 내어 동작하게 만드는 코드입니다. 주로 레거시 브라우저나 오래된 Node.js 런타임에서 최신 웹 표준을 에뮬레이션할 때 사용됩니다. 하지만 Shim은 잘못 설계될 경우 성능 저하, 충돌, 유지보수 어려움이 발생할 수 있기 때문에 최적화가 필수입니다. 이 글에서는 실무에서 유용한 Shim 코드 최적화 기법을 정리합니다.
조건부 로딩과 존재 여부 검사
Shim의 핵심 목적은 ‘없는 기능을 대신 제공’하는 것이므로, **기능이 이미 있는 경우에는 건드리지 않아야** 합니다. 이를 위해 가장 기본적인 패턴이 바로 "존재 여부 검사"입니다:
if (!window.Promise) {
// Promise Shim을 로드하거나 구현
}
Shim을 작성할 때는 항상 **기능 탐지(Feature Detection)**를 먼저 수행해야 하며, 이를 위해 Modernizr 같은 도구를 사용할 수도 있습니다. 조건부 로딩은 성능을 향상시킬 뿐 아니라, 최신 브라우저에서 Shim 코드가 오히려 기능을 덮어쓰는 문제를 방지해줍니다.
또한 동적으로 Shim을 로드하는 방식도 고려할 수 있습니다. 예:
if (!window.fetch) {
import('./shim/fetch.js').then(() => {
console.log('Fetch Shim 로드됨');
});
}
이 방식은 초기 로딩 속도에 부담을 주지 않고, 필요한 시점에만 Shim을 불러올 수 있어 성능적인 이점이 있습니다.
최소 범위 오염 및 모듈화
Shim은 글로벌 객체나 기본 프로토타입을 수정하게 되므로, 자칫하면 다른 코드와 충돌하거나 예기치 않은 부작용을 초래할 수 있습니다. 이를 방지하기 위한 가장 중요한 전략은 **모듈화와 네임스페이스 분리**입니다.
예를 들어, 직접 전역 객체를 수정하기보다는 Shim 함수를 별도로 정의하고 선택적으로 사용할 수 있도록 만듭니다:
function defineCustomBind(obj) {
if (!obj.bind) {
obj.bind = function(fn) {
// 사용자 정의 bind 구현
};
}
}
defineCustomBind(Function.prototype);
또는 모듈 번들링 도구(Webpack, Rollup)를 활용해 필요한 Shim만 포함하도록 구성할 수 있습니다. 다음은 예시 Webpack 설정입니다:
// webpack.config.js
module.exports = {
entry: {
main: './index.js',
shim: './shims/es5.js',
},
optimization: {
splitChunks: {
chunks: 'all',
},
},
};
이렇게 Shim을 별도의 번들로 분리하면, 필요할 때만 로드되므로 전체 파일 크기를 줄이고 유지보수도 용이합니다. 또한 외부 라이브러리 Shim(ex: es5-shim, core-js)은 필요한 기능만 가져오도록 tree-shaking이나 커스텀 빌드가 가능하도록 구성하는 것이 바람직합니다.
성능 영향 최소화와 테스트 전략
Shim은 런타임에서 기본 API의 대체 역할을 하므로, 성능에 영향을 줄 수 있습니다. 특히 반복 호출되는 메서드나 루프 안에 있는 코드에 Shim이 개입되면 병목이 발생할 수 있습니다. 이를 방지하기 위한 전략은 다음과 같습니다:
- 최소 구현: 표준 사양의 모든 기능을 구현하기보다는 실제 사용하는 범위만 구현
- 함수 캐싱: 자주 호출되는 내부 함수는 캐싱하여 중복 연산 최소화
- 실행 전 검사: 초기화 시점에만 조건 검사하고, 이후는 빠르게 실행
예를 들어, 배열의 includes
Shim을 구현할 때 다음과 같이 작성할 수 있습니다:
if (!Array.prototype.includes) {
Array.prototype.includes = function(value) {
return this.indexOf(value) !== -1;
};
}
또한 **Shim 코드의 테스트는 일반 유닛 테스트 외에도 호환성 테스트가 필수**입니다. 대표적인 전략은 다음과 같습니다:
- IE11, Edge Legacy, Android WebView 등 실제 레거시 환경 테스트
- Jest, Mocha 등으로 Shim 함수 유닛 테스트 작성
- 라이브 환경 Shim 적용 여부를 자동 확인하는 기능 포함
CI/CD 파이프라인에 브라우저 테스트 환경을 포함시키면, Shim 코드 변경 시 호환성 이슈를 조기에 발견할 수 있어 안정성을 크게 높일 수 있습니다.
Shim은 레거시 브라우저나 미지원 환경에서도 최신 웹 기능을 구현할 수 있게 해주는 유용한 도구입니다. 하지만 무분별한 사용은 코드 중복, 충돌, 성능 저하로 이어질 수 있으므로, 조건부 로딩, 네임스페이스 분리, 성능 고려, 자동화된 테스트 등을 통해 철저하게 최적화하는 것이 중요합니다.