NGINX 초보자 가이드: 설정 파일과 기본 운용

NGINX 초보자 가이드: 설정 파일과 기본 운용

NGINX를 처음 설치했을 때 가장 먼저 마주치는 것이 바로 '어떻게 시작하고, 설정을 어떻게 다시 읽히나'라는 질문이에요. 이 가이드는 이렇게 기본적인 운용 방법부터 설정 파일이 어떻게 생겼는지, 정적 콘텐츠를 서빙하고 리버스 프록시로 바꾸는 과정을 한 번에 잡아줄게요. NGINX가 이미 설치돼 있다고 가정하고 진행하니, 아직 설치 전이라면 설치 안내부터 확인해 주세요.

출처: NGINX 공식 문서 - Beginner's Guide

마스터 프로세스와 워커 프로세스

NGINX는 하나의 **마스터 프로세스(master process)**와 여러 **워커 프로세스(worker process)**로 나뉘어 동작해요. 마스터는 설정 파일을 읽고 해석하는 일, 그리고 워커 프로세스를 유지·관리하는 역할을 맡아요. 실제 요청 처리(HTTP 요청을 받아 응답을 돌려주는 일)는 전부 워커 프로세스가 담당하죠.

이벤트 기반 모델과 운영체제가 제공하는 메커니즘을 조합해 워커 프로세스 사이에 요청을 효율적으로 나눠주는데, 워커의 개수는 설정 파일에서 정할 수 있어요. 고정된 숫자 대신 가용 CPU 코어 수에 맞춰 자동으로 조정되게 할 수도 있는데, 이는 worker_processes 지시어로 제어해요.

설정 파일의 기본 이름은 nginx.conf고, /usr/local/nginx/conf, /etc/nginx, /usr/local/etc/nginx 같은 디렉터리에 위치해요.

시작, 중지, 설정 다시 읽기

NGINX를 시작하려면 실행 파일을 그냥 실행하면 돼요. 이미 실행 중일 때는 실행 파일에 -s 파라미터를 붙여 신호(signal)를 보내는 방식으로 조작해요. 신호에는 네 가지가 있어요.

nginx -s signal
  • stop — 빠른 종료
  • quit — 정상 종료 (현재 처리 중인 요청을 마칠 때까지 기다림)
  • reload — 설정 파일 다시 읽기
  • reopen — 로그 파일 다시 열기

예를 들어 워커 프로세스가 지금 응답 중인 요청을 마치도록 기다렸다가 종료하고 싶다면, NGINX를 시작한 것과 같은 사용자로 다음 명령을 실행하면 돼요.

nginx -s quit

설정 파일을 수정해도 reload 신호를 보내거나 재시작하기 전까지는 변경 내용이 적용되지 않아요. 설정을 다시 읽으려면 다음과 같이 실행하죠.

nginx -s reload

마스터 프로세스가 리로드 신호를 받으면 새 설정 파일의 문법이 유효한지 먼저 검사하고, 문제가 없으면 새 워커 프로세스를 띄웁니다.

설정 파일의 구조

NGINX는 설정 파일에 적힌 지시어(directive)를 통해 각 모듈을 제어해요. 지시어는 크게 **단순 지시어(simple directive)**와 **블록 지시어(block directive)**로 나뉩니다.

단순 지시어는 이름과 파라미터를 공백으로 구분해 나열하고 마지막에 세미콜론(;)으로 끝나요. 블록 지시어는 단순 지시어와 구조가 같지만, 세미콜론 대신 중괄호({ })로 묶인 추가 명령들을 담아요. 블록 지시어가 중괄호 안에 다른 지시어를 품을 수 있을 때 그 블록을 **컨텍스트(context)**라고 불러요. 대표적인 예가 events, http, server예요.

어떤 컨텍스트에도 속하지 않고 설정 파일 최상위에 적힌 지시어는 **메인 컨텍스트(main context)**에 있는 것으로 간주해요. eventshttp는 메인 컨텍스트에, serverhttp 안에, locationserver 안에 들어갑니다. # 다음부터 줄 끝까지는 주석으로 처리돼요.

정적 콘텐츠 서빙

구성 예시가 주석 처리로 들어 있는 기본 설정에서 시작해서, server 블록을 새로 만들고 주석 블록은 전부 지우세요.

http {
    server {
    }
}

설정 파일은 포트와 서버 이름에 따라 여러 server 블록을 가질 수 있어요. 요청을 처리할 server 블록이 정해지면, 이제 server 블록 안에 location 블록을 추가해서 어떤 파일을 줄지 정합니다.

location / {
    root /data/www;
}

location 블록은 요청 URI의 " / " 프리픽스와 비교돼요. 매칭되는 요청은 root 지시어에 지정된 경로(/data/www)에 URI를 붙인 파일을 로컬 파일 시스템에서 찾아 응답해요. 매칭되는 location 블록이 여러 개라면 NGINX는 가장 긴 프리픽스를 가진 것을 선택합니다. 위 location / 은 프리픽스 길이가 1로 가장 짧아서, 다른 location 블록이 매칭되지 않을 때만 사용돼요.

이제 두 번째 location 블록을 추가해 볼게요.

location /images/ {
    root /data;
}

/images/ 로 시작하는 요청은 이 블록과 매칭돼요(location / 도 매칭되지만 프리픽스가 더 짧아요). 결과적으로 server 블록은 다음과 같이 되구요, 포트 80에서 http://localhost/ 로 접근할 수 있는 정상 동작하는 설정이 됩니다.

server {
    location / {
        root /data/www;
    }

    location /images/ {
        root /data;
    }
}

/images/ 로 시작하는 요청은 /data/images 디렉터리에서 파일을 보내줘요. 예를 들어 http://localhost/images/example.png 요청이 오면 /data/images/example.png 파일을 응답하고, 파일이 없으면 404 에러를 돌려줘요. 그 밖의 URI는 /data/www 디렉터리에 매핑됩니다.

새 설정을 적용하려면 NGINX를 시작하거나, 마스터 프로세스에 리로드 신호를 보내면 됩니다. 뭔가 예상대로 동작하지 않는다면 /usr/local/nginx/logs/var/log/nginxaccess.logerror.log 를 확인해 보세요.

간단한 프록시 서버 만들기

먼저 설정 파일에 server 블록을 하나 더 추가해 프록시 대상 서버(백엔드)를 정의해요.

server {
    listen 8080;
    root /data/up1;

    location / {
    }
}

이 서버는 8080 포트에서 요청을 받아 전부 /data/up1 디렉터리에 매핑하는 단순한 서버예요. listen 8080 은 앞에서 80 포트를 기본으로 썼기 때문에 처음으로 포트를 명시적으로 지정한 부분이에요. /data/up1 디렉터리를 만들고 그 안에 index.html 파일을 넣어 두세요.

이제 앞에서 만든 서버 설정을 수정해서 프록시 서버로 바꿔볼게요. 첫 location 블록에 proxy_pass 지시어로 프록시 대상 서버의 프로토콜·이름·포트를 지정해요.

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

    location /images/ {
        root /data;
    }
}

두 번째 location 블록은 /images/ 프리픽스로 시작하는 요청을 /data/images 파일로 매핑하던 것을, 이미지 확장자를 가진 요청만 매칭하도록 바꿔볼게요.

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

~ 다음에 오는 것은 정규표현식이라, .gif, .jpg, .png 로 끝나는 모든 URI와 매칭돼요. NGINX는 location 블록을 선택할 때 먼저 프리픽스(prefix) 지시어들을 검사해 가장 긴 프리픽스를 기억해 두고, 그다음에 정규표현식을 검사해요. 최종 프록시 서버 설정은 다음과 같아요.

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

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

이 설정은 .gif, .jpg, .png 로 끝나는 요청을 걸러 /data/images 디렉터리로 매핑하고, 나머지 요청은 전부 proxy_pass 로 지정된 백엔드 서버에 넘겨줍니다.

FastCGI 프록시

포스팅, 게시판 같은 동적 콘텐츠를 PHP-FPM 같은 FastCGI 서버와 연결할 때도 비슷한 원리가 적용돼요. 요청을 fastcgi_pass 로 넘기고 fastcgi_param 으로 필요한 파라미터를 지정해요.

server {
    location / {
        fastcgi_pass  localhost:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param QUERY_STRING    $query_string;
    }

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

여기서 $document_rootroot 지시어의 값, $fastcgi_script_name 은 요청 URI를 나타내는 NGINX 변수예요. 이미지 요청은 정적으로 처리하고, 그 외 요청은 9000 포트의 FastCGI 서버가 처리하는 구조이죠.

더 알아보기 (Learn more)