나만의 배당주 사이트 만들기) 4-3. 배포 단계 - 배포 마무리!!(nginx, 도메인 연결, https : ssl인증, collectstatic, wsgi:gunicorn)

2025. 2. 18. 13:06프로젝트

이 전 글들이 궁금하다면 ?

 

0. 사이트를 만드려는 이유

https://hsjoo126.tistory.com/80

 

1-1. 프로젝트 가능성 보기

https://hsjoo126.tistory.com/81

 

pandas 와 jupyter 이용해서 테스트해보기 

https://hsjoo126.tistory.com/82

 

1-2. 기획 단계 - 디자인, 와이어 프레임, ERD 등

https://hsjoo126.tistory.com/83

 

2. 개발 단계 - 계획짜기, 구현해보기

https://hsjoo126.tistory.com/84

 

2-1. 개발 단계 - 배당지불일, 시장별 티커리스트 구하기

https://hsjoo126.tistory.com/85

 

2-2. 개발 단계 - 코드 정리

https://hsjoo126.tistory.com/86

 

2-3. 개발 단계 - 사이트에 적용하기(장고)

https://hsjoo126.tistory.com/87

 

2-4. 개발 단계 - 사이트 로딩 속도 줄이기

https://hsjoo126.tistory.com/88

 

2-5. 개발 단계 - 주식별 동적인 페이지 만들기

https://hsjoo126.tistory.com/89

 

2-6. 개발 단계 - 티커리스트 db에 저장해서 불러오기, 해결하지 못한 트러블슈팅

https://hsjoo126.tistory.com/91

 

2-7. 429에러를 해결하기위한 노력, 로직 대폭 수정하기 엉엉... 그리고 해냄...

https://hsjoo126.tistory.com/92

 

2-8. cron.py , view.py 작성하기, 디테일 잡기

https://hsjoo126.tistory.com/93

 

2-9. 개발 단계 - 주가그래프그리기(matplotlib), Non-GUI 백엔드? Agg가 뭐야!, 상세페이지 수정, 페이지네이션 등

https://hsjoo126.tistory.com/94

 

2-10. 개발 단계 - 배포를 위한 준비단계!(pip list 정리, 도커 관련, postgresql 접속하기, 트러블 슈팅 등)

https://hsjoo126.tistory.com/96

 

3. 디자인 - 잠깐 쉬어가자! 그런김에 디자인~!

https://hsjoo126.tistory.com/90

 

4-1. 배포 단계 - nginx작성 ec2 배포, http 설정

https://hsjoo126.tistory.com/97

 

4-2. 배포 단계 - 로컬에 있는 DB(postgresql) 백업 후 EC2에 복원하기 (docker 사용함)

https://hsjoo126.tistory.com/98

 


 

 

배포를 오랜만에 하다보니.. 생각나는 대로 배포를 진행했다 

그래서 순서가 뒤죽박죽일 수 있다! 

대부분 '아 맞다 ... 나 이거 안 하지 않았나 ?' -> 급하게 함 

 

그래서 원래는 블로그 글과 동시에 쓰면서 프로젝트를 진행하는데 

이번에는 모든 과정을 다 끝내고! 블로그 글을 쓴다

TMI 라면 TMI 지만 어쨌든 ~ 

 

오늘은 배포 마무리를 진행해보도록 하겠다! 정리 시작~ 

 

오늘의 목차

➡️ 1차 nginx

➡️ 도메인 연결

➡️ https : ssl 인증

➡️ 2차 nginx

➡️ collectstatic (어라... css 왜 안되지 ? 앗차차)

➡️ wsgi : gunicorn (어라 ... 나 뭐 까먹었는데 ? 앗차차)

 

 

 


 

➡️ 1차 nginx

nginx 관련된 건 다음과 같이 작성했다. 

설명은 주석을 참고하자

#docker-compose.yml
nginx:
    image: nginx:latest #제일 최신 버전 사용
    volumes: 
      - /etc/letsencrypt:/etc/letsencrypt #ssl인증서 관련
      - ./nginx.conf:/etc/nginx/conf.d/default.conf #nginx.conf 파일을 컨테이너 내부의 Nginx 기본 설정 파일로 덮어씀
    ports: 
      - "80:80" #http요청 받을 수 있게
    depends_on:
      - web #web컨테이너 먼저 실행하고 nginx 실행할 수 있게
#nginx.conf
server {
    listen 80; #80번 포트로 들어온 요청만 허용
    server_name 서버ip주소; 
    location / { # / 주소로 들어올 경우
        proxy_pass http://web:8000; #web컨테이너로 전달 & 8000포트로 요청
        proxy_set_header Host $host; #클라이언트가 요청한 원래 호스트 정보를 유지하도록 설정.
        proxy_set_header X-Real-IP $remote_addr; #클라이언트의 실제 IP 주소를 Django에 전달. 기본적으로 프록시를 거치면 클라이언트의 IP가 프록시 IP로 바뀌는데, 이를 방지함.
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #클라이언트가 여러 개의 프록시를 거칠 경우, 전체 IP 경로를 전달.
        proxy_set_header X-Forwarded-Proto $scheme; #클라이언트가 요청한 프로토콜(HTTP 또는 HTTPS)을 Django에 전달.
    }
}

 


 

➡️ 도메인 연결

도메인은 가비아를 통해 연결했다

사실 저번 프로젝트 때 썼던 도메인을 그대로 갖다 쓰는 거라 

자세한 설명은 건너뛰겠다 ... (기대했다면 ㅈㅅㅈㅅ)

 


➡️ https : ssl 인증 &  ➡️ 2차 nginx

sudo apt update
sudo apt install certbot python3-certbot-nginx

 

 

 

sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

 

이런식으로 해서 인증서 발급 받고

 

nginx 를 수정해주었음!

server {
    listen 80;
    server_name hsjoo.site;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    server_name hsjoo.site;

    ssl_certificate /etc/letsencrypt/live/hsjoo.site/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/hsjoo.site/privkey.pem;


    location / {
        proxy_pass http://web:8000;
        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;
    }
}

 

그리고 도커에서도 https인 443 포트를 추가해줌

  nginx:
    image: nginx:latest
    volumes: 
      - /etc/letsencrypt:/etc/letsencrypt
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
      - static_volume:/var/www/static
    ports: 
      - "80:80" 
      - "443:443" #https
    depends_on:
      - web

 

사실 우여곡절이 많았지만 ..... 해결하느라 블로그에 담을 시간이 없었음 ㅜ

아무튼.. nginx 까지 잘 설정하고 사이트는 매우매우 잘 돌아갔음!



➡️ collectstatic (어라... css 왜 안되지 ? 앗차차)

 그리고 사이트를 보는데 css 가 다 날라가버린 것임!

ㅋㅋㅋㅋㅋㅋㅋㅋ 알고보니 ..... 내가 collectstatic을 안 해줘서 그런 거였음 ...

 

collectstatic 이란?(도와줘요 gpt!)

collectstatic은 Django에서 정적 파일(static files)을 모아주는 명령어입니다.

Django 프로젝트에서는 CSS, JavaScript, 이미지 파일과 같은 정적 파일을 관리해야 하는데, 
개발 중에는 각 앱의 static/ 디렉토리에서 이 파일들을 사용합니다. 
하지만 운영 환경(Production)에서는 성능 최적화와 보안 문제로 
이러한 정적 파일들을 별도의 디렉토리(일반적으로 STATIC_ROOT)에 모아 
웹 서버(Nginx, Apache 등)를 통해 서빙하는 것이 일반적입니다.

collectstatic의 역할
프로젝트의 모든 앱에 있는 static/ 디렉토리와 STATICFILES_DIRS에 정의된 경로에서 정적 파일을 검색합니다.
검색한 모든 정적 파일을 STATIC_ROOT 디렉토리로 복사하거나 링크를 생성합니다.
이렇게 모아진 파일들은 운영 환경에서 정적 파일을 효율적으로 제공하기 위해 사용됩니다.

 

 

그렇다고 한다~

 

그래서 settings.py에 static_root를 추가하고

 

nginx 한테도 위치를 알려주었다.

server {
    listen 443 ssl;
    server_name hsjoo.site;

    ssl_certificate /etc/letsencrypt/live/hsjoo.site/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/hsjoo.site/privkey.pem;

    location /static/ {
        alias /var/www/static/; #위치 알려줌
    }

    location / {
        proxy_pass http://web:8000;
        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;
    }
}

 

도커에도 볼륨을 추가해서 도커가 껐다 켜져도 static 데이터가 안 날라가게끔 했다

#docker-compose.yml
	web:
    build: .
    command: >
      sh -c "python manage.py migrate && 
            python manage.py crontab add && 
            service cron start && 
            python manage.py runserver 0.0.0.0:8000"
    volumes:
      - .:/app
      - static_volume:/var/www/static #삭제 안 되게 볼륨 추가
    ports:
      - "8000:8000"
    depends_on:
      - redis
      - db
  nginx:
    image: nginx:latest
    volumes: 
      - /etc/letsencrypt:/etc/letsencrypt
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
      - static_volume:/var/www/static #삭제 안되게 볼륨 추가
    ports: 
      - "80:80" 
      - "443:443"
    depends_on:
      - web
volumes:
  postgres-data:  
  static_volume: #web과 nginx가 공유하는 외부 볼륨 추가

 

이렇게 다 적었으면 도커 한 번 재시작하고

web 컨테이너로 가서 명령어를 입력해주면 됨!

#web 컨테이너 접속
sudo docker-compose exec web bash

#명령어 입력
python manage.py collectstatic

 

이렇게 하고 홈페이지 들어가면 ? css 매우 잘뜸 휴 -


 

 

 

➡️ wsgi : gunicorn (어라 ... 나 뭐 까먹었는데 ? 앗차차)

 

위에까지 마친 후에 음.... 나 또 뭐 까먹은 거 없나?

하면서 둘러보는데 생각해보니 ㅋㅋㅋㅋㅋㅋ wsgi 설정을 안 해놨음...

..

 

원랜 nginx전에 했어야했는데 .... 

그냥 .... 까먹어버림 앗차차 -

ㅋㅋㅋㅋㅋㅋㅋ ㅠㅠ

 

이제라도 생각났으니 다행이란 마음으로 ... wsgi 설정을 해줌

 

wsgi가 뭐에요 ? ⬇️⬇️⬇️⬇️⬇️

https://hsjoo126.tistory.com/67

 

ASGI가 뭐에요? 에서 시작된... WSGI, CGI... 동기와 비동기

장고에서 채팅을 구현하다가, ASGI 라는 말이 나오길래 엥? 저게 뭐지..? 에서 시작된 글이다 ! 그냥 공식 문서 보고 이해가 되었다면 좋았을텐데... 안타깝게도 그렇지 않았음.ASGI 정리글 이라고

hsjoo126.tistory.com

 

 

wsgi인 gunicorn을 사용했고 먼저 docker file을 변경해줌

# Django Dockerfile
FROM python:3.10.11

# 프로젝트 작업 디렉터리
WORKDIR /app

# 프로젝트 요구사항 파일 복사 및 설치
COPY requirements.txt /app/
RUN apt-get update && apt-get install -y python3-pip cron fonts-nanum && \
    pip install --no-cache-dir -r requirements.txt && \
    pip install gunicorn #gunicorn 설치


# 프로젝트 파일 복사
COPY . /app/


# 포트
EXPOSE 8000

# 장고 서버 실행
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "dividend_stock.wsgi:application"] #실행명령어도 gunicorn 관련으로 변경

 

web 컨테이너에서도 wsgi 가 실행할 수 있도록 바꿔줌

  web:
    build: .
    command: >
      sh -c "python manage.py migrate && 
            python manage.py crontab add && 
            service cron start && 
            gunicorn dividend_stock.wsgi:application --bind 0.0.0.0:8000" #wsgi 실행할 수 있도록 변경
    volumes:
      - .:/app
      - static_volume:/var/www/static
    ports:
      - "8000:8000"
    depends_on:
      - redis
      - db

 

 

이미 장고에 wsgi.py 가 존재하고 있기 때문에 이렇게 바꾸는 것만으로도 

사이트는 문제없이 잘 돌아갔음

(밑에는 gpt 슨생님 설명임! 참고!)

 Django 프로젝트에는 기본적으로 wsgi.py 파일이 포함되어 있는데, 
 이 파일이 WSGI 서버(Gunicorn 등)와 Django 애플리케이션 간의 연결을 제공합니다.

wsgi.py의 역할:
project_name.wsgi:application은 Gunicorn이 Django 애플리케이션에 접근할 수 있는 진입점입니다.
WSGI 서버는 이 application 객체를 호출하여 Django와 통신합니다.

 


 

휴... 정리끝!! 

기억을 되살려서 정리를 하다보니.. 빈틈이 많을 거라 예상 ,,, 되지만 어쩔 수 없지! 

일단 배포까지 다 했다!

 

사실 실감 안 남 ㅋㅋㅋㅋㅋㅋㅋㅋㅋ 

거의 마무리 한 거나 다름 없어서 깃허브나 사이트 공개하고 싶지만?

일단 주변 사람들한테 피드백 먼저 받고 블로그에도 공개하도록 하겠다!

 

다음 글은 ,,, 피드백 보충 or 새 기능 추가가 되지 않을까 ? ㅋㅋㅋㅋㅋㅋ

다음 글에서 봐요 여러분 안뇽!