최근에 Codesandox에서 Express 코드를 작성하면서 겪었던 문제를 공유하고자 적어봅니다. 앱을 HTTPS로 연결했음에도 불구하고, req.protocol
이 계속 http
로 출력되는 문제였습니다. 이 글에서는 그 문제를 어떻게 해결했는지 간단하게 적어두고자 합니다. (채찍피티의 도움으로 해결했습니다.)
스터디 과제를 위해 Codesandbox에서 Express 코드를 작성하면서, req.protocol
을 콘솔에 출력해보았습니다. 예상했던 것과 다르게, HTTPS로 연결했음에도 불구하고 req.protocol
은 항상 http
로 출력되었습니다. 이런 현상이 발생하는 이유는 무엇일까요?
이 문제는 실제 요청이 Codesandbox의 프록시 서버를 거쳐서 전달되기 때문에 발생되는 것으로 추정합니다. 프록시 서버는 요청을 받아서 대상 서버로 전달하는 중간 서버로, 원본 요청의 프로토콜 정보가 변경될 수 있습니다. 이 문제를 해결하려면, 요청 헤더에서 원래의 프로토콜 정보를 가져와야 합니다.
Express에서는 원본 요청의 프로토콜 정보를 복원하기 위해 trust proxy
설정을 사용할 수 있습니다. 다음은 추가 시도 예시입니다:
const express = require('express');
const app = express();
// Trust proxy setting
app.set('trust proxy', true);
app.get('/', (req, res) => {
console.log('Protocol: ', req.protocol);
res.send('Hello, World!');
});
// 기존 코드의 나머지 부분
app.set('trust proxy', true);
코드는 Express 애플리케이션에 프록시 서버를 믿을 수 있다고 알려줍니다. 이 설정을 활성화하면, Express는 요청 헤더의 X-Forwarded-Proto
값을 사용하여 원래 프로토콜을 복원합니다. 이렇게 하면 req.protocol
이 정상적으로 https
로 표시되어야 합니다.
그러나 이렇게 하면 https
를 받을 수 있으나 http
로 접근을 시도했을 때 Codesandbox가 내부적으로 접근을 차단하는 것 같습니다. 응답이 없어요.
프록시 서버는 클라이언트와 목적지 서버 사이에서 데이터를 중계하는 역할을 하는 서버입니다. 클라이언트의 요청을 받아 목적지 서버로 전달하고, 목적지 서버의 응답을 다시 클라이언트에게 전달합니다. 프록시 서버는 보안, 캐싱, 로드 밸런싱 등의 목적으로 사용됩니다.
프록시 서버가 원본 요청의 프로토콜 정보를 변경하는 과정에서 문제가 발생하는 이유는 다음과 같습니다.
프록시 서버는 클라이언트의 요청을 받아서 목적지 서버로 전달하는 중간 서버로 작동하기 때문에, 요청이 프록시 서버를 거치면서 일부 정보가 변경될 수 있습니다. 예를 들어, 클라이언트가 HTTPS 프로토콜을 사용하여 요청을 보냈지만, 프록시 서버가 HTTP 프로토콜로 목적지 서버에 전달하는 경우입니다. 이로 인해 목적지 서버는 요청이 HTTP로 전달된 것으로 인식할 수 있습니다.
프록시 서버가 요청 헤더를 수정하여 원본 프로토콜 정보를 포함하지 않는 경우, 목적지 서버는 원본 요청의 프로토콜 정보를 알 수 없습니다. 이 경우, 목적지 서버는 기본 프로토콜(일반적으로 HTTP)로 요청을 처리하게 됩니다.
프록시 서버가 요청을 중계하는 과정에서 프로토콜 정보를 변경할 수 있으며, 이로 인해 원본 요청의 프로토콜 정보가 손실될 수 있습니다. 따라서 목적지 서버는 클라이언트의 원래 프로토콜을 확인할 수 없게 됩니다.
이러한 문제를 해결하기 위해서는 프록시 서버에서 원본 요청의 프로토콜 정보를 목적지 서버에 전달해야 합니다. 이를 위해 프록시 서버는 일반적으로 X-Forwarded-Proto
헤더를 사용하여 원본 요청의 프로토콜 정보를 목적지 서버에게 전달합니다. 목적지 서버는 이 헤더를 사용하여 원본 요청의 프로토콜 정보를 복원할 수 있습니다. 이때, 목적지 서버가 프록시 서버를 신뢰할 수 있다고 판단하여 이 정보를 사용하는지에 대한 설정이 필요하며, Express에서는 trust proxy
설정을 사용하여 이를 구현할 수 있습니다.
Express 외에 다른 웹 프레임워크에서도 비슷한 문제를 겪을 수 있습니다. 각 프레임워크에서 이 문제를 해결하는 방법은 다음과 같습니다.
Koa 프레임워크에서는 app.proxy = true;
설정을 사용하여 프록시 서버를 신뢰할 수 있다고 알려줄 수 있습니다. 이렇게 설정하면 Koa는 요청 헤더의 X-Forwarded-Proto
값을 사용하여 원래 프로토콜을 복원합니다.
const Koa = require('koa');
const app = new Koa();
// Trust proxy setting
app.proxy = true;
app.use(async (ctx, next) => {
console.log('Protocol: ', ctx.protocol);
ctx.body = 'Hello, World!';
await next();
});
// 기존 코드의 나머지 부분
Hapi 프레임워크에서는 서버 옵션에 proxy
설정을 추가하여 프록시 서버를 신뢰할 수 있다고 알려줄 수 있습니다. 이렇게 설정하면 Hapi는 요청 헤더의 X-Forwarded-Proto
값을 사용하여 원래 프로토콜을 복원합니다.
const Hapi = require('@hapi/hapi');
const server = Hapi.server({
host: 'localhost',
port: 3000,
routes: {
// Trust proxy setting
proxy: { passThrough: true },
},
});
server.route({
method: 'GET',
path: '/',
handler: (request, h) => {
console.log('Protocol: ', request.headers['x-forwarded-proto'] || request.server.info.protocol);
return 'Hello, World!';
},
});
// 기존 코드의 나머지 부분
위의 예제들처럼 각 웹 프레임워크에서 프록시 서버를 신뢰할 수 있다고 설정하면, 요청 헤더의 X-Forwarded-Proto
값을 사용하여 원본 요청의 프로토콜 정보를 복원할 수 있습니다. 이렇게 하면 프록시 서버를 거치는 환경에서도 원본 요청의 프로토콜 정보를 올바르게 사용할 수 있습니다.
이 글에서는 Express에서 req.protocol
이 http
로 출력되는 문제와 그 원인에 대해 설명하였습니다. 또한, 이 문제를 해결하기 위해 Express의 trust proxy
설정을 사용하는 방법을 소개하였습니다. 비슷한 문제가 다른 웹 프레임워크에서 발생하는 경우에도 프록시 서버를 신뢰할 수 있는 설정을 사용하여 원본 요청의 프로토콜 정보를 복원할 수 있습니다. 이를 통해 개발자들은 프록시 서버를 사용하는 환경에서도 웹 애플리케이션을 올바르게 작동시킬 수 있습니다.
이러한 문제를 해결하는 과정에서 개발자들은 프록시 서버와 관련된 다양한 설정을 이해하고 적용할 수 있어야 합니다. 프록시 서버를 사용할 때에는 다음과 같은 추가적인 고려사항들도 고려해야 합니다:
클라이언트의 실제 IP 주소를 얻기 위해서는 X-Forwarded-For
헤더를 사용할 수 있습니다. 이 헤더는 클라이언트의 실제 IP 주소를 포함하며, 프록시 서버를 거쳐 갈 때마다 IP 주소가 추가됩니다.
프록시 서버를 사용할 때, 클라이언트의 실제 포트 번호를 얻기 위해서는 X-Forwarded-Port
헤더를 사용할 수 있습니다. 이 헤더는 클라이언트의 실제 포트 번호를 포함합니다.
프록시 서버를 사용할 때는 웹 애플리케이션의 성능과 보안을 최적화하기 위해 캐싱, 압축, 인증, 로드 밸런싱 등의 기능을 사용할 수 있습니다.
프록시 서버를 사용하는 경우, 웹 애플리케이션의 로깅 및 모니터링 설정을 적절하게 구성하여 실제 클라이언트의 정보를 추적하고 기록할 수 있어야 합니다.
이 글을 통해 Express, Koa, Hapi 등 다양한 웹 프레임워크에서 프록시 서버를 사용하는 환경에서 발생할 수 있는 문제와 그 해결 방법에 대해 이해할 수 있었기를 바랍니다. 이러한 지식을 활용하여 프록시 서버를 사용하는 웹 애플리케이션의 구성 및 관리를 개선하고 최적화할 수 있습니다.
퍼갑니다
감사합니다
Express 앱에서 프록시 서버를 사용할 때의 문제와 해결 방법 - https://economiceco.tistory.com/m/17556