티스토리 뷰

728x90
반응형

https://mongoosejs.com/

현재시간에서 3분 뒤의 시간을 default 값으로 가지는 스키마 완성된 코드 예시 : 

const EmailAuthSchema = new mongoose.Schema({
	email: { type: String, required: true, unique: true, lowercase: true, trim: true, validate: validateEmail },
	authCode: { type: String, required: true, validate: validateAuthCode },
	expirationTime: { type: Date, required: true, default: () => Date.now() + 3*60*1000 },
});

시간 없으신 분은 위에 코드를 보시면 되고, 설명이 필요하신 분은 아래 긴 글을 읽어주시면 되겠습니다.

 

저는 우선 이메일 인증 코드 스키마를 작성하려고 합니다. 그러던 와중에 인증 만료시간을 현재시간으로부터 3분이 지난 시간으로 하고 싶었습니다. 그래서 알아보던 중에 아래와 같은 코드를 발견했습니다.

const EmailAuthSchema = new mongoose.Schema({
	email: { type: String, required: true, unique: true, lowercase: true, trim: true, validate: validateEmail },
	authCode: { type: String, required: true, validate: validateAuthCode },
	expirationTime: { type: Date, required: true, default: new Date() },
});

위와 같이 new Date() 로 하게 되면, application을 실행하는 그 시점을 default 값으로 가집니다. 그래서 default 값으로 new Date() 함수 실행 시점에 반환 되는 값을 기본 값으로 할 것이 아니라, new Date() 함수 그 자체를 default 값으로 넘겨줘야 합니다.

질문! Mongoose 에서 default 는 value 뿐만 아니라 function 도 처리하나요? 네, 값 뿐만 아니라 함수도 default 값으로 지정할 수 있습니다. 함수를 default 값으로 지정하게 되면 사용하게 될 때마다 해당 함수를 실행시켜 그 반환 값을 기본값으로 가집니다. 자세한 건 아래 사이트를 참고해주세요.
https://mongoosejs.com/docs/defaults.html#default-functions

그렇기 때문에 다시, default 에 함수 형태로 넘겨준다면 아래와 같은 코드가 되겠습니다. () => new Date() 

const EmailAuthSchema = new mongoose.Schema({
	email: { type: String, required: true, unique: true, lowercase: true, trim: true, validate: validateEmail },
	authCode: { type: String, required: true, validate: validateAuthCode },
	expirationTime: { type: Date, required: true, default: () => new Date() },
});

그리고 위 코드에서 만약에 현재시간으로부터 3분이 지난 시간을 default 시간 값으로 가지고 싶다면, 아래와 같이 작성하면 되겠습니다. 우선 바깥에 있는 new Date() 로 시간을 설정해주는데, 안에 있는 현재 시간인 new Date() 를 +(더하기)연산자를 앞에 붙여줘서 정수값으로 만들고, 거기에 뒤에 있는 3*60*1000 과 연산하여 나온 값을 바깥의 new Date()의 인자로 들어가서 현재시간으로부터 3분 지난 값이 default 로 설정됩니다.

const EmailAuthSchema = new mongoose.Schema({
	email: { type: String, required: true, unique: true, lowercase: true, trim: true, validate: validateEmail },
	authCode: { type: String, required: true, validate: validateAuthCode },
	expirationTime: { type: Date, required: true, default: () => new Date(+new Date() + 3*60*1000) },
});

+new Date() 가 익숙하지 않은 분들을 위해서 아래 실행 결과 값을 작성해봅니다. +는 단순히 new Date()를 정수형으로 변환해주는 역할을 합니다.

C:\Users\DomDom>node
> new Date()
2021-07-06T18:37:34.479Z
> +new Date()
1625596656007

 

그러면 위와 같은 코드를 사용해도 될까요? 사실 기능상 문제는 없지만 성능상에는 문제가 있다고 합니다. 바로 방금 위에서 본 +new Date() 부분이 문제가 되는데요. 왜그런가 하면 매번 현재 시간 값을 구할 때마다 Date 라는 새로운 인스턴스를 생성하기 때문인데요. 그 때문에 garbage collector 에 어느정도 압박을 주게 된다고 합니다. 

 

그래서 이런 문제를 피하기 위해서 우리는 new Date() 대신에 Date.now() 를 사용하게 된답니다.

.now() 메소드는 Date 클래스에서 static 메소드에 해당하기 때문에, 별도로 인스턴스(instance)를 생성하지 않고 바로 숫자값을 return 하기 때문에 비교적 성능상 이점을 가지고 있습니다. Garbage Collection 이 굳이 Date 인스턴스를 따로 헤치울 필요가 없게 되었기 때문이죠.

 

그래서 결과적으로 현재시간으로부터 3분 뒤의 시간을 mongoose schema 에서 default 값으로 설정하기 위해서는 최상단에서도 있다시피, 아래와 같은 코드가 되겠습니다.

const EmailAuthSchema = new mongoose.Schema({
	email: { type: String, required: true, unique: true, lowercase: true, trim: true, validate: validateEmail },
	authCode: { type: String, required: true, validate: validateAuthCode },
	expirationTime: { type: Date, required: true, default: () => Date.now() + 3*60*1000 },
});

 

여기서 추가로 내용을 덧붙이자면 아래와 같은 코드를 보신 분도 계실텐데요. 이렇게 해도 현재시간을 default 값으로 가지게 하는 () => Date.now() 와 동일한 기능을 하게 됩니다.

const EmailAuthSchema = new mongoose.Schema({
	email: { type: String, required: true, unique: true, lowercase: true, trim: true, validate: validateEmail },
	authCode: { type: String, required: true, validate: validateAuthCode },
	expirationTime: { type: Date, required: true, default: Date.now },
});

사실 문법 상으로 당연한 거지만, 잘 모르는 분들을 위해서 아래 추가적으로 node 콘솔창에서 결과를 비교해보면서 설명하겠습니다.

C:\Users\DomDom>node
> const a = () => Date.now()
undefined
> const b = Date.now
undefined
> a
[Function: a]
> b
[Function: now]
> a()
1625597228770
> b()
1625597229427

위 실행 결과를 보면 아시다시피, () => Date.now() 도 결국 return 값은 함수 그 자체이고, Date.now 도 return 값이 함수 그 자체인 것을 알 수 있습니다. 그렇기 때문에 a와 b는 모두 함수를 받았기 때문에 일반적으로 함수를 호출하기 위해서 쓰이는 괄호를 이용해서 대입받은 함수를 실행시킬 수 있는 것이죠. 그리고 a 는 이름이 없는 익명 함수를 대입받았기 때문에 함수 이름이 [Function: a] 인 것이죠.

 

결과적으로 () => Date.now() 와 Date.now 는 동일한 것이기 때문에 좀 더 짧은 Date.now 를 쓰는 게 일반적인 경우겠습니다!!

 

 

- 끝 -

728x90
반응형
댓글