이 글은 작성 시점인 2023년 4월 15일을 기준으로 작성되었습니다.
시간에 따라 Nest.js와 Typescript Decorator의 구현에 차이가 있을 수 있으니 변경점을 발견하신다면 언제든 댓글 달아주세요!
--experimentalDecorators
의 사용을 유지하기로 하였습니다.자세한 변경 사항은 링크를 참고해 주세요.
이 중에서도 눈여겨 볼 점이 바로 Decorator가 정식으로 도입되었다는 점인데요, NestJS등 여러 프레임워크와 라이브러리에서 사용하고 있는 기능이니만큼 언젠가는 정식 기능으로 도입될거라고 생각했죠. 그런데....
기존 NestJS는 클래스 / 메소드 / 접근자 / 프로퍼티 / 매개변수 데코레이터를 제공하며 각 상황에 맞게 데코레이터 함수에 매개변수를 넣어 주고 있었습니다.
// 메소드 데코레이터 예시
function deco(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log('데코레이터가 평가됨');
}
class TestClass {
@deco
test() {
console.log('함수 호출됨')
}
}
// 실행 결과
데코레이터가 평가됨
함수 호출됨
그런데 Typescript5.0의 데코레이터는 아래와 같이 다른 형식으로 구현되어 있습니다.
function loggedMethod(originalMethod: any, context: ClassMethodDecoratorContext) {
const methodName = String(context.name);
function replacementMethod(this: any, ...args: any[]) {
console.log(`LOG: Entering method '${methodName}'.`)
const result = originalMethod.call(this, ...args);
console.log(`LOG: Exiting method '${methodName}'.`)
return result;
}
return replacementMethod;
}
기존 PropertyDescriptor
에는 이런 값들이 들어있었습니다.
interface PropertyDescriptor {
configurable?: boolean;
enumerable?: boolean;
value?: any;
writable?: boolean;
get?(): any;
set?(v: any): void;
그런데 새로 만들어진 ClassMethodDecoratorContext
에는 final 여부, 메소드 이름 등 간단한 값만 들어있고 PropertyDescriptor
에서 제공하는 여러 값들은 더 이상 제공하지 않게 되었습니다.
PropertyDescriptor
를 사용하여 유저 입력 데이터의 글자수 / 정규식 검증 등을 진행하고 있는 NestJS 에게는 큰 일이 발생해버렸죠. 애초에 인터페이스도 안맞아서 쓸 수도 없었구요.
다행히 --experimentalDecorators
플래그를 tsconfig에서 바로 제거하지 않았고, 한동안은 제거하지 않을 것 같습니다. 그래서 기존에 Nest.js로 개발을 하시던 분들은 기존 tsconfig를 그대로 유지한 채로 Typescript 버전을 올리는 것이 가능할 것 같습니다.
이 궁금증을 해결하기 위해 Nest.js 공식 디스코드를 확인해보았습니다.
여러 내용들이 있는데요, 요약하자면 우선은 --experimentalDecorators
을 그대로 유지한 채 사용하는 것을 권장하고 있습니다.
그리고 조금씩 작업을 하고 있다고는 합니다. 언제 다 끝날지는 모르겠네요😂
Typescript 5.0에서 정식으로 도입된 Decorator 기능! 하지만 기존 실험적 기능을 통해 제공되던 Decorator의 구현과 많은 부분이 달라져서, NestJS 등 기존 Decorator를 사용하던 많은 프레임워크들과 라이브러리들에게 큰 숙제를 안겨준 것 같습니다.
하지만 우리는 언제나 고쳐나가겠죠? 늘 그랬던 것 처럼요👩💻