Spring 개발자의 NestJs 적응하기

김동영
직방 기술 블로그
8 min readFeb 7, 2022

--

기존에 저는 Java Spring framework로 주로 개발을 하던 개발자였습니다. 하지만 직방에서 근무하게 되면서 Typescript와 NestJs에 적응해야할 필요가 생겼습니다. 그 과정에서 Spring과의 유사점들을 생각해보면서 공부하니 빠르게 익숙해질 수 있었습니다. 여기서 NestJs의 주요 기능들을 차례대로 Spring의 유사한 기능들과 비교해보면서 간단히 사용하는 법을 써보려 합니다.

Controllers

일단 처음 NestJs 문서를 보면 나오는 항목은 Controller입니다. HTTP route를 관리하기 위한 친구로 Spring의 Controller와 사용법이나 형태가 매우 유사하여 쉽게 익숙해질수 있었습니다.
먼저 스프링에서는 ‘/test’라는 경로로 Get요청이 왔을때 ‘OK’라는 응답을 주고 싶을 때 다음과 같이 작성하게 됩니다.

위와 매우 유사하게 NestJs에서는 다음과 같이 사용합니다

이외에도 Spring Controller 에서 사용되는 Annotation들과 유사한 기능을 수행해주는 decorators들이 존재하여 Spring에서 하던 이런게 필요하다 하여 검색해보면 바로바로 대응되는것을 찾아 적용할 수 있었습니다.

Providers

Providers는 Nest에서 관리해주는 기본적인 클래스 단위입니다. Spring에서 Bean과 같은개념이라고 보면 이해하기 쉽습니다.
Spring에서 Bean Annotation으로 빈으로 선언하는것과 유사하게 Nest에서는 Injectable decorator를 class위에 붙이면 됩니다. 그 후 사용하기 원하는 다른 Provider에서 스프링에서 생성자를 통해 Bean을 주입받는것과 같이 생성자의 파라미터로 적어두면 됩니다.

하지만 실제로 주입을 받기위해서는 스프링과는 조금 다르게 아래에서 다루는 Modules 을 작성할 필요가 있습니다.

Modules

Modules는 Nest에서 Providers들의 관계와 의존성을 관리하기위한 class입니다. Spring 에서는 IoC container에 해당한다고 보면 됩니다. 다른점은 Modules는 최소 한개 이상 존재할수 잇으며 다른 Modules를 Import할 수 잇고 서로 참조할수 있는 Provider를 Export로 별도로 설정해주어야 한다는 점입니다. 그것을 통해서 Provider에 대한 접근을 제어할 수 있다는게 특징입니다.

위와 같이 모듈을 선언함으로써 TestService에서는 HelloModule에서 export된 providers를 주입받을수 있고 다른 module이 TestModule을 import 함으로써 TestService를 주입받을수 잇게 됩니다.

Middleware

Middleware는 HTTP request가 전달되엇을때 route Handler가 처리하기 이전에 request와 response에 접근하여 작업을 수행할수잇는 class입니다. Spring과는 Interceptor와 유사하다고 보면 됩니다. 단 middleware는 route handle 전에 실행이된다는 점이 다릅니다.

Middleware를 만들기위해서는 NestMiddleware 를 구현하는 class를 작성하면 됩니다.

처럼 간단하게 요청이 올때마다 로그를 작성하는 Middleware를 구현할수 있습니다. 그리고 해당 Middleware를 적용하려면 여러가지 방법이 존재하는데

Module에 적용하는 방법과 NestApplication 전체에 적용하는 방법이 있습니다.

전체에 적용할때는 NestApp에서 use로 해당 middleware를 넣어주기만 하면 되며 Module에 적용할때는

다음과같이 적용을 해주면 됩니다.

Exception Filters

Exception Filters는 해당 요청에대한 응답이 Exception일경우 대응해주기 위한 class로 Spring에서 Exception handler와 같은 처리를 할수가 있습니다.

Exception Filter는 기본적으로 HttpException이나 해당 Exception을 상속받는 Exception을 구현하여 throw하면 적용이되며 직접 커스텀하게 작성하고 싶으면 Exception Filter를 구현하는 Class를 새로 작성하면 됩니다.

이런식으로 간단하게 Exception을 받아 response를 작성하여 요청에 응답할수 있습니다.

실제 Filter를 적용할때는 UseFilter decorator를 원하는 Controller나 method위에 넣고 해당 filter를 파라미터로 넣어주면 적용이 됩니다.

만약 전역으로 적용하고 싶을때는 middleware와 유사하게 NestApplication에 useGlobalFilters로 해당 필터를 넣어주면 적용이 됩니다.

Pipes

Pipes는 요청 파라미터를 받는 decorators 인자로 넣어주어 validate 또는 데이터 수정을 할수 있는 class 입니다. Spring에서는 Argument Resolver와 Validator 역할을 하는 class라고 생각하면 됩니다.

Pipes는 PipeTransform을 구현하는 클래스를 작성해주면 됩니다.

간단하게 이런식으로 작성하고 내부에서 validate후 Exception을 던지거나 value를 변형하고싶을경우 바꾸면 됩니다.

해당 Pipes를 사용하고 싶을때는 Controller에서 파라미터를 받을때 사용하는 decorator인 param, body, query 등에 파라미터로 해당 Pipes를 넣어주면 적용이 됩니다.

Guards

Guards 는 route Handler에 접근할수 있는지 없는지를 권한체크등을 통해 제어하는 class로 Spring 에서는 security의 일부기능과 유사한 기능을 합니다.

Guards는 CanActivate를 구현하는 class를 작성해주면 됩니다.

Guards에서는 요청에대한 접근을 차단할지 통과시킬지를 판단하고 boolean으로 반환해주면 됩니다. 그리고 적용할 대상위에 UseGuards로 해당 클래스를 넣어주면 적용이 되게 됩니다. 또한 SetMetaData decorator를 사용하여 role을 부여하고 해당 role을 확인하여 Guards에서 통과여부를 체크하는 식으로 Spring security처럼 구현도 가능합니다.

Interceptors

Interceptors는 Nest에서 AOP를 구현하기 위해 만든 Class입니다. 하지만 Spring의 Aop와는 다르게 Controller에서 route handler하는 시점에서만 적용이 되기에 Aspect 보다는 Spring interceptor와 매우 유사한 기능을 수행합니다.

Interceptor는 NestInterceptor 를 구현하는 클래스를 작성해서 만들수 있습니다.

interceptor내 로직이 전에 수행될 로직이며 nest.handle()로 작성한 로직이 대상이 종료된후 수행될 로직입니다. 이런식으로 전처리 후처리를 구현하여 Spring Interceptor처럼 request, response를 로깅하거나 하는게 가능합니다.

마무리

간단하게 NestJs 가이드 문서를 보면서 스프링과 유사한 기능을 생각해보면서 사용하는 방법을 익혀볼수 있었습니다. NestJs는 스프링과 매우 유사한 구조를 하고 있어서 스프링 개발자로서 쉽게 적응하고 코드를 작성할수 있었습니다. 물론 언어 자체가 다른점이 있어서 해당하는 부분을 더 익힐 필요가 있었지만 Java에 비해 Typescript가 쉽고 빠르게 코드를 작성할수 있다는 장점 덕분에 적응을 하게 되면 더 빠르게 코드를 작성할수 있습니다.

조금 아쉬운 부분으로는 Spring의 경우에는 Java reflection을 활용하여 package scan으로 Annotation만 적어두고 다양한 기능 사용이 가능했지만 NestJs는 직접 적용할 곳에 decorator를 작성해두거나 Module등에 선언을 해두어야만 적용이 된다는 점이었습니다. 그 부분만 유의하면서 개발을 하면 Spring때처럼 빠른 개발이 가능했습니다.

참조

https://docs.nestjs.com/
https://spring.io/guides/gs/rest-service/
https://velog.io/@junguksim?tag=NestJS
https://medium.com/google-developers/exploring-es7-decorators-76ecb65fb841

--

--