공부/JS, TS

[React, JS] 리액트 컴포넌트 모듈 바깥의 js 코드는 import할 때마다 실행될까?

Sadie Kim 2024. 1. 14. 21:03

Next + React Query로 SNS 서비스 만들기 강의를 듣다가 dayjs에 대해 알게 되었고, 강의 내에서의 dayjs configuration 코드를 보다가 알게 된 점이 있어 글로 남기고자 한다. (강의 내용과는 무관)

 

dayjs는 플러그인 같은 개념이 있어서 쓰고자 하는 기능이 있으면 필요한 플러그인을 등록해줘야 한다고 한다.

예를 들면 이런 식이다.

import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import "dayjs/locale/ko";

dayjs.locale("ko");
dayjs.extend(relativeTime);

export default function Post() {
  // ... 기타 리액트 코드
}

내가 이 코드를 봤을 때 든 생각은 다음과 같았다.

 

설정 코드를 이렇게 리액트 컴포넌트 함수 코드 바깥에 두면, 컴포넌트가 리렌더링되거나 import될 때마다 저 코드가 매번 실행되는 거 아닌가?

 

내가 보기에 저 dayjs.locale()과 dayjs.extend() 구문은 한 번만 실행되어야 함에도 불구하고, 해당 파일이 import되거나 리렌더링될 때마다 계속 새롭게 실행이 될 것 같았다.

그러니까 내가 생각했던 바람직한 코드 방식은 이런 느낌이었던 거다.

import { useEffect } from "react";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import "dayjs/locale/ko";

export default function Post() {
  useEffect(() => {
      //설정 코드는 useEffect 안에
    dayjs.locale("ko");
    dayjs.extend(relativeTime);
  }, []);
  //...기타 리액트 코드
}

 

이렇게 useEffect 안에 넣어 줘야만 해당 설정코드들이 한 번만 도는 거 아닌가?! 밖으로 빼면 계속 실행되지 않나?!?! 라는 의문이었다.

 

결론부터 말하자면 틀렸다.

GPT에게 물어보았다.

이런 의문을 영어로 잘 번역해서 GPT 4 선생님께 여쭤보았고, 몇 번의 대담을 반복했다.

결론적으로 나의 의문에 대해 GPT는 이렇게 대답해 주었다.

React 컴포넌트 외부에서 dayjs를 구성하면 애플리케이션에서 컴포넌트가 렌더링되거나 다시 렌더링되는 횟수에 관계없이 구성 코드가 한 번만 실행됩니다. 이는 자바스크립트 모듈의 작동 방식 때문입니다.

자바스크립트에서 모듈의 코드(예: ES6 모듈 파일)는 모듈을 처음 가져올 때 한 번만 실행됩니다. 이후 다른 파일이나 컴포넌트에서 동일한 모듈을 가져오면 전체 모듈의 코드가 다시 실행되지 않고 이미 실행된 모듈을 재사용할 뿐입니다. 이 동작은 왜 React 컴포넌트 외부에서 dayjs 구성을 수행해야 하는지 이해하는 데 핵심적인 역할을 합니다.

 

결국 자바스크립트 모듈 코드는 import될 때마다 실행되는 게 아니라 최초에만 실행되고 이후에는 재사용된다는 소리다.

즉, 나는 dayjs configuration 코드가 있는 Post 컴포넌트를 다른 곳에서 import할 때마다 해당 설정 코드가 계속 호출되는 게 아닌가 하는 의문을 갖고 있었는데, 설정 코드가 실행되는 건 최초에 import되는 단 한 번뿐만인 모양이다.

 

정말로 그런지 테스트를 해보았다.

GPT의 말만 100% 믿을 순 없으므로 실제로 자바스크립트 코드가 최초 import에만 실행되는지 테스트를 해보았다.

 

 

테스트에서 여러 번 실행되는지 확인하기 위한 파일은 CounterModule.js이다.

ComponentA와 ComponentB는 둘 다 해당 파일을 import하고 있고, App.js에서는 A와 B를 여러 번 렌더링한다.

 

만약 CounterModule.js가 import될 때마다 새롭게 실행되는 거라면,

코드 맨 윗 레벨에 있는 'counterModule 자체 실행' console.log나 incrementLoadCount 함수 안에 있는 console.log가 Component가 새로 나올 때마다 찍혀 있어야 한다.

하지만 실제 콘솔을 보면, 해당 로그는 딱 한 번만 찍혀 있다.

혹시나 해서 ComponentA에 useState를 추가해서 리렌더링되는 경우도 살펴보았다. 하지만 버튼을 클릭해도 CounterModule.js의 로그가 다시 찍히진 않는다.

 

이를 내가 헷갈린 케이스로 치환하면,

Post 컴포넌트를 여러 곳에서 import하더라도 컴포넌트 모듈 바깥의 dayjs 플러그인 등록 코드는 한 번만 실행된다는 말이 된다.

여전히 알쏭달쏭 헷갈리지만 의문은 풀렸다.

'공부 > JS, TS' 카테고리의 다른 글

requestAnimationFrame() 왜 쓰나요?  (0) 2023.06.14
var, const는 변수 호이스팅이 되지 않을까?  (0) 2023.06.11
타입스크립트 - 개념  (0) 2022.10.13