Project/codestates-final-project

코드스테이츠 파이널 프로젝트 완료

fullfish 2022. 5. 21. 17:44

클라이언트 주소

https://just-moment-trip.ml/

 

just-moment-trip

 

just-moment-trip.ml

Git

https://github.com/codestates/just-moment-trip

 

GitHub - codestates/just-moment-trip

Contribute to codestates/just-moment-trip development by creating an account on GitHub.

github.com

 

사이트 맵

Wire frame

https://wireframe.cc/pro/pp/31bd8a1dd539807

 

Home - Wireframe.cc Preview

Lorem ipsum dolor sitammet quam Lorem ipsumdolor sitammet quam 여행이름 국가 기간 ~ 기간 금액 여행이름 국가 기간 ~ 기간 금액 LoremipsumdolorsitammetquamLoremipsumdolorsitammetquam Lorem ipsum dolor sitammet quam Lorem ipsumdolor sit

wireframe.cc

 

Prototype

https://www.figma.com/file/LcuNVrcQf6Uz7IqPZ1q95u/Untitled

 

Figma

Created with Figma

www.figma.com

 

그밖의 세부내용은 맨위의 git참조

 

프로젝트를 시작하기전에는 프론트와 백엔드 어디가 더 취향에 맞을지 확신하지 못했다.

그러나 막연하게 백엔드가 더 맞겠다고 생각했고 2번의 프로젝트 모두 백엔드를 맡아서 진행했다.

프론트는 변경내용이 눈에 바로보이는점이 매력있지만

나는 데이터를 관리하는 백엔드에 더 매력을 느꼈다.

단순히 데이터를 받고 주는것이 다가아니며 조금 더 고민을 해서 효율적인 코드를 짜면

그것이 실직적인 속도및 용량에 이점을 주며 서버비를 줄일 수 있다.

단적인 예로 서버관련 비용이 1억이 나가고있을때 코드 성능을 10%만 끌여올려도 1000만원을 절감할 수 있다.

 

api와 db스키마 그리고 CRUD는 필수적이며 기본적인 내용이므로 오래걸리지 않았으며

advanced로 무엇을 도전해볼까하다가

 

제가 구현한것이

  • slack을 이용한 로그 남기기
  • cron 스케쥴러를 이용해서 쓰레기값 삭제
  • fuzzy검색(정규표현식, 리벤슈타인 거리, n-Gram 활용 및 하이라이트 적용)
  • google map api를 이용한 가계부 열람시 해당 물품 구매한 장소 map에 랜더
  • socket.io를 이용한 실시간 채팅

slack을 이용한 이유는

로그를 남기면 나중에 해당 요청(get, post와 같은 요청들)이 언제 일어났는지 알 수 있으며

어떠한 정보에 접근했는지, 어떠한 정보가 생성, 수정, 삭제되었는지를 알 수 있다.

또한 개발단계에서도 내가 놓쳤던 에러부분이 존재하더라도

다른 팀원들이 테스트중에 에러가 발생했다면 (그 에러를 클라이언트에서 눈치 채기 어렵더라도) slack에 해당 에러로그가 남으므로 에러의 존재여부를 알 수 있다.

또한 slack어플을 이용해 스마트폰으로 쉽고 빠르게 로그를 볼 수 있다.

 

cron 스케쥴러를 사용한 이유는

스케쥴러라는 기능을 넣고자는 했지만 마땅히 사용할 곳이 없었다.

처음에는 전날치 로그들을 묶어가지고 하루에 한번 주기적으로 메일로 보내려고 하였으나

사실 필요없는 기능이라고 생각해서 사용처를 고민하던 와중에 좋은 아이디어가 생각났다.

현재 db스키마가

user - trip이 1 : N

trip : diary가 1 : N

diay : hashtag가 N : M이다

sequelize에서 관계설정을 해주고

onDelete와 onUpdate 옵션을 'CASCADE'를 줘서 상위 테이블인

user를 삭제시 하위의 trip이 삭제되며

삭제된 trip의 하위 diary도 삭제되며

diary의 하위 join table인 diary_hashtag table도 삭제된다.

하지만 hashtag는 삭제되지 않는데 그 이유는 

diary와 hashtag가 N : M연결이기 때문에

삭제된 diary가 사용하고 있는 hashtag가 다른 diary에서도 사용하고 있을 수 있기때문이다.

그러나 join table이 삭제되면서 아무곳에서도 참조하지않는 hashtag의 값이 생긴다면

이 값은 쓰레기값이 되며 메모리 용량만을 차지하고 있게 된다.

그렇다고 join table의 변경시마다 hashtag table을 참조해서 쓰레기값 여부를 확인하는것은

리소스 낭비이므로 스케쥴러를 이용해서 주기적으로 쓰레값을 삭제해주었다.

 

fuzzy 검색 로직

fuzzy검색으로 정규표현식, 리벤슈타인 거리, n-Gram을 이용했다

정규표현식으로 초성 검색 및 중간 생략검색 구현

-> 해당 데이터에 오차값 1이하를 true로 두는 리벤슈타인 거리 데이터를 중복데이터를 제외하고 추가 시켜 줬으며

-> 3-Gram이 0.27이상인 값 또한 중복데이터를 제외하고 추가시켜줬다.

이러한 순서로 한것은

정규표현식으로 찾은 값 -> 리벤슈타인 거리로 찾은 값 -> n-Gram으로 찾은값 순서로

유사도가 높다고 판단했기 때문이다.

그리고 성능 및 사용자 경험을 개선하기 위해서

정규식으로 찾은 데이터를 일치하는 글자간 거리를 기준으로 오름차순, (유사도에 따라 가중치를 주었다.)

리벤슈타인 거리의 시간복잡도와 공간복잡도를 줄임,

n-Gram을 1글자 단위가 아닌 자음, 모음단위로 끊어서 구현했다.

그리고 검색을 한 글자와 일치하는 데이터의 글자마다 빨간색으로 색을 바꿔서 하이라이트를 줬다.

 

Google map api 사용처

나는 평소에도 가계부를 쓰며 여행갔을때 역시 기록을 한다.

여러 여행 가계부를 써봤을때 불편했던 점이 있는데

검색기능이 없으며 -> 그래서 구현함

map기능이 없거나 불편하게되어있었다.

그래서 구현한 map관련 기능을 넣었는데 이 기능의 필요성은

물건을 사거나 음식을 먹었을때 나중에 그곳의 위치를 알기 위해서이며

로직은 가계부 페이지 접속시 해당 위치 gps를 세션스토리지에 저장해 놓고

가계부 작성시 세션스토리지값을 참조해서 db에 저장했다.

그리고 해당 구매 물품을 열람시 db에 저장된 gps값을 가져오고

그값을 google map api를 활용해서 map에 랜더해준다. 

이때 구매한 물품의 이름은 props로 받아서 map내의 마커에 출력되게끔 해줬다.

세션스토리지를 이용한 이유는

로컬스토리지는 데이터를 수동으로 삭제하지 않는 이상 영구히 남아있는데

세션스토리지는 탭을 닫으면 삭제되는 데이터이기 때문이다.

gps의 값은 계속 변하므로 영구성이 없는 세션스토리지에 저장을 했다.

 

처음에는 정규표현식을 이용한 fuzzy검색을 시도했는데

정규표현식이 생소하며 너무 어려워보였으며

특히나 한글 초성검색의 경우에는 글자를 초성, 중성, 종성으로 분해할 수 있어야하기에

이걸 기간내에 할 수 있을까 싶었지만

결국에는 완료후 리벤슈타인거리, n-Gram도 적용 및 성능 개선을 했으며 하이라이트도 줬다.

또한 다른 어드벤스드 내용까지 구현했다. 

결국 겁먹을것없이 하면되며 가계부 어플을 사용하다가 있었으면 하는 기능들을 직접구현에 성공하니까

성취감이 있다.