본문 바로가기

회고

[회고]nginx

nginx 애증의 도구이다.

 

nginx를 통해서 간편하게 로드밸런싱, 라우팅, 네트워크 설정... 할 수 있었지만,

간편한만큼 문제를 겪은 부분도 많았다.

 

특히 네트워크 CS 지식이 없었더라면, 문제가 생기더라도 확인하고, 수정할 수 없었을 것이다.

 

nginx에 대해서 간단히 소개하자면 아래와 같은 기능을 한다.

 

Nginx는 경량의 고성능 웹 서버, 리버스 프록시 서버, 메일 프록시 서버로, 주로 다음 기능에 사용된다:

  • HTTP 웹 서버: 정적 파일 제공, 리버스 프록시, 로드 밸런싱 등.
  • 리버스 프록시 서버: 클라이언트 요청을 백엔드 서버로 전달하고 그 결과를 반환.
  • 로드 밸런서: 여러 서버에 부하를 분산하여 처리.
  • SSL/TLS 처리: HTTPS를 지원하여 보안 통신 가능.

나는 4가지 기능을 전부 사용했다.

 

하나씩 기억 나는대로 작성하고자 한다.

1. 정적 파일 제공

frontend에서 nginx를 하나 따로 사용했다.

이 정적 파일 제공 기능을 사용하기 위함인데, index.html 파일, 이미지 파일 등..을 관리하기 편하게 하기 위해 사용했다.

예를 들어 403, 401오류가 나온다면 index.html 파일로 보낸다던지...

 

2. 리버스 프록시

클라이언트 요청을 선두로 먼저 받아서 백엔드 서버로 결과를 반환하는데, 

이 리버스 프록시 개념 자체는 중요한 개념이기 때문에 나중에 따로 자세히 다루겠다.

프로젝트에서는 ec2 인스턴스에서 nginx 처리를 통해서 백엔드 서버의 리버스 프로시를 다루었다.

 

3. 로드 밸런서

upstream에 docker로 배포한 같은 서버를 등록한다면 알아서 로드 밸런싱을 이룬다.

하지만 이번 프로젝트에서는 사용하지 않았다.

 

4. SSL/TLS 처리

HTTPS를 지원하기 위해 Let's Encrypt를 사용했다.

 

이 말고도 다른 설정도 진행했는데, 스크립트와 설명을 추가하겠다.

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       80;
        server_name  ssafy11s.com;

        # Redirect to www.ssafy11s.com
        return 301 http://www.ssafy11s.com$request_uri;
    }

    server {
        listen       80;
        server_name  www.ssafy11s.com;
        index index.html;

        location / {
            proxy_pass http://172.19.0.2:80;
            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_set_header X-Forwarded-Proto $scheme;
            try_files $uri $uri/ /index.html =404;
        }

        location /user/public {
            proxy_pass http://172.19.0.9: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_set_header X-Forwarded-Proto $scheme;
        }

        location /user {
            access_by_lua_file /etc/nginx/lua/jwt_checker.lua;
            proxy_pass http://172.19.0.9: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_set_header X-Forwarded-Proto $scheme;
        }
        
        location /profile {
            access_by_lua_file /etc/nginx/lua/jwt_checker.lua;
            proxy_pass http://172.19.0.9: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_set_header X-Forwarded-Proto $scheme;
        }

        location /problem {
            proxy_pass http://172.19.0.10:8081;
            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_set_header X-Forwarded-Proto $scheme;
        }

        location /multi {
            access_by_lua_file /etc/nginx/lua/jwt_checker.lua;
            proxy_pass http://172.19.0.11:8082;
            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_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_http_version 1.1;
        }

        location /ws-multi {
            proxy_pass http://172.19.0.11:8082;
            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_set_header X-Forwarded-Proto $scheme;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
        }

        location /rank {
            access_by_lua_file /etc/nginx/lua/jwt_checker.lua;
            proxy_pass http://172.19.0.12:8083;
            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_set_header X-Forwarded-Proto $scheme;
        }

        location /battle {
            access_by_lua_file /etc/nginx/lua/jwt_checker.lua;
            proxy_pass http://172.19.0.13:8084;
            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_set_header X-Forwarded-Proto $scheme;
        }

        location /ws-battle {
            proxy_pass http://172.19.0.13:8084;
            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_set_header X-Forwarded-Proto $scheme;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
        }

        location /ws-chat {
            proxy_pass http://172.19.0.14:8085;
            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_set_header X-Forwarded-Proto $scheme;
        }

        location /single/public {
            proxy_pass http://172.19.0.15:8086;
            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_set_header X-Forwarded-Proto $scheme;
        }

        location /single {
            access_by_lua_file /etc/nginx/lua/jwt_checker.lua;
            proxy_pass http://172.19.0.15:8086;
            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_set_header X-Forwarded-Proto $scheme;
        }

        listen [::]:443 ssl ipv6only=on; # managed by Certbot
        listen 443 ssl; # managed by Certbot
        ssl_certificate /etc/letsencrypt/live/ssafy11s.com/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/ssafy11s.com/privkey.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
    }

    server {
        listen 80;
        listen [::]:80;
        return 404; # managed by Certbot
    }
}

 

1. worker_processes 1;

  • Nginx는 하나의 워커 프로세스로 실행됨. (CPU 코어가 1개일 때 적합)

2. events 블록

  • worker_connections 1024;는 각 워커 프로세스가 동시에 처리할 수 있는 최대 연결 수를 1024개로 설정.

3. http 블록

  • mime.types 파일을 포함하여 파일 확장자에 따라 올바른 MIME 타입을 설정.
  • 기본적으로 MIME 타입이 없는 파일은 application/octet-stream으로 처리.
  • sendfile on;은 Nginx가 커널 기능을 사용해 파일을 효율적으로 전송하도록 설정.
  • keepalive_timeout 65;는 Keep-Alive 연결 유지 시간 65초로 설정.

4. 서버 블록 1

  • 포트 80에서 클라이언트 요청을 수신.
  • server_name ssafy11s.com;에서 도메인 이름 설정.
  • ssafy11s.com으로 요청이 들어올 경우, www.ssafy11s.com으로 리다이렉션.

5. 서버 블록 2

  • server_name www.ssafy11s.com;에서 www 서브도메인을 처리.
  • /로 들어온 요청은 proxy_pass http://172.19.0.2:80;로 리버스 프록시 설정.
  • proxy_set_header를 사용하여 클라이언트의 원래 IP 주소, 호스트 정보 등을 전달.
  • try_files를 사용하여 요청 경로에 파일이 없으면 /index.html로 리다이렉트. 404 오류 발생 시 404 반환.

6. /user/public, /user, /profile 경로

  • /user/public: proxy_pass로 172.19.0.9:8080 서버로 요청 전달.
  • /user, /profile: Lua 스크립트를 이용한 JWT 인증(jwt_checker.lua) 후 리버스 프록시 수행.

7. /problem, /multi, /ws-multi, /ws-battle 경로

  • 각각 다른 백엔드 서버로 요청 전달(proxy_pass).
  • WebSocket 연결 지원을 위해 Upgrade와 Connection 헤더 설정.

8. SSL 설정 (Certbot)

  • 443 포트에서 SSL을 사용해 HTTPS 통신.
  • Let's Encrypt를 통해 발급된 SSL 인증서를 사용하여 보안 통신 처리.
  • ssl_certificate와 ssl_certificate_key에서 인증서 경로 지정.
  • 추가로 보안 강화를 위한 ssl_dhparam 설정.

9. 서버 블록 3

  • 포트 80에서 404 응답을 반환해, 불필요한 HTTP 요청 차단.