http-proxy-middleware에서 onProxyRes만 썼는데 500 에러가? 이유는 selfHandleResponse 때문
2025. 6. 30. 16:47
728x90

문제 상황: 예상치 못한 500 에러 발생

Express + http-proxy-middleware 조합으로 API Gateway를 구성하는 도중, 단순히 로그만 찍기 위해 onProxyRes를 사용했음에도 불구하고 500 Internal Server Error가 발생하는 현상을 마주하게 되었습니다.

onProxyRes: (proxyRes, req, res) => {
  logger.info(`Proxy response from ${req.url}`);
}

응답을 직접 가공하거나 처리하는 코드는 없었는데도, 프록시가 응답을 제대로 전달하지 못하고 요청이 실패했습니다.

이 문제는 다음 옵션을 명시한 뒤에야 해결되었습니다:

selfHandleResponse: false

배경 지식: selfHandleResponse란?

http-proxy-middleware의 selfHandleResponse 옵션은 다음과 같은 의미를 가집니다:

"프록시 응답을 내가 직접(res 객체 말고, proxyRes 스트림으로) 처리하겠다."

기본값은 false이며, 이 경우 프록시 응답은 자동으로 Express의 res 객체로 전달됩니다.

하지만 onProxyRes 콜백을 사용하는 경우, 프록시 내부에서는 selfHandleResponse를 true처럼 오해할 수 있습니다.


내부 동작: 왜 문제가 생겼는가?

다음은 실제 설정 예시입니다:

createProxyMiddleware({
  target: 'http://backend:3000',
  changeOrigin: true,
  onProxyRes: (proxyRes, req, res) => {
    logger.info(`Received response from: ${req.url}`);
  },
});

이 설정에서 문제가 발생한 이유는:

  1. onProxyRes를 사용함으로써, 프록시 미들웨어는 “사용자가 응답을 직접 다루려는 것 같다”고 판단할 수 있습니다.
  2. 그러나 실제로는 res.writeHead(), res.end() 등의 응답 전송 메서드를 호출하지 않았습니다.
  3. 결과적으로 프록시는 응답을 Express에 넘기지 않고 대기하게 되고, Express는 처리되지 않은 요청으로 인해 500 에러를 반환합니다.

해결 방법: selfHandleResponse를 명시적으로 false로 설정

createProxyMiddleware({
  target: 'http://backend:3000',
  changeOrigin: true,
  selfHandleResponse: false,
  onProxyRes: (proxyRes, req, res) => {
    logger.info(`Received response from: ${req.url}`);
  },
});

이 설정을 통해:

  • 프록시가 받은 응답을 자동으로 Express에 전달하게 됩니다.
  • onProxyRes는 단순 로깅 용도라는 의도를 명확히 전달할 수 있습니다.

결론 및 실무 팁

상황 권장 설정
onProxyRes만 사용하고 응답을 직접 처리하지 않음 selfHandleResponse: false 명시
응답을 직접 가공하거나 스트리밍 처리할 경우 selfHandleResponse: true 설정 후 res.write() 등 명시적으로 응답 처리

실무에서는 onProxyRes를 사용할 때 응답을 직접 다루지 않는다면, selfHandleResponse: false를 항상 명시하는 것을 추천합니다.

반응형