우리는 한다, 개발을.

Res 객체 이모저모

⌛ 8 mins

Express res 객체 메소드

1. res.send([body])

  • 목적: HTTP 응답 본문을 전송
  • 특징:
  • 문자열, 객체, 배열, Buffer 등 다양한 타입을 보낼 수 있음
  • 타입에 따라 Content-Type 자동 설정됨
  • 응답 후 자동으로 연결 종료 (res.end() 호출), 추가 응답 불가.
app.get('/text', (req, res) => {
    res.send('Hello, World!'); // Content-Type: text/html
});

app.get('/json', (req, res) => {
    res.send({ message: 'Hello, JSON!' }); // Content-Type: application/json
});

2. res.json([body])

  • 목적: JSON 형식의 응답 전송 (REST API에서 주로 사용)
  • 특징:
  • JavaScript 객체를 JSON 문자열로 변환하여 전송
  • Content-Typeapplication/json으로 설정
app.get('/api', (req, res) => {
    res.json({ status: 'success', data: [1, 2, 3] });
});

3. res.status(code)

  • 목적: HTTP 응답 상태 코드 설정
  • 특징:
  • 응답을 전송하지 않고 상태 코드만 설정
  • 메소드 체이닝을 통해 다른 응답 메소드와 함께 사용해야 함.
  • 상태 코드를 설정한 후 반드시 send()json()을 호출해야 클라이언트가 응답을 받을 수 있음.
app.get('/not-found', (req, res) => {
    res.status(404).send('Page Not Found');
});

4. res.sendStatus(statusCode)

  • 목적: 상태 코드 설정 + 상태 코드에 맞는 기본 메시지 전송
  • 특징:
  • res.status(code).send(message)와 동일한 효과
  • 별도 응답 본문을 지정할 수 없음.
app.get('/not-found', (req, res) => {
    res.sendStatus(404); // 응답 본문: 'Not Found'
});

5. res.render(view [, locals] [, callback])

  • 목적: 템플릿을 렌더링하여 HTML 응답 전송
  • 특징:
  • view: 렌더링할 템플릿 파일 이름
  • locals: 템플릿에서 사용할 데이터 객체
  • 템플릿 엔진 설정 필요 (app.set('view engine', 'ejs') 등)
app.set('view engine', 'ejs');
app.get('/home', (req, res) => {
    res.render('home', { username: 'John' });
});

6. res.redirect([status,] path)

  • 목적: 클라이언트를 특정 URL로 리다이렉트
  • 특징:
  • 기본적으로 302 상태 코드 사용
  • 첫 번째 파라미터로 상태 코드를 명시적으로 지정 가능
app.get('/old-page', (req, res) => {
    res.redirect(301, '/new-page');
});

7. res.set(field [, value]) 또는 res.header(field [, value])

  • 목적: HTTP 응답 헤더 설정
app.get('/headers', (req, res) => {
    res.set('Custom-Header', 'myHeaderValue');
    res.send('Header set!'); // 다른 응답 메소드와 함께 사용 가능
});

8. res.cookie(name, value [, options])

  • 목적: 쿠키 설정
  • 특징:
  • options 객체를 통해 expires, maxAge, secure, httpOnly, sameSite 등을 지정 가능
app.get('/set-cookie', (req, res) => {
    res.cookie('token', '12345', { httpOnly: true, maxAge: 900000 });
    res.send('Cookie set!');
});

9. res.clearCookie(name [, options])

  • 목적: 쿠키 삭제
  • 특징:
  • 쿠키를 설정할 때 사용한 옵션이 일치해야 쿠키가 올바르게 삭제됨.
  • httpOnly, path, domain 등 설정이 달라지면 삭제되지 않을 수 있음.
app.get('/clear-cookie', (req, res) => {
    res.clearCookie('token', { httpOnly: true }); // httpOnly 속성을 포함하여 쿠키 삭제
    res.send('Cookie cleared!');
});

10. res.sendFile(path [, options] [, fn])

  • 목적: 파일을 응답 본문으로 전송
  • 특징:
  • Content-Type이 자동으로 설정됨 (예: .pdfapplication/pdf로 지정됨)
app.get('/download', (req, res) => {
    res.sendFile(__dirname + '/files/sample.pdf');
});

11. res.download(path [, filename] [, options] [, fn])

  • 목적: 브라우저가 파일 다운로드하도록 유도
  • 특징:
  • 선택적으로 다운로드될 파일의 이름을 지정 가능 (예: example.pdf)
  • 내부적으로 res.sendFile()을 사용하여 파일을 전송함.
app.get('/download-file', (req, res) => {
    res.download(__dirname + '/files/sample.pdf', 'example.pdf');
});

NestJS에서 Response 응답 보내기

  • NestJS에서 응답 보내는 방법
  • return을 사용해 자동으로 응답 보내기
  • @Res() 데코레이터를 활용해 직접 응답 객체를 조작하기

return을 사용해 자동으로 응답 보내기

@Get('users/:id')
getUser(@Param('id') id: number) {
  return {
    status: 'success',
    message: 'User data fetched successfully',
    data: {
      id,
      name: 'John Doe',
      email: 'john@example.com',
    },
  };
}
  • NestJS는 일반적으로 자동 응답 처리 기능을 제공
  • @Res() 없이 데이터를 반환하면 자동으로 application/json 응답이 생성됨.

@Res()가 필요한 경우

  • 파일 다운로드, 쿠키 설정, 리다이렉트 등 직접 응답을 조작해야 하는 특별한 경우에 사용
  • @Res() 데코레이터를 사용하면 NestJS는 해당 라우트의 응답 처리를 개발자가 직접 관리한다고 판단 → Interceptors, Exception Filters 등 NestJS의 자동 응답 처리 기능이 작동하지 않음.
  • @Res()를 사용하면 return으로 JSON을 반환하는 대신 res.json()을 직접 호출해야 함.
  1. 파일 다운로드 (res.download())
    • NestJS의 기본 응답 처리는 JSON을 반환하지만, 파일은 바이너리 데이터로 응답해야 함.
  @Get('download')
  downloadFile(@Res() res: Response) {
    const filePath = join(__dirname, '../uploads/sample.pdf');
    return res.download(filePath); // 파일을 다운로드하도록 응답
  }
  1. 쿠키 설정 (res.cookie())
    • 클라이언트에게 인증 토큰을 쿠키로 저장하도록 할 때
    • NestJS 기본 응답 방식으로는 쿠키를 설정할 수 없음 → @Res()를 사용해서 쿠키를 직접 설정
  @Get('login')
  login(@Res() res: Response) {
    res.cookie('token', 'jwt-token-example', { httpOnly: true });
    return res.status(200).json({ message: 'Logged in successfully' });
  }
  • 리다이렉트 응답 (res.redirect()) → @Redirect() 로 대체 가능
  • 응답 헤어 직접 설정 (res.setHeader()) → @Header() 로 대체 가능

@Res({ passthrough: true }) 옵션

  • 정의: passthrough: true 옵션을 사용하면 개발자가 응답 객체(res)를 직접 조작하더라도 NestJS의 기본 응답 처리 기능이 유지됨.
// passthrough 사용 X
@Get()
example(@Res() res: Response) {
  res.cookie('exampleCookie', 'cookieValue');
  res.status(HttpStatus.OK).json({ message: 'Example response' });
}

// passthrough 사용 O
@Get()
example(@Res({ passthrough: true }) res: Response) {
  res.cookie('exampleCookie', 'cookieValue');
  return { message: 'Example response' }; // NestJS 자동 응답 가능
}
  • res.cookie()를 사용하여 쿠키를 설정했지만, 응답은 return {} 형태로 반환됨. (NestJS 기본 응답 방식이 유지됨.)
  • Interceptor, Exception Filter 같은 NestJS 기능을 그대로 적용하면서 추가적으로 응답을 조작하고 싶을 때 사용 가능

[결론]

일반적인 JSON 응답이나 DTO 반환이라면 @Res() 없이 NestJS 기본 응답 방식을 사용하는 것이 좋다.