[Trouble Shooting]Nginx configuration 설정파일
이번 학부 연구를 진행하면서 nginx설정 파일을 건드릴 일이 있었는데, 난 그냥 우리 랩에 있는 phd친구가 만들어놓은 탬플릿을 따라 썼을 뿐, 자세히 들여다보진 않았다. 그러다 보니 오류가 발생해도 어디서 왜 발생했는지 몰랐어서 너무 답답했다. 그래서 이번에는 nginx 설정 파일에서 각각의 코드들은 무엇을 의미하고, 어떤 설정을 하는지에 대해 잠깐 기록하고 넘어가겠다.
먼저, 내가 가장 헷갈렸던 부분은 `upstream` 블록이었다. 애초에 이 블록이 무슨 일을 하는지도 몰랐다. `upstream`이 뭔지 알기 전에, 먼저 `stream`이 무슨 뜻인지부터 보고 넘어가자.
`stream`은 사전적 의미로 "흐름", 즉 물의 흐름이라는 뜻이다. 데이터가 흐르는 모양이 물처럼 흐른다고 하여 스트림이라는 이름을 지어줬다. `upstream`과 `downstream`이 있는데, 물은 수압이 높은 곳에서 낮은 곳으로 흐르듯, `upstream`은 물의 상류를 의미한다. 그렇다면 Nginx 설정 파일에서의 `upstream`은 무슨 말일까?
Nginx에서 `upstream` 블록은 하나 이상의 서버를 정의하여 로드 밸런싱과 프록시 기능을 제공하는 데 사용된다. 이를 통해 Nginx는 클라이언트 요청을 여러 백엔드 서버로 분산시켜 처리할 수 있다. 예를 들어, 다음과 같이 설정할 수 있다:
upstream frontend {
server localhost:3000;
}
upstream backend {
server localhost:8080;
}
이 설정은 두 개의 `upstream` 블록을 정의하고, 각각의 블록은 프론트엔드와 백엔드 서버를 나타낸다. 이후, 서버 블록 내에서 `location` 지시자를 사용하여 트래픽을 적절히 라우팅한다.
server {
listen 80;
server_name your-domain.com;
# 프론트엔드 요청 처리
location / {
proxy_pass http://frontend;
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-Proto $scheme;
}
# 백엔드 API 요청 처리
location /api/ {
proxy_pass http://backend;
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-Proto $scheme;
}
# 추가적인 설정
}
이 설정에서는 다음과 같이 동작한다:
1. `/`로 시작하는 모든 요청은 프론트엔드 서버(`localhost:3000`)로 전달된다.
2. `/api/`로 시작하는 모든 요청은 백엔드 서버(`localhost:8080`)로 전달된다.
`upstream` 블록을 사용하면 Nginx는 클라이언트의 요청을 지정된 백엔드 서버로 전달하며, 여러 서버 간에 로드 밸런싱을 통해 성능을 향상시킬 수 있다. 또한, 백엔드 서버가 다운되었을 때 자동으로 다른 서버로 요청을 재분배하는 기능도 제공한다.
따라서 Nginx 설정 파일에서의 `upstream`은 상류에 위치한 서버 그룹을 정의하여 클라이언트 요청을 적절히 분산시키고 관리하는 중요한 역할을 한다.
Trouble shooting
내가 진행중인 프로젝트에서 헷갈렸던 부분이 있다. 나는 nginx가 리버스 프록시, 로드 밸런싱 등등을 담당하는 웹 서버 소프트웨어로써 벡엔드쪽의 일을 할 줄 알고 계속 백엔드와의 사투를 벌였다. 내가 생각한 로직은 내 frontend와 backend 모두 'screen'을 통해 백그라운드에서 실행중이고, 이제 nginx설정파일을 건드려서 백엔드 api처리 등등 여러가지 일을 수행하는줄 알았다. 하지만, upstream 블록에 frontend를 설정하지 않고 backend만 설정했더니(다시, 나는 nginx가 프론트엔드와 전혀 관련이 없는 줄 알았다) 도메인을 통해 접속하면 계속 nginx에러가 뜨는 것이였다.
이것 때문에 지난 사흘간 머리가 아팠다. "아니 분명, upstream에서 지정한 서버는 backend서버를 명시하고, 아래 location 블록에서 proxy_pass를 통해 프록시할 URL을 지정해줘야 하는데, 왜 upstram에서 react앱이 돌고있는 포트번호 3000번을 입력하면 웹이 동작하고, 백엔드가 실행중인 8080번을 입력하면 왜 안되는지 궁금했었다.
그런데... 오늘 우리 랩에 있는 phd 친구한테 받은 답변:

살짝 머리가 띵... 했다. 내가 아예 nginx가 하는 일과 왜 쓰는지에 대한 이유를 잘 몰랐구나 싶었다. 저 친구가 말한 내용은 백엔드의 upstream이 아예 필요하지 않다는 것이였다. backend의 연결은 POST 요청을 통해 프론트와 연결했고(서버에 직접 요청을 보내는 경우에는 backend의 upstream 블록이 필요하지 않다), 우리는 front부분만 설정 하면 된다는 것이였다.
그렇다면, 왜 프론트엔드(React App)만 nginx에서 upstream으로 지정되어 여러가지 설정을 해줘야할까?
먼저, 랩실 phd 학생의 답변이다.

즉, 우리가 개발을 하면 로컬 / 원격 서버에서 개발 환경을 분리하여 개발하는데, 말 그대로 로컬 환경에서 개발중인 애플리케이션은 "나한테" 만 보일것이다. 남들에게 내 웹사이트를 공개하려면 서버, 도메인 등등 여러가지가 필요한데, 여기서 "서버"의 역할을 해 주는것이 nginx이다.
1. 정적 파일 제공 (Static File Serving)
프론트엔드 애플리케이션은 일반적으로 HTML, CSS, JavaScript와 같은 정적 파일로 구성된다. Nginx는 정적 파일 제공에 매우 효율적이며, 클라이언트 요청에 대해 빠른 응답을 제공할 수 있다.
2. 리버스 프록시 설정 (Reverse Proxy)
프론트엔드가 API 서버(백엔드)와 통신할 때 Nginx를 리버스 프록시로 사용하면, 클라이언트의 요청을 프론트엔드와 백엔드로 라우팅할 수 있다. 이렇게 하면 모든 트래픽이 하나의 도메인으로 통합되어 관리되기 때문에 보안과 관리가 용이해진다.
3. 로드 밸런싱 (Load Balancing)
프론트엔드 서버가 여러 개의 인스턴스로 실행될 경우, Nginx는 로드 밸런서를 통해 요청을 여러 인스턴스에 분산시켜 성능을 최적화할 수 있다.
4. 캐싱 (Caching)
Nginx는 정적 콘텐츠 캐싱을 통해 클라이언트 요청에 대한 응답 속도를 크게 향상시킬 수 있다. 이는 UX를 개선하는 데 도움이 된다.
5. 보안 (Security)
Nginx는 SSL/TLS 설정, 방화벽 설정 등 다양한 보안 기능을 제공하여 애플리케이션을 보호할 수 있다. 이를 통해 프론트엔드 애플리케이션이 더 안전하게 운영될 수 있다.
upstream frontend {
server 127.0.0.1:3000; # 프론트엔드 서버 주소
}
upstream backend {
server 127.0.0.1:8080; # 백엔드 서버 주소
}
server {
listen 80;
server_name your-domain.com;
# 프론트엔드 요청 처리
location / {
proxy_pass http://frontend;
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-Proto $scheme;
}
# 백엔드 API 요청 처리
location /api/ {
proxy_pass http://backend;
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-Proto $scheme;
}
}
이 예시에서:
- `/`로 시작하는 모든 요청은 프론트엔드 서버로 전달된다.
- `/api/`로 시작하는 모든 요청은 백엔드 서버로 전달된다.