[algo-with-me] 디자인, 스토리 보드, BE 아키텍처까지 (3)

아직 첫주차에 벌어진 일들입니다. 저번 포스트도 중요했지만 이번 포스트는 더 중요한것같네요.

 

 

제목에 써놓았듯이 이번 포스트에서는 디자인, 스토리 보드, BE 아키텍처에 대한 내용을 담았습니다.

 

프론트 - 무지, 콘, 네오

백 - 저(제이지), 프로도

 

 

디자인

우리는 디자인은 최소화 하기로 이야기 했습니다. 프론트 분들이 디자인 보다는 기술적인 부분들에 대한 학습과 구현을 원하셔서 디자인에는 최소한의 힘을 들이기로 결정했습니다. 그래서 프로그래머스, 백준 사이트의 UI를 마구마구 따와서 만들었습니다.

피그마 링크 (https://www.figma.com/file/V42mrxheeNAvLQMbbvrZli/%EB%94%94%EC%9E%90%EC%9D%B8?type=design&node-id=0%3A1&mode=design&t=fS9T1KdBSXbNQ3HK-1)

 

우선 대회 화면입니다.

네 그냥 프로그래머스 UI 와 거의 유사하게 구현하기로 했습니다. 백준 처럼 사용자가 입출력을 제어하지 않고 solution 함수를 사용하기로 했는데, 이 부분을 어떻게 구현할지 좀 감이 안왔습니다. 자세한 이야기는 나중에 많이 할 예정입니다.

 

 

다음은 대시보드 화면입니다.

구글링해서 나온 ICPC 대시보드 화면을 그대로 복사해 조금 다듬은 수준입니다.

 

로그인 화면입니다. SIMPLE IS THE BEST.

오로지 깃허브로그인만 가능하게 디자인해뒀습니다.

 

저희 메인페이지입니다. 개최중인, 종료된 대회 정보들을 볼 수 있습니다.

백준꺼 가져왔습니다.

 

대회 생성 페이지입니다.

역시나 백준꺼 가져왔습니다.

 

왼쪽 위부터 순서대로 문제 정보, 대회 종료 이후 대회 정보, 대회 종료 이전 대회 정보 입니다.

5주간 3명이 프론트 작업을 해야하는데 이정도면 분량이 조금 많을 수 있다고 하더군요, 그래서 저희는 가장 핵심로직부분을 가장 먼저 구현하기로 했습니다. 대회화면이 최우선이죠!

 

5명이서 이렇게 사진 가져오고 약간의 후추를 뿌리니 나름 괜찮은(?) 디자인을 만들었습니다.

 

 

스토리 보드

이부분은 사실 처음에 막막했습니다. 애자일 방법론에 쓰이는 방법이라고 하네요. 부스트캠프에서는 EPIC -> STORY -> TASK 로 백로그를 분할하는 방법을 설명해주었습니다.

EPIC은 대주제, STORY는 중주제, TASK는 소주제 정도로 이해하면 좋을것 같네요. 조금 더 설명을 보태자면, EPIC은 정말 큰 대주제고, STORY는 유저의 관점에서 어떤 행동을 하는 것이고, TASK는 그 STORY에 따라 구현해야 할 기능들?이라고 보면 좋을것같아요.

 

그런데 저희는 조금 다른 방법으로 했습니다. 콘님이 알려주신 방법인데, 거의 비슷하지만 조금 다른느낌인 방법입니다. 제가 느끼기엔 EPIC이 없다? 정도의 방법이었어요.

위 방법과 마찬가지로 STORY를 가지고, TASK를 만드는 방법이었습니다. STORY는 정말 철저히 유저관점에서 생각하고 그에따른 FE, BE가 개발해야 될것들을 나누어 봤어요. 처음에 되게 막막했는데 하다보니까 생각보다 빨리 정리가 되었습니다. 완벽한것 같아요.(쳐맞기 전까진)

 

그렇게 스토리 보드를 만들었습니다! 한 3시간 걸린것 같네요.

나름 그럴싸해 보이죠? 글 작성하고 있는 지금이 2주차 3일째인데 계속 변동이 생기고 있습니다. 주니어 개발자가 가장 어려워하는게 이런거죠. 할일을 나누고 예상시간을 산정한 다음 주차별 계획을 세우는것. 경험이 없어서 힘들어요. 계획은 계획일뿐

초록색이 STORY, 보라색이 FE, 분홍색이 BE TASK 입니다. 2주차1일째에 이 TASK들을 주차별로 나누었어요.

이렇게 나눈 것을 가지고 github projects에 매주 월요일 마다 이슈를 등록해 백로그를 처리해 나가기로 했습니다.

 

백엔드 아키텍처

대망의 백엔드 아키텍처입니다. 솔직히 말하면 작년 부스트캠프에 저희와 주제가 거의 비슷한 팀이 있어 그 팀의 아키텍처와 동일합니다. 저희가 정말 머리 싸매고 고민했는데 가장 좋은것 같더라구요. 그 글을 찾아 참고하기 전까지도 그 팀의 아키텍처와 비슷한 생각을 그리고 있었으니까요.

 

 
 

채점 과정을 중심으로 흐름을 설명해보겠습니다.

1. 유저가 푼 문제코드를 제출합니다.

2. API서버는 제출한 문제코드를 DB에 저장한 뒤 REDIS MESSAGE QUEUE에 이벤트를 하나 넣습니다.

3. 채점서버가 큐에 값이들어오면 가져와 제출한 문제코드를 도커에게 보내 실행시킵니다.

4. 결과값을 가져와 API서버에게 전달합니다.

5. API 서버는 결과값을 유저에게 보내줍니다.

 

조금 모호해 보이죠? 처음에는 이렇게 생각했습니다. 디테일까지 신경쓰지 못했어요. 예를들면, 테스트케이스는 어디서 가져오지?, 메모리 사용량은 어떻게 체크하지?, 채점 서버에서 정확히 어떤 데이터들이 필요하지? 등등..

그래서 좋다고 생각했죠. 응렁러ㅓㄱ얽

 

이제 각 기술스택 선정 이유에 대해 설명해보려고 합니다.

API 서버, 채점서버: nestJs

일단 저희가 js or ts를 사용하는 것이 필수였습니다. 저희는 ts를 사용하기로 했습니다. 배워보고 싶기도 했고, js가 타입 표시가 안되서 너무너무 불편하다고 혼자 부스트캠프를 진행하면서도 느꼈는데 같이 작업을하면 더더욱 힘들것이라 생각했어요. 그래서 만장일치로(2명뿐이지만) ts를 사용하기로 했습니다.

그리고 저는 nestJS를 사용하고 싶었는데, 프로도님이 그냥 express 사용해도 되지않나? 라는 생각을 갖고 있으셔서 설득하기위해 nestJs를 써야되는 이유들을 정리해 보았습니다. ㅋㅋㅋㅋㅋ (반박시 여러분말이 맞음. 댓글로 적어주세요)

 

  1. 많은 기능을 이미 만들어 포함하고 있어 생산성이 훨씬 좋다. express는 필요한 것이 있을 경우 하나하나 찾아서 설치해야되는데 이런 시간들을 무시할 수 없다. ex) pipe validation, 기본 환경 설정, orm
  2. 스프링과 비슷한 면이 있다(DI, IoC). 스프링은 국내에서 가장 많이 쓰기 때문에 취업에도 유리하다.
  3. 객체지향 프로그래밍에 유리하다.
  4. express는 꾸준한 업데이트가 이루어지지 않고 있다.
  5. ts를 적극적으로 사용한다. nest js는 TS만으로 작성되었다.
  6. swagger 같은 api 명세서 사용이 편하다.
  7. 아키텍처가 정해져 있기 때문에 여러명이 코드를 작성하더라도 어느정도 일관성을 유지할 수 있다.
  8. 원한다면 nest에서 express를 직접 사용하는 것도 가능하다.
  9. crud, 서비스 유닛 테스트, dto, 엔티티까지 모두 CLI를 통해 자동으로 만들 수 있다.
  10. 6주만에 만들려면 시간이 오래걸리는 부분(아키텍처, 환경설정, 라이브러리 설치, 의존성 관리 등)에 신경을 최대한 덜 써야 한다. 이런점에서 좋다.

프로도님은 마음이 한 5대5셨는데 저의 설득과 고민끝에 nestJS 사용에 동의하셔서 사용하기로 결정했습니다!

 

DB: PostgreSQL

db 종류가 정말 많죠, 뭘 써야하나 고민 많이했고 처음엔 mySQL을 선택했다가, PostgreSQL로 변경했습니다.

우선 ORCLE, MS SQL -> 유료고 사용해본 경험이 없기 때문에 패스했습니다.

mariaDB -> 생태계가 크지 않아 패스했습니다.

 

결국 가장 많이쓰는 mySQL과 PostgreSQL 중에 고민하게 되었습니다. 처음 mySQL을 선택했던 이유는, dashboard의 정보를 대회중에는 실시간으로 업데이트 해 줄텐데(3초마다 polling 방식 생각중이었습니다.) 이러면 조회성능이 더좋다고 하는 mySQL을 써야 좋겠구나! 라고 생각했습니다. 정말 단순했죠. 멘토링 이후 멘토님이 사용자마다 db를 3초마다 때릴텐데 이거 감당되냐고 물어봐서 할말을 잃었습니다. 사실 잘 모르거든요. 여튼 그래서 멘토님은 실시간 대시보드는 메모리db 즉 redis를 사용하는 것이 좋고, SSE 방식을 추천해 주셨습니다. 종료된 대회 대시보드만 db에서 조회하면 될것같다고 하셨죠. polling 방식은 클라이언트든 서버든 쉽지 않을거라고 하셨어요.

그래서 저희는 생각했습니다, 어 그럼 db 조회 별로 안할것같은데요? 그쵸? 문제 제출을 생각해보면 쓰기가 많을것같고, 도메인도 좀 복잡해서 조인도 많을것 같은데 이럴 때 유리한 PostgreSQL 을 쓸까요? 해서 바꾸게 되었습니다!

 

정리해보면 다음과 같은 이유로 PostgreSQL 을 사용하기로 결정했습니다.

  • 코드 제출 등의 이유로 쓰기 연산이 더 많을것이라고 생각한다.
  • 테스트 케이스는 file로, dashboard는 in memory에 저장하고 최종 결과만 db에 저장하기 때문에 읽기 연산이 많지 않을 것이라고 예상한다.
  • 도메인이 조금 복잡해서 Join 연산이 비교적 많을것이라고 예상한다.

기술 스택 선정하면서 db들이 어떤 특징을 갖고있는지 알게되었어요.

 

네 이제 두개 끝났습니다. 헉헉.. 절반왔네요!

 

메시지 큐: Redis

메시지 큐는 Redis를 사용하기로 했습니다. 그 이유는 다음과 같습니다.

채점 프로그램: Docker

도커를 왜 굳이 써야하는지? 에대한 이유들을 정리해보았어요.

 

장점

  1. CPU, memory, disk 등 컴퓨터 자원에 제한적으로 접근하는 방법을 쉽게 적용할 수 있다.
  2. docker를 사용한다면 개발/운영 공수가 추가로 들어가는데, 이렇게 추가적으로 들어가야 하는 공수에 비해 docker를 도입했을 때 구현의 용이성을 높이는 측면이 더 크기에 docker를 선택한다.

단점

  1. docker를 쓴다면 thread/process를 쓰는 것에 비해 약간의 성능 손실이 있을 수 있다.

개발을 진짜 시작하지 않아서 예상되는 장단점을 적어봤는데 이부분이 이유를 찾는게 많이 어려웠던것 같아요. 그래도 확실한 가장 큰 이유는 제출한 코드가 어떤 이유로 터졌을 때 도커밖에 영향을 미치지 않는다 가 있겠네요!

 

CI/CD: Github Action

거론된 후보로는 Github Action, Jenkins가 있습니다. 열심히 열심히 구글링해서 장단점을 긁어모아본 결과 Gihub Action 을 사용하는 것이 더 좋다고 생각했습니다.

  • 프로젝트 규모가 크지 않아, 복잡한 기능이 필요하지 않다
  • Jenkins를 쓰는 경우 서버에 올려야 하기 때문에, 서버에 부담이 될 수 있다.
  • Github repo를 통해 배포 과정을 쉽게 파악, 공유할 수 있다.
  • Github를 사용하고 있기 때문에, 연동하기 좋다.
  • 비교적 CI/CD 파이프라인을 구현하는 것이 빠르다.

웹서버: nginx

이건 추후 도입이 필요하다고 느낄 때 사용하기로 했습니다.

 

부하테스트: Altillery

얼마정도의 사용자까지 감당할 수 있을지 부하테스트를 해보기 위해 도와주는 툴들을 찾아보았습니다.

nGrinder, Altillery 등이 있었는데 Altillery 를 사용하기로 결정했습니다.

  • 자료가 많다.
  • jS로 로직을 작성할 수 있다.
  • CLI, GUI로 모두 테스트 정보를 확인할 수 있다.
  • npm으로 간단하게 설치해서 사용할 수 있다.

 

모니터링

추후 모니터링 기능까지 개발이 가능하다고 생각 될때 정하기로 했습니다.

 

 

자 모든 결정이 끝났습니다!

기술 스택을 선정하는데 근거를 찾으려고 많이 노력했습니다. 항상 왜? 를생각해 보려고 하고 있어요.(이러다 사회성 떨어지는거 아니야??)

추가로 생각나는 이유나, 저희의 선택이 별로라면, 근거를 말씀해주시면 저의 성장에 정말 큰 도움이 될것같습니다!

 

글이 많이 길어졌네요 읽어주셔서 감사합니다! 다음편은 제목을 뭘로 할까요,, 지금이 2주차 3일째인데, 2주차 내용을 다뤄보려고 합니다. 아! 환경 세팅하는 글을 쓰면 될것같네요. 제~~~~~~~~일 골치아픈 일중 하나죠. 환경 세팅. 다음 포스트 기대해주세요! ESlint, prettier 등 서버 구축과 환경 세팅에 대해 포스팅 할게요!