반려견 MBTI 검사와 커뮤니티 기능을 제공하는 웹사이트
부트캠프를 수료하고 기업협업 인턴십을 했던 회사에서 8월까지 유급인턴으로 일하기로 계약을 하고 근무하게 되었다.
인턴 근무를 하던 중에 다른 동기들은 스터디를 하는 것 같아서 나도 스터디에 참가하게 됐고, 스터디 팀원으로부터 프로젝트 하나 같이 해보자는 제안을 받아서 참여하게 되었다.
위코드 교육과정에서 하게 되는 프로젝트 말고 동기들끼리 자발적으로 진행하는 프로젝트를 하면 좋은 경험이 될 것 같았다.
되돌아 보니 초기 기획 단계에서 적극적으로 참여하지 못한 게 아쉽다. 주제 선정 단계부터 의견을 많이 냈어야 했다.
위코드 1, 2차 프로젝트 같이 클론코딩 위주가 아니라 직접 기획부터 웹 디자인까지 해야 했기 때문에 기획단계에서 생각보다 시간이 오래 걸렸다. 기획과 디자인에 3주 정도, 개발환경 초기 세팅부터 배포까지는 한 달 정도 걸렸다
처음에는 FastAPI로 백엔드 개발을 하려고 했다.
FastAPI를 배우다 보니 여러 장점들이 마음에 들었지만, SQLAlchemy라는 ORM을 비롯하여 새롭게 배워야 할 것이 생각보다 꽤 많았다.
인턴 근무까지 하면서 러닝커브를 올리는 게 쉽지 않아서 이번 프로젝트는 익숙한 Django로 개발하기로 했다.
Django로 개발한다면 자연스럽게 그동안 못 써본 Django Rest Framework를 공부해서 써볼까 생각했지만 FastAPI를 공부하면서 Django Ninja라는 괜찮은 프레임워크가 있다는 걸 알게 됐다.
Django Ninja의 튜토리얼을 조금 따라해보니 내가 원했던 FastAPI의 개발 방식과 여러 가지 장점이 좋아 보여서 DRF 대신 이걸 쓰기로 결정했다.
Django Ninja의 특장점
RDBMS는 Django와 궁합이 좋다는 Postgresql을 선택했다. 다만 Django에서 Postgresql을 위해 준비해 놓은 다양한 기능(full text search, GIN Index 지원 등)을 활용하진 못했다.
프론트엔드 팀원과 합의하여 채팅 기능을 위해 웹소켓이 아닌, 웹소켓 기반의 라이브러리인 Socket.IO 를 쓰게 되었다.
웹소켓 보다 Socket.IO를 활용하는 게 개발 속도와 편의성, 기능구현에 장점이 있어서 선택하게 됐다.
웹소켓과 Socket.IO는 완벽하게 호환되지 않으며 나의 목표는 따로 채팅 전용의 node.js 서버를 만드는 게 아니라 Django와 Socket.IO 서버를 통합해서 배포하는 것이었다.
채팅 기능 구현을 위해 웹소켓을 쓸 경우 일반적으로 Django Channels를 많이 쓰는 것 같은데, 상기한 이유로 python-socketio라는 패키지를 활용하게 되었다.
채팅 메시지를 저장하기 위해 MongoDB Cloud를 활용했다.
문서 몇 번 보고 활용법을 완전히 이해했다고 착각하여 코드가 잘못 된 적이 많았다. 무지성 코딩은 지양하자.
API 엔드포인트 경로 설정 시 순서가 중요한데 이를 지키지 않아서 405 에러가 났다.
/users/me
와 /users/{user_id}
가 있다면 /users/me
를 사용하는 함수가 /users/{user_id}
보다 앞에 있어야 한다. FastAPI도 이런 식이었는데 ninja도 같은 방식인 것 같다.Django Ninja의 리퀘스트/리스폰스 Schema에 관련된 다양한 에러를 경험했다.
대부분 리퀘스트/리스폰스가 미리 정의한 Schema 형식에 맞지 않아 유효성 검사를 통과하지 못하거나(422에러) 리턴하는 Queryset 코드가 잘못되어 생긴 에러였다.
Put/Patch 메서드와 Form, File을 사용할 경우 생기는 문제가 있었고 미들웨어 추가로 해결했다.
JWT를 httponly 쿠키로 저장하는 과정에서 겪은 시행착오
프론트엔드 팀원과 통신하는 과정에서 Content-type 문제와 fetch/axios의 잘못된 문법 때문에 통신이 제대로 안되는 오류를 많이 경험했다.
다른 문제들은 대부분 하루 이틀 안에 해결됐지만, socket.io 서버를 통합하는 작업이 3일 정도로 가장 오래 걸렸다. 패키지 버전 때문에 에러 난 것도 있었고 그 외 매우 다양한 종류의 에러를 경험했다.
공식 문서에 나오는 내용을 무작정 따라할 게 아니라 차분하게 생각하면서 적용해야 한다는 것을 깨달았고 영어 독해력도 코딩 못지않게 중요하다는 걸 실감했다.
처음 써보는 기술을 블로그나 강의가 아닌 공식문서만 보고 학습해서 개발해본 경험이 늘었다.
구글링해서 얻은 코드를 적절히 수정하고 충분한 테스트를 거쳐 검증하고 활용하였다.
함수, 클래스 리팩토링으로 중복 코드를 줄였다.
black
, flake8
, isort
등으로 코드 포맷팅을 하고, 리팩토링을 위해 Sourcery AI의 도움을 받았다.
스키마에서 Field에 alias로 정의하고 모델 클래스에서 @property
를 추가하여 활용하는 방법을 배웠다.
배포하고 도메인까지 구입하고 연결해봤다.
Nginx에서 https 설정하고 리버스 프록시로 백엔드 서버를 연결했다.
HTTP의 다양한 Content-type들에 대해 더 깊이 배웠다.
자바스크립트의 fetch/axios에 대한 이해도가 늘었다.
인증/인가에 대해 더 깊이 배웠다.
프론트엔드 팀원과 더 활발하게 소통하고 함께 문제를 해결하는 경험이 늘었다.
크고 작은 실수로 코드 실행이 안되고 에러나는 걸 많이 경험하면서 고통받았지만 대부분 해결했고, 그 만큼 나도 성장했다고 믿는다.