이번 자율 프로젝트에서는 이미 알고있던 팀원들과 함께 뭉쳤습니다!

 

2022년, 1년 간의 추억을 되돌아보며 실물 롤링페이퍼 및 꽃배달 서비스를 기획하고 개발하게 되었습니다.

(현재는 프로젝트 기간이 종료되어 공식적으로 제공되는 AWS 서버가 회수되었지만, 비공식적으로 팀원들끼리 AWS 서버를 한대 구매해서 이것저것 시도해보고 있습니다 ㅎㅎ)

 

이번 프로젝트에서는 어떤 걸 했고 무엇을 배웠으며 어떤 부분에 대해 보충해야 할 지에 대해서 간단하게 정리해보았습니다.

 

목차


    0. 팀 컬쳐

    이번에도 역시 Notion을 주로 사용했습니다.

    기록해야 하는 것들이 있으면 Notion에 전부 기록했고, 기타 알림이나 실시간으로 전달해야 하는 부분들은 Mattermost를 연결해서 사용하거나 카톡방, 혹은 Jira를 사용했습니다.

     

     

    0.0. 팀 규칙

    이전 프로젝트에서 사용했던 팀 규칙을 현재 프로젝트에 맞게 살짝 수정한 형태로 사용했습니다.

    특별히 다른 부분이 있다면 이번에는 MR(Merge Request)를 날리고 나서 2명 이상의 동의가 있을 때만 적용하도록 자체적인 규칙을 설정해서 끝까지 지켰습니다.

    (GitLab 무료버전은 몇 명 이상이 Approved를 해야 MR 적용이 되는 기능이 유료.. 입니다 ㅠ)

     

     

    0.1. 갤러리

    이전 2번의 프로젝트에서도 그랬듯이 이번에도 갤러리를 운영했습니다.

    특히 이번 프로젝트는 대부분이 오프라인으로 진행되었기에 사진 관리가 다소 어려운 부분이 있었으나, 제가 하겠다고 선언한 이상 시간을 투자해서 철저하게 관리했습니다.

     

     

    0.2. 회의록

    스크럼때 이야기를 나누기에는 시간이 부족하다고 느낀 경우 아예 시간을 길게 잡고 회의를 진행했습니다.

    회의를 진행한 내용은 서기 혹은 대체자가 직접 Notion에 정리해두었습니다.

     

     

    0.3. 고민한 내용들 게시판

    이전 프로젝트에서의 삽질 게시판이 고민한 내용들 게시판으로 이름이 변경되었습니다.

    이전보다 조금더 자유로운 형식으로 자신이 고민한 내용들을 정리해두었습니다.

     

     

    0.4. 개선사항

    개발 초반부에 MR의 단위를 상세하게 나누지 않아서 누구는 양이 엄청 많아지고 누구는 양이 적은 등 차이가 나는 문제가 발생했습니다.

    Git 담당자로서 Commit 컨벤션이나 폴더구조와 같은 것들 뿐만 아니라 MR도 많이 신경을 썼어야 했는데 그런 부분에 있어서 조금 아쉬웠기에 다음번에는 MR컨벤션도 자세하게 나눠서 처리해볼 생각입니다.

     

    또한 이전 ImTeller 프로젝트에서 진행했던 다른 팀과의 코드리뷰 혹은 개인 공부 내용 발표와 같은 것들을 진행하지 못한 부분이 다소 아쉬웠습니다.

    이 부분은 팀원들이 여유있게 개발을 진행하고 싶다는 의견을 받아서 없앤 부분이었기 때문에 개선을 해야할 내용이라고 보기에는 어려울 수 있지만, 개인적으로 다소 아쉬웠던 부분중에 하나입니다.

    제 나름대로 지친 부분도 있겠지만, 꾸준하게 공부하는 것이 중요하기에 주기적으로 기술블로그를 작성함으로써 이러한 기술 부채, 혹은 기술 습득 욕망을 해결해나갈 예정입니다.

     


    1. 기획단계

    구현 내용이 양 보다는 새로운 기술의 시도쪽에 가까웠기 때문에 생각보다 빠르게 기획 내용이 정리되었습니다.

    덕분에 개발 시간을 넉넉하게 확보할 수 있었고, 예상보다는 조금 늦었지만 정해진 기한 안에 서비스 배포와 이벤트 진행까지 마무리할 수 있었습니다.

     

    1.0. 디자인

    이번에도 디자인 협업에 Figma가 사용되었습니다.

    이것저것 기능들이 추가되면서 지저분하게 늘어난 감이 있지만, 피그마로 작성한 내용들은 모두 실제로 구현했습니다.

     

     

    1.1. ERD

    ERDCloud를 사용했습니다.

    처음에는 롤링페이퍼가 주 서비스 내용이었기 때문에 기본적인 CRUD를 기반으로 몇 가지 테이블만 추가하면 될 거라고 생각했는데, 꽃과 꽃다발, 배송, 신고 등등 다양한 기능들이 추가되면서 연관관계가 점차 증가하여 다소 복잡한 ERD가 완성되었습니다.

    카카오페이를 이용한 가상결제시스템을 도입할 때 최대한 컬럼의 수를 줄이고자 노력해서 배송 테이블에 들어가는 내용이 비교적 적은 편이었지만, 실제로 결제 시스템과 배송 시스템을 구현한다고 하면 이것보다 훨씬 더 많은 컬럼이 필요했을 것 같습니다. (예를 들자면 할인률과 같은 컬럼들이 존재할 수 있겠죠?!)

     

     

    1.2. API 문서

    API와 관련된 내용 역시 Notion에 자세히 기록하려고 노력했습니다.

    기능별로 API의 첫 주소를 나누고, 각 주소에 맞는 API의 URI와 설명, 그리고 현재 작업 진행 정도를 나타내는 페이지를 만들어서 관리했습니다.

    해당 페이지로 개발을 진행하던 중 롤링페이퍼와 메시지간의 역할이 비슷한 부분 때문에 어디에 특정 API를 넣어야 할까에 대해 많은 고민을 했던 기억이 나네요 ㅎㅎ

    (처음에는 롤링페이퍼 조회 안에 모든 메시지를 가져오는 방식을 사용하려고 했으나, 최종적으로는 롤링페이퍼 조회와 메시지 조회를 각각 나누어서 관리했습니다!)

     

     

    1.3. Git

    이전 프로젝트의 GitHub-Flow 전략을 버리고 다시 Git-Flow로 돌아왔습니다.

    실제 큰 프로젝트에서 진행하는 것과 비슷하게 Git 전략을 사용해보고 싶다는 팀원들의 의견을 받아들였습니다.

     

    그 외에도 Commit 컨벤션의 경우 Gitmoji를 사용했습니다.

    그리고 편의상 커밋 메시지는 한글로 작성하였습니다.

     

     

    gitmoji

    :truck: Move or rename resources (e.g.: files, paths, routes).

    gitmoji.dev

     


    2. 개발단계

    2.0. 기술 스택

    세 번의 프로젝트를 진행하면서, 매번 같은 기술 스택만 사용하는 것이 굉장히 마음에 걸렸습니다.

    그렇다고 해서 프론트엔드에 익숙하지 않은 팀원들이 있는데 새로운 기술 스택을 마구 도입하는 것 역시 이기적인 선택일 수 있겠다는 생각을 했습니다.

     

    그래서 팀원들과 많은 이야기를 나누었고, 문제가 발생한다고 해도 제가 커버해낼 수 있다고 생각한 한도 내에서 새로운 기술 스택을 선정하였습니다.

    대표적으로 새롭게 도입하게 된 기술 스택은 바로 Recoil이었습니다.

    이전 프로젝트에서 여러 차례 사용해봤고, 익숙한 Redux와 Redux-Toolkit을 버리고 Recoil을 선택한 이유는 Redux 계열 상태관리 라이브러리에 비해서 간단하게 쓸 수 있고, React와 동일하게 Meta에서 만든 상태관리 라이브러리였기 때문입니다.

    언젠가 한 번 사용해보고 싶었던 기술 스택이었는데, 시간적 여유가 있고 리액트에 익숙한 팀원들이 많은 이번 기회에 사용해보자는 마음을 먹었고 모두가 동의해줘서 사용하게 되었습니다.

     

    그리고 드디어 CRA를 버리고 Vite를 사용하였습니다.

    로컬에서 프론트엔드 서버를 켜면 웹팩에 의해 빌드하는데 걸리는 시간이 오래 걸려 개선하고 싶다는 생각을 한 것이 한두번이 아닙니다.

    이걸 해결하기 위해서는 모듈 번들러 차원의 개선이 필요했는데, Webpack이 아닌 ESBuild를 사용하는 Vite를 사용하면 속도면에서 엄청난 개선을 얻을 수 있다는 것을 이미 이전에 Vite를 사용해봤기 때문에 알고 있었습니다. 그래서 Vite를 사용함으로써 겪어야 하는 다양한 불편함 (정보의 부족, 특정 라이브러리의 미지원)을 감수하고 도입하게 되었습니다.

     

     

    실제로 Vite를 도입하고 배포하는 과정에서 도커 컨테이너로 요청이 제대로 전달이 안되는 과정이 발생했는데, 해당 오류를 고치기 위해서 꽤 오랜 시간을 고민했던 경험이 있습니다.

     

     

    제가 겪었던 문제에 대한 Vite 공식문서의 내용을 추가로 첨부합니다.

     

     

    Vite

    Vite, 차세대 프런트엔드 개발 툴

    vitejs-kr.github.io

     

    하지만 이런 어려움에도 불구하고 프로그램 동작과 관련해서 Vite가 문제를 일으키는 부분들을 모두 제거할 수 있었고, 속도의 장점만을 얻어낼 수 있었습니다!

     

    이렇게 새롭게 도입한 두 가지 요소를 제외하면 나머지는 익숙한 기술스택들을 사용했습니다.

    프론트엔드는 TypeScriptReact를 사용하였으며, CSS 처리를 위해 Emotion을 사용했습니다.

    백엔드는 Spring BootMySQL를 사용했습니다. ORM으로 JPA를 사용했으며, QueryDSL을 사용하려고 했으나 실제로 적용하지는 못했습니다. (코드가 간단해서 Native로 모두 처리했습니다.)

    추가로 로그인 과정에서 액세스 토큰을 사용하기에 이걸 따로 저장해두어 로그아웃 시 해당 액세스 토큰을 사용하지 못하도록 하기 위해서, 그리고 리프레시 토큰을 이용한 유효성 검사를 하기 위해서 Redis를 사용했습니다.

    CI/CD로는 DockerJenkins를 사용했습니다.

     

     

    2.1. 실제 개발 과정

    아이디어 회의부터 기획이 약 1주 반만에 끝났기 때문에 개발 기간을 2주 반, 최대 3주 반까지 잡았고 나머지 1주일은 이벤트 진행 및 QA를 진행하려고 계획했고, 실제로 개발 기간은 약 3주 정도가 걸렸습니다.

     

    특히 프로젝트는 9-6를 거의 완벽하게 지켜냈다는 점에서 매우 만족했습니다.

     

     

    그래도 개발 막바지의 커밋을 보면 새벽에 진행된 몇 커밋이 존재하긴 합니다 ㅎㅎ

    프로젝트 막판에 출력부분과 iOS 지원 관련 문제때문에 조금 고생했습니다...

     

     

    개발과는 무관할 수도 있지만,, 개발이 종료되고 QA를 진행하면서 동시에 이벤트를 2차례 진행했고, 모두 성황리에 종료되어서 당첨자들에게 꽃다발과 실물 롤링페이퍼까지 전달할 수 있었습니다!

     

     

    2.2. 폴더 구조

    프론트엔드 폴더 구조는 크게 특별한 요소가 존재하지 않습니다.

     

    pages 폴더에는 각각의 페이지가 들어있고, 페이지를 구성하는 요소들은 components에서 관리합니다.

    api 폴더에는 api 요청을 편리하게 사용하기 위해 객체 형태로 함수들을 정리해놓은 파일들을 모아놓았습니다.

    assets 폴더에는 애플리케이션에 필요한 다양한 사진 자료들이 들어있고, kakao 폴더에는 카카오 로그인과 관련된 파일들이 들어있습니다.

    recoil 폴더에는 전역에서 관리해야 하는 다양한 상태값들이 들어있고, utils에는 dateFormatters 함수와 액세스 토큰과 리프레쉬 토큰을 업데이트하기 위한 updateTokens가 들어있습니다.

     

     

    백엔드 폴더 구조 역시 단순합니다.

     

    Controller에서 사용자의 요청을 받고, Service에서 비즈니스 로직을 처리합니다.

    Converter 폴더에는 DB에서 데이터를 가져온 후에 그대로 사용하지 않고 DTO형태로 변경해서 사용하기 위한 용도의 파일들이 들어있고, DTO 폴더에는 입력값과 반환값에 대한 정보가 들어있습니다.

    Entity 폴더에는 DB의 테이블에 해당하는 정보가 들어있고, Repository 폴더에는 JPA를 사용하기 위한 파일들이 들어있습니다.

    마지막으로 util 폴더에는 S3와 관련된 내용들이 들어있습니다.

     

    추가로 resources의 env.yml에는 Kakao Developer에서 생성한 꽃바다 애플리케이션의 adminKey가 들어있습니다.

    해당 내용은 중요한 정보이므로 Git에 올라가지 않습니다.

     

     

    2.3. 담당 개발 기능

    이번 프로젝트에서 저에게 주어진 가장 큰 임무는 서버 배포를 처음부터 끝까지 하는 것이었습니다.

    이전 프로젝트들에서 Docker와 Jenkins를 사용하는 모습들을 여러 차례 봐오기도 했고, 그러한 배포 작업들에 관심도 있었고 실제로 작은 부분에서는 관여하기도 했었기 때문에 크게 무리 없이 자동 배포까지 완료했습니다.

     

    사실 배포 과정에서 여러 작은 문제들이 발생하기도 했습니다만...

    (대표적으로 위에서 언급한 Vite 관련 문제가 있겠네요...)

     

    몇 가지 예시를 들자면 백엔드 도커파일을 잘못 이해해서 이상하게 작성한다거나 (jar파일의 이름을 잘못 적었습니다 ㅠㅠ)

     

     

    Vite의 기본 포트를 EC2 서버가 허락하지 않아서 3000으로 접속한 이후 포트포워딩 해야했다거나

     

     

    와 같은 다양한 시행착오들이 있었습니다.

     

    특히 가장 기억에 남는 실수는 방화벽을 켜면서 22번 포트를 열지 않고 서버를 종료한 것이었습니다...

    분명히 젠킨스에서 자동 빌드도 성공적으로 이루어졌고, 서버도 잘 돌아가는데 ssh가 접속이 안됐습니다.

    하필 전날 방화벽을 설정하고 집으로 갔던 탓에 문제가 무엇인지 정확히 파악하는데 시간이 오래 걸렸습니다..

    (아니 어제 집가기 전까지는 잘되던게 오늘 아침에 왜 안되는거지? 라고 생각했습니다 ㅠ) 

     

     

    도대체 뭐가 문제일까.. 한참을 고민했는데

    포팅매뉴얼에 적기 위해 찍어둔 포트상태를 확인해보니...

     

     

    22번 포트가 닫혀버려서 접근할 수 없는 상황....

    어쩔 수 없이 서버를 초기화 하고 세팅을 다시 했습니다 ㅋㅋㅋㅋㅋ

    절대 잊지 않을 것 같습니다 22번 포트 ㅠ

     

     

    한번 실수하고 나니 포트 만지는게 살짝 겁이 났지만..

    두 번째 시도에는 무사히 세팅을 마칠 수 있었습니다.

     

     

    CI/CD 작업을 마치고 진행한 개발은 카카오페이를 연동하여 결제 시스템을 적용하는 부분이었습니다.

    저희가 만드는 애플리케이션으로는 사업자 등록을 할 수 없는 상황이었기 때문에 어쩔 수 없이 테스트 결제로 구현해야했습니다.

     

    결제 시스템 초기 구현

     

    결제 시스템 구현까지는 크게 어려운 일은 아니었습니다.

    필요한 데이터를 서버에 넘겨주고, 서버에서 카카오페이 테스트 API를 요청하는 동시에 결제 및 배송 관련 데이터를 MySQL에 저장합니다.

    그리고 카카오페이 테스트 API의 결과로 돌아오는 정보들을 다시 화면에 띄워주기만 하면 쉽게 완료되는 구조였습니다.

     

    하지만 테스트 과정에서 예상치 못한 문제가 하나 발생했는데, 분명 코드가 작동을 잘 하는데 아주 가끔씩 결제가 정상적으로 되지 않는 현상이 발생했습니다.

    코드적으로 무언가 문제가 있나 싶어서 하루종일 찾아봤는데, 아무리 생각해도 코드에는 문제가 없었습니다.

     

    그래서 카카오페이 API에서 F1002에러에 대해서 정말 많이 찾아봤고, 공식 답변들도 찾아보았지만 답변을 얻지 못했는데.. 

    카카오 DevTalk 게시판에 아래 질문들을 남겨주신 분이 있어서 원인을 파악할 수 있었습니다.

    하지만 공식 답변이 달려있지 않아서.. 원인파악은 했지만 궁극적인 해결은 할 수 없었던 부분이 조금 아쉬웠습니다.

    (우선은 천천히 결제하는 수밖에.. ㅠ)

     

     

    결제 관련 UI를 모두 만들고 난 이후에는 다른 팀원들의 일 중에서 도움이 필요하거나 미흡한 부분을 고쳐주었습니다.

     

    그리고 개발 막바지에 제가 중심이 되어서 진행했던 일이 프론트엔드 최적화였는데요,

    최적화와 관련해서 가장 먼저 적용했던 부분이 바로 코드 스플리팅이었습니다.

    워낙 그림 데이터가 많다보니, 과도하게 그림 데이터를 요구하는 페이지는 해당 페이지를 실제로 사용해야 할 때 그 그림 데이터를 가져오는 방식으로 구조를 변경하면 초기 로딩속도가 향상될 것이라고 생각했고, 실제로 맞아떨어졌습니다.

     

     

    어떻게 보면 결국 모든 서비스를 이용하기 위해서는 같은 시간이 들겠지만, 과도한 초기 로딩을 잡음으로써 유저들이 처음부터 답답해서 빠져나가지 않도록 막는 하나의 장치를 마련했다고 생각합니다. 

     

     

    그럼에도 불구하고 분명 성능 부분에서 부족한 부분이 많았고, LightHouse를 돌려보면서 문제점들을 조금 더 자세하게 파악할 수 있었습니다.

     

    그 중에서도 가장 예상 로딩 절감치가 높았던 텍스트 압축 사용에 대해서 찾아보게 되었고, GZip 최적화에 대해서 알게 되었습니다.

     

     

    데이터를 그대로 넘겨주는 것이 아니라 서버에서 압축해서 처리하는 방식을 사용하는 것인데, 압축률을 높이면 클라이언트에서의 로딩속도는 줄겠지만 압축에 따른 서버의 부하가 늘어난다는 Trade-off가 있는 방식이었습니다.

     

    지금 당장은 서버에 여유가 있고, 유저가 직접 경험하는 로딩속도를 줄이는 것이 우선이었기 때문에 nginx.conf의 gzip 관련 옵션들의 주석을 풀었고, 이를 통해 로딩시간을 상당히 많이 줄일 수 있었습니다.

     

    기본적으로 만들어져있는 nginx.conf에는 gzip 옵션이 주석처리 되어있는데, 이걸 풀어줬습니다!

     

    절감치가 드라마틱하게 줄어듦을 확인할 수 있었습니다!

     


    3. 종합

    서버를 다루고 Docker와 Jenkins로 자동배포를 구현해본다는 것은 정말로 색다른 경험이었습니다.

    제 손짓 하나로 서버가 닫혀버려서 초기화가 강제되는 위험천만한 상황도 겪어보았고, 로컬에선 잘 되는 코드가 서버에 올라갔을 때 문제가 발생해서 nano에디터를 이용해서 shell 환경에서 하나하나 고치는 경험도 해볼 수 있었습니다.

    프론트엔드, 그리고 백엔드를 담당했을 때는 분명 실수를 만회할 수 있는 기회가 어느정도 주어지는 느낌이었는데 Shell을 직접 다루고 CI/CD를 구축하고 배포환경을 구성하는 일은 정말 꼼꼼하게 공부해서 처리하지 않으면 다른 팀원들의 시간까지 상당수 뺏어버릴 수 있다는 것을 깨달았습니다.

    이번 기회를 통해 개발에 있어 더욱 꼼꼼해야 할 필요가 있다는 것을 몸소 체감할 수 있었습니다.

     

    특히 메모에 대한 중요성을 더더욱 많이 느꼈던 프로젝트였습니다.

    CI/CD를 전담했지만, 다른 팀원들 역시 CI/CD에 대해 관심이 굉장히 많았고, 한번 쯤은 경험해보고 싶다는 의견이 많았습니다.

    그래서 다른 팀원들도 제가 배포를 성공적으로 마친 후에 쉽게 따라할 수 있도록 최대한 자세하게 포팅매뉴얼을 작성하였고, 현재 새로운 배포 서버에서 다른 팀원이 배포과정을 겪으면서 제가 작성한 포팅매뉴얼을 수정하기도 하고 다양하게 의견을 나누기도 하면서 학습하고 있습니다.

    이러한 문서화 과정을 통해서 제가 실제로 공부하고 적용했던 부분들에 대해 쉽게 되돌아볼 수 있고 다른 팀원들의 피드백을 받을 수 있다는 점에서 문서화의 소중함을 깨달았고, 앞으로도 제가 새롭게 공부해서 적용한 부분에 대한 내용, 적용에 대한 근거와 같은 것들을 적어놓으면 미래의 제가 훨씬 편하게 개발을 할 수 있을 거라는 확신을 얻을 수 있었습니다.

     

    새로운 도전이 꽤 있었음에도 이전의 프로젝트들에 비해 확실히 여유있는 개발이었고, 팀원들간의 캐미도 좋은 편이었고 서로에 대해 알아가는 시간도 그다지 필요하지 않았기 때문에 정말 편하게 개발할 수 있었던 것 같습니다.

    정말 감사하게도 운영진 측에서 노력을 인정해주셨는지 최우수상을 수여해주셨고, 별개로 UCC상까지 2관왕을 거머쥘 수 있었습니다.

    1년 간의 여정을 행복하게 마칠 수 있어서 정말로 기분 좋은 프로젝트였습니다!

     


    4. 애플리케이션 화면 사진

    꽃다발 생성 1
    꽃다발 생성 2 (개봉일 전에는 봉오리 상태)
    새 메시지 작성
    개봉일 이후 메시지 확인 및 신고 기능
    꽃다발 결제 1
    꽃다발 결제 2
    꽃다발 프린트
    그린하우스 (롤링페이퍼 목록)
    꽃가게 (꽃다발 및 꽃 구매)
    마이페이지

     


    5. 참고자료 및 기술 스택 관련 자료

     

    Vite

    Vite, 차세대 프런트엔드 개발 툴

    vitejs-kr.github.io

     

    Recoil

    A state management library for React.

    recoiljs.org

     

    Redis

    Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache, and message broker

    redis.io

     

    Kakao Developers

    카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

    developers.kakao.com

     

    Code-Splitting – React

    A JavaScript library for building user interfaces

    reactjs.org

     

    nginx 에 gzip 으로 컨텐츠 압축 설정하기

     

    www.lesstif.com

     

    반응형
    • 네이버 블로그 공유하기
    • 네이버 밴드에 공유하기
    • 페이스북 공유하기
    • 카카오스토리 공유하기