Python 으로 GUI 프로그램을 개발하는건 처음이기 때문에 일단 빈 창을 만드는 것 부터 시작하려 한다.

이 프로젝트는  PyCharm 환경에서 진행된다.  

 

1. PySide

 이번 프로젝트에서 사용할 GUI 개발 도구는 PySide6 이다.  PySide6는 오픈소스 C++ 개발 프레임워크인 QT의 

Python 바인딩 버전이다.  원래 Riverbank Computing 에서 만든 PyQt 란 이름의 바인딩 버전이 별도로 있었지만

PyQt는 GPL 라이선스의 오픈소스이기 때문에 외부 배포시 해당 소프트웨어의 전체 소스코드를 공개해야한다.

그런데 QT를 개발한 QT Company 가 정식으로 Python 바인딩 버전인 PySide 를 지원하기로 했고 이 PySide는

소스코드를 수정하지 않고 라이브러리로만 사용할 경우에 한해서는 소스코드를 공개할 필요가 없는 LGPL 라이선스의

오픈소스이다.  PyQt 와 PySide 는 그 기능과 사용법이 거의 99퍼센트 동일하고 이 프로젝트가 상업적인 목적으로 

개발하는 것도 아니기 때문에 어느쪽을 사용하더라도 문제는 없지만 어차피 거의 같은 기능이라면 규제가 덜한쪽에

익숙해지는 것이 좋을 것 같아서 PySide 쪽을 선택하게되었다.

 

 

2. PySide6 설치

python -m pip install --upgrade pip
pip install PySide6

 PyCharm 에서 프로젝트를 생성한 후 터미널에서 위 명령어를 실행하여 pip을 업그레이드하고 PySide6 를 설치한다.

 

 

3. 빈 창 띄우기

 이제 이번 글의 목적인 빈 창(window)을 띄워보자.

 

먼저 프로젝트의 main.py 를 위와 같이 수정해준다.  실행할 앱, 즉 QApplication 객체를 생성한 뒤 이를 실행하고

앱이 종료되면 프로그램이 정상종료되도록 하는 코드이다.  QApplication 객체를 생성할 때 넣어준 sys.argv 는 현재

실행중인 파이썬 코드(main.py)가 실행되면서 받아온 인자 값들이다. argv[0] 에는 기본적으로 실행된 파이썬 코드의

절대경로가 들어있다.  그런데 위의 코드를 실행하면 아무 창도 나타나지 않는다.  앱을 생성하고 실행했을 뿐 아무

위젯도 붙여주지 않았기 때문이다.

 

QWidget 이라는 클래스를 추가로 import 해준 다음 QWidget 클래스를 상속한 MyApp 클래스를 만들어준다.

그리고 생성자인 __init__ 메소드를 선언한다. __init__ 메소드에서는 슈퍼클래스 QWidget의 생성자인 super().__init__

메소드를 먼저 호출한 뒤 자신의 메소드인 init_ui 함수를 호출한다.  그리고 init_ui 메소드는 윈도우의 타이틀을

인자로받은 문자열로 지정하고 MyApp 위젯을 화면에 뿌려준다.  이제 QApplication 의 객체를 생성하고 방금 만든

위젯인 MyApp 의 객체를 생성한 뒤 앱을 실행해보자. 

 

윈도우 타이틀로 지정해준 MyFirstApplication 이라는 제목을 가진 빈 창 하나가 나타나는 것을 볼 수 있다.

 

 

'개인 프로젝트 > Accounting Program' 카테고리의 다른 글

#5 메인 윈도우(Main Window)  (0) 2021.10.17
#4 툴팁  (0) 2021.10.17
#3 버튼  (0) 2021.10.16
#2 어플리케이션 아이콘 넣기  (0) 2021.10.16
#0 프로젝트 시작  (0) 2021.10.16

 어머니가 회사에서 회계업무를 하는데 회사에서 지원하는 회계 프로그램으로는 할 수 없는 여러 계산 작업들을

스프레드 시트의 함수기능을 사용하여 직접 구현하고 쓰고계셨다. 그런데 매일 늘어나는 데이터를 년단위로 보관해야

하다보니 정기적으로 정리작업을 해주지 않으면 파일을 한번 열람하는데도 한참 시간이 걸리는 비효율적인 상황이다.

복잡한 기능을 필요로 하지 않는 작업들이고 마침 파이썬으로 GUI 프로그램을 개발해보는 연습을 하고싶었던 참이라

실용성이 있을지는 둘째치더라도 한번 프로젝트의 주제로 삼아보기로했다. 아직 확실하진 않지만 UI 개발을 위해서는

Pyside 를 사용하고 데이터베이스는 이전 pybo 프로젝트에서 다루었던 PostgreSQL 을 사용해볼 생각이다.  

먼저 PySide 를 다루는 기본적인 방법부터 알아본 뒤 본격적으로 프로젝트를 진행해보기로 한다.

'개인 프로젝트 > Accounting Program' 카테고리의 다른 글

#5 메인 윈도우(Main Window)  (0) 2021.10.17
#4 툴팁  (0) 2021.10.17
#3 버튼  (0) 2021.10.16
#2 어플리케이션 아이콘 넣기  (0) 2021.10.16
#1 빈 창 띄우기  (0) 2021.10.16

pybo 가 그동안 사용해온 SQLite 는 개발단계에서 사용하기엔 유용하지만 운영환경에서 사용하기에는 많이 부족한

데이터베이스이다.  본격적으로 시스템을 운영하려면 보다 성능이 좋은 데이터베이스를 설치할 필요가 있다.

오라클 등의 상용 데이터베이스를 사용할 수도 있지만 작은 규모의 서비스는 대부분 MySQL 이나 PostgreSQL 등의

무료 데이터베이스를 사용한다.  여기서는 PostgreSQL 을 설치하여 사용해본다.

 

1. PostgreSQL 설치

  직접 PostgreSQL을 설치하여 적용할 수도 있지만 이는 다음 기회로 미루고 여기서는 AWS 라이트세일이 제공하는

데이터베이스 인스턴스를 사용하기로 한다. 

 

AWS 라이트세일 홈페이지에서 데이터베이스 탭으로 들어가면 위와 같은 화면을 볼 수 있다. 

Create database 를 클릭하자.

 

pybo 가 사용할 데이터베이스인 PostgreSQL 를 선택한다.  2021년 10월 16일자 기준으로 최신버전은 12.8 이다.

 

이제 사용할 플랜을 선택해야한다. 첫 3달의 무료지원을 제공하는 15달러 플랜을 선택한다.

 

 

데이터베이스의 이름을 지정하고 생성한다.

 

 

데이터베이스 인스턴스가 생성되었다.  생성한 뒤 10-15분 정도 기다리면 Creating 이었던 상태가 Available 로 바뀌며

인스턴스가 활성화된다.

 

상세페이지에 들어가보면 사용자 이름인 dbmasteruser 와 패스워드, 데이터베이스 주소(endpoint) 를 확인할 수 있다.

이 세 가지 내용은 pybo에서 데이터베이스에 접속하기 위해 필요한 정보이니 기억해두어야한다.

 

 

2. 데이터베이스 생성

 이제 PostgreSQL 인스턴스에 pybo 가 사용할 데이터베이스를 생성할 차례이다.

 

 

sudo apt install postgresql-client

MobaXterm 으로 서버에 접속, 가상환경에 진입한 뒤 위 명령어를 실행하여 PostgreSQL 의 클라이언트를 설치한다. 

중간에 선택지가 나오면 y(yes) 를 선택해준다.

 

 

createdb pybo --username=dbmasteruser -h <데이터베이스주소>

위 명령어를 실행하여 pybo 라는 db를 생성한다.  username 과 데이터베이스 주소, 그리고 명령어 실행시 물어보는

패스워드는 데이터베이스 인스턴스의 상세페이지에서 본 것을 사용하면 된다.

 

 

3. 데이터베이스 접속

 

pip install psycopg2-binary

 django 에서 PostgreSQL 에 접속하려면 psycopg2 모듈이 필요하다.  pip 을 통해 psycopg2-binary 를 설치한다.

 

서버 환경 설정파일 prod.py 를 위와 같이 수정하여 데이터베이스를 등록한다.

 

default 는 디폴트로 사용되는 데이터베이스를 의미하며 만약 여러개의 데이터베이스를 사용한다면 default 외에도

추가적으로 데이터베이스를 등록할 수 있다.

ENGINE 은 데이터베이스 접속에 사용할 모듈을 의미한다.  여기선 psycopg2 가 된다,

NAME 은 데이터베이스 이름이다.  여기서는 pybo 가 된다.

USERPASSWORD 는 데이터베이스의 유저명과 암호이다. 데이터베이스 인스턴스 상세페이지의 내용대로 입력한다.

HOST 는 데이터베이스 주소이다. 마찬가지로 데이터베이스 인스턴스 상세페이지에 표시된대로 입력한다.

PORT 는 데이터베이스의 포트이다.  PostgreSQL 의 기본포트는 5432 이다. 인스턴스 상세페이지에서 확인할 수도 있다.

 

설정파일을 변경했으니 원격저장소에 push 하고 서버에 반영한다.

 

 

4. 테이블 생성

 이제 서버의 데이터베이스가 변경됐으니 마이그레이션 작업을 수행해야한다.  makemigrations 는 이미 처음 서버에

파이보를 설치할 때 수행했기 때문에 migrate 명령어만 수행해줘도 간단히 완료된다. 작업이 완료되면 createsuperuser

명령어를 실행하여 슈퍼유저 계정도 다시한번 생성해준다. 

 

pybo 가 정상적으로 동작하는 것을 확인한다.

 

 

5. pgAdmin

SQLite 를 처음 사용했을 때 데이터베이스의 내부를 살펴보기 위해 GUI 도구인 DB Browser for SQLite 를 사용했었다.

이번에는 PostgreSQL 의 GUI 도구인 pgAdmin 을 사용해보자.  pgAdmin 은 pgAdmin 공식 웹사이트에서 다운로드

받을 수 있다.

 

pgAdmin 을 설치하고 실행해보면 위와 같은 화면이 보인다.  Add New Server 를 선택하여 서버를 추가한다.

 

 

접속에 필요한 정보들을 입력하고 save 를 누르면 접속할 수 없다는 메시지가 뜰 것이다.  데이터베이스 인스턴스를

public 으로 설정하지 않았기 때문이다. 

 

pgAdmin 테스트를 위해 잠시만 데이터베이스 인스턴스를 public 으로 설정을 변경해보자.  상세페이지에서 네트워크

탭으로 가면 설정을 변경할 수 있다.

 

다시한번 save 를 눌러보면 이번엔 정상적으로 접속이 되는 것을 볼 수 있다.   AWS 서버의 데이터베이스는 다시

public 모드를 끄는 것을 잊지말자.  

 

여기까지의 과정으로 pybo 프로젝트는 일단 완료되었다. 앞으로는 추가적인 기능들을 구현해볼 일이 생길때만

포스팅하기로 한다.

'개인 프로젝트 > Django-mysite' 카테고리의 다른 글

#37 로깅(Logging)  (0) 2021.10.15
#36 DEBUG  (0) 2021.10.15
#35 서버 관리자  (0) 2021.10.15
#34 Nginx  (0) 2021.10.15
#33 Gunicorn  (0) 2021.10.15

서버가 사용자의 요청을 처리하다보면 예기치 못한 동작으로 오류가 발생할 때도 있을 것이다.  개발환경에서는

DEBUG 가 True 로 설정되어있어 이러한 오류가 발생했을 때 웹 페이지상에 상세 정보가 표시되며 명령 프롬프트에서도

이를 확인할 수 있다. 하지만 운영 환경에서는 DEBUG 를 False 로 해두었기 때문에 에러가 발생해도 자세한 내용을

알 수가 없다.  이런 상황에서 발생한 오류의 상세 내역들을 기록한 로그 파일을 사용하면 운영 환경에서 정보를

노출하지 않으면서도 오류의 상세 내용도 확인할 수 있다.

 

1. DEFAULT_LOGGING

 로그를 파일로 저장하기 위해 DEFAULT_LOGGING 설정에 대해 알아야 한다. 장고의 DEFAULT_LOGGING 설정은

다음과 같다.

 

DEFAULT_LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse',
        },
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'formatters': {
        'django.server': {
            '()': 'django.utils.log.ServerFormatter',
            'format': '[{server_time}] {message}',
            'style': '{',
        },
    },
    'handlers': {
        'console': {
            'level': 'INFO',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
        },
        'django.server': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'django.server',
        },
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler'
        },
    },
    'loggers': {
        'django': {
            'handlers': ['console', 'mail_admins'],
            'level': 'INFO',
        },
        'django.server': {
            'handlers': ['django.server'],
            'level': 'INFO',
            'propagate': False,
        },
    }
}

version 은 logging 모듈이 업그레이드되어도 현재 설정을 보장하기 위해 항상 고정값 1을 사용해야 한다.

 

disable_existing_loggers 는 True로 설정하면 기존에 설정된 로거를 비활성화시킨다.  여기서는 그럴 이유가 없으니

False 로 설정한다.

 

filters 는 특정 조건에서 로그를 출력하거나 출력하지 않기 위해 사용한다. require_debug_false 필터는 DEBUG 값이

False 인지 판단하는 필터이며 require_debug_true는 그 반대로 DEBUG 값이 True 인지 판단하는 필터이다.

각각 django.utils.log.RequireDebugFalse, django.utils.log.RequireDebugTrue 함수를 호출하여 이를 판단한다.

 

formatters 는 로그를 출력할 형식을 정의한다.  server_time 은 서버의 시간, message 는 출력 내용을 의미한다.

 

handlers 는 로그의 출력 방법을 정의한다. DEFAULT_LOGGING 설정에 등록된 핸들러는 다음과 같다.

  • console : 콘솔에 로그를 출력.  로그 레벨이 INFO 이상이고 DEBUG 가 True 일 때만 로그를 출력
  • django.server : python manage.py runserver 로 구동하는 개발용 서버에서만 사용하는 핸들러이다.
                        콘솔에 로그를 출력한다.
  • mail_admins : 로그 내용을 이메일로 전송하는 핸들러로, 로그 레벨이 ERROR 이상이고 DEBUG 가 False 일 때만
                      로그를 전송한다.  환경설정 파일에 ADMINS 항목을 추가하고 관리자 이메일을 등록, 이메일 발송을
                      위한 SMTP 설정해야 사용 가능하다.

loggers 는 로그를 출력하는 프로그램에서 사용하는 로거의 이름을 의미한다. DEFAULT_LOGGING 설정에 등록된

로거는 다음과 같다.

  • django : django 프레임워크가 사용하는 로거로 로그 레벨이 INFO 이상일 경우에만 로그를 출력한다.
  • django.server : 개발 서버가 사용하는 로거로 로그 레벨이 INFO 이상일 경우에만 로그를 출력한다.
                        'propagate': False 의 의미는 django.server 가 출력하는 로그를 django 로거로 전달하지
                        않는다는 의미이다. 로그가 이중으로 출력되는 것을 막기 위해서이다.

 

 2. 로그 레벨

 로그의 레벨은 다음의 5 단계로 분류된다.

  • 1단계 : DEBUG : 디버깅 목적으로 사용
  • 2단계 : INFO : 일반 정보를 출력할 목적으로 사용
  • 3단계 : WARNING : 경고 정보를 출력할 목적으로 사용 (작은 문제)
  • 4단계 : ERROR : 오류 정보를 출력할 목적으로 사용 (큰 문제)
  • 5단계 : CRITICAL : 아주 심각한 문제를 출력할 목적으로 사용

단계가 높아질수록 심각한 오류이며 로그는 설정한 레벨 이상의 로그만이 출력된다.

 

 

3. 로그 파일

 현재 서버환경에서 오류가 발생하면 확인할 방법이 없다. 이를 해결하기 위해 다음의 두 가지 방법을 사용할 수 있다.

  • 오류 발생시 관리자 이메일로 오류내용을 발송한다. mail_admins 핸들러가 존재하기 때문에 이메일 발송을 위한
    관리자 이메일 등록과 SMTP 설정만으로 사용 가능해진다.

  • 서버 환경에서 오류 발생 시 특정 파일에 로그 출력

 

우선 여기서는 파일에 로그를 출력하는 방식을 알아보자.

 

먼저 위에서 살펴본 DEFAULT_LOGGING 설정을 변수명만 LOGGING 으로 바꾸어 config/settings/base.py 에 추가해준다.

 

formatters 에 앞으로 사용할 로그의 formatter인 standard 를 추가해준다. 

'현재시간 [로그레벨] 로거명: 메시지' 의 형태로 로그를 출력할 것이다.

 

handlers 에 파일에 로그를 저장할 핸들러인 file 을 추가해준다.

 

level 은 INFO 레벨 이상의 에러에 대해 로그를 출력하도록 하며

filters 는 운영 환경에서 사용할 것이니 required_debug_false 필터를 적용한다. 

class 는 logging.handleres.RotatingFileHandler 를 사용한다. 이 클래스를 사용하면 로그파일이 지정크기 이상으로

커질 경우 파일에 인덱스를 붙여 정해진 파일 갯수를 유지하며 로깅하기 때문에 로그파일로 디스크가 포화되는 위험을

방지할 수 있다.

filename 은 logs 디렉토리 내의 mysite.log 로 지정한다.

maxBytes 는 로그파일의 최대크기이다. 5MB로 설정한다.

backupCount 는 유지할 로그파일의 갯수이다. 여기서는 우선 5개의 파일로 유지되도록 설정한다. 

formatter 는 위에서 만들었던 standard 를 사용한다.

 

 

 

마지막으로 loggers 의 django 로거에 file 핸들러를 등록해주고 commit, push 한뒤 서버에 반영해준다.

또한, 서버환경과 로컬환경 모두에서 로그가 저장될 logs 디렉토리를 생성해줘야한다.  로컬 환경에서는 DEBUG 값이

True 이기 때문에 로그가 파일형태로 출력되지 않지만 디렉토리가 없으면 에러가 발생한다.

 

로그파일이 버전관리의 대상이 되지 않도록 gitignore 에 추가해준다.

 

이제 일부러 에러가 발생할 코드를 삽입하여 서버에 반영한 뒤 서버에 접속해보자

 

500 에러가 발생한 것을 확인할 수 있다.  이제 로그 파일을 확인해보자.

 

pybo/base_views.py 의 index 함수에서 3 / 0  으로 인해 ZeroDivisionERror 가 발생했음을 기록한 것을 볼 수 있다.

 

 

 

4. 로거 추가

 이번엔 django 나 dajngo.server 와 같은 기존의 로거가 아닌 직접 만든 로거로 로그를 출력하는 방법을 알아보자.

 

pybo/base_views.py  를 위와 같이 수정한다.  logging 모듈을 import 하여 pybo 라는 로거를 통해 원하는 레벨의

로그를 출력할 수 있다. 

 

config/settings/base.py 에서 pybo 로거를 등록해준 뒤 서버에 반영시켜보자.

 

먼저 pybo 에 접속한 뒤에 로그를 확인해보면 출력한 로그가 제대로 쓰여진 것을 볼 수 있다.

 

 

※ logger = logging.getLogger('pybo') 에서 'pybo' 대신 __name__ 을 사용해도 __name__ 이 실행중인 모듈의

   이름이고 현재 실행중인 파일은 pybo.views.base_views.py 이기 때문에 모듈명이 pybo가 되어 'pybo' 를 넣어준

   것과 동일하게 동작한다. 

 

'개인 프로젝트 > Django-mysite' 카테고리의 다른 글

#38 PostgreSQL 설치  (0) 2021.10.16
#36 DEBUG  (0) 2021.10.15
#35 서버 관리자  (0) 2021.10.15
#34 Nginx  (0) 2021.10.15
#33 Gunicorn  (0) 2021.10.15

django 의 환경 설정 파일에는 DEBUG 항목이 있다.  이는 기본값이 True 로 되어있으나 django 공식 문서에서는

운영 환경에서 반드시 False 로 설정하라고 되어있다. 그 이유는 실행 도중 오류가 발생할 경우 DEBUG 가 True 로

되어있으면 오류 내역을 상세하게 화면에 출력하는데, 이 내용에 settings.py 와 urls.py 에 설정한 내용들이 모두 나타나

서버의 정보를 과다하게 노출하게 되기 때문이다.

 

1. DEBUG 설정

 

개발환경에서 서버의 환경 설정 파일인 config/prod.py 를 위와 같이 수정하고 commit, push 한 뒤 서버에서

git pull 을 실행하여 반영하자. 물론 Gunicorn 서비스를 재시작하는 것도 잊어선 안된다.

 

 

2. DEBUG 테스트

이제 DEBUG 값에 따라 어떤 차이가 발생하는지 로컬 환경과 서버 환경에서 각각 에러를 발생시켜 비교해보자.

 

먼저 DEBUG 값이 디폴트로 True 상태인 로컬 환경이다. 존재하지 않는 url을 요구하여 404 에러가 발생하고

pybo/urls.py 의 내용이 그대로 노출된다.

 

서버의 경우 단순히 표준적인 404 에러 페이지가 보여질 뿐이다.

 

 

3. 404 페이지

 DEBUG=False 일 때 표시되는 기본 404 페이지는 굉장히 밋밋하다. 404 페이지를 원하는 형태로 바꿔보자.

 

개발환경에서 config/urls.py 에 위와 같이 handler404 변수를 지정해준다.  이 변수에 뷰 함수를 지정해주면

404 에러가 발생했을 때 해당 뷰 함수가 자동으로 호출된다.

 

common/views.py 에 실제로 page_not_found 함수를 구현한다.  exception 변수에는 오류에 대한 상세 정보가

담겨있다. 만약 오류의 내용을 화면에 나타내고싶다면 exception 변수를 읽어서 나타낼 수 있다.

 

마지막으로 templates/common/404.html 을 생성하여 위와 같이 404 페이지를 작성해준 뒤 commit, push 해준다.

 

서버에서 git pull 로 변경사항을 반영하고 Gunicorn 서비스를 재시작한다.

 

이제 404 페이지가 위와 같이 표시된다.  다른 오류 페이지들도 이와 같은 방식으로 변경해줄 수 있다.

 

 

'개인 프로젝트 > Django-mysite' 카테고리의 다른 글

#38 PostgreSQL 설치  (0) 2021.10.16
#37 로깅(Logging)  (0) 2021.10.15
#35 서버 관리자  (0) 2021.10.15
#34 Nginx  (0) 2021.10.15
#33 Gunicorn  (0) 2021.10.15

1. 슈퍼유저 계정 생성

 개발 환경에서 사용했던 Django Admin 을 서버 환경에서 사용하기 위해 이번에도 슈퍼유저 계정을 생성해본다.

 

python manage.py createsuperuser

 

서버의 가상환경에서 python manage.py createsuperuser 명령을 실행하여 슈퍼유저를 생성한다.

 

그런데 Django Admin 페이지에 접속해보면 화면이 위와 같이 깨져서 표시된다.  이는 Django Admin 의 static 파일들이

우리가 Nginx에 static 파일 경로로 지정해준 디렉토리에 존재하지 않기 때문이다.

 

 

2. STATIC_ROOT

Django Admin 의 static 파일들은 ~/venvs/mysite/lib/<Python 버전>/site-packages/django/contrib/admin/static

에 위치한다.  Nginx가 이를 정상적으로 인식하도록 하려면 django 환경설정 파일에 STATIC_ROOT 디렉토리를 설정하고

python manage.py collectstatic 명령을 실행하여 관리자 앱의 static 파일들을 STATIC_ROOT 디렉토리로 복사해야한다.

 

개발환경으로 돌아와 서버측 설정파일인 config/prod.py 를 위와 같이 수정한다.  Nginx 가 인식하는 static 디렉토리가

~/projects/mysite/static 이기 때문에 설정파일에서도 마찬가지로 그 디렉토리를 static 디렉토리로 인식하게 한다.

 

그리고 base 설정파일의 STATICFILES_DIRS 의 BASE_DIR / 'static/' 와 충돌하지 않도록 하기 위해 STATICFILES_DIRS 를

빈 상태로 설정한다. 수정이 완료되었으면 commit 한 뒤 원격저장소에 push 한다.

 

서버측에서는 git pull 을 실행하여 변경 내역을 적용하고 서버 프로그램이 변경되었으니 반영을 위해 gunicorn

서비스를 재시작해준다.

 

 

3. collectstatic

 이제 처음에 말했던 것 처럼 python manage.py collectstatic 명령어를 실행하여 관리자 앱의 정적 파일을 복사하자.

이 명령어는 관리자앱 뿐 아니라 다른 설치된 앱들의 모든 정적파일을 복사해준다.

 

명령어를 실행하면 정말 static file을 복사해올지 선택지가 표시된다. yes 를 선택하여 진행한다.

 

ls -l 명령어를 사용하여 static 디렉토리를 확인해보면 admin 디렉토리가 추가된 것을 확인할 수 있다.

 

이제 Django Admin 이 정상적인 모습으로 보여진다.

'개인 프로젝트 > Django-mysite' 카테고리의 다른 글

#37 로깅(Logging)  (0) 2021.10.15
#36 DEBUG  (0) 2021.10.15
#34 Nginx  (0) 2021.10.15
#33 Gunicorn  (0) 2021.10.15
#32 WSGI  (0) 2021.10.15

이번에는 웹 서버중 하나인 Nginx 를 설치하고 Nginx를 통해 pybo에 접속할 수 있도록 설정해본다.

 

1. Nginx 설치

 MobaXterm 으로 AWS 서버에 접속하여 가상환경에 진입, 아래 명령어를 실행하여 관리자 권한으로 Nginx를 설치하자

 

sudo apt install nginx

 

정상적으로 설치되는 것을 확인할 수 있다.  중간에 선택지가 나올 경우 y(yes)를 선택해준다.

 

 

2. Nginx 설정

cd /etc/nginx/sites-avilable
sudo vi mysite

 

 

/etc/nignx/sites-available 디렉토리로 이동하여 mysite 라는 설정 파일을 위와 같이 관리자 권한으로 작성해준다. 

 

listen 80 은 웹 서버를 80 포트로 서비스한다는 의미이다.  HTTP 프로토콜의 기본포트가 80이기 때문에 이렇게 해두면

앞으로는 서버에 접속할 때 :8000 과 같은 포트번호를 생략할 수 있다.

 

server_name 은 서버의 고정 IP이다.

 

location /static 은 정적파일에 대한 설정으로, /static 으로 시작되는 url 요청에 대해 지정된 디렉토리에서 파일을 읽어

처리하도록 하는 설정이다.

 

location / 은 location /static 에서 설정한 것 이외의 모든 요청은 Gunicorn 이 처리하도록 하는 설정이다.

proxy_pass 는 Gunicorn 의 유닉스 소켓 경로이다.

 

 

cd /etc/nginx/sites-enabled
sudo rm default
sudo ln -s /etc/nginx/sites-available/mysite

 

이번에는 /etc/nginx/sites/sites-enabled 로 이동한다.  이 디렉토리는 활성화하려는 설정 파일을 링크로 관리하는

디렉토리이다.  기존의 default 링크를 관리자 권한으로 삭제하고 마찬가지로 관리자 권한을 사용하여 위에서 작성한

/etc/nginx/sites-available/mysite 설정파일의 심볼릭 링크를 생성한다. 

 

 

3. Nginx 실행

이제 변경된 설정을 적용하기 위해 Nginx를 다시 실행해야한다. 

 

sudo systemctl restart nginx

 

이제 Nginx 와 Gunicorn 모두 설정이 완료되었다.

 

브라우저에서 포트번호 없이 고정ip만으로 접속해보면 pybo가 정상적으로 작동하는 것을 볼 수 있다.

 

 

4. Nginx 오류 확인

Nginx 의 설정 파일에 오류가 있는지 확인하려면 다음 명령을 실행하면 된다.

sudo nginx -t

 

위의 경우 설정파일에 문제가 없기에 정상적으로 작동하지만 만약 설정 파일에 오류가 있다면 명령어 실행결과

오류가 발생하고 서버가 정상적으로 실행되지 않을 것이다.

'개인 프로젝트 > Django-mysite' 카테고리의 다른 글

#36 DEBUG  (0) 2021.10.15
#35 서버 관리자  (0) 2021.10.15
#33 Gunicorn  (0) 2021.10.15
#32 WSGI  (0) 2021.10.15
#31 터미널 접속  (0) 2021.10.14

 이번에는 저번 게시글에서 언급했던 WSGI 서버중 하나인 Gunicorn(구니콘)을 설치해본다.

 

1. Gunicorn 설치

 Gunicorn 은 운영을 위한 도구이기 때문에 서버 환경에 설치한다. MobaXterm 으로 AWS 서버에 접속하고

가상환경에 진입한 뒤 다음 명령어를 실행하여 Gunicorn 을 설치한다.

 

pip install gunicorn

 

Gunicorn 이 정상적으로 설치되었다.

 

 

2. Gunicorn 테스트

 이제 Gunicorn 이 정상적으로 실행되는지 다음 명령을 실행하여 확인해보자.

 

gunicorn --bind 0:8000 config.wsgi:application

 

--bind 0:8000 은 8천번 포트로 WSGI 서버를 실행한다는 의미이며 config.wsgi:application 은 WSGI 서버가 호출할

WSGI 애플리케이션이 config/wsgi.py 파일의 application 이라는 의미이다. 실행하면 정상적으로 서버가 구동되는 것을

확인할 수 있다.

 

그런데 서버에 접속해보면 위와 같이 화면이 이상하게 표시된다. 이는 Gunicorn 이 동적 페이지만을 처리하는 

서버라서 정적 파일인 css 파일 등을 해석하지 못하기 때문이다.  정적 페이지의 처리는 웹 서버인 Nginx 에서 할 일이니

우선 Gunicorn 이 정상 동작하는 것만 확인하고 서버를 종료한다.

 

 

3. Gunicorn 소켓

 앞서 테스트에서 Gunicorn 을 실행한 것 처럼 포트번호를 통해 서버를 구동할 수도 있지만 Unix 계열 시스템에서는

포트로 서비스하는 것 보다 유닉스 소켓을 사용하는 것이 빠르고 효율적이다.  현재 pybo 가 설치된 서버는 Linux 환경이니 유닉스 소켓을 사용하여 서버를 구동해보자. 

 

gunicorn --bind unix:/tmp/gunicorn.sock config.wsgi:application

 

--bind 뒷부분이 0:8000 대신 unix:<소켓 경로> 의 형식인 것을 확인할 수 있다. 

 

포트로 구동했을 때와 달리 소켓으로 서버를 구동하면 직접 서버에 접속할 수 없으며 Nginx 와 같은 웹 서버를 통해서

접속해야 한다.

 

 

4. Gunicorn 서비스

이제 AWS 서버에 Gunicorn 을 서비스로 등록하여 Gunicorn 의 시작, 중지를 쉽게하고 AWS 서버를 다시 시작할 때

Gunicorn을 자동으로 실행하도록 해보자. 

 

 

먼저 ~/venvs 디렉토리에서 mysite.env 파일을 위와 같이 작성하자.  nano 혹은 vi를 사용하여 작성하면 된다.

Gunicorn 이 서비스로 실행될 경우 alias 나 셸스크립트 등을 통해 생성되는 DJANGO_SETTINGS_MODULE 환경변수가

생성되지 않기 때문에 직접 환경변수 파일을 생성해두어야 한다.

 

 

cd /etc/systemd/system/
sudo vi mysite.service

 

 

그리고 /etc/systemd/system/ 디렉토리에 위와 같이 mysite.service 라는 파일을 작성한다.  시스템 디렉토리에 파일을 저장해야하기 때문에 슈퍼유저 권한을 사용하여 작업한다.  서비스 파일에는 유저와 그룹, 작업디렉토리와 환경변수

파일, 실행 명령어 등을 정의해둔다.  --workers 2 는 프로세스를 두개 사용한다는 의미이다.

 

 

 

sudo systemctl start mysite.service
sudo systemctl status mysite.service

이제 위의 두 명령어를 실행하여 서비스를 실행하고 정상적으로 실행중인지 확인하자.  정상적으로 실행되지 않을 경우

/var/log/syslog 의 로그를 확인하여 오류를 확인, 수정해야한다.

 

 

마지막으로 아래의 명령어를 실행하여 서비스가 AWS 서버가 켜졌을 때 자동으로 실행되도록 등록해준다.

 

systemctl enable mysite.service

 

 

이제 AWS 서버가 켜지면 Gunicorn 서버가 자동으로 구동된다.

 

 

5. Gunicorn 서비스 종료, 재시작

 서비스를 종료하거나 재시작하고 싶을 경우 아래 두 명령어를 사용하면 된다.

# 서비스 종료
sudo systemctl stop mysite.service

# 서비스 재시작
sudo systemctl restart mysite.service

 

'개인 프로젝트 > Django-mysite' 카테고리의 다른 글

#35 서버 관리자  (0) 2021.10.15
#34 Nginx  (0) 2021.10.15
#32 WSGI  (0) 2021.10.15
#31 터미널 접속  (0) 2021.10.14
#30 settings.py 분리  (0) 2021.10.14

 지금까지는 django 서버를 구동하기 위해 python manage.py runserver 를 실행하여 django 의 내장 서버를

구동하는 방식을 사용했다.  그러나 이 내장서버는 기능도 단순하고 대량 요청과 동시 요청을 효율적으로 처리하지

못하기 때문에 운영 환경에 적합하지 못하다.  즉, 개발은 내장서버로 하더라도 실제로 배포하여 운영할 때는 다른

서버를 사용할 필요가 있는 것이다.

 

1. 웹 서버

 웹 서버는 웹 브라우저로부터 요청을 받아 이를 처리하여 결과를 브라우저에게 보내준다. 대표적인 웹 서버로

아파치(Apache)엔진엑스(Nginx) 가 있다.  이 프로젝트에서는 Nginx 를 웹 서버로 사용하기로 한다.  

 

 

2. WSGI(Web Server Gateway Interface) 서버

 브라우저가 웹서버에 요청한 것이 정적 페이지(static page)라면 단순히 서버내에 존재하는 요청에 대응하는 페이지를

브라우저에 보내주면 간단히 처리할 수 있다.  하지만 동적 페이지(dynamic page)라면 얘기가 조금 복잡해진다.

동적 페이지를 처리하기 위해서는 개발에 사용한 언어에 따라 여러 프로그래밍 언어의 코드를 실행할 필요가 있다.

pybo 의 경우는 파이썬 코드를 실행해야 동적 페이지에 대한 요청을 처리할 수 있을 것이다. 개발환경에서 사용했던

django 내장서버에는 파이썬 코드를 실행할 수 있는 기능이 내장되어있었다. 하지만 Nginx 나 Apache 같은 일반적인

웹서버들에는 그런 기능은 존재하지 않는다. 그렇기 때문에 대신 동적 페이지를 처리해줄 WSGI 서버가 필요하다. 

 

정리하자면, Nginx, Apache 등의 웹 서버가 브라우저로부터 동적 페이지에 대한 요청을 받으면 웹 서버는

Gunicorn, uwsgi 등의 WSGI 서버를 호출하여 그 처리를 맡긴다.  그리고 WSGI 서버가 django, Flask 등의

WSGI 애플리케이션호출하면 WSGI 애플리케이션이 실제로 코드를 실행하여 그 결과를 반환하고 WSGI 서버가

처리 결과를 웹 서버가 처리할 수 있는 형태로 변환하여 반환하면 웹 서버는 이를 웹 페이지의 형태로 브라우저에게

반환한다. 

 

Pybo에서 사용할 WSGI 서버는 Gunicorn 이며 WSGI 애플리케이션은 당연히 지금까지 사용한 django 이다.

 

'개인 프로젝트 > Django-mysite' 카테고리의 다른 글

#34 Nginx  (0) 2021.10.15
#33 Gunicorn  (0) 2021.10.15
#31 터미널 접속  (0) 2021.10.14
#30 settings.py 분리  (0) 2021.10.14
#29 AWS  (0) 2021.10.14

 지금까지는 서버상의 작업을 AWS 의 웹 터미널을 통해서 해왔지만 AWS 웹 터미널은 연결도 자주 끊어지고 상당히

불편하다. 이번에는 다른 터미널 프로그램을 사용하여 작업하는 방법에 대해 알아본다.

 

1. 프라이빗 키

 웹 터미널 대신 일반 터미널에서 AWS 서버에 접속하려면 AWS 계정 프라이빗 키가 필요하다. 

 

AWS 라이트세일 홈페이지에서 계정(Account) 메뉴로 들어간다.

 

SSH keys 탭에서 Download 를 클릭하면 프라이빗 키 파일(.pem 파일)을 다운로드 받을 수 있다.  이 파일을

<프로젝트명>.pem 으로 이름을 바꾸어 로컬 개발환경의 venvs 디렉토리로 이동시킨다.

 

 

2. 터미널 프로그램

 터미널 프로그램은 다양하지만 여기서는 강좌대로 MobaXterm 을 사용하기로 한다.  개인적으로도 쓸만한 터미널

프로그램들을 찾아봤는데 MobaXterm 이 무료 터미널 프로그램중에서는 평가도 가장 좋은편이고 기능도 좋아보였다.

MobaXterm 다운로드 페이지에서 무료버전을 받아 설치하자. 

 

실행하면 위와 같은 화면이 보인다. Session 을 클릭하자.

 

종류는 SSH로 하고 Remote host 에 서버의 고정 ip를, Specify username 에 ubuntu를(인스턴스의 SSH 클라이언트

기본명이 ubuntu 로 되어있다), private key는 프라이빗 키 파일(mysite.pem)의 경로를 지정해준다. 그리고 ok를 누르면

이제 서버에 접속하기 위한 설정이 완료되었다.

 

이제 MobaXterm 에서 서버에 접속할 수 있다.

 

MobaXterm 은 기본적으로 SFTP 기능을 내장하고있어 원격접속한 서버와 파일을 주고받기 위해 별도의 프로그램을

사용할 필요가 없다. 좌측의 SFTP 탭에서 드래그앤 드롭만으로 서버와 파일을 주고받을 수 있다.

'개인 프로젝트 > Django-mysite' 카테고리의 다른 글

#33 Gunicorn  (0) 2021.10.15
#32 WSGI  (0) 2021.10.15
#30 settings.py 분리  (0) 2021.10.14
#29 AWS  (0) 2021.10.14
#28 검색과 정렬  (0) 2021.10.12

+ Recent posts