최종 프로젝트가 끝나고, 약 2주의 시간이 흘러 이제서야 회고록을 작성하게 되었다.
약 5주간 최종 프로젝트를 진행하게 되었으며, 기획부터 설계, 구현 등 모든 과정을 팀원들과 함께 진행해왔다. 이러한 과정속에서 팀원들과 함께 수많은 우여곡절을 겪으며 함께 헤쳐 나갔었다.
이러한 경험을 토대로 KPT 회고를 작성하려 한다.
KPT
회고란 Keep, Problem, Try의 약자로 회고 방법 중 하나라고 한다.
Keep
은 좋았거나 계속 이어갔으면 하는 부분
Problem
은 부족했거나 개선이 필요한 부분
Try
는 어떻게 개선할 것인지에 대한 부분
최종 프로젝트를 진행하기 전, 주제에 대해서 팀원들과 수많은 의견을 나눴었다. 일단 생각나는대로 아이디어가 떠오르면 무조건 적어봤고, 그 중에서 현실성있고 해볼만하며, 가장 괜찮았던 주제를 선정하게 됐다. 그중에서, 딸깍! 레시피
라는 주제를 선택하게 되었다.
사실, 사용해보고 싶었던 기술을 녹여서 주제를 선정하고 싶었던 욕심이 있었다. 그러나, 프로젝트의 목적이 그것이라면, 과연 의미 있는 결과물이 나올까?
필자는 프로젝트란, 생활속에서 불편함을 느끼고 이를 해결할 수 있는 무엇가를 직접 만드는 것이라고 생각했다. 그렇기에, 기술에 초점을 두기보단, 의미에 초점을 두게 되었으며 요리 레시피에 사용되는 재료를 한번에 주문하는 서비스
를 기획하게 되었다.
요리를 하고싶을 때, 작성된 레시피를 참고하며 재료와 조리 과정을 참고하는 경우가 종종 있다. 하지만, 재료를 구하는 과정에서 많은 시간과 귀찮음이 동반되기에, 이를 해결하기 위해서 나온 서비스이다.
즉, 딸깍! 레시피
란, 레시피에 적힌 재료를 버튼 클릭 한번으로 정량의 식재료를 구매할 수 있는 서비스이다.
사실, 해당 서비스는 만개의 레시피
에서 나온 불편함을 해결하고자 만들어진 것이다.
만개의 레시피
같은 경우는, 식재료를 구매할 수 있는 버튼이 나열돼있지만, 하나하나 구매 버튼을 누르면서 진행해야하며, 정량의 재료를 구매하기가 어려울 수도 있으며, 쇼핑몰 사이트로 이동되고 거기서 결제를 진행해야 된다.
그러나, 딸깍! 레시피
의 경우, 사용자가 필요한 식재료를 선택한 다음, 레시피에서 요구하는 여러 식재료를 정량에 맞춰 한 번에 결제할 수 있도록 도와준다. 식재료를 구매하면서 겪는 번거로운 과정을 한 번에 압축시켜 놓은 서비스라 봐도 무방하다.
단, 해당 서비스에서 제공해주는 식재료에 대해서만 레시피를 작성 및 구매할 수 있다는 단점이 존재하며, 현재는 테스트 버전으로 실제 주문과 결제가 이뤄지진 않는다.
만약, 실제로 서비스가 활성화된다면, 결제 수단으로 쓰이는 카카오페이를 활성화시킬 예정이다.
(그냥, 재미로만 보시길 바란다.)
해당 서비스의 흐름은 위와 같은 사진이었지만, 지금은 바뀐 부분과 없는 기능이 몇개 존재한다. 하지만, 큰 흐름은 바뀌지 않았다.
와이어프레임이라고 보기엔 민망할 수준이라고 생각이 든다. 그러나, 그건 중요치 않다. 팀원들이 다 같은 생각을 갖는지가 중요하다.
처음에는 와이어프레임의 중요성을 잘 몰랐지만, 이 과정을 거치지 않는다면 각자 다른 UI 화면을 생각할 확률이 높다. 그렇기에, 이러한 과정을 통해서 서로 같은 생각을 하고 있는지 확인할 필요가 있다.
초기 버전의 시스템 구성도는 위의 사진과 같았다. Nginx를 통해 웹 서버를 띄우고, 백엔드의 무중단 배포가 가능하도록 Reverse Proxy처럼 사용되게끔 설계를 하였다.
RDB를 PostgreSQL로 사용하려 했으나, 조사를 진행해본 결과 규모가 작은 서비스에는 MySQL과 큰 차이를 두지 않을 수 있다고 하였다. 그렇기에, 서비스의 규모가 커졌을 때 PostgreSQL로 마이그레이션을 해보기로 했으며, 지금은 팀원들이 익숙해하던 RDB인 MySQL을 사용하기로 결정했다.
캐싱 또는 빠른 데이터 접근성을 위해 Redis를 사용하기로 했으며, AWS에서 Redis를 사용할 수 있는 서비스인 ElastiCache가 있다는 사실을 알게되어 이를 사용하기로 해보았다. 그러나, 해당 서비스에서 Redis의 필요성을 느끼지 못하여 결국 사용하진 않았다. 대규모 트래픽이 쏠린다면, 그때 캐싱을 도입하여 문제를 해결해보면 어떨까라는 생각이 들었다.
백엔드 CI/CD는 Github Actions를 통해 구축하기로 했다. 간단하게 workflow 명세서 작성만으로 설정해줄 수 있으며, 기본적으로 worker에 Docker가 깔려있으므로 Docker Hub를 통해 이미지를 업로드하고 EC2에 배포하기 적합한 환경이었다.
프론트는 React로 구현해보려 했으나, React를 모르는 상태에서 구현하게 된다면 React를 학습하는데만 시간이 많이 들것이라고 생각이 들었다. 그래서 빠르게 배워서 사용할 수 있는 프론트 기술이 무엇이 있는지 팀원들과 얘기를 나눈 바, Vue가 적당할 것이라는 얘기가 나와서 이를 사용하기로 했었다.
그러던 순간, 필자의 머릿속에서 프론트 기술인 Svelte가 갑자기 떠올랐었다. Svelte는 거의 바닐라 JS라고 봐도 무방할 정도로 가독성과 직관성이 매우 높은 기술로 알고있었다. JS만 알고있으면 구현하는데 큰 어려움이 없을 정도였으며, 빠른 시간내로 학습하여 구현해야하는 상황에서 가장 적합한 기술이라고 판단하였다. 그렇게, 팀원들과 상의하여 프론트를 Svelte로 구현하게 되었다.
사진으로만 봐도, Svelte에서 상태를 이렇게 쉽게 관리할 수 있다는 모습을 볼 수 있다. 게다가, VDOM을 사용하지 않으며 성능 또한 괜찮다는 평을 볼 수 있었다. 배우기도 쉽고, 성능도 좋다면 선택하지 않을 이유가 있는가?
있긴 하다. 참고할 자료가 잘 없다는 단점이 존재하기 때문이다. 하지만, 이는 Svelte의 공식 문서를 보고 어느정도 극복할 수 있으며, 비교적 자료가 많은 React의 코드를 보고 Svelte로 바꾸기만 하면 되기 때문에, 그리 큰 문제는 아니었다.
그렇게 시스템 구조도의 수정본이 아래와 같이 새로 도출되었다.
특이한 점은, 프론트 서버가 외부로 빠졌다는 것이다. Netlify에서 서버 배포도 해주고, CI/CD도 자동으로 구성해주기 때문에 엄청 간편하게 프론트를 배포할 수 있었다. 단, 한 달에 CI/CD 사용량이 정해져있기에, 이를 의식하며 신중하게 배포를 했어야 했다. 아무튼, 잘만 사용한다면 무료로 배포와 CI/CD를 계속 사용해줄 수 있는 플랫폼이 존재했기에, 이를 사용해보았다.
또한, HTTPS 설정하는 부분이 조금 달라졌다. 원래는 Nginx에 CertBot을 통해 SSL/TLS 인증서를 발급받고 적용하려 했으나, 어차피 도메인을 필요로 한다면 HTTPS를 간단히 설정해줄 수 있는 AWS의 서비스를 사용하면 어떨까라는 생각이 들게 되었다. 그렇게 Route 53에서 도메인을 구매한 뒤, ACM을 통해 인증서를 발급받고 ELB를 통해 HTTPS로 리다이렉트가 되도록 설정해 두었다. 마우스 클릭 몇번만으로 HTTPS를 설정해줄 수 있었다.
단, ELB를 설정해줄 때, 타겟 그룹으로 라우트시킬 포트 번호를 잘 적용해줘야 한다. 기본적으로 스프링 부트는 8080 포트번호를 가지기 때문에, 8080으로 설정해야 하지만 잘 몰랐기에, 삽질을 몇 번 하게 되었다.
설계하는 과정에서 정말 많은 시간을 사용한 것 같았다. 구현하는 도중에 문제가 생겨 막혀버리는 상황이 발생하지 않기를 바랬던 마음이 컸기 때문이다. 특히, ERD를 설계할 때 가장 많은 노력을 쏟아부었다.
우선, 첫번째 ERD는 위의 사진과 같이 도출되었다. 레시피가 가장 중요 포인트라고 생각이 들었고, 이를 중심으로 테이블을 설계해 나아갔다.
가장 골치아팠던 테이블은 식재료
부분이었다. 해당 서비스는 사용되는 식재료마다 가격이 정해져야 했으며, 어떻게 가격을 책정할 것인지, 수량은 어떻게 관리할 것인지에 대해 깊은 고민을 하게 되었다.
결국, 딸깍! 레시피
는 쇼핑몰 사이트가 아니기에, 만약 상용화가 된다면 식재료 부분은 외부 업체와 협약을 맺어 수량과 가격을 책정한다고 약속하며 진행하게 되었다. 그래서 지금은 수량은 무한대로, 가격은 공공 데이터에 나열된 식재료의 가격을 참고하여 임시 데이터를 생성하여 진행하고 있다.
나중에, 공공 데이터에 올라오는 식재료 데이터를 기반으로 식재료 데이터를 계속 업데이트시켜줄 의향도 있었다. 해당 기능은 추가 기능으로 생각해두며 일단 구현에 집중하였다.
레시피에 관련된 기능을 구현하면서, 주문 기능에 대해 구현할 차례가 다가오게 되었다. 이를 위해, 주문 테이블을 상세히 설계해보는 시간을 갖게 되었다.
결제 기능을 구현하게 되면서 결제 테이블도 만들어보는 시간을 가졌으며, 장바구니와 레시피_식재료 테이블의 수정이 발생하였다.
레시피_식재료
테이블은 레시피와 식재료의 매핑 테이블로 사용됐지만, 식재료 데이터가 삭제될 수 있다는 점을 고려하여 해당 테이블만의 기본키를 생성하게 되었다. 그렇기에, 장바구니 테이블도 레시피_식재료
테이블을 참조할 수 있도록 기본키를 외래키로 갖도록 수정하게 되었다.
결론적으로, 위와 같은 ERD가 도출되었으며, 매핑 테이블의 기본키를 복합키로 구성하도록 수정하였다. 큰 의미는 없었지만, 인덱싱 처리를 해줄 때 도움이 될거라고 판단이 되었으며, 나중에 새로운 속성이 추가되어도 큰 영향을 안끼치기 위해 복합키로 설정해 두었다.
이렇게 총 4번의 ERD를 수정하며 최종적으로 가장 마지막의 ERD로 DB를 설계하게 되었다.
구현하기 전에 API 명세서를 작성해두고, 구현하면서 수정되거나 추가된 API를 계속 기록해가며 작업하였다. 최대한 RESTful하게 API를 작성하려 노력했지만, 결코 쉽지 않은 작업이었다.
또한, 명세서를 수정하는 일이 빈번하게 일어났으며, 명세서와 작업 현황이 맞지 않는 경우가 종종 발생했었다. 그렇기에, API 명세서를 자동으로 생성해주는 Swagger를 도입하여 실시간으로 API와 DTO의 형태를 파악할 수 있게 되었다.
이렇게 기획과 설계를 거쳐서 구현에 들어가게 되었고, 마침내 서비스를 출시할 수 있게 되었다.
직접 부딪힌 난관이 정말 많았지만, 포기하지 않고 노력하다보니 극복하게 되었다. 나중에 가서는 욕심이 날 정도였다.
더 설명하자면 끝도 없이 말할 수 있지만, 설계에 대한 얘기는 여기까지 하고 KPT 내용을 적어보도록 하겠다.
일단, 팀원들에게 정말 고생많았다는 말을 전해주고 싶다.
다른 프로젝트를 진행해본 경험은 있었지만, 실제로 서비스를 배포해보고 유저 테스트를 통해 피드백을 받은 것은 이번이 처음이었다. 직접 겪어보니, 클라우드 컴퓨팅의 자원을 설정하는 것과 사용자들의 피드백이 얼마나 중요한지를 알게 되었다. 또한, 설계의 중요성 또한 매번 느끼고 있다. 이번 프로젝트에 대해선 확실하게 설계를 하고 진행해 보았는데, 시간은 그만큼 걸릴지라도 구현 단계에서 큰 문제가 발생하지 않았기 때문에 많은 빛을 발휘했다고 생각한다.
아직 딸깍! 레시피
의 최적화가 남아있기에, 프로젝트의 여정은 끝나지 않았다고 필자는 생각하고 있다. 계속 학습해 나아가면서 끊임없이 성장할 수 있는 개발자가 되도록 노력하자.