첫 번째 대형 프로젝트(+프로젝트 구조, WSGI)

조호원·2020년 11월 4일
1

프로젝트 전의 이야기

(글자수를 줄이기 위해 존댓말을 사용하지 않았음을 알려드립니다. ㅎㅎ)

추석날 할머니집에 내려와 동아리 Change Maker 동아리에서 했던 '에너지 지킴이' 프로젝트의 API 문서를 작성하던 도중 아버지께서 내가 코딩하는 것을 보시더니 아버지 회사에서 아버지가 주도하는 프로젝트를 해보지 않겠냐는 제안을 받게되었다. 그 때는 그냥 지나가는 식의 말로 끝났지만. 지금은 나혼자 프로젝트를 계획하고 설계하여 주도적으로 이끌게 되었다.

사실 Change Maker에서 했던 IOT 프로젝트를 제외하면 큰 웹 프로젝트를 혼자서 진행하는 일은 처음이다. 그래도 전에 완성했었던 프로젝트들을 희망삼아 아버지의 제안을 받아드렸다. 사실 이 프로젝트는 아버지가 정부에게 지원을 받은 연구과제로써 현재 진행중인 프로젝트였고 외주를 맡긴 업체쪽에서 제대로 일처리가 되지않아 나에게 일이 넘겨진 것이다.

하지만, 그렇다고해서 이 일에 믿음이 없던 것은 아니였다. 10월달에 시작했지만 나는 지금도 충분히 이 프로젝트의 사회적 가치를 믿는다. 공기압축기 서비스 관리자들이 앱으로 기계들을 관리하고 데이터를 수집하여 고장을 예측하고 부품 교체 주기를 알려주는 애플리케이션이다. 더 나아가 고객 회사(공장 주인)과 서비스 회사(공기압축기 관리 회사)간 연결 고리를 이어주는 플랫폼을 만들 것이다.
이른바 CSP(Compessor Service Platform)인 것이다.

Restplus의 발견

위에서 말했던 '에너지 지킴이' 프로젝트에서는 그냥 Flask로 Rest API를 작성했다.
하지만 이번 프로젝트를 하면서 엄청난 발견을 하게되었다. Flask에서 제공하는 Restful 확장인 Flask-Restplus는 Swagger와 연결되어 바로바로 API 문서를 작성하고 프로젝트를 쉽게 구조화할 수 있었다. 이때까지 노션이나 MarkDown(아무것도 모르던 시절 ㅠㅠ)으로 API 문서를 작성했다면 Flask-Restplus는 파이썬 코드로 API 문서를 작성 할 수 있게된 것이다! (과거의 내가 바보였다고 느끼게 되었다.) 그렇다면 기존 프로젝트의 구조와 현재 프로젝트의 구조 차이를 보겠다.

기존 프로젝트 구조(에너지 지킴이)

  • app
    • api
      • device_api.py
      • raspberry_api.py
      • web_api.py
    • models.py
    • __init__.py
  • config.py


    기존 프로젝트 구조는 파일 하나에 코드를 전부 넣어서 코드가 복잡하고 오류가 발생할 때 디버깅하기 힘들었다. 또 manage.py를 이용한 Flask-script 기능이 없어서 매 파이썬 쉘을 사용할 때마다 모델 객체를 임포트 해주어야했다.
    가장 힘들었던 점은 curl을 이용해서 api를 하나하나 테스트를 했다는 점이다.

새 프로젝트 구조(CSP)

  • app
    • apis
      • user.py
      • user_company.py
    • resources
      • user.py
      • user_company.py
      • function.py
    • __init__.py
    • models.py
  • config.py
  • manage.py

아직 계속 진행중인 프로젝트지만 지금까지 프로젝트 구조중에 가장 마음에 드는 구조이다. manage.py를 이용하면 파이썬 쉘을 킬 때마다 모델들을 자동으로 임포트 해주고 apis 디렉토리는 Swagger 문서를 작성하는 코드들을 담고 resources 디렉토리는 실제 api를 구현한 코드들과 자주쓰는 함수들을 모듈화 했다.
Swagger는 단순히 클릭 몇번으로 요청을 보낼 수 있어 curl를 이용한 방법보다 몇십배는 효율적이게 코딩할 수 있게되었다.

WSGI가 도대체 먼데?

새 프로젝트를 시작할 겸 WSGI에 대해 알아 보았다. Flask를 처음 시작할 때 WSGI나 Werkzeug처럼 알수없는 단어들을 나중에 공부하리라하고 넘어갔는데 그게 지금이 되었다.

WSGI란 Web Server와 Web Application간의 HTTP 통신을 위한 명세(쉽게 말해 규칙)이다.

그렇다면 Web Server와 Web Application 그리고 WSGI, uwsgi 관계에 대해 알아보자.

기본적으로 웹 애플리케이션은 HTTP 형식의 요청과 응답을 주고받는 형식. 요청은 1차적으로 Web Server(nginx나 Apache가 양대산맥을 이루고 있다. 이미지나 html과 같은 정적파일을 다룬다.)를 통해 처리되는데 이 중에 서버사이트에서 처리가 필요한 경우 uwsgi라는 데몬(백그라운드에서 실행되는 프로그램)이 이 처리를 담당한다.

uwsgi는 Application Container로써 적재한 Web Application을 실행 시켜주는 역할만 한다. 그렇다고 모든 Web Application을 uwsgi에 적재할 수 있는 것이 아니라 uwsgi가 실행할 수 있도록 명세를 따라야 한다. 그리고 우린 이러한 명세를 WSGI라고 말한다. 정리하면 uwsgi는 WSGI명세를 따른 Application만을 실행 시켜주는 컨테이너다.

간단히 WSGI를 설명하면 Python 표준으로 HTTP를 통해 요청을 받아 응답하는 Application에 대한 명세이고 이러한 명세를 만족하는 클래스나 함수(__call__()를 호출할 수 있는)객체를 WSGI 애플리케이션이라고 한다.

위 그림과 같이 WSGI Application(WSGI 명세를 따른 callable한 객체)를 작성하고 사용자가요청을 하면 Web Server의 uwsgi 데몬이 Application을 실행한 뒤 그 결과로 응답한다. 그럼 직접 WSGI Application을 만들어 보자.

 def app(environ, start_response):
    response_body = b'Hello World'
    status = '200 OK'
    response_headers = [('Content-Type', 'text/plain'),
                        ('Content-Length', str(len(response_body)))]

    start_response(status, response_headers)

    return [response_body]

from wsgiref.simple_server import make_server

httpd = make_server('',  8000, app)
httpd.serve_forever()

127.0.0.1:8000 으로 접속하면 제대로 응답을 받는 것을 확인할 수 있다.
이제 Flask에 대한 안목이 생겼다. Flask로 백엔드 개발자들은 웹 서버가 아니라 애플리케이션을 개발하는 사람들이고 Flask는 복잡하고 귀찮은 WSGI 구조를 사용하기 편하도록 추상화한 Framework인 것이다. 예를들면 위의 코드에 environ은 Flask의 request객체로 대체되어 복잡도를 줄였다.

그럼 다음에는 WSGI 유틸리티인 Werkzeug에 대해 공부해봐야겠다.




훨씬 잘 설명한 블로그들 (출처)
WSGI
https://spoqa.github.io/2011/12/24/about-spoqa-server-stack.html
WSGI를 Flask로 구현하기
https://spoqa.github.io/2012/01/16/wsgi-and-flask.html

profile
세상을 바꾸는 사람

0개의 댓글