Backend&Devops/Nginx

[Nginx] 리버스 프록시(Reverse Proxy) 개념 및 사용법

기은P 2022. 6. 3. 16:32
반응형

1. 개요

리버스 프록시란? 클라이언트 요청을 대신 받아 내부 서버로 전달해주는 것을 리버스 프록시(Reverse Proxy) 라고 합니다.

저도 사실 프록시라는 개념이 낯설었는데요, 일단 프록시라는 개념부터 확인해야 합니다.

프록시란 대리라는 의미로, 정보를 대신 전달해주는 주체라고 생각하면 되는데, 만약 이 프록시 없이 웹 서버를 운영한다고 가정합니다.

 

localhost:3000

 

라고 하는 웹서버를 열어서 운영했을 때, 사용자가 갑자기 많아지거나, 웹서버가 그대로 노출되어 있기 때문에 보안적으로 위험성이 있겠죠? nginx를 사용하면 로드 밸런싱으로 부하를 줄여줄 수 있고, 분산 처리 또한 가능하며 웹서버의 SSL 인증도 적용할 수 있습니다.

 

따라서 아래와 같이 사용자 -> nginx -> 웹서버로 구성해서 사용자의 요청을 nginx가 대신 웹서버로 전달해주도록 구성합니다.

출처: https://velog.io/@chickenfondue/nginx-docker-compose%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EB%A6%AC%EB%B2%84%EC%8A%A4-%ED%94%84%EB%A1%9D%EC%8B%9C-%EA%B5%AC%EC%84%B1

 

 

 

 

2. 리버스 프록시의 장점

장점은 아래와 같습니다.

  • 로드 밸런싱 : Nginx는 클라이언트의 요청을 프록시 서버에 분산하기 위해 로드 밸런싱을 수행하여 성능, 확장성 및 신뢰성을 향상시킬 수 있습니다.
  • 캐싱 : Nginx를 역방향 프록시로 사용하면 미리 렌더링된 버전의 페이지를 캐시하여 페이지 로드 시간을 단축할 수 있습니다. 이 기능은 프록시 서버의 응답에서 수신한 콘텐츠를 캐싱하고 이 콘텐츠를 사용하여 매번 동일한 콘텐츠를 프록시 서버에 연결할 필요 없이 클라이언트에 응답하는 방식으로 작동합니다.
  • SSL 터미네이션 : Nginx는 클라이언트와의 연결에 대한 SSL 끝점 역할을 할 수 있습니다. 수신 SSL 연결을 처리 및 해독하고 프록시 서버의 응답을 암호화합니다.
  • 압축 : 프록시 서버가 압축된 응답을 보내지 않는 경우 클라이언트로 보내기 전에 응답을 압축하도록 Nginx를 구성할 수 있습니다.
  • DDoS 공격 완화 : 수신 요청과 단일 IP 주소당 연결 수를 일반 사용자에게 일반적인 값으로 제한할 수 있습니다. 또한 Nginx를 사용하면 클라이언트 위치와 "User-에이전트" 및 "Referer"와 같은 요청 헤더 값을 기준으로 액세스를 차단하거나 제한할 수 있습니다.

 

 

 

3. 코드

nginx.conf

user nginx;
worker_processes  auto;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
events {
    worker_connections  1024;
}
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

	# 백엔드 upstream 설정
    # upstream myweb-api {
    #     server api:8080;
    # }

	# 프론트엔드 upstream 설정
    upstream next-server {
        server 172.17.0.1:3000; # docker를 사용하지 않는다면 localhost:3000(웹서버주소)
    }

    server {
        listen 80;

		# /api 경로로 오는 요청을 백엔드 upstream 의 /api 경로로 포워딩
        # location /api {
        #     proxy_pass         http://myweb-api/api;
        # }

		# / 경로로 오는 요청을 프론트엔드 upstream 의 / 경로로 포워딩
        location / {
            proxy_pass         http://next-server/;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }
    }
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    keepalive_timeout  65;
    # include /etc/nginx/conf.d/*.conf;
}

 

주의깊게 봐야할 부분은 http 블럭 안의 upstream 블럭과 server 블럭입니다.

 

1. 사용자가 nginx 서버 주소로 요청합니다(localhost:80). 기본적으로 http는 80포트를 사용하기 때문에 nginx에서는 listen 80포트로 구성합니다.

2. nginx서버는 location 블럭에서 proxy_pass로 지정된 주소로 요청을 전달해줍니다.

3. 만약 운영중인 서버가 localhost:8080, 혹은 localhost:3000이면 upstream 블럭에 localhost:8080, localhost:3000으로 적어줍니다.(필자는 docker-compose로 구성했기 때문에 172.17.0.1로 작성했습니다).

4. 웹서버(port 3000)를 시작하고, nginx도 시작해줍니다.

5. nginx 서버 주소로 요청하면(localhost:80), proxy_pass로 지정한 웹 서버로 요청이 전달됩니다.

 

 

4. docker-compose 사용시

 docker-compose.yml

version: "3.8"

networks:
  corp:
    driver: bridge

services:
  nginx_proxy:
    image: nginx:1.21.5-alpine
    container_name: nginx_proxy    
    ports:
      - 80:80
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf

  next-client:
    container_name: next-client
    build:
      context: ./
      dockerfile: ./Dockerfile
    ports:
      - 3000:3000

docker-compose.yml 폴더 위치에 nginx 폴더를 생성하고 nginx.conf 파일을 생성해줍니다.

nginx_proxy 블럭의 내용은 고정입니다.

밑의 next-client는 docker로 띄울 웹 서버의 정보입니다.

필자는 Next.js로 웹 서버를 만들었고, Dockerfile로 빌드하도록 설정했습니다.

 

 

 

참고

https://jjeongil.tistory.com/1490

 

https://velog.io/@chickenfondue/nginx-docker-compose%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EB%A6%AC%EB%B2%84%EC%8A%A4-%ED%94%84%EB%A1%9D%EC%8B%9C-%EA%B5%AC%EC%84%B1

 

반응형