React.js & Django 배포를 위한 Nginx 설정

DARTZ·2023년 4월 24일
0

Projects

목록 보기
3/5

서론

React.js와 Django 배포를 위한 Nginx 설정 방법을 정리합니다. FrontEnd와 BackEnd를 배포하는 방법은 크게 4가지로 나눌 수 있습니다. 다음은 지인 개발자분께 배포 방법에 대해서 설명받은 내용입니다.

DNS A 레코드
어떤 서비스 제공사던 도메인을 사면 DNS에 레코드를 추가할 수 있다. 여기서 A 레코드는 거의 자유자재로 추가할 수 있는데, 하나의 A 레코드마다 서브도메인을 포함한 도메인 주소를 IP에 연결한다고 볼 수 있다. 게다가 A레코드별로 IP가 달라야한다는 조건도 없기 때문에, 모든 서브도메인에 대하여 같은 IP를 분배할 수도 있다.

1. 같은 서버, 같은 도메인, 같은 서브 도메인
1. 하나의 서버에 서로 다른 포트에 서로 다른 서비스 (front, back 이라던지)를 배포한다.
2. Nginx를 이용해 전체 도메인 (서브도메인 + 도메인)으로 들어온 요청을 받아준다.
3. Nginx 설정을 하면서, location 디렉티브를 이용해 요청 경로에 따라 요청을 front 또는 back으로 분배해준다.

이 경우 sub.domain.com/ 로 들어온 요청은 한 포트로, sub.domain.com/api/ 로 들어온 요청은 다른 포트로 보내는 Nginx 설정이 필요하다. 이게 은근 복잡하지만 한번 해보는것도 나쁘지 않다.

2. 같은 서버, 같은 도메인, 다른 서브 도메인
1. 하나의 서버에 서로 다른 포트에 서로 다른 서비스 (front, back 이라던지)를 배포한다.
2. Nginx를 이용해 하나의 서브도메인 + 도메인에 대한 설정을 만들고, 하나의 포트로 요청을 분배한다.
3. 마찬가지로 Nginx를 이용해 다른 서브도메인 + 도메인에 대한 설정을 만들고 나머지 포트로 요청을 분배한다.

이 경우 sub1.domain.com/ 로 들어온 요청은 한 포트로, sub2.domain.com/ 로 들어온 요청은 다른 포트로 보낼 수 있다. 이는 listen 디렉티브로 어떤 도메인을 향한 요청인지를 작성하게 되는데, 설정을 두개 만들어야 되서 어려워 보이지만 실제로 변경하는 부분은 listen 부분만이고 설정 파일을 복붙해서 사용할 수 있어서 오히려 쉽다. 반면에 이전 방식은 locationrewrite 등 NGinx 지식이 더 많이 필요.

3. 다른 서버, 같은 도메인, 다른 서브 도메인
두번째 방식과 동일한데, 하나의 서버에서 Nginx 설정을 두개 만드는 것이 아니라 각각 서버에서 설정을 하나씩 만들고, 서브 도메인 별로 A 레코드도 따로 만드는 방식이다.

4. 다른 도메인
여전히 똑같다. 그냥 A레코드에 어떤 서버로 요청을 보낼지만 정확히 정의해주면 된다. DNS 레코드는 보통 도메인 별로 관리가 되기 때문에 더 쉽다.

저는 2번째 방법 같은 서버, 같은 도메인, 다른 서브 도메인으로 배포를 진행했고 관련 설정을 공유하려고 합니다.
기본적으로 Django의 배포방법은 참고에 정말 잘 정리되어 있습니다. 여기서 응용해서 React.js와 Django를 배포하려고 합니다.

본문

nginx의 site 설정 파일을 편집기로 여시면 됩니다.
저는 /etc/nginx/sites-available의 mysite 파일입니다.

# 프론트 엔드
server {
  #add_header Access-Control-Allow-Origin *;
  listen 80; # 80포트가 기본이고 도메인에 별다른 포트가 없을 경우 80포트가 기본으로 접속됩니다.
  server_name 도메인;
}

# 프론트 엔드 https
server {
  listen 443 ssl;
  server_name 도메인;
  ssl_certificate /etc/letsencrypt/live/도메인/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/도메인/privkey.pem;
  ssl_prefer_server_ciphers on;
  location / {
  root /home/ubuntu/projects/frontend/dist;
  index index.html;
  try_files $uri $uri/ /index.html;
  }
}

# 백 엔드. 백 엔드를 서브 도메인을 사용했습니다.
server {
  listen 80;
  server_name 서브도메인;
  rewrite^ https://$server_name$request_uri? permanent;
}
server {
  listen 443 ssl; 
  server_name 서브도메인;
  ssl_certificate /etc/letsencrypt/live/서브도메인/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/서브도메인/privkey.pem;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES25
  6-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECD
  HE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA
  -AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA3
  84:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!
  aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
  ssl_prefer_server_ciphers on;
  location /static {
      alias /home/ubuntu/projects/backend/static;
  }
  # nginx를 통해서 서버에 접근하기 때문에 static file과 media file의 경로는 location을 통해서 설정해줘야합니다.
  location /media {
      alias /home/ubuntu/projects/backend/media;
  }
  location / {
    include proxy_params;
    proxy_pass http://unix:/tmp/gunicorn.sock;
  }
}

이렇게 되면 aws 서버 하나에 프론트 엔드와 백엔드 둘다 배포하게 됩니다. 그리고 도메인과 서브 도메인을 통해 각각 프론트 엔드 백엔드에 접속 가능합니다.

참고) https 등록은 도메인, 서브 도메인 둘다 진행해야합니다.

추가

파일 업로드를 위한 nginx 설정입니다.
/etc/nginx의 nginx.conf 파일입니다.
다음 설정들을 사이트 목적에 맞게 바꿔주시면 됩니다.

gateway time out이 발생하면
connect_timeout 과 send_timeout 은 기본값인 60초를 넘길 일이 거의 없고, upstream 에게 정상적인 응답 요청(request)을 보내기 전이므로 시스템적으로 큰 문제가 발생하지 않습니다.
되도록 read_timeout만 설정해주면 됩니다.


http {

  ##
  # Basic Settings
  ##

  sendfile on; # nginx에서 정적파일을 보내도록 설정합니다.
  tcp_nopush on; # 클라이언트로 패킷이 전송되기 전에 버퍼가 가득 찼는지 확인하여, 다 찼으면 패킷을 전송하도록 하여 네트워크 오버헤드를 줄이도록 설정합니다.
  tcp_nodelay on; # tcp_nodelay를 활성화하면 소켓이 패킷 크기에 상관없이 버퍼에 데이터를 보내도록합니다.
  keepalive_timeout 30; # 클라이언트와 연결을 유지하는 시간입니다. 높게 잡으면 클라이언트는 좋지만 요청도 없이 접속만 되어 있을 수 있어서 적절하게 설정해야합니다.
  types_hash_max_size 2048;
  large_client_header_buffers 4 16k;
  client_max_body_size 0; # 사용자 업로드 파일 용량 제한 0 = 제한 없음
  
  # 아래는 값을 적게 설정하면 gateway time out이 발생합니다. 
  proxy_read_timeout 300; # 백엔드 서버 접속 제한시간을 정의합니다. 이 값은 읽기/쓰기 시간 초과와는 다릅니다. 즉, 엔진엑스가 이미 백엔드 서버에 접속된 상태라면 proxy_connect_timeout은 적용될 수  없습니다.
  proxy_connect_timeout 60; # 백엔드 서버로부터 데이터를 읽을 때의 제한시간으로, 이 제한시간은 전체 응답 지연 시간에 적용되는 것이 아니라 두 개의 읽기 작업 사이에 적용됩니다.
  proxy_send_timeout 60; # 백엔드 서버로 데이터를 전송할 때의 제한시간으로, 이 제한시간은 전체 응답 지연 시간에 적용되는 것이 아니라 두 개의 쓰기 작업 사이에 적용 됩니다.
  proxy_request_buffering off;
}

nginx 관련 설정은 다음 문서에서 확인할 수 있습니다 -> 문서

profile
사람들이 비용을 지불하고 사용할 만큼 가치를 주는 서비스를 만들고 싶습니다.

0개의 댓글