나만의 블로그 만들기 - 4. 초보자를 위한 Nginx, 프록시 서버 사용하기

Nginx?

하나의 마스터 프로세스와 여러개의 워커 프로세스를 가지고 있다. 마스터 프로세스의 목적은 설정들을 읽고 평가하며 워커 프로세스를 관리하는 것이다. 워커 프로세스는 실제 요청을 처리한다. 이벤트 기반의 모델을 채용했고 운영체제에 의존적인 메커니즘을 사용해서 요청을 워커 프로세스에게 효과적으로 분산한다. 워커 프로세스의 수는 설정 파일에 정의되어 있고 아마 고정된 수이거나 자동적으로 이용가능한 cpu 코어 수에 따라 맞춰진다. 아래의 표를 참고하자.

  • 워커 프로세스 수 정의하기
Syntax:worker_processes number | auto;
Default:worker_processes 1;
Context:main
🦦

최적의 값은 cpu 코어의 수, 데이터를 저장하는 디스크의 수, 불러오는 방식을 포함하여 많은 요소에 의존하는데, 처음에는 이용가능한 cpu 코어 수 만큼 설정하는 것이 좋은 시작이다. auto 값을 사용하면 알아서 이용가능한 코어 수를 찾아서 해준다.

The auto parameter is supported starting from versions 1.3.8 and 1.2.5.
참조링크


nginx 와 모듈들의 작동 방법은 설정 파일에 정의되어 있다. 기본적으로, 설정 파일은 nginx.conf 라는 이름이고 /usr/local/nginx/conf, /etc/nginx, or /usr/local/etc/nginx 폴더에 위치한다.

시작, 정지, 설정파일 재로딩

nginx 를 시작하려면 실행가능한 파일 을 실행하면 된다. 한번 시작되면 실행파일을 -s 파라미터와 함께 실행함으로써 조작이 가능하다. 다음과 같은 문법이다.nginx -s 신호들

  • 실행가능한 파일

설치된 nginx 의 실행 파일을 의미한다. 우분투에서 file 명령어로 해당 파일의 타입을 출력했고, which 명령어를 통해 nginx 의 경로를 변수로 사용했다. which 명령어는 PATH 에 등록되어 있는 결과가 나온다.

ubuntu@muleo:~$ file $(which nginx)
/usr/sbin/nginx: ELF 64-bit LSB pie executable,
bash

나는 /usr/sbin/nginx 이라는 executable 파일을 실행하면 nginx 가 시작된다.


신호들 은 다음 4가지 중 하나이다.

  • stop — 빠른 강제종료
  • quit — 우아한 강제종료
  • reload — 설정파일 재로딩
  • reopen — 로그 파일 다시열기 (로그 파일 회전, 교체

예를 들어, 워커 프로세스들에게 할당된 현재 요청까지 끝낸 후에 nginx 프로세스들을 정지하고 싶다면 다음 명령어를 실행하면 된다.

nginx -s quit
🦦

이 명령어는 무조건 nginx 를 실행한 사용자와 같은 사용자가 실행해야 합니다.

변경된 설정파일은 리로드 명령어가 실행되기 전 또는 재시작 전까지는 반영되지 않는다. 설정파일을 리로드 하려면 다음 명령어를 실행하면 된다.

nginx -s reload

마스터 프로세스가 설정파일 리로드 신호를 받으면, 문법을 확인하고 설정들을 적용한다. 만약 성공하면, 마스터 프로세스는 새로운 워커 프로세스들을 시작하고, 기존의 워커 프로세스들에게 종료될 것을 요청한다. 실패하면, 변경사항을 원래대로 되돌리고 옛날 설정으로 지속된다. 종료를 요청받은 이전 워커 프로세스들은 새로운 연결을 맺는 것을 그만두고 받았던 요청이 완료될 때 까지 지속된다. 그다음 종료된다.


kill 같은 유닉스 명령어로 nginx 프로세스들에게 신호가 전달될 때가 있는데, 이런 경우 주어진 프로세스 ID 에 해당되는 프로세스로 직접 전달된다. 마스터 프로세스의 ID 는 nginx.pid 파일에 적혀있다. 파일의 경로는 nginx.conf 파일에 써있다. 기본 경로는 /usr/local/nginx/logs/nginx.pid 이다

ubuntu@muleo:~$ cat /etc/nginx/nginx.conf 
user www-data;
worker_processes auto;
pid /run/nginx.pid;
bash
ubuntu@muleo:~$ cat /run/nginx.pid 
1125
bash

예를 들어 마스터 프로세스의 ID 가 1125 라면 다음 명령은 quit 신호로 우아한 종료를 하게 된다.

kill -s QUIT 1628

이 신호말고 여러가지 신호들이 있는데, 관심이 있다면 여기 를 참고하자. 모든 신호는 kill 명령어와 함께 써주면 된다.


실행되고 있는 모든 nginx 프로세스를 보려면 다음과 같이 하면 된다.

ps -ax | grep nginxps -ax | grep nginx

설정 파일 구조

nginx 는 설정파일에 있는 지시문에 의해 조작되는 모듈들로 구성되어 있습니다. 이 지시문들은 간단한 지시문들과 블록 지시문들로 나뉩니다. 간단한 지시문은 이름과 파라미터가 공백으로 구분되고 끝에 세미콜론을 붙여줍니다. 블록 지시문은 간단한 지시문과 같은 구조를 가지지만, 끝의 세미콜론 대신에 중괄호로 감싸진 추가적인 지시사항들의 집합이 있습니다. 만약 블록 지시문이 중괄호 안에 다른 지시문들을 가진다면 이 지시문은 context 라고 불립니다. (예를 들어 events, http, server, location 이 있습니다)

설정 파일에 있고 context 밖에 존재하는 지시문들은 main context 안에 있는 것으로 여겨집니다. main context eventshttp 가 있고, http 안에는 server 가, server 안에는 location 이 있습니다.

  • main
    • events
    • http
      • server
        • location

주석은 # 로 표기합니다.

정적 콘텐츠 제공하기

웹서버는 파일을 제공하는 중요한 작업을 합니다. 이미지나 정적 HTML 페이지 등등. 파일이 요청에 따라 다른 폴더들로 부터 제공되는 예제를 구현해봅시다. /data/www 경로는 HTML 파일을 포함하고 있고, /data/images 경로는 이미지를 가지고 있습니다. 일단 설정 파일을 편집할 필요가 있습니다. 2 개의 location 블록을 가지는 server 블록을 http 블록 안에 설정해봅시다.

다음과 같은 구조로 선언해봅시다.

  • http
    • server
      • location
      • location

첫번째로, /data/www 폴더를 일단 만들고 index.html 파일을 넣어줍시다. 그리고 /data/images 폴더를 만들고 이미지도 몇개 넣어줍시다.

다음으로, 설정파일을 엽시다. server 블록을 포함하는 기본 설정파일이 이미 있을 텐데, 대부분 주석처리 되어 있을 겁니다. 다른 모든 블록을 주석 처리하고, 새롭게 server 블록을 만들어 줍시다.

# 설정 파일
http {
server {
}
}
bash

일반적으로, 설정 파일은 여러개의 server 블록을 가지고 있고 구분될 수 있게 포트와 이름들을 가지고 있습니다. nginx 에서 어떤 server 가 요청을 처리할지 결정할때, 요청 헤더에 있는 URL 와 location 지시문들에 있는 파라미터를 비교합니다.

location 블록을 server 블록에 추가해줍시다.

# 설정 파일
http {
server {
location / {
root /data/www;
}
}
}
bash

여기서 location 블록에 prefix 인 / 를 적어줬는데, 이걸 요청의 URI 랑 비교합니다. 만약 일치한다면, 로컬 파일 시스템에서 요청된 파일을 찾기위해 root 지시문에 추가적으로 선언된 경로를 URI 에 더해서 로컬 파일 시스템에 대한 경로를 만듭니다. 만약 일치하는 location 블록이 많다면 가장 긴 prefix 를 가지고 있는 location 블록을 선택합니다. 이 예제에서 제공한 location 블록은 단순 길이 1짜리인 prefix 로 일치하는 경로 중에서 우선순위가 제일 낮습니다.

다음으로, 새로운 location 블록을 추가해줍시다.

# 설정 파일
http {
server {
location / {
root /data/www;
}
location /images {
root /data;
}
}
}
bash

설명하자면, /images/ 로 시작하는 요청이 올때 일치하게 되는 새로운 location 을 추가했습니다.(물론 그 요청은 / 에도 일치한다)

이미 이 구성 자체로 80 번 포트로 열려있는 서버를 설정되고, http://localhost/ 로 접근 가능해집니다. /images 로 시작하는 요청들은 서버가 /data/images 폴더에 있는 파일들을 보내줄것입니다. 예를 들어, http://localhost/images/example.png 요청은 /data/images/example.png 파일은 보내줄 것입니다. 만약 이 파일이 없다면, 404에러에 해당하는 응답을 보내줍니다. 다른 경로는 /data/www 폴더에서 제공할 것입니다. 예를 든다면, http://localhost/some/example.html 요청은 /data/www/some/example.html 파일로.

이제 새로운 설정 파일을 적용하기 위해서, 아직 시작을 안했다면 시작을 해주고, reload 신호를 마스터 프로세스에 보내줍시다.

nginx -s reload
🦦

뭔가 잘 안된다면, 그 이유를 로그파일에서 볼 수 있습니다.
access.log and error.log files in the directory /usr/local/nginx/logs or /var/log/nginx.

간단한 프록시 서버 설정하기

nginx 의 주요 사용처 중 하나는 프록시서버를 만들 때 입니다. 프록시 서버는 요청을 받아서 정해진 서버로 전달하고 응답을 다시 클라이언트에세 보내주는 서버를 의미합니다.

간단한 프록시 서버를 구성해봅시다. 이미지에 대한 요청을 받으면 이 요청 모두 프록시 서버가 처리하도록 합시다. 여기서는 2개 서버 모두 하나의 nginx 로 처리합니다.

server 블록을 다음과 같이 하나 더 만듭시다.

# 프록시 된 서버 구성
server {
listen 8080;
root /data/up1;

location / {
}
}
bash

8080 포트에서 수신하는 간단한 서버입니다. ( listen 지시문은 80 포트를 사용할 것이라면 적어주지 안아도 됩니다.) 그리고 모든 경로에 대해 /data/up1 로 매핑하고 있습니다. 여기서 봐야할 것은 root 지시문이 server context 에 위치한다는 것입니다. 이 경우, root 지시문이 선언되지 않은 location 블록들을 위해 사용됩니다.

다음으로, 이전에 설정한 서버 구성을 사용해서 프록시 서버 구성으로 변경해봅시다. 첫번째 locatio 블록에서 proxy_pass 지시문을 프로토콜과 프록시된 서버의 이름과 포트 파라미터로 적어줍시다.

# 프록시 서버 구성
server {
location / {
proxy_pass http://localhost:8080;
}

location /images/ {
root /data;
}
}
bash

이번에는 두번째 location 블록을 특정 파일 확장자로 지정해서 일치할 수 있게끔 바꿔봅시다.

server {
location / {
proxy_pass http://localhost:8080/;
}

location ~ \.(gif|jpg|png)$ {
root /data/images;
}
}
bash

정규식은 무조건 ~ 가 앞에 들어가야 하고, 여기서는 이미지 확장자로 끝나는 URI 들과 일치시켰습니다. 우선순위는 정확하게 매칭되는 것이 첫번째이고, 그다음은 정규 표현식 매칭 그다음이 앞서 배운 길이 우선 입니다.

🦦

우선순위 정리

  1. 정확한 매칭
  2. 정규 표현식 매칭
  3. 길이 매칭 (접두어 매칭)
  4. ^~ 매칭

더 많은 프록시 관련 지시문들은 다음에 다루어 보겠습니다.