[Nginx] 리버스 프록시

2024. 8. 4. 01:17BE/Nginx

 

 

NGINX Reverse Proxy | NGINX Documentation

NGINX Reverse Proxy Configure NGINX as a reverse proxy for HTTP and other protocols, with support for modifying request headers and fine-tuned buffering of responses. This article describes the basic configuration of a proxy server. You will learn how to p

docs.nginx.com

 

1. 리버스 프록시 설정법

 

위와 같이 path가 /일 경우는 react를 빌드한 정적인 파일을 주고 path가 /api/v1인 경우 8080 포트의 Spring-Boot 백엔드 서버로 요청을 전달한다.

 

#example.conf
server {
    listen 80;  # IPv4
    listen [::]:80; # IPv6

    server_name example.com;

    location / {
        root /app/build;
        try_files $uri /index.html;
    }

    location /api/v1/ {
        proxy_pass http://backend: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 /robots.txt {
        return 200 "User-agent: *\nDisallow: /";
    }
}

 


2. server block

server {
    listen 80;  # IPv4
    listen [::]:80; # IPv6

    server_name example.com;
    ...
}
  • listen 80; # IPv4
    : IPv4를 통해 포트 80에서 요청을 수신합니다.
  • listen [::]:80; # IPv6
    : IPv6를 통해 포트 80에서 요청을 수신합니다.
  • server_name example.com;
    : 서버의 도메인 이름을 설정합니다.
    : example.com의 도메인을 가진 경우에 대하여 실행한다.

 


3. 정적 파일 처리

location / {
    root /app/build;
    try_files $uri /index.html;
}
  • location / {
    : 루트 경로에 대한 설정을 정의합니다.
  • root /app/build;
    : 정적 파일의 루트 디렉터리를 /app/build로 설정.
  • try_files $uri /index.html;
    : 요청된 파일이 없으면 /index.html을 반환합니다.

 


4. 프록시 설정

location /api/v1/ {
    proxy_pass http://backend: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 /api/v1/ {...}
    : /api/v1의 경로를 가진 요청에 대하여 작업을 수행.

  • proxy_pass http://backend:8080;
    : 포트 번호 80번으로 들어온 /api/v1 요청을 8080번 http://backend:8080으로 보낸다.
    : 8080번 스프링부트는 http프로토콜로 /api/v1 + 나머지 url로 요청을 받는다.
    : backend는 docker network 내부에서 통신할 때 사용되는 이름이다. (아래 docker-compose.yml 참고)
    : http://example.com과 같은 url이나 특정 named group도 위치할 수 있다.

  • proxy_pass <http://backend:8080>;
    : 요청을 http://backend:8080으로 전달합니다.

  • proxy_set_header Host $host;
    : proxy 요청에 원래 호스트 헤더를 설정.

  • proxy_set_header X-Real-IP $remote_addr;
    : 클라이언트의 실제 IP를 X-Real-IP 헤더에 설정.
    : 백엔드 서버가 실제 클라이언트의 IP를 알기 위함.
    : 로깅, IP 제한, 지리적 위치 서비스 등에 사용.

  • proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    : 클라이언트의 IP와 경유한 프록시 서버의 IP 목록을 전달.
    : 백엔드 서버가 전체 경로를 추적할 수 있게 함.

  • proxy_set_header X-Forwarded-Proto $scheme;
    : 프로토콜을 X-Forwarded-Proto 헤더에 설정.
    : 프로토콜이 http인지 https인지 알기 위함.
    : 보안 분석, 트래픽 분석 등에 사용.

 


5. 로봇 접근 제한

# Disallow all bots
location /robots.txt {
    return 200 "User-agent: *\nDisallow: /";
}
  • location /robots.txt {return 200 "User-agent: *\\nDisallow: /"; }
    : 모든 봇의 접근을 차단.

 

여기서 말하는 로봇이란 웹 크롤러나 스크래퍼와 같은 자동화된 봇을 의미한다.

 

웹사이트를 방문하여 정보를 수집하거나 인덱싱을 수행한다.

 


6. Buffer 설정

 

예시에는 없지만 Buffer에 대한 설정도 추가할 수 있다.

 

기본적으로 Nginx는 프록시된 서버의 응답을 버퍼링 한다.

 

응답은 내부 버퍼에 저장되며 전체 응답을 받을 때까지 클라이언트로 전송되지 않는다.

 

버퍼링은 비교적 처리 속도가 느린 클라이언트와의 통신에서 성능 최적화에 도움이 된다.

 

응답이 Nginx에서 클라이언트로 동기적으로 전달될 경우 프록시된 서버(보통 WAS)가 클라이언트의 처리속도에 맞춰야 하기에 시간이 낭비될 수 있다.

 

버퍼링이 활성화되면 프록시된 서버는 응답을 Nginx에게 주고, NGINX는 클라이언트가 다운로드하는 데 필요한 시간 동안 응답을 저장한다.

 

proxy_buffering이란 지시어로 버퍼링을 활성화 및 비활성화할 수 있다.

 

location /some/path/ {
    proxy_buffers 16 4k;
    proxy_buffer_size 2k;
    proxy_pass http://localhost:8000;
}
  • proxy_buffers
    : 요청에 할당된 버퍼의 크기와 수를 제어.
  • proxy_buffer_size
    : 프록시된 서버(WAS)에서 오는 응답의 첫 번째 부분은 별도의 버퍼에 저장된다.
    : 응답의 첫 번째 부분은 보통 이후의 응답과 비교해 응답 헤더의 크기가 작아서 나머지 응답을 위한 버퍼보다 작게 설정할 수 있다.

 

location /some/path/ {
    proxy_buffering off;
    proxy_pass http://localhost:8000;
}

버퍼링이 비활성화되면 응답이 프록시된 서버로부터 수신되는 동안 클라이언트에게 동기식으로 전송된다.

 

가능한 한 빨리 응답을 받아야 하는 경우 사용한다.

 

예를 들어 빠릿빠릿하게 반응해야 하는 대화형 클라이언트에게 바람직할 수 있겠다.

 

이 경우 Nginx는 당장 전달할 부분만 proxy_buffer_size 크기의 버퍼에 저장한다.

 


7. Outgoing IP 주소 설정

 

예를 들어 로드 밸런싱 같은 경우, 같은 요청을 여러 곳에서 처리하고 있다.

 

만약 특정한 요청만 특정한 곳에서 처리하게 만들고 싶다면 proxy_bind를 사용하면 된다.

location /app1/ {
    proxy_bind 127.0.0.1;
    proxy_pass <http://example.com/app1/>;
}

location /app2/ {
    proxy_bind 127.0.0.2;
    proxy_pass <http://example.com/app2/>;
}
  • /app1/ 경로로 들어오는 요청은 로컬 IP 127.0.0.1을 사용하여 http://example.com/app1/로 전달.
  • /app2/ 경로로 들어오는 요청은 로컬 IP 127.0.0.2을 사용하여 http://example.com/app2/로 전달.

 

proxy_bind 지시어로 IP 주소를 지정한다.

 

location /app3/ {
    proxy_bind $server_addr;
    proxy_pass <http://example.com/app3/>;
}

$server_addr 변수는 해당 요청을 수락하는 네트워크 인터페이스의 IP 주소를 의미한다.

 


 

이해를 돕기 위한 docker-compose.yml:

services:

  db:
    image: mysql:8.4.1
    volumes:
      - 'mysql_data:/var/lib/mysql'
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DB}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      TZ: Asia/Seoul
    healthcheck:
      test: [ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ]
      timeout: 20s
      retries: 10
    expose:
      - "3306"
    networks:
      - myNetwork
    container_name: db

  backend:
    depends_on:
      db:
        condition: service_healthy
    build:
      context: ./backend
      dockerfile: Dockerfile
    image: backend
    env_file: '.env'
    restart: 'always'
    environment:
      SPRING_PROFILES_ACTIVE: ${PROFILE}
      MYSQL_HOST: ${MYSQL_HOST}
      MYSQL_PORT: ${MYSQL_PORT}
      MYSQL_DB: ${MYSQL_DB}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      JWT_SECRET_KEY: ${JWT_SECRET_KEY}
      DDL_AUTO_OPTION: ${DDL_AUTO_OPTION}
      GOOGLE_CLIENT_NAME: ${GOOGLE_CLIENT_NAME}
      GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
      GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET}
      GOOGLE_REDIRECT_URI: ${GOOGLE_REDIRECT_URI}
      GOOGLE_AUTHORIZATION_GRANT_TYPE: ${GOOGLE_AUTHORIZATION_GRANT_TYPE}
      GOOGLE_SCOPE: ${GOOGLE_SCOPE}
      LIVEKIT_API_KEY: ${LIVEKIT_API_KEY}
      LIVEKIT_API_SECRET: ${LIVEKIT_API_SECRET}
      REDIRECT_URI: ${REDIRECT_URI}
    expose:
      - "8080"
    networks:
      - myNetwork
    container_name: backend

  frontend:
    depends_on:
      - backend
    build:
      context: ./frontend
      dockerfile: Dockerfile
      args:
        PROFILE: ${PROFILE}
    image: frontend
    volumes:
      - "/etc/nginx/:/etc/nginx/"
    restart: 'always'
    ports:
      - "80:80"
    container_name: frontend
    networks:
      - myNetwork

volumes:
  mysql_data:

networks:
  myNetwork:
    driver: bridge

'BE > Nginx' 카테고리의 다른 글

[Nginx] HTTPS 적용  (5) 2024.08.04
[Nginx] Nginx란?  (0) 2024.08.03