
JavaScript 모듈 시스템은 웹 개발에서 효율성과 일관성을 높이는 중요한 기능입니다. 여러
<script> 태그에서 동일한 모듈을 참조하더라도, 모듈은 단 한 번만 실행됩니다. 위 내용은 Javascript Modules(for mdn)에 있는 설명입니다. 하지만.. 놀랍게도 한국어로 번역하면 해당 내용이 사라진답니다.. 궁금하신 분들은 영어 원문으로 확인하시면 아래와 같이 확인할 수 있습니다.
Modules are only executed once, even if they have been referenced in multiple<script>tags.
이는 모듈의 성능을 최적화하고, 일관성을 유지하는 중요한 원칙입니다. 이번 포스팅에서는 이 원리를 다양한 예제와 함께 설명하고, React 환경에서 이 원리를 어떻게 적용할 수 있는지 알아보겠습니다.
모듈의 단 한 번 실행 원리
JavaScript 모듈은 처음 로드된 후 캐싱됩니다. 동일한 모듈을 다시 참조하면, 이미 캐싱된 모듈이 재사용되며, 추가 실행은 발생하지 않습니다. 이 원리는 성능과 메모리 효율성을 크게 향상시킵니다.
예제 1: 모듈의 단 한 번 실행 확인하기
먼저, 간단한 모듈과 이를 여러 곳에서 참조하는 HTML 파일을 만들어보겠습니다.
module.js:console.log('Module is being executed');
export function greet() {
return 'Hello from the module!';
}
index.html:<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Module Execution Example</title>
</head>
<body>
<script type="module" src="module.js"></script>
<script type="module">
import { greet } from './module.js';
console.log(greet());
</script>
<script type="module">
import { greet } from './module.js';
console.log(greet());
</script>
</body>
</html>
위 예제를 실행하면,
"Module is being executed" 메시지가 단 한 번만 출력됩니다. 모듈은 처음 로드된 후 캐싱되며, 이후 동일한 모듈을 참조하더라도 추가 실행이 발생하지 않습니다.예제 2: 모듈 수정과 재사용
이번에는 모듈을 수정해보는 상황을 고려해 보겠습니다. 모듈의 캐싱으로 인해 동일한 모듈을 여러 번 참조해도 단 한 번만 실행된다는 원칙이 적용되지만, 모듈의 상태를 변경할 경우 그 결과는 어떻게 될까요?
module.js:let counter = 0;
export function increment() {
counter += 1;
return counter;
}
index.html:<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Module State Example</title>
</head>
<body>
<script type="module">
import { increment } from './module.js';
console.log(increment()); // 1
</script>
<script type="module">
import { increment } from './module.js';
console.log(increment()); // 2
</script>
</body>
</html>
여기서
increment 함수는 모듈의 상태(counter)를 변경합니다. 이 상태는 모듈이 캐싱된 후에도 유지되므로, 두 번째 스크립트에서 increment 함수를 호출하면 counter 값은 2로 증가합니다. 모듈의 상태가 전역적으로 공유되는 것을 확인할 수 있습니다.React에서 모듈의 단 한 번 실행 적용하기
React 애플리케이션에서도 모듈의 단 한 번 실행 원칙이 동일하게 적용됩니다. React에서는 컴포넌트가 여러 번 렌더링되더라도, 모듈이 단 한 번만 실행되고 상태가 유지됩니다.
counter.js:let counter = 0;
export function incrementCounter() {
counter += 1;
return counter;
}
App.js:import React from 'react';
import { incrementCounter } from './counter';
function App() {
return (
<div>
<h1>Counter: {incrementCounter()}</h1>
<button onClick={() => alert(`Counter value: ${incrementCounter()}`)}>
Show Counter
</button>
</div>
);
}
export default App;
결과:
incrementCounter 함수는 단 한 번만 실행되고, 상태(counter)는 공유됩니다. 버튼을 클릭할 때마다 증가된 카운터 값이 표시됩니다.React에서 모듈 수정에 따른 동작
React에서 모듈의 상태를 변경할 때도 마찬가지로 모듈이 단 한 번만 실행된다는 원칙이 적용됩니다. 이는 여러 컴포넌트에서 동일한 모듈을 참조할 때 특히 유용합니다.
counter.js:let counter = 0;
export function incrementCounter() {
counter += 1;
return counter;
}
export function getCounter() {
return counter;
}
ComponentA.js:import React from 'react';
import { incrementCounter } from './counter';
function ComponentA() {
return (
<div>
<h2>Component A: {incrementCounter()}</h2>
</div>
);
}
export default ComponentA;
ComponentB.js:import React from 'react';
import { getCounter } from './counter';
function ComponentB() {
return (
<div>
<h2>Component B: {getCounter()}</h2>
</div>
);
}
export default ComponentB;
App.js:import React from 'react';
import ComponentA from './ComponentA';
import ComponentB from './ComponentB';
function App() {
return (
<div>
<ComponentA />
<ComponentB />
</div>
);
}
export default App;
결과:
ComponentA가 incrementCounter를 호출하여 카운터 값을 증가시키면, ComponentB에서도 변경된 값을 확인할 수 있습니다. 이는 모듈이 단 한 번만 실행되고, 상태가 전역적으로 유지되기 때문입니다.JavaScript 모듈은 성능 최적화와 코드 일관성을 유지하기 위해 여러 곳에서 참조되더라도 단 한 번만 실행됩니다.
이 원리는 웹 애플리케이션의 효율성을 크게 향상시키며, React 같은 프레임워크에서도 중요한 역할을 합니다.
모듈의 상태를 공유하거나, 복잡한 애플리케이션에서 모듈을 재사용할 때 이 원리를 잘 활용하면, 더욱 견고하고 유지보수하기 쉬운 코드를 작성할 수 있습니다.
실제 코드에서 예를 든다면,
React-Query의 new QueryClient() 생성자를 한번만 실행하고, 그 모듈을 모든곳에서 import 받는다면 같은 queryClient를 사용한다는 것입니다. 어떤가요? 놀랍지 않나요?앞으로는 MDN문서를 한국어로만 보지 말고.. 영어 원문으로도 확인을 해봐야 디테일 하나하나 놓치지 않을 것 같다는 생각이 드는 하루였습니다.. 긴 글 읽어주셔서 감사합니다!


댓글 열기