1539 단어
8 분
nginx를 통한 리버스 프록시 설정
2025-03-15

서비스 운영 중 마주한 문제#

서비스 출시 준비를 하면서 다음과 같은 문제를 마주했다.

1. 앱 배포 시 HTTP 차단 문제#

앱 배포 시 HTTPS 사용이 필수라는 점이었다. Google Play Store와 Apple App Store의 개발자 가이드라인에 따르면, 네트워크 요청 시 HTTP를 사용할 경우 차단될 수 있다는 후기가 있었다. HTTP 허용 설정은 있지만 이는 임시 해결책이며 심사에서는 거부당한다고 하였다.

2. API 엔드포인트 관리 및 확장성 문제#

현재는 단일 서버에서 운영하고 있지만, 향후 트래픽 증가에 따라 스케일아웃을 진행할 경우, IP 기반 API 요청이 복잡해진다.

즉, 클라이언트가 특정 API 서버의 IP 주소로 직접 요청을 보내면, 새로운 API 서버가 추가될 때 클라이언트에서 해당 주소를 수정해야 한다.

해결 과정#

위 2가지 문제를 해결하기 위해 다음과 같은 방법을 도입하였다.

  1. HTTPS 없이 앱을 배포할 수 없으므로 SSL/TLS 인증서를 적용하여 HTTPS를 적용한다.

  2. 단일 서버 운영에서 확장성을 고려하여 API 엔드포인트를 도메인 기반으로 변경한다.

이러한 문제를 해결하기 위해 Nginx를 기반으로 프록시 서버를 도입하여 보안 강화 및 API 요청 관리를 최적화하였다.

도메인 발급#

먼저 우리 서비스 이름으로 gabia에서 도메인을 발급 받았다. buddyya.com은 .com 도메인이 인기 많아서 그런지 비용이 꽤나 들길래 할인을 해주는 buddyya.store로 발급 받았다.

가비아 이미지

이제 발급 받은 도메인을 배포한 ec2 서버의 ip주소를 등록해줘야 한다.

A 레코드가 도메인을 특정 IP 주소와 연결하는 역할을 하고, 사용자가 도메인을 입력하면 해당 서버로 접근할 수 있도록 해야 하므로 다음과 같이 DNS 설정을 해주었다.

www -> 3.39.xxx.xx
@ -> 3.39.xxx.xx

이제 www.buddyya.store, buddyya.store에서 접근이 가능하다.

cmd를 활용하여 등록한 도메인의 ip 주소를 확인하면 다음과 같이 잘 나타나는 것을 볼 수 있다.

가비아 이미지

Nginx 기반 프록시 서버 도입#

Nginx 리버스 프록시는 클라이언트가 직접 백엔드 서버와 통신하지 않고, Nginx가 중간에서 요청을 받아 백엔드 서버로 전달하는 방식이다. 이를 통해 보안 강화, API 엔드포인트 통합, 서버 확장성을 확보할 수 있다.

기존 구조 vs Nginx 도입 후 구조#

기존 구조 (Nginx 적용 전)

nginx 구조
  • 클라이언트가 EC2의 IP(3.39.xx.xxx)를 사용하여 직접 요청
  • 백엔드 서버가 외부에 노출되어 보안 위험

Nginx 적용 후 구조 nginx 구조

  • 클라이언트는 https://buddyya.store/api로 요청을 보냄
  • Nginx가 내부적으로 백엔드 서버로 요청을 전달하고 응답을 반환함.
  • 백엔드 서버는 외부에 직접 노출되지 않음.

Nginx 설정 및 HTTPS 적용#

도메인을 구매한 후, SSL 인증서를 발급받아 Nginx를 통해 HTTPS를 적용하고, API 요청을 하나의 엔드포인트로 통합하였다.

Let’s Encrypt SSL 인증서 발급#

sudo yum install epel-release
sudo yum install certbot
sudo yum install nginx
sudo certbot certonly --standalone -d {domain} -d www.{domain} --debug-challenges

리눅스 환경에서 SSL 인증서를 발급받기 위해 Let’s Encrypt를 설치하였고 certbot을 사용해서 인증서를 발급 받았다. 그 후 Nginx에 발급 받은 SSL 인증서를 등록해야 한다.

Nginx 리버스 프록시 설정#

server {
    listen 80;
    server_name buddyya.store www.buddyya.store;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name buddyya.store www.buddyya.store;

    ssl_certificate /etc/letsencrypt/live/buddyya.store/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/buddyya.store/privkey.pem;

    location / {
        proxy_pass http://3.39.xx.xxx:8080; 
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

코드를 하나하나 살펴보면 다음과 같다.

http 요청 https로 redirect#

server {
    listen 80;
    server_name buddyya.store www.buddyya.store;
    return 301 https://$host$request_uri;
}

이 부분은 https가 아닌 http로 요청이 오면 https로 강제 리다이렉트 시킨다.

서버 설정#

server {
    listen 443 ssl;
    server_name buddyya.store www.buddyya.store;

    ssl_certificate /etc/letsencrypt/live/buddyya.store/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/buddyya.store/privkey.pem;

다음은 Nginx가 443 포트(HTTPS)에서 요청을 처리하도록 설정한다.

  • server_name에 등록된 도메인(buddyya.store, www.buddyya.store)을 통해 해당 서버로 접근이 가능하다.

  • ssl_certificate와 ssl_certificate_key를 통해 Let’s Encrypt에서 발급받은 SSL 인증서를 적용한다.

리버스 프록시 설정#

location / {
        proxy_pass http://3.39.xx.xxx:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
  • proxy_pass http://3.39.xx.xxx:8080; : 클라이언트가 보낸 요청을 내부의 Spring 서버(3.39.xx.xxx:8080)로 전달한다.

  • proxy_set_header : 클라이언트 요청 정보를 유지하면서 백엔드 서버로 전달하기 위한 헤더 설정.

전체 구조#

nginx 구조

마지막으로 정리하면 다음과 같다.

클라이언트와 SpringBoot(WAS) 사이 Nginx의 리버스 프록시 서버를 두고 서버의 요청과 사용자의 요청을 대신 받는다.

클라이언트는 리버스 프록시 서버 뒷단의 WAS 존재를 알지 못하기에 보안이 강화된다. 또한 기존에 직접 ip주소에 요청을 보냈지만 클라이언트는 이제 ip주소가 아닌 도메인에 요청만 보내면 된다.

리버스 프록시 서버에 SSL 인증서를 발급하여 HTTPS를 적용한다. WAS 서버가 여러대로 늘어나도 SSL 인증서 발급을 추가로 하지 않아도 되어 확장성이 좋다.`

리버스 프록시 적용을 하면서 보안성, 확장성, 그리고 관리의 편의성이 모두 향상된 인프라 환경을 구축할 수 있었다.

참고 자료#

nginx를 통한 리버스 프록시 설정
저자
Joonyoung Hwang
게시일
2025-03-15