미들웨어

Nginx로 중계서버(Reverse Proxy) 구성해보기

nayoungs 2024. 12. 16. 21:37
728x90

Nginx는 대표적인 웹 서버(Web Server, WS)로, 리버스 프록시(Reverse Proxy) 역할의 중계 서버로도 사용할 수 있다. 오늘은 Nginx를 통해 중계 서버(리버스 프록시)를 구성해보자.

 

Nginx란?

Nginx는 가벼우면서도 고성능을 제공하여, 현재 많은 사랑을 받고 있는 웹 서버이다. 리버스 프록시, 로드 밸런서 등 다양한 용도로 활용된다. Nginx에 대해서는 자세히 다뤄본 포스팅(역사와 구조 등)이 있으니 참고할 수 있다.

 

웹 서버의 성장 : Nginx와 Apache

엔지니어라면 대표적인 웹 서버(Web Server, WS)인 Nginx와 Apache를 사용해본 경험이 있을 것이다. Nginx는 2021년을 기준으로 아파치(Apache) 서버를 제치고, 전 세계 HTTP/HTTPS 서버 점유율 1위를 기록했다.

nayoungs.tistory.com

오늘은 Nginx의 설정 파일인 nginx.conf 를 작성해보며, 중계 서버(리버스 프록시 서버)로 활용해보자.

 

nginx.conf

nginx.conf는 Nginx의 핵심 설정 파일로, Nginx 서버의 동작 방식을 정의하는 파일이다. 주로 다음과 같은 설정들을 포함한다:

  • 서버의 기본 동작 설정 (워커 프로세스 수, 로깅 등)
  • 가상 호스트(Virtual Host) 설정
  • 프록시 설정
  • SSL/TLS 설정
  • 캐시 설정

설정 파일은 기본적으로 /etc/nginx/nginx.conf 경로에 위치하며, 계층 구조로 구성된다.

 

기본 구조

아래 Sample은 Nginx를 웹 서버로서 활용할 때의 대표적인 기본 설정이다.

# 메인 컨텍스트
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;

# 이벤트 컨텍스트
events {
    worker_connections 1024;
}

# HTTP 컨텍스트
http {
    # 서버 컨텍스트
    server {
        listen 80;
        server_name example.com;
  
        access.log /var/log/nginx/access.log
        keepalive_timeout 65;
        
        # 로케이션 컨텍스트
        location / {
            root /usr/share/nginx/html;
            index index.html;
        }
    }
}

각 컨텍스트는 특정한 범위의 설정을 담당하며, 중괄호({})를 사용하여 계층 구조를 형성한다. 이러한 구조적 특성 덕분에 설정을 체계적으로 관리할 수 있다.

 

중계 서버(리버시 프록스)의 관점에서 설정을 더 살펴보자. 중계 서버로서 Nginx는 클라이언트의 요청을 받아 내부의 다른 서버로 전달하고, 그 서버의 응답을 클라이언트에게 다시 전달하는 역할을 한다.

http {
    upstream server1 {
        server server1.example.com;
    }
    
    upstream server2 {
        server server2.example.com;
    }

    server {
        listen 80;
        server_name example.com;
        
        #ssl 설정
        #ssl_certificate /app/ssl/nginx/prox_ssl/access.log;
        #ssl_certificate_key /app/ssl/...key
        
        #ssl_session_cache shared:SSL:1m;
        #ssl_session_timeout 5m;
        #ssl_protocols TLSv1.2 TLSv1.3;
        
        #ssl_ciphers HIGH:!aNULL:!MD5;
        #ssl_prefer_server_ciphers on;

        # 로그 설정
        access_log /var/log/nginx/access.log;  # 접근 로그 파일 설정
        error_log /var/log/nginx/error.log;    # 에러 로그 파일 설정

        location /server1 {
            proxy_pass <http://server1>;  # HTTP 요청을 server1으로 전달
        }

        location /server2 {
            proxy_pass <http://server2>;  # HTTP 요청을 server2로 전달
        }
    }
}

stream {
    upstream tcp_backend {
        server tcp1.example.com:12345;  # TCP 요청을 처리할 서버
        server tcp2.example.com:12345;  # 또 다른 TCP 서버
    }

    server {
        listen 12345;  # TCP 요청을 수신할 포트
        proxy_pass tcp_backend;  # TCP 요청을 tcp_backend로 전달

        # TCP 로그 설정
        access_log /var/log/nginx/tcp_access.log;  # TCP 접근 로그 파일 설정
        error_log /var/log/nginx/tcp_error.log;    # TCP 에러 로그 파일 설정
    }
}

http

http 요청을 처리하는 설정을 포함하는 블록이다. upstream , server 블록 등이 하위에 작성된다.

upsream 블록

라우팅할 서버를 정의하는 블록이다. 여러 대의 서버를 정의할 수 있다.

예를 들어 다음과 같이 여러 대를 작성하면, 2개의 서버에 로드밸런싱된다.

upstream server1 {
	server server11.example.com;
	server server12.example.com;
}

server

http 요청을 수신하고 처리하는 서버 블록이다. listen 은 요청을 수신할 포트를, server_name 은 서버 블록이 응답할 도메인을 설정한다.

server {
    listen 80;
    server_name example.com;

location

location은 특정 경로로 들어오는 요청을 처리하는 블록이다.

다음과 같이 작성하면 /server1 경로로 들어오는 요청을 upstream server 으로 전달한다.

location /server1 {
    proxy_pass <http://server1>;  # HTTP 요청을 server1으로 전달
}

stream

tcp/udp 요청을 처리하는 설정을 포함하는 블록이다.

upstream tcp_backend {
    server tcp1.example.com:12345;  # TCP 요청을 처리할 서버
    server tcp2.example.com:12345;  # 또 다른 TCP 서버
}

 

Nginx 중계 서버 구축하기

다음 그림과 같이 Nginx 서버로 요청을 보냈을 때 Server1과 Server2로 라우팅되도록 구성해보자.

  • nginx-server.com:3000/server1http://server1:5000
  • nginx-server.com:3000/server2http://server2:4000

다음과 같이 nginx를 구성할 수 있다.

nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;

events {
    worker_connections 1024;  
}

# HTTP 블록
http {
    include mime.type;
    default_type application/octet-stream;
	send_file on;
    keepalive_timeout 65;


    upstream server1 {
        server 54.242.167.98:5000;
    }

    upstream server2 {
        server 3.81.137.250:4000;
    }

    server {
        listen 3000;
        server_name example.com;

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;
        

        location /server1 {
            proxy_pass http://server1;  # HTTP 요청을 server1으로 전달
        }

        location /server2 {
            proxy_pass http://server2;  # HTTP 요청을 server2로 전달
        }
    }
}

nginx -t 를 통해 nginx.conf 파일의 문법을 검사할 수 있다.

syntax is ok 가 표시된다면, 문법적으로는 오류가 없다는 것이다.

$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

nginx 기동하기

$ nginx 

기동 후 다음과 같이 nginx 프로세스가 떠 있는 것을 확인할 수 있고,

$ ps -ef | grep nginx
root        4504       1  0 12:35 ?        00:00:00 nginx: master process nginx
www-data    5172    4504  0 12:36 ?        00:00:00 nginx: worker process
ubuntu      5230    1112  0 12:36 pts/0    00:00:00 grep --color=auto nginx

netstat 로 확인해보면, 3000 번 포트를 리스닝 중인 것을 확인할 수 있다.

$ netstat -anp | grep LISTEN
(No info could be read for "-p": geteuid()=1000 but you should be root.)
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.54:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:3000            0.0.0.0:*               LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      -                   
unix  2      [ ACC ]     STREAM     LISTENING     8287     -                    /var/lib/amazon/ssm/ipc/health
unix  2      [ ACC ]     STREAM     LISTENING     8288     -                    /var/lib/amazon/ssm/ipc/termination
unix  2      [ ACC ]     STREAM     LISTENING     8950     -                    /run/user/1000/systemd/private
unix  2      [ ACC ]     STREAM     LISTENING     8960     -                    /run/user/1000/bus
unix  2      [ ACC ]     STREAM     LISTENING     8964     -                    /run/user/1000/gnupg/S.dirmngr
unix  2      [ ACC ]     STREAM     LISTENING     8966     -                    /run/user/1000/gnupg/S.gpg-agent.brow
....

server1, server2 각각에는 간단한 Flask 앱을 실행하여, 자신의 서버를 확인하는 텍스트를 출력할 수 있도록 해보자.

from flask import Flask
app = Flask(__name__)

@app.route('/')
def home():
    return "I am server1!"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000) #server2는 port=4000으로

Flask 앱을 통해 server1/ 으로 요청을 보내면 다음과 같이 I am Server1! 을 출력한다.

$ curl localhost:5000
I am server1!

이제 Nginx 중계서버로 요청을 보내보자.

---

/server1 으로 보냈을 때는 1번 서버의 5000번 포트로,

$ curl http://nginx-server.com:3000/server1
I am server1!

/server2 로 보냈을 때는 2번 서버의 4000번 포트로 잘 중계되는 것을 확인할 수 있다.

$ curl http://nginx-server.com:3000/server2
I am server2!

이처럼 Nginx는 웹 서버 뿐만 아니라, 리버시 프록시 서버로서의 기능을 제공하여 다양하게 활용될 수 있다.

지금까지 Nginx를 중계서버(리버스 프록시 서버)로 구성하는 것을 진행해보았다.

 

 

Reference

 

 

 

728x90