Search

Nginx

Nginx란?

경량화된 소프트웨어 웹 서버이다.
웹서버란 인터넷 네트워크 위에서 HTTP 프로토콜을 이용해 HTML, CSS, Javascript, image/mediafile과 같은 정적인 정보들을 웹 브라우저에 전송한다.
Nginx는 Single-thread로 동작하며 비동기 non-blocking I/O 이벤트 기반으로 요청을 처리한다. 따라서 적은 자원으로 효율적인 트래픽 처리가 가능하다.
멀티 스레드를 사용한다면 요청이 들어올 때마다 스레드가 생성되고 context-switching 횟수가 증가하므로 자원이 낭비될 수 있다.

Nginx의 기능

HTTP Server로서 정적 파일을 Serve 해준다
클라이언트(유저)로부터 요청을 받았을 때 WAS를 거치지 않고 요청에 맞는 정적 파일을 응답해주는 HTTP server로서 활용할 수 있다.
HTML, CSS 같은 정적인 리소스에 대한 요청을 Nginx가 처리해준다.
React의 build 된 파일들도 정적인 리소스라고 볼 수 있고 따라서 Nginx가 index.html 같은 메인 페이지를 랜더링 해줄 수 있다.
Reverse Proxy Server로서 Client와 Server를 중개해준다.
Reverse Proxy Server로서 Client의 Request와 Server의 Response를 중계하는 서버로 동작하게 할 수 있다. 이 과정에서 nginx는 로드밸런서로서의 역할을 수행할 수 있다.
동적으로 계산되거나 전달되어야 하는 사항들은 WAS에게 맡긴다.

Apache와 다른 점

Apache와 같은 웹서버는 클라이언트로부터 받은 요청을 처리할 때 새로운 프로세스 또는 쓰레드를 생성하여 처리합니다.
요청마다 쓰레드가 생성되므로 접속하는 사용자가 많으면 그만큼 쓰레드가 생성되어 CPU와 메모리 자원의 소모가 커집니다.
Nginx는 Event-Driven 구조로 동작하기 때문에 한 개 또는 고정된 프로세스만 생성하여 사용하고, 비동기 방식으로 요청들을 Concurrency 하게 처리할 수 있습니다.
위의 그림에서 보이듯이 Nginx는 새로운 요청이 들어오더라도 새로운 프로세스와 쓰레드를 생성하지 않기 때문에 프로세스와 쓰레드 생성 비용이 존재하지 않고, 적은 자원으로도 효율적인 운용이 가능합니다.
이러한 Nginx의 장점 덕분에 단일 서버에서도 동시에 많은 연결을 처리할 수 있습니다.

Nginx의 구조

Nginx는 하나의 Master Process와 다수의 Worker Process로 구성되어 실행됩니다.
Master Process는 설정 파일을 읽고, 유효성을 검사합니다. 그리고 Worker Process를 관리합니다.
모든 요청은 Worker Process에서 처리합니다.
Nginx는 이벤트 기반 모델을 사용하고, Worker Process 사이에 요청을 효율적으로 분배하기 위해 OS에 의존적인 메커니즘을 사용합니다.
Worker Process의 개수는 설정 파일에서 정의되며, 정의된 프로세스 개수와 사용 가능한 CPU 코어 숫자에 맞게 자동으로 조정됩니다.

Proxy Server

클라이언트가 데이터를 요청하면 중간에 클라이언트의 요청을 서버로 보내주는 Proxy라고 불리는 서버가 하나 존재한다.
클라이언트와 서버가 서로 직접적으로 통신하지 않고, 프록시 서버를 이용해서 리소스를 전달하며 보안, 트래픽 분산, 캐시 사용(속도 향상) 등 여러 장점을 가지는 중요한 서버이다.

Forward Proxy

클라이언트가 외부 인터넷에 직접 접근하는 것이 아니라
Proxy Server에 외부 인터넷 접근 요청을 하고
Proxy Server가 외부 인터넷에 대신 접속하여 결과를 받은 후
클라이언트에 전달하는 서버
포워드 프록시 방식은 정해진 사이트에만 연결이 가능하게끔 설정이 가능해서
주로 회사 내부의 인트라넷 등 보안이 중요한 환경에서 주로 사용된다.

Reverse Proxy

클라이언트가 Reverse Proxy에 요청하면
Reverse Proxy가 관련 요청에 따라 적절한 내부 서버에 접속하여
결과를 받은 후 클라이언트에 전달하는 서버
리버스 프록시 서버는 실제 서버가 어디서 동작하는지 감추는 역할을 한다.
클라이언트는 리버스 프록시를 통해서 리소스를 요청하기 때문에 서버의 IP주소를 알 수 없다.
그리고 리버스 프록시 서버는 실제 서버들에 대한 주소를 매핑하고 있어야 한다.

Nginx에서 제공하는 로드밸런싱 방법

Round Robbin
운영체제 스케줄링 방법에도 있는 방식이다. 주어진 서버들을 순차적으로 돌아가면서 선택하는 방법이다.
Least-connected
현재 접속자 수가 가장 적은 서버를 선택하는 방법이다.
ip-hash
hash function을 사용해서 클라이언트 ip를 hash 한 결과에 따라서 다른 서버를 할당해주는 방법이다.

nginx.conf 설정

nginx가 작동하는 방식을 결정하는 구성파일로 /etc/nginx/nginx.conf 이 위치에 존재
크게 user, worker_processes, pid, events, http 항목으로 이루어짐
sites-enabled 폴더는 sites-available 폴더의 심볼릭 링크 폴더
sites-available 폴더에 파일을 작성하면 sites-enabled 폴더에 넣어진 것으로 보고 nginx.conf의 http 항목에서 include를 통해 설정이 적용됨
user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; use epoll; } http { include /etc/nginx/conf.d/*.conf; include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_arrd - $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; client_max_body_size 75M; server_tokens off upstream docker-nginx { server nginx:80; } upstream docker-apache { server apache:80; } server { listen 80 default_server; listen [::]:80 default_server; ... root /var/www/html; ... index index.html index.htm index.nginx-debian.html; ... server_name _; ... location / { try_files $uri $uri/ =404; ... rewrite regex URL break; ... proxy_pass http://docker-apache; proxy_redirect off; 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-Host $server_name; proxy_set_header X-Forwarded-Proto $scheme; } } }
Shell
복사
user
worker 프로세스를 실행할 사용자를 설정하고 이 사용자에 따라 권한이 달라질 수 있다.
worker_processes
이벤트를 처리하는 프로세스의 수를 정의하는 지시어이다.
일반적으로 CPU의 core 수만큼 할당하고, auto로 설정하면 자동으로 값을 알맞게 설정
error_log
오류 로그를 남길 파일 경로 지정
pid
NGINX 마스터 프로세스 ID 를 저장할 파일 경로 지정
events
worker_connections
하나의 프로세스가 동시에 몇 개의 연결을 처리할 수 있는지 설정해준다
보통 512 또는 1024로 설정한다
use
Linux에서 socket을 관리하는 데 사용하는 방식
epoll : 현재 활성화 된 소켓만 확인해서 연결을 설정
poll : 해당 프로세스에 연결된 모든 connection file을 스캔
select : 해당 프로세스에 연결된 모든 connection file을 스캔
http
include
파일을 읽어들임
default_type
기본 MIME 타입 설정
log_format
엑세스 로그 포멧 설정
access_log
엑세스 로그 저장경로
sendfile
응답을 보낼 때 user 영역 buffer가 아닌 kernel file buffer를 사용
keepalive_timeout
타임아웃 시간 설정
client_max_body_size
nginx를 통해서 이동하는 파일의 최대 크기를 지정해 줄 수 있는 지시어
server_tokens
nginx 버전을 숨길 수 있다. (보통 숨기는게 일반적)
upstream
컨테이너별 server 설정
server
listen
listen은 HTTP 요청을 받을 포트를 설정
default_server는 모든 웹서버 요청을 받는다는 의미
두번째 listen은 IPv6 포트 관련 설정
root
요청이 왔을 때 응답해줄 HTML 파일이 있는 폴더의 경로
index
HTML 파일의 이름 리스트 (앞에서부터 찾음)
server_name
요청을 받을 도메인 이름 설정
localhost나 별도 도메인 이름이 없다면 기본 설정
location
URI에 대한 파일을 찾고 없다면 404 응답을 하는 설정
location 문단을 추가하며 URI 매핑 가능
location 문단 내에 root 설정 가능
rewrite를 통해 내부 서버에 요청할 URL을 변경할 수 있음
proxy 설정은 실제 클라이언트의 정보를 내부 서버에 전달하기 위한 설정

error_page 설정

error_page 403 404 405 406 411 497 500 501 502 503 504 505 /error.html; location = /error.html { root /usr/share/nginx/html; }
Shell
복사

캐시 설정

location ~* \.(ico|css|js|gif|jpe?g|png)$ { expires max; add_header Pragma public; add_header Cache-Control "public, must-revalidate, proxy-revalidate"; }
Shell
복사

Nginx 명령

$ service nginx restart #재시작
Shell
복사

nginx.conf 샘플

#유저, 권한 설정 user nginx; #worker process의 수 설정 worker_processes auto; #daemon 설정 daemon off; #error log 경로와 master process의 경로 설정 error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid; #네트워크 작동환경 설정 events { #한 개의 worker process가 동시에 처리할 수 있는 connection의 수 worker_connections 1024; } #http 관련 설정 http { #mime.types 파일 불러오기 include /etc/nginx/mime.types; #기본 타입 설정 default_type application/octet-stream; #엑세스 로그 포맷 설정 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 api 설정 sendfile on; #타임아웃 시간 설정 keepalive_timeout 65; #nginx 버전 가리기 server_tokens off; #호스트 설정 server { #http 요청을 받을 포트 설정(default_server는 모든 서버로부터 요청 받음) listen 80 default_server; #IPv6에 대한 설정 listen [::]:80 default_server; #요청을 받을 도메인 이름 설정 server_name _; #URI 매핑 설정 location / { #지원되지 않는 HTTP 메소드 차단 if ($request_method !~ ^(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)$) { return 405; } proxy_pass http://localhost:8080; proxy_redirect off; 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-Host $server_name; proxy_set_header X-Forwarded-Proto $scheme; } } }
JavaScript
복사