본문 바로가기

blah/Records

20240524 프로젝트 회고

5월 24일 금요일, 내 첫 팀 프로젝트가 끝났다.

 

교육장에서 2인으로 약 8일간 진행한 프로젝트인데, 외부로 공개하는 것이 금지되어 있어서 자세한 내용은 말할 수 없다. (그런데 검색해보면 많이 나오더라. 왜지?)

 

프론트엔드는 Vue.js, 백엔드는 Django REST framework로 진행했다. 내 역할은 백엔드 전반과 프론트엔드의 기초 레이아웃 및 리팩토링이었고, 다른 팀원 분의 역할은 데이터 수집 및 전처리, 추천 알고리즘, 일부 데이터베이스가 필요하지 않은 작업과 스타일링이었다.

 

7일이란 기간은 짧았다. 발표 자료도 제출해야 돼서 시간이 빠듯했다. 구체적으로 기획을 짠 다음 백엔드 ↔ 프론트엔드로 역할을 분리하긴 힘들 거라고 판단했다. 또한 기획을 얼마나 구현할 수 있을지도 미지수였다.

 

따라서 기획과 무관하게 필수적으로 진행해야 하는 부분 중에서 서로 무관한 작업들을 배분하기로 했다. 나의 경우에는 회원 관리 기능, 게시판 CRUD를 담당했다. 그리고 개인적으로 Postman 따위의 도구를 이용해서 백엔드 기능을 확인하는 것보다 웹페이지에서 직접 확인하는 게 기획의 발전에 도움이 된다고 생각했기에 Axios를 통한 기초적인 백엔드-프론트엔드 통신까지 구현했다. 팀원분은 그 동안 데이터 수집과 전처리를 진행했고, 프론트엔드 측에서 아예 다른 API로부터 데이터를 받아오는 부류의 기능 구현을 진행하셨다.

 

이렇게 진행한 덕분에 시간을 조금 벌었다. 그 시간에 추천 알고리즘 관련해서 더 고민할 수 있었고, 몇몇 버그들을 진득하게 들여보는 것도 가능했다.

 

그렇게 나온 결과물은, 아쉽지 않다면 거짓말이다. 원하던 기능을 많이 넣지 못했다. 예를 들면 게시글 작성자가 탈퇴하더라도 게시글을 온존시켜 작성자의 이름을 (탈퇴회원)이라고 바꾼다거나, 게시글 내용에 스타일을 적용하고 이미지를 삽입해서 위치를 조절하는 기능이라거나. 특히 후자는 어떻게 구현해야 할지 감이 잘 오지 않았다. 블록 씌운 부분을 어떻게 구분할 것인가? 그걸 어떻게 별개의 대상으로 관리할 수 있을까? 검색하면 나올 터였고 그걸 참고하면 금방 할 수 있었겠지만, 그러고 싶지 않았다.

 

ChatGPT가 많은 도움이 되었다. 대충 질문하다가 ChatGPT가 헛소리를 하면 화가 나서 설명을 제대로 하는 과정에서 뭔가를 깨닫게 되는 일이 잦았다. 역시 사람이 대상을 너무 뭉뚱그려 생각하기만 하면 좋지 않다. 물론 ChatGPT의 답변 퀄리티도 좋았다. 도중에 몸살이 나서 진행이 늦어진 구간이 있었는데, 손이 잘 안 움직여서 지시사항과 내가 쓸 기능들을 모조리 기입한 다음 ChatGPT에게 물어봐서 얻은 결과를 일단 끼워넣은 적도 있었다. 당연히 컨디션이 약간 돌아온 뒤에는 내가 싹 다시 구현하긴 했지만, ChatGPT가 없었더라면 일정이 늦춰졌을 것이다.

 

재밌었던 부분은 역시 버그가 날 때였다. 수많은 버그는 모르기 때문에 일어난다. 정확히 말하자면 덜 알고 있거나 잘못 알고 있기 때문에 일어나는 것이다. 내 앎과 실제 구성 사이의 간극을 메우는 작업은 퍼즐을 푸는 것과 크게 다르지 않다. 물론 단순 실수로 일어난 버그는 재밌지 않긴 했는데……. 시간이 없다는 핑계로 몇몇 문제는 거슬러 올라가며 원인을 찾지 않고 대증적인 해결을 시도했다.

 

예를 하나 들자면, SPA를 구성하는 과정에서 하위 컴포넌트를 mount할 때, 하위 컴포넌트에 필요한 데이터들을 백엔드 측에 요청하고 받아와서 변수에 할당하고 그를 렌더링하는 과정에서 선후 관계를 정확히 지정하지 못해 에러가 났다. 비동기 동작의 순서와 Pinia 라이브러리의 생명 주기 관리법, Vue.js의 lifecycle에 대해 명확히 알았더라면 이런 일이 없었을 텐데. 해결 방법은 v-if의 반응성을 통해서 해당 변수가 null이 아니게 되는 순간 데이터를 포함한 태그가 렌더링되도록 하는 것이었다. 누수는 저 안쪽에서 일어나는데 일단 내가 눈에 보이는 곳을 테이프로 칭칭 감아두는 느낌이라 마음에 들진 않았다.

 

어려웠던 부분은 코드를 재구성하는 것이었다. 코드의 규약을 설정하지 않았다 보니 나와 팀원분의 코드 작성 스타일이 상이했는데, 일단 내 스타일을 기준으로 일관성을 부여하기로 했다. 이건 어렵지 않았다. 보다 어려운 부분은 코드의 반복을 줄이는 작업이었다. 예를 들어 http://127.0.0.1:8000을 BASE_URL이라는 변수에 집어넣는 일을 반복한다거나, 기능이 겹치는 함수를 하나의 함수로 만들어 pinia 스토어에 집어넣는다거나.

 

당연히 내 능력만으로는 해결할 수 없는 일이 있었고, 검색을 하거나 ChatGPT에게 물어보는 순간이 있었는데, 제일 흥미로웠던 건 비동기 요청을 보내는 Axios의 '전역 객체'를 만들어 각 컴포넌트에 보급하는 작업이었다. 이렇게 함으로써 401 에러나 404 에러에 대해 일괄적인 반응을 보이도록 구현할 수 있었다. 객체의 생명 주기까지 위임하는 것은 아니라 의존성 주입까지는 아닌 것 같고  싱글턴 패턴을 바탕으로 하는 의존성 역전 원칙의 간단한 구현이라고 하는 편이 옳아보인다. 아직 OOP와 디자인 패턴을 잘 몰라서 잘못된 생각일 수도 있긴 한데.

 

백엔드 지망인데(오히려 그렇기 때문이라고도 할 수 있겠지만) 기능적으로 백엔드에서 많이 배우거나 시도한 게 없어 아쉬웠다. 아키텍쳐를 고려한다거나, 테스트 코드를 작성해본다거나… 말로만 들어봤던 것들을 적용해볼 시간은 없었다. 예를 들면 인증과 인가를 단순히 token(정확히는 Django REST framework의 플러그인인 dj-rest-auth의 TokenAuthentication을 사용했다)으로 구현했는데, 이 방식을 사용하면 HTTP가 아닌 HTTPS를 사용해야 한다거나 하는 부분들은 들여다보지 못했고, 당연히 다른 대안에 대해서도 그다지 생각하지 못했다.

 

DB 구성에 관해서는… 단순화하자면 작성한 댓글의 목록을 볼 수 있는 페이지에서 각 댓글이 어떤 게시글에 달려 있는지도 표시하고 싶다고 할 때, 단순히 foreign key를 전달하여 해당 key를 pk로 갖는 게시글 튜플을 따로 찾는 것보다 댓글 생성 시 게시글의 제목도 DB에 저장하는 편이 낫겠다고 생각해서 그렇게 진행한 부분이 나름 괜찮은 선택이었던 것 같다. 그리고 아마도 게시글의 다른 정보도 표시해야 했다면 그런 선택을 하지 않았겠지만. 그런데 오늘 찾아보니 데이터베이스에는 인덱스라는 게 있어서 특정 튜플을 pk로 찾는 데 걸리는 시간이 O(N)이 아니라 O(logN)이라던데(정확한 메커니즘은 아직 공부하지 못했다) 역시 세상은 이미 충분한 최적화가 이루어져 있구나 싶었다.

 

기획과 ERD, API 문서 등의 선후관계를 생각해봤을 때 중요한 건 '기존의 코드를 수정할 필요가 적은 방식의 코딩'인 것 같다. 요구사항은 바뀌기 마련이고, 따라서 기능은 추가되거나 삭제되는데, 그런 점에 영향을 최대한 덜 받도록 코드를 작성해야 편하다는 걸 느꼈다. 생각해보면 확장-폐쇄 원칙이나 아키텍처, RESTful API 같은 부분들이 그런 지점을 이야기하고 있는 것 같다. 재밌긴 한데 너무 방대해보인다. 아마 다음 프로젝트에선 이런 것들을 시도해볼 텐데 욕심을 적당히 부릴 줄 알아야 할 것이다.

 

프로젝트를 마무리하면서 하고 싶은 게 늘어만 가는 것 같다. Python 백엔드의 강력함은 역시 Python의 수많은 라이브러리에서 오는 듯해서, 또 한 번 Django 혹은 다른 Python 백엔드 프레임워크를 써서 데이터를 다루거나 간단한 AI 관련 프로젝트를 해보고 싶다. 그러려면 내가 데이터와 AI에 대한 최소한의 이해는 갖춰야 할 테고. 정적 타입을 지닌 언어로 보다 strict하고 경계가 명확한 프로젝트를 진행해보고 싶기도 하다. 프론트엔드도 React 정도는 다뤄보면 좋을 것 같고, Express.js나 Spring 등을 다루면서 각 언어와 프레임워크 사이의 차이를 느끼며 내가 갖고 있는 단편적인 이해를 넓힐 수 있다면 좋겠다.

 

자원은 한정적이다. 선택지를 좁혀야겠지. 어려운 고민이 될 것 같다. 프로젝트는 즐거웠으니, 그 고민과 이후의 실천도 즐거웠으면 좋겠다.

'blah > Records' 카테고리의 다른 글

2024년 하반기 되돌아보기  (0) 2025.01.24
240517 solved.ac  (0) 2024.05.17
240414 solved.ac  (0) 2024.04.14
240406 solved.ac  (0) 2024.04.06
240330 solved.ac  (0) 2024.03.30