[TIL #32] 자바스크립트와 싱글톤

2024. 11. 18. 17:37·Camp/T.I.L.

싱글톤

싱글톤에 대해 아시는가.

전역에서 단 한 번만 초기화되어 항상 같은 인스턴스를 공유하는 것

을 두고 흔히 싱글톤이라 한다.

 

그럼 두 번 초기화되는 일은 없어야 할 것이다.

하지만 그게 발생할 수도 있다.

노드의 모듈 임포트 구조는 왜 이래야만 했는가... 하는 의문도 있다.

 

 

싱글톤이지만 싱글톤이 아니다

import DungeonState from './dungeonState.js';
import EnemyAttackState from './enemyAttackState.js';
import MonsterDeadState from './monsterDeadState.js';

이러한 임포트가 있다고 하자.

임포트 하는 ``.js`` 파일의 이름은 실제로 카멜 케이스를 따르고 있다.

 

그런데 이래도 임포트는 된다.

import DungeonState from './DungeonState.js';
import EnemyAttackState from './EnemyAttackState.js';
import MonsterDeadState from './MonsterDeadState.js';

임포트 시 주는 파일의 이름을 다 파스칼 케이스로 변경했다.

IDE에서도 문제없이 경로를 찾는다.

하지만 저것들이 싱글톤일 경우?

서로 다른 인스턴스로 취급된다.

 

아니 뭐 이런 게 다 있단 말인가...

이름이 다르면 임포트가 되질 말아야지...

 

테스트를 해 보자.

싱글톤 클래스 ``SessionManager``의 구조는 다음과 같다.

// src/managers/sessionManager.js

let instance;

class SessionManager {
  constructor() {
    if (instance) {
      console.log(`기존 세션 관리자 인스턴스 반환`);
      return instance;
    }
    
    console.log(`세션 관리자 생성`);
    SessionManager.instance = this;
    Object.freeze(this);
  }

const sessionManager = new SessionManager();
export default sessionManager;

진짜로 싱글톤인지 다음의 테스트 코드를 통해 테스트해 보자.

 

import SessionManager1 from '#managers/sessionManager.js';
import SessionManager2 from '#managers/sessionManager.js';

if (SessionManager1 === SessionManager2) {
  console.log('같은 인스턴스를 공유 중!')
}
else {
  console.log('다른데?');
}

// 결과
세션 관리자 생성
같은 인스턴스를 공유 중!

매니저 파일의 이름은 실제로 카멜 케이스이다.

그럼 이제 매니저 2의 임포트 경로의 파일 이름을 파스칼 케이스로 변경하고 테스트해 보자.

 

import SessionManager1 from '#managers/sessionManager.js';
import SessionManager2 from '#managers/SessionManager.js';

if (SessionManager1 === SessionManager2) {
  console.log('같은 인스턴스를 공유 중!')
}
else {
  console.log('다른데?');
}

// 결과
세션 관리자 생성
세션 관리자 생성
다른데?

생성자가 2번 호출된다.

그럼 인스턴스가 다르므로 당연히 서로 같지 않을 것이다.

아니 왜 파일 이름이 다른데 임포트가 되냐고...

초기화 호출 과정을 보면서 대체 뭐가 문제인가 하고 새벽에 몇 시간을 뚫어져라 봤는데, 진이 다 빠진다.

 

 

어이없는 이유

이유는 다음과 같다.

일반적으로 윈도우 환경에선 대소문자를 구분하지 않는다. (Mac도 기본은 그럴 것이다. 맥 안써봐서 잘 모름...)

리눅스는 보통 대소문자를 구분한다.

 

여기서 ``Node.js``의 모듈 캐싱이 등장한다.

노드는 ``require()``나 ``import``로 모듈을 불러올 때 캐시를 사용한다.

이때, 모듈의 식별자로는 파일의 절대 경로를 사용한다고 한다.

 

윈도우는 대소문자를 구분하지 못하니

'#managers/sessionManager.js'
'#managers/SessionManager.js'

이는 같은 파일을 가리키게 되는 것이다.

하지만 노드에선 다른 식별자로 구분한다.

 

결과적으로

  1. 같은 물리 파일을 가리키지만
  2. 대소문자 차이 등으로 같으면서도 다른 경로로 임포트 하게 되면
  3. 노드는 별개의 모듈로 인식해 각각의 인스턴스를 생성
  4. 싱글톤이 깨진다

의 흐름이 된다.

 

 

결론

``import``시 경로를 일관되게 잘 쓰자.

대소문자가 다르다면 ``당연히`` 제대로 가져올 수 없는 거라는 생각을 ``Node.js``에선 버리자.

 

그냥 어이가 없다고 볼 수 있다.

'Camp > T.I.L.' 카테고리의 다른 글

[TIL #34] Docker 및 Docker Compose 올려보기  (0) 2024.12.03
[TIL #33] 마법의 엘리베이터  (0) 2024.11.20
[TIL #31] 상태 업데이트의 벽  (0) 2024.10.31
[TIL #30] 모의 면접을 준비하며  (0) 2024.10.30
[TIL #29] 점 찍기  (0) 2024.10.25
'Camp/T.I.L.' 카테고리의 다른 글
  • [TIL #34] Docker 및 Docker Compose 올려보기
  • [TIL #33] 마법의 엘리베이터
  • [TIL #31] 상태 업데이트의 벽
  • [TIL #30] 모의 면접을 준비하며
BVM
BVM
  • BVM
    E:\
    BVM
  • 전체
    오늘
    어제
    • 분류 전체보기 (173)
      • Thoughts (14)
      • Study (75)
        • Japanese (3)
        • C++ & C# (50)
        • Javascript (3)
        • Python (14)
        • Others (5)
      • Play (1)
        • Battlefield (1)
      • Others (10)
      • Camp (73)
        • T.I.L. (57)
        • Temp (1)
        • Standard (10)
        • Challenge (3)
        • Project (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

    • 본 블로그 개설의 목적
  • 인기 글

  • 태그

    Asio
    로깅
    FF14
    Dalamud
    boost
    네트워크
    스타필드
    cloudtype
    JS
    Server
    OSI
    IOCP
    db
    Python
    베데스다
    discord py
    C++
    포인터
    네트워크 프로그래밍
    discord
    7계층
    Network
    bot
    Selenium
    프로그래머스
    서버
    c#
    클라우드
    암호화
    docker
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
BVM
[TIL #32] 자바스크립트와 싱글톤
상단으로

티스토리툴바