[Nginx] 백엔드 단의 API가 제대로 포트포워딩이 되지 않는다.

이진송·2025년 5월 23일
post-thumbnail

개인 프로젝트를 진행하던 도중, Nginx 포트포워딩을 작업중이었다.
https를 도입하기 전, http에서 포트포워딩을 수행하는 작업이다.

먼저 포트포워딩에 대해 알아보자

포트포워딩(Port Forwarding)

포트포워딩(Port Forwarding)의 정의는 다음과 같다.

In computer networking, port forwarding or port mapping is an application of network address translation (NAT) that redirects a communication request from one address and port number combination to another while the packets are traversing a network gateway, such as a router or firewall.
출처

즉, 하나의 Address와 Port 조합으로 온 request를 redirect 해주는 NAT 기능을 말한다.

포트포워딩을 사용하는 이유

우리는 개발할때 localhost:5173(React), localhost:8080(SpringBoot)와 같은 IP와 Port를 가진 서버를 사용한다.

물론 IP와 Port를 명시하여 원하는 서버에 request, response를 받을 수 있지만, 우리가 네이버 서비스를 이용할때 http://123.123.123.123:5173 을입력해서 사용하진 않는다.

이때 Nginx를 이용하여 외부 아이피: 특정 포트 로 접속하면 내부 아이피: 특정 포트로 맵핑해준다.

URL 구조


URL 구조에 대한 자세한 설명은 아래 출처를 통해 확인해주길 바란다.
출처

위와 같은 이유로 Nginx를 활용해 포트포워딩을 수행하던 도중, 문제가 발생했다.

문제) Front(웹주소)는 문제없이 구매한 도메인으로 접속이 되었으나, Front에서 Back의 API로 Request를 보냈지만, 404 ERROR가 발생했지만, Domain Name에 포트번호를 붙이자 문제없이 통신이 되었다.

원인 분석: front에서는 문제없이 내가 구매한 도메인 주소로 접속이 되었었다. back만이 안되는 문제때문에, 원인을 찾는데 아주 오랜 시간이 걸렸다.

아래 코드는 내가 사용한 nginx 설정파일이다.

# nginx/default.conf
server {
    listen 80;
    listen [::]:80;
    server_name 구매한 도메인 주소;

    # React 정적 파일 서빙
    location / {
        root /usr/share/nginx/html;
        index index.html;
        try_files $uri /index.html;
    }

    # API 프록시 설정
    location /api/v1/ {
        # docker network 내부에서 통신
        proxy_pass http://backend:8080;
        # proxy 요청에 원래 호스트 헤더를 설정
        proxy_set_header Host $host;
        # 클라이언트의 실제 IP를 X-Real-IP 헤더에 설정. 백엔드 서버가 실제 클라이언트의 IP를 알기 위함. -> 로깅, IP 제한, 지리적 위치 서비스 등에 사용.
        proxy_set_header X-Real-IP $remote_addr;
        # X-Forwarded-For 클라이언트의 IP와 경유한 프록시 서버의 IP 목록을 전달. 백엔드 서버가 전체 경로를 추적할 수 있게 함.
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # 프로토콜을 X-Forwarded-Proto 헤더에 설정. 이유는 프로토콜이 http인지 https인지 알기 위함 -> 보안 분석, 트래픽 분석 등에 사>용.
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

GPT의 도움도 받아봤지만, GPT의 대답은 설정에 문제가 없고 안되는게 이상함! 이라는 답변만 받게 되었다. 아래는 내가 직접 확인해본 과정들을 기록한다.

1. 설정파일이 컨테이너 내부에 '정말로' 존재하는지?

EC2에서 docker exec -it 컨테이너명 sh 명령어를 통해 직접 컨테이너에 들어가서 내 설정파일이 존재하는지, 확인하는 방법이다.

# nginx/Dockerfile
FROM nginx:alpine
COPY conf.d/default.conf /exec/nginx/conf.d/default.conf
COPY dist/ /usr/share/nginx/html/

nginx에 사용한 Dockerfile이다. 해당 컨테이너 내부에 내 설정파일은 존재했고, 코드 내용도 존재했다.

2. 통신이 정상적으로 되는가?

통신 테스트를 할때, EC2에서 직접 컨테이너로 들어가서 확인하는 방법(내부 통신)과
Postman을 통해 API테스트(외부 통신)를 해보는 것이었다.

nginx 컨테이너 내부에서 통신한 결과는 다음과 같았다.

curl http://backend:8080/api/v1/~~
curl http://구매한 도메인:8080/api/v1/~~
 -> 200 OK !! Response가 제대로 도착함.

curl http://backend/api/v1/~~
curl http://구매한 도메인/api/v1/~~
 -> 404 ERROR 발생 !!

Postman을 통해 API 테스트 결과는 다음과 같았다

curl http://backend:8080/api/v1/~~
curl http://구매한 도메인:8080/api/v1/~~
 -> 200 OK !! Response가 제대로 도착함.

curl http://backend/api/v1/~~
curl http://구매한 도메인/api/v1/~~
 -> 404 ERROR 발생 !!

여기서 나는 엄청난 혼란이 왔다.
Front 내가 구매한 도메인으로는 아무런 문제 없이 Front화면단이 나왔으나, 어째서 Back통신만 제대로 포트포워딩이 되지 않는것인지?
해당부분을 고민하고 해결하느라 시간을 많이 소모했다.

문제의 원인은 정말 간단한 이유였고, 헛웃음이 나왔다.

먼저 Front단의 화면단이 아무런 문제 없이 나왔던 이유는 내가 구매했던 도메인의 DNS를 설정했기 때문이었다.

그렇다면 back의 api는 왜 포트포워딩이 제대로 되지 않았을까?

docker exec -it 컨테이너 명 nginx -T

위 명령문을 입력하자, 내 설정파일을 확인할 수 있었다.

설정파일은 내가 넣은 파일이 아닌 기본 설정파일이 적용되고 있었다!!!

ㅋㅋ

# nginx/Dockerfile
FROM nginx:alpine
COPY conf.d/default.conf /etc/nginx/conf.d/default.conf
COPY dist/ /usr/share/nginx/html/

해당 내용을 수정하여 경로를 맞추고 기본 설정파일에 내 설정파일이 덮어씌워지게 수정하니 문제없이 포트포워딩이 되었다.

import axios from "axios";

// SpringBoot -> Front 데이터 조회 
export const getData = async () => {
    const response = await axios.get(`/api/v1/~~`);
  
    return response.data;
  };

해당 코드는 프론트 코드이다. 도메인명 뿐만 아니라 포트번호를 입력하지 않아도 위 사진과 같이 Response를 받을 수 있었다.

이로써 문제해결을 하며 포트포워딩을 무사히 마쳤다.

다음시간엔...

CertBot을 활용해 SSL 인증서를 발급하고, https로 변경하는 시간을 갖도록 하겠다.
해당 포스트를 통해 https를 사용하는 이유와 함께 간단한 과정을 적도록 하겠다.

profile
개발자 뉴비, 새로운 것을 배워가고 특정한 주제에 대해 고민하는 것을 즐거워합니다.

0개의 댓글