thumbnail

JavaScript 모듈은 한번만 실행된다.

생성일2024. 8. 14.
태그
작성자지한솔

notion image
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;
결과: ComponentAincrementCounter를 호출하여 카운터 값을 증가시키면, ComponentB에서도 변경된 값을 확인할 수 있습니다. 이는 모듈이 단 한 번만 실행되고, 상태가 전역적으로 유지되기 때문입니다.
 
JavaScript 모듈은 성능 최적화와 코드 일관성을 유지하기 위해 여러 곳에서 참조되더라도 단 한 번만 실행됩니다.
이 원리는 웹 애플리케이션의 효율성을 크게 향상시키며, React 같은 프레임워크에서도 중요한 역할을 합니다.
모듈의 상태를 공유하거나, 복잡한 애플리케이션에서 모듈을 재사용할 때 이 원리를 잘 활용하면, 더욱 견고하고 유지보수하기 쉬운 코드를 작성할 수 있습니다.
 
실제 코드에서 예를 든다면, React-Querynew QueryClient() 생성자를 한번만 실행하고, 그 모듈을 모든곳에서 import 받는다면 같은 queryClient를 사용한다는 것입니다. 어떤가요? 놀랍지 않나요?
 
앞으로는 MDN문서를 한국어로만 보지 말고.. 영어 원문으로도 확인을 해봐야 디테일 하나하나 놓치지 않을 것 같다는 생각이 드는 하루였습니다.. 긴 글 읽어주셔서 감사합니다!