싱글톤
싱글톤에 대해 아시는가.
전역에서 단 한 번만 초기화되어 항상 같은 인스턴스를 공유하는 것
을 두고 흔히 싱글톤이라 한다.
그럼 두 번 초기화되는 일은 없어야 할 것이다.
하지만 그게 발생할 수도 있다.
노드의 모듈 임포트 구조는 왜 이래야만 했는가... 하는 의문도 있다.
싱글톤이지만 싱글톤이 아니다
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'
이는 같은 파일을 가리키게 되는 것이다.
하지만 노드에선 다른 식별자로 구분한다.
결과적으로
- 같은 물리 파일을 가리키지만
- 대소문자 차이 등으로 같으면서도 다른 경로로 임포트 하게 되면
- 노드는 별개의 모듈로 인식해 각각의 인스턴스를 생성
- 싱글톤이 깨진다
의 흐름이 된다.
결론
``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 |