| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
- Java
- next.js
- mongoose
- nest.js
- typescript
- react
- mysql
- WIL
- javascript
- 생각일기
- 생각로그
- mongo
- 생각정리
- js
- 회고
- 코테
- MongoDB
- Git
- til
- 자바스크립트
- 트러블슈팅
- 알고리즘
- CS
- 기록
- 리눅스
- array
- 주간회고
- 네트워크
- Grafana
- 피드백
- Today
- Total
코딩일상
[Nest.js] nest.js 뿌수기 공식 docs 모조리 파헤치기[Interceptors] 본문

NestJS의 인터셉터는 요청(Request)과 응답(Response)의 흐름 사이에서 로직을 가로채고 변형할 수 있는 아주 강력한 도구입니다. AOP(관점 지향 프로그래밍) 기술을 기반으로 하며, 애플리케이션 전반에 걸쳐 공통된 로직을 깔끔하게 처리할 수 있게 해줍니다.
1. 인터셉터의 핵심 역할
인터셉터는 단순히 흐름을 끊는 것이 아니라 다음과 같은 다양한 역할을 수행합니다:
- 함수 실행 전/후 로직 추가: 로깅(Logging)이나 시간 측정 등에 활용됩니다.
- 결과 변환 (Response Mapping): 컨트롤러가 반환한 데이터를 가공하여 일관된 형식으로 클라이언트에게 전달합니다. (예: { data: 결과값 })
- 예외 변환 (Exception Mapping): 발생한 에러를 가로채서 특정 예외(Exception)로 변경합니다.
- 스트림 오버라이딩 (Overriding): 특정 조건(예: 캐시가 있는 경우)에서 컨트롤러 실행을 건너뛰고 바로 응답을 보냅니다.
2. 요청 수명 주기와 실행 순서
인터셉터는 요청이 들어오고 나가는 양방향에서 작동하며, 바인딩된 범위에 따라 순서대로 실행됩니다.
[실행 순서]
- Global 인터셉터 🌏
- Controller 인터셉터 🏢
- Method 인터셉터 🎯
Tip: 응답이 나갈 때는 반대로 Method → Controller → Global 순으로 거꾸로 처리됩니다. 양파 껍질 구조를 생각하면 이해하기 쉽습니다!
3. 주요 구현 포인트
인터셉터는 intercept() 메서드를 구현해야 하며, ExecutionContext와 CallHandler를 인자로 받습니다.
- ExecutionContext: 현재 실행 중인 클래스(getClass())와 메서드(getHandler())의 정보를 담고 있습니다.
- CallHandler: handle() 메서드를 호출해야 실제 라우트 핸들러(컨트롤러)가 실행됩니다.
[주의사항: @Res() 사용 금지] ⚠️ 컨트롤러에서 @Res()를 사용하여 직접 응답을 보내면
Nest의 표준 응답 로직을 건너뛰기 때문에 인터셉터의 응답 변환 로직이 작동하지 않습니다.
만약 쿠키 설정 등이 필요해 반드시 사용해야 한다면 @Res({ passthrough: true }) 옵션을 사용해야 인터셉터와 공존할 수 있습니다.
⚖️ @Res() vs @Res({ passthrough: true }) 비교
팀원들과의 의사소통 미스를 방지하기 위해 이 차이점을 명확히 정리해두면 좋아요.
| 특징 | @Res() (기본) | @Res({ passthrough: true }) |
| 응답 주도권 | 개발자 (Express/Fastify 객체) 🕹️ | NestJS 프레임워크 🏗️ |
| 인터셉터 작동 | 작동 안 함 (Response Mapping 불가) ❌ | 정상 작동 ✅ |
| 데이터 반환 | res.send() 등으로 직접 전송 📧 | return 문 사용 가능 ↩️ |
| 주요 용도 | 프레임워크 기능을 완전히 벗어날 때 🛠️ | 쿠키 설정 등 특정 객체 기능만 필요할 때 🍪 |
💡 실전 예시
팀원들과의 협업 중 쿠키를 설정해야 하는 상황이라고 가정해 볼게요.
@Get()
findAll(@Res({ passthrough: true }) res: Response) {
res.cookie('key', 'value'); // (1) res 객체로 특정 작업 수행
return { message: 'Hello' }; // (2) 값을 return하여 인터셉터가 작동하게 함
}
이렇게 하면 res 객체도 쓰고, 우리가 아까 배운 인터셉터의 map(data => ({ result: data })) 로직도 안전하게 실행됩니다!
1. ExecutionContext
ExecutionContext는 현재 실행 중인 요청의 **맥락(Context)**을 담고 있는 가방과 같습니다.
- 주요 메서드와 반환값:
- getClass<T>(): 요청을 처리 중인 컨트롤러 클래스 정보.
- getHandler(): 실행될 라우트 메서드 정보.
- switchToHttp(): HTTP 환경(Request, Response 객체 등)으로 전환하는 헬퍼.
- 실무 활용 예제: 로깅 및 보안 🛠️
- 메타데이터 추출: 특정 API에 @Roles('admin') 같은 커스텀 데코레이터가 붙어 있는지 확인하여 접근을 제어할 때 사용합니다.
- 정밀한 로깅: context.getClass().name과 context.getHandler().name을 조합하면 "UserController - findOne 메서드 실행 중"과 같은 상세한 로그를 남길 수 있습니다.
========================================================================
@Injectable()
export class DetailLoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const request = context.switchToHttp().getRequest(); // 1번 선택지: Request 객체 획득
const className = context.getClass().name; // 컨트롤러 이름
const handlerName = context.getHandler().name; // 메서드 이름
console.log(`[시작] ${request.method} ${request.url} | ${className}.${handlerName}`);
return next.handle().pipe( // 컨트롤러 실행
tap(() => console.log(`[종료] ${className}.${handlerName}`))
);
}
}
========================================================================
[시작] GET /users/profile | UsersController.getProfile
[종료] UsersController.getProfile
4. RxJS를 활용한 고급 스트림 제어
인터셉터는 next.handle()이 반환하는 Observable 스트림을 활용하여 강력한 기능을 구현합니다:
- map(): 응답 데이터를 변형합니다.
- catchError(): 예외 상황을 처리하고 에러를 변환합니다.
- timeout(): 일정 시간 이상 응답이 없으면 에러를 발생시킵니다.
- tap(): 데이터에 영향을 주지 않고 로깅 등의 사이드 이펙트를 실행합니다.
5. 바인딩 순서
바인딩 순서 및 우선순위
인터셉터는 적용된 위치에 따라 실행 순서가 결정됩니다.
| 순서 | 바인딩 수준 | 설정 방법 |
| 1 | Global 🌏 | app.useGlobalInterceptors() 또는 APP_INTERCEPTOR |
| 2 | Controller 🏢 | 클래스 레벨에 @UseInterceptors() 사용 |
| 3 | Method 🎯 | 특정 라우트 메서드에 @UseInterceptors() 사용 |
- 요청 시: Global → Controller → Method 순으로 실행됩니다.
- 응답 시: Method → Controller → Global 순으로 거꾸로 나갑니다.
'개발 공부 > nest.js' 카테고리의 다른 글
| [Nest.js] @Module 알다가도 헷갈리는 모듈의 개념 정리!! (0) | 2026.01.12 |
|---|---|
| [Nest.js] nest.js 뿌수기 공식 docs 모조리 파헤치기[Pipes] (0) | 2025.12.23 |
| [nest.js] nest.js 뿌수기 공식 docs 모조리 파헤치기[exception-filters] (1) | 2025.12.16 |
| [nest.js] NestJS 제공 라이브러리 및 데코레이터 완벽 정리 (0) | 2025.12.14 |
| [nest.js] Middleware vs Guards vs Interceptors (0) | 2025.12.14 |