• Nginx 리버스 프록시 연결 안정화 팁 좀 부탁드려요

    개인 포트폴리오용 간단한 웹사이트 돌리려고 서버 세팅 중입니다.
    백엔드는 Django 돌리고, 앞에 Nginx로 리버스 프록시 걸려고 하는데, 가끔 요청 처리하다가 연결이 불안정해지거나 끊기는 느낌을 받아요.

    혹시 Nginx가 백엔드 서비스(로컬 포트)랑 통신할 때, 세션 유지나 연결 안정성을 높일 만한 설정 팁 같은 게 있을까요?
    타임아웃 설정이나 헤더 관련해서 신경 써야 할 부분이 있을지 궁금합니다.

    너무 복잡한 건 싫고, 그냥 개인 프로젝트 수준에서 '이 정도면 충분하다' 싶은 실용적인 팁 위주로 알고 싶습니다.

  • 안녕하세요, 서버 세팅하시느라 고생 많으시네요.
    개인 포트폴리오 수준에서 Nginx 리버스 프록시 구성하시는 거, 정말 기본적인 단계부터 짚고 넘어가야 할 부분이 많아서 막막할 수 있어요.
    저도 예전에 비슷한 상황에서 연결 불안정 겪어봤던 경험이 있어서, 몇 가지 실질적으로 도움이 되었던 팁들 위주로 정리해 드릴게요.
    일단 말씀하신 '연결 불안정'이나 '끊김' 증상은 대부분 타임아웃 설정이나 연결 유지(Keep-Alive) 설정이 미흡할 때 발생해요.
    Django 같은 WSGI/ASGI 기반 백엔드를 Nginx로 프록시할 때는 HTTP 통신 프로토콜 레벨에서 몇 가지 설정을 건드려줘야 안정성이 확 올라가거든요.
    --- ### 1.
    가장 기본 중의 기본: 타임아웃 관련 설정 (Timeout) 이 부분이 제일 중요하고, 제일 많이 놓치는 부분이에요.
    Nginx는 기본적으로 통신에 시간이 지나면 연결을 끊어버리려는 경향이 있어요.
    Django 같은 백엔드가 요청을 처리하는 데 시간이 좀 걸리거나, 혹은 요청-응답 사이의 간격(예: 클라이언트가 페이지를 로드하고 API를 호출하기 전에 잠시 멈추는 경우)이 생기면 Nginx가 "응답이 너무 느리네?" 하고 연결을 닫아버릴 수 있거든요.
    필수하게 추가해 볼 설정: location 블록 내부나 http 블록에 아래 지시어를 추가해 보세요.
    nginx proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; 이게 무슨 뜻인가요? * proxy_connect_timeout: Nginx가 백엔드 서버(Django가 돌아가는 로컬 포트)에 연결을 시도할 때, 연결 성공을 기다리는 최대 시간이에요.
    기본값이 너무 짧으면, 서버가 부팅 중이거나 약간의 부하가 걸릴 때 연결 자체를 못 맺고 실패할 수 있어요.

    • proxy_send_timeout: Nginx가 요청(헤더나 본문 데이터)을 백엔드 서버로 전송할 때, 백엔드로부터 응답을 받지 못하고 대기하는 최대 시간입니다.
    • proxy_read_timeout: 백엔드 서버가 요청을 받고 실제로 응답 데이터를 보내기 시작해서, 클라이언트에게 모든 데이터를 전송할 때까지 기다리는 최대 시간이에요.
      이게 보통 제일 많이 문제가 되는 부분입니다.
      백엔드에서 시간이 좀 걸리는 쿼리나 복잡한 로직을 돌리면, 이 시간이 초과되면서 연결이 뚝 끊기는 것처럼 보일 수 있어요.
      팁: 개인 프로젝트라면 30초나 60초 정도로 넉넉하게 잡는 것을 추천해요.
      만약 API 호출이 매우 길게(예: 1분 이상) 걸리는 작업이 아니라면, 60초 정도면 충분히 넉넉하게 잡을 수 있습니다.
      --- ### 2.
      연결 유지(Keep-Alive) 및 헤더 문제 요즘 웹 애플리케이션은 보통 여러 요청을 한 번의 연결 세션 내에서 연속적으로 보내는 경우가 많아요.
      이때 연결을 계속 열어두는 것이 효율적인데, 이걸 'Keep-Alive'라고 합니다.
      설정 확인: Nginx가 클라이언트와 백엔드 간의 연결을 너무 빨리 닫지 않도록 설정해 주는 게 좋아요.
    proxy_set_header Connection ""; # 연결 헤더 관련하여 명시적으로 비워주는 것도 도움이 됩니다.
    ``` **`proxy_http_version 1.1`의 중요성:** HTTP/1.1은 연결을 재사용하는 Keep-Alive 메커니즘을 기본으로 하죠.
    이 설정을 명시적으로 해주는 게 안정적인 연결 관리에 도움이 될 때가 많습니다.
    **💡 흔한 실수 (헤더 관련):** 만약 Django에서 세션 기반으로 동작하거나, 특정 인증 토큰 같은 것을 주고받는 경우, **Host 헤더**를 제대로 넘겨주지 않으면 백엔드 서버가 요청을 잘못 처리할 수 있어요.
    ```nginx proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; ``` `$host`를 사용해서 클라이언트가 접속한 도메인 이름 그대로 백엔드에 전달해 주는 게 가장 안전합니다.
    --- ### 3.
    Django/Python 측 고려 사항 (Nginx 바깥의 영역) 이건 Nginx 설정은 아니지만, 연결 안정성을 위해 반드시 확인해야 할 부분이라 같이 말씀드릴게요.
    Nginx가 아무리 잘 설정되어 있어도, Django나 WSGI 서버(Gunicorn이나 uWSGI 등) 자체의 설정이 불안정하면 소용이 없어요.
    **Gunicorn/uWSGI 사용 시:** 만약 Nginx 뒤에 Gunicorn 같은 프로세서가 돌고 있다면, 이 프로세서의 워커(Worker) 개수나 타임아웃 설정을 점검해 보세요.
    1.
    **워커 개수:** 서버의 코어 개수(CPU)에 맞게 워커 수를 설정하는 것이 일반적이지만, 트래픽이 매우 적은 개인 프로젝트라면 너무 높게 잡을 필요는 없어요.
    (예: CPU 코어 수 * 2 + 1 정도가 가이드라인이긴 하지만, 일단 적당히 시작하는 게 좋아요.) 2.
    **프로세스 재시작 주기:** Gunicorn 같은 경우, 장시간 구동 시 메모리 누수나 기타 이유로 프로세스가 불안정해질 수 있어요.
    주기적으로 재시작되도록 관리하는 것이 좋습니다.
    (이건 운영체제 레벨의 서비스 관리자(systemd 등) 설정을 통해 주기적으로 재시작되게 하는 게 가장 확실해요.) --- ### 4.
    종합적인 적용 예시 (요약) 실제 `server` 블록이나 `location` 블록에 넣을 때, 이렇게 묶어서 적용하는 걸 추천합니다.
    ```nginx location / { # 1.
    타임아웃 설정 (넉넉하게 60초로 설정) proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; # 2.
    연결 유지 및 헤더 설정 proxy_http_version 1.1; 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 Connection ""; # Keep-Alive 관련 명시 # 3.
    백엔드 주소 설정 (Django가 돌아가는 주소: 포트) proxy_pass http://127.0.0.1:8000; # <- 여기에 실제 Django 포트를 넣어주세요.
    } ``` **마지막 주의사항:** 위 설정들을 적용하신 후에는 **반드시** Nginx 설정을 테스트하고 리로드 해주셔야 합니다.
    `sudo nginx -t` 로 문법 검사를 먼저 하시고, 문제가 없으면 `sudo systemctl reload nginx` (또는 사용하시는 서비스 관리 명령어)로 적용해주세요.
    이렇게 설정하시면, 단순히 요청/응답 시간이 길어지거나 연결이 잠시 끊기는 상황에 대한 내구성은 훨씬 좋아질 거예요.
    개인 프로젝트 수준에서는 이 정도만 잡고 가셔도 대부분의 '연결 불안정' 문제는 해결될 거라고 보건대요.
    혹시 특정 에러 메시지(예: 504 Gateway Timeout)가 뜬다면, 그 메시지를 가지고 다시 질문해주시면 더 구체적인 답변 드릴 수 있을 것 같습니다!