dotenv는 Node.js 프로젝트에서 환경 변수를 로드하는 데 도움을 주는 패키지이다. dotenv.config()는 이러한 dotenv 패키지의 기능 중 하나로, 환경 변수를 로드하는 메서드이다.
import { createClient, RedisClientType } from 'redis';
class Redis {
private static instance: Redis;
private readonly client: RedisClientType;
constructor() {
this.client = createClient({
url: process.env.REDIS_URL,
});
}
static getInstance(): Redis {
if (!Redis.instance) {
Redis.instance = new Redis();
}
return Redis.instance;
}
// redis연결
async connect(): Promise<void> {
await this.client.connect();
}
}
redis를 연결하는 부분은 싱글턴
패턴을 이용하여 제작하였는데, createClient하는 부분을 생성자에서 dotenv를 이용하여 .env파일에 있는 값을 사용해서 url을 넣어주었다. 이 redis 파일에서는 dotenv를 import해주지 않았다.
import dotenv from 'dotenv';
import Redis from './utilies/redis';
dotenv.config();
const redis = Redis.getInstance();
await this.redis.connect();
왜냐면 최상단인 app.ts에서 dotenv.config() 함수를 호출하여 이미 환경변수들을 로드하였고, redis를 연결하는 함수는 그 밑에서 호출하였기 때문이다.
하지만 redis를 연결하였을때 url값이 undefined
가 들어가 에러가났다. 분명히 app.ts 최상단에서 환경변수들을 load해주었는데 왜 undefined
로 값이 나온걸까?
그래서 dotenv.config()와 생성자 부분을 디버깅 해보았다. 여기선 console.log()로 설명하겠다. 위 그림처럼 찍으면 1번이 찍히고 2번이 찍힐 줄 알았는데 생성자부분인 2가 먼저 찍혔다. 그렇다면 마지막 범인은 static
이 하나 밖에 남지 않았다.
Javascript에서 static
키워드를 사용하여 정의한 변수는 클래스 자체에 속하는 변수로, 클래스의 인스턴스와는 별개로 존재한다. 즉, 모든 클래스 인스턴스가 공유하는 변수인 것이다. 싱글턴
에서는 인스턴스를 하나만 사용하기위해 instance변수를 static으로 선언해주었다.
JavaScript에서 static 키워드를 사용하여 선언된 변수는 클래스가 로드될 때 기본적으로 초기화된다. 이 값은 클래스가 처음으로 로드될 때 한 번 초기화된다
. 드디어 원인을 찾았다.
따라서 Redis파일이 로드 될때, static함수인 getInstance()가 호출 되었고, new Redis()로 인스턴스가 만들어 진 것이다. 따라서 이건 dotenv.config()가 호출되기 전이므로 환경변수가 undefined가된 것이다.
사실 싱글턴에서 Instance만 공유하면 되므로 Instance를 가져오는 getInstance() 까지는 static으로 지정할 필요가 없었다. static변수의 동작방식도 잘 알지못하고 남발(?)한 실수였다. 이번 실수를 통해 static변수를 제대로 알게되었다.. :(