NGINX API Gateway URI rewrite 설정 방법

이 포스트에서는 NGINX 서버를 API Gateway 로 간단하게 구성하고, URI rewrite 설정을 통해 클라이언트 요청 URI를 재작성(Rewrite)하여 백엔드 서버로 전달하는 방법에 관해 설명합니다.

API Gateway 구성 이전에 NGINX 설치가 필요하다면 NGINX 설치(OSS)NGINX Plus 설치를 참고하세요.

목차

1. API Gateway란?
2. 백엔드 서버 구성
3. NGINX API Gateway 기초 설정

4. NGINX API Gateway URI rewrite 설정
5. NGINX API Gateway URI rewrite 결론

1. API Gateway란?

NGINX API Gateway URI rewrite

API Gateway는 클라이언트와 백엔드 서비스 간의 통신을 관리하기 위한 중앙 허브 역할을 합니다. API Gateway는 클라이언트와 백엔드 서버 사이에 위치하여 요청을 라우팅하고, 적절한 백엔드 서비스로 전달하는 역할을 합니다. 이를 통해 클라이언트와 서비스 간의 보다 효율적인 통신이 가능하고, 인증, 인가, rate limiting 및 캐싱과 같은 작업을 처리할 수 있습니다.

2. 백엔드 서버 구성

NGINX API Gateway를 통해 요청이 전달될 path1, path2 서버는 NGINX 서버로, 다음과 같이 구성했습니다.

# path1.conf

server {
    listen 81;

    location / {
        default_type text/plain;
        return 200 'Server address: $server_addr:$server_port\nServer name: Path1\nURI: $request_uri\nRequest ID: $request_id\n';
    }
}
# path2.conf

server {
    listen 82;

    location / {
        default_type text/plain;
        return 200 'Server address: $server_addr:$server_port\nServer name: Path2\nURI: $request_uri\nRequest ID: $request_id\n';
    }
}

서버(192.168.200.174)의 81번/82번 포트로 각각 요청을 수신하여 서버 주소, 서버명, 요청 URI, 요청 ID 정보를 반환하도록 구성했습니다.

path1 서버와 path2 서버의 설정 파일은 아래 경로에 구성했습니다.

/etc/nginx/conf.d/
├── path1.conf
└── path2.conf

3. NGINX API Gateway 기초 설정

1. /etc/nginx 경로에 API Gateway 구성을 위한 api_gateway.conf 파일을 작성합니다.

server {
    listen       80;
    server_name  localhost;

    access_log  /var/log/nginx/default_access.log main;
    error_log   /var/log/nginx/default_error.log;


    location /api/path1 {                          # 서버의 /api/path1 경로로 요청 시 
            proxy_pass http://192.168.200.174:81;  # path1 서버로

    }

    location /api/path2 {                          # 서버의 /api/path2 경로로 요청 시 
            proxy_pass http://192.168.200.174:82;  # path2 서버로
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}

서버의 지정된 경로로 요청을 수신하면, 해당 요청을 앞서 구성한 path1, path2 서버로 프록시 되도록 설정했습니다.

# api_gateway.conf


upstream path1_server {                      # path1 엔드포인트 서버 그룹
        server 192.168.200.174:81;
        server 192.168.200.174:8181;
}

upstream path2_server {                      # path2 엔드포인트 서버 그룹
        server 192.168.200.174:82;
        server 192.168.200.174:8282;
}

server {
    listen       80;
    server_name  localhost;

    access_log  /var/log/nginx/default_access.log main;
    error_log   /var/log/nginx/default_error.log;


    location /api/path1 {                        # /api/path1 경로로 요청 시 
            proxy_pass http://path1_server;  # path1 upstream 그룹으로 전달
    }

    location /api/path2 {                        # /api/path2 경로로 요청 시 
            proxy_pass http://path2_server;  # path2 upstream 그룹으로 전달
    }

    ...

}

단일 백엔드 서버가 아닌 여러 서버로 로드 밸런싱 구성이 필요한 경우, 위와 같이 upstream 블록을 통해 블록 내부의 서버로 로드 밸런싱 되도록 할 수 있습니다. NGINX의 로드 밸런싱에 대한 더 자세한 내용은 여기를 참고하세요.

2. 작성한 api_gateway.conf 파일을 /etc/nginx/nginx.conf 파일에 include 합니다.

# nginx.conf

user  nginx;
worker_processes  auto;

...


http {

    ...

    include /etc/nginx/api_gateway.conf;
    include /etc/nginx/conf.d/*.conf;        # path1/2 서버 파일 경로
}

메인 설정 파일인 nginx.conf 파일이 다른 설정 파일을 읽기 위해선 위와 같이 경로를 설정해야합니다.

3. 변경된 설정을 적용합니다.

$ sudo nginx -s reload

4. 앞서 설정한 경로로 요청을 전송하여, 응답을 확인합니다.

$ curl 192.168.200.174/api/path1

Server address: 192.168.200.174:81
Server name: Path1
URI: /api/path1
Request ID: 3edc27f7830169774664645c80031b1a


$ curl 192.168.200.174/api/path2

Server address: 192.168.200.174:82
Server name: Path2
URI: /api/path2
Request ID: 9e4e4eb86ba6d6bbf6b1de55d3cc7a85

이로써 단일 NGINX 서버를 통해 요청이 각각의 백엔드 서버로 라우팅되는 기본적인 API Gateway 구성이 완료되었습니다.

4. NGINX API Gateway URI rewrite 설정

NGINX는 ngx_http_rewrite_module을 통해서 요청의 URL을 재작성 할 수 있습니다.

재작성 규칙은 다음과 같이 동작합니다.

rewrite <재작성 조건 URI> <지정 URI> <추가옵션(선택)>;

요청의 URI가 조건과 일치하면, 해당 URI는 지정 URI로 재작성됩니다. 재작성 조건 URI는 정규 표현식으로 작성할 수 있습니다. NGINX의 정규표현식은 PCRE 라이브러리를 기반으로 동작합니다.

기존 api_gateway.conf 파일의 /api/path2 경로에 rewrite 옵션을 다음과 같이 작성했습니다. 설정 파일 변경 후엔 nginx -s reload 명령어로 변경된 설정을 적용해야합니다.

# api_gateway.conf

server {
    listen       80;
    server_name  localhost;

    ...

    location /api/path2 {
            rewrite ^/api/path2/(.*)$ /$1 break;
            proxy_pass http://192.168.200.174:82;
    }

    ...

}

위와 같이 설정 시 /api/path2/(문자열) 요청을 /문자열 요청으로 재작성합니다. 그리고 break 옵션을 통해 바로 proxy_pass가 실행됩니다. 옵션을 좀 더 자세히 살펴보면 다음과 같습니다.

  • 재작성 조건 URI
    • ^ : 문자열의 시작을 나타냅니다
    • (.*) : 모든 문자열(.*)을 괄호로 그룹화하여 캡처합니다
    • $ : 문자열의 끝을 나타냅니다
  • 지정 URI
    • $1 : 앞서 캡처한 그룹(.*)을 참조합니다
  • 추가옵션(break)
    • 추가적인 location 블록 매칭을 하지 않고, 블록 내의 남은 지시문(proxy_pass)을 수행합니다.

rewrite 옵션을 확인하기 위해 아래와 같이 요청을 전송했습니다.

$ curl 192.168.200.174/api/path2/nginxstore

Server address: 192.168.200.174:82
Server name: Path2
URI: /nginxstore
Request ID: 5177babe183aee01494221912d5e8ec9



$ curl 192.168.200.174/api/path2/nginxstore/rewrite/module

Server address: 192.168.200.174:82
Server name: Path2
URI: /nginxstore/rewrite/module
Request ID: 9f5d3eb8ac385f9eb780bac242ba1be2

rewrite 옵션에 따라 /api/path2 이후로 작성되는 모든 문자열로 URI가 재작성 되어, 백엔드 서버인 path2 서버로 전달되는 것을 확인할 수 있습니다.

이전의 rewrite 옵션에서 break 옵션을 제거할 시 해당 요청이 proxy_pass 지시문을 통해 해당 블록 내부의 백엔드 서버로 전달되지 않고, 재작성된 URI에 맞는 location 블록 매칭을 시도합니다. 예시를 위해 api_gateway.conf 파일을 다음과 같이 작성했습니다.

# api_gateway.conf

server {
    listen       80;
    server_name  localhost;

    ...

    location /api/path2 {
            rewrite ^/api/path2/(.*)$ /$1 ;  # break 옵션 제거
            proxy_pass http://192.168.200.174:82;
    }

    location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
    }

    location /nginxstore {
            return 200 'This is nginxstore\n';
    }

    ...

}

변경된 설정을 적용 후 다음과 같이 요청을 보내 확인합니다.

$ curl 192.168.200.174/api/path2/nginxstore

This is nginxstore

$ curl 192.168.200.174/api/path2/nginx

<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.25.4</center>
</body>
</html>

/api/path2/nginxstore 요청은 /nginxstore 요청으로 재작성되어, 해당되는 location 블록과 매칭되고, /api/path2/nginx 요청은 /nginx location 블록이 존재하지 않아 기본 location 블록과 매칭됩니다.
기본 location 블록의 /usr/share/nginx/html 디렉토리에 /nginx 디렉토리와, 파일이 존재하지 않아 404 에러를 반환합니다.

rewrite 옵션은 server 블록 내부에도 작성할 수 있습니다.

# api_gateway.conf

server {
    listen       80;
    server_name  localhost;

    access_log  /var/log/nginx/default_access.log main;
    error_log   /var/log/nginx/default_error.log;


    rewrite ^/nginx/(.*)$ /api/$1 ;

    location /api/path1 {
            proxy_pass http://192.168.200.174:81;
    }

    location /api/path2 {
            rewrite ^/api/path2/(.*)$ /$1 break;  # break 옵션 재적용
            proxy_pass http://192.168.200.174:82;
    }

    ...

}

rewrite 설정에 따라 요청 URI가 변화하여, URI에 맞는 location 블록과 매칭됩니다.

$ curl 192.168.200.174/nginx/path1

Server address: 192.168.200.174:81
Server name: Path1
URI: /api/path1
Request ID: 75b236fc69fe0f8484dde530642becf0


$ curl 192.168.200.174/nginx/path2/nginxstore
Server address: 192.168.200.174:82
Server name: Path2
URI: /nginxstore
Request ID: c252a03f7b0d7ff38ec9c180077d5457

/nginx/path1 요청이 /api/path1 요청으로 rewrite 되어 path1 location 블록과 매칭되고, /nginx/path2/nginxstore 요청이 /api/path2/nginxstore 요청으로 rewrite 되어 path2 location 블록과 매칭되고, 해당 블록 내부의 rewrite 규칙에 따라 다시 /nginxstore 요청으로 rewrite 됩니다.

5. NGINX API Gateway URI rewrite 결론

이번 포스트에서는 NGINX를 간단한 API Gateway로 구성하고 URI rewrite 설정을 적용하는 방법에 대해 알아봤습니다. API Gateway를 통해 클라이언트와 백엔드 서비스 간의 통신을 관리할 수 있고, URI rewrite 설정을 통해 클라이언트 요청을 유연하게 처리하고, 다양한 백엔드 서비스로 라우팅할 수 있습니다.

NGINX STORE를 통한 솔루션 도입 및 기술지원 무료 상담 신청

* indicates required