간만에 겜린더 개발 일지를 작성해 보는데
이번에는 백엔드를 중심으로 작업이 되었고
필수 기능들이 대부분 구현이 되었기 때문에 이렇게 정리한다.
사실 노션에 정리해둔거 여기다가 백업한다
겜린더의 이번 목표는
단순 사이드 프로젝트에서 멈추는 게 아닌 진짜 서비스를 목표로 제작하는 것이 목표다.
사실 이전에도 서비스를 목표로 만들었고 열심히 업데이트를 했지만
항상 맨날 언급한 컨텐츠 문제, 그리고 스케일업이 불가능한 서버 구조로 인해 결국 지금은 서버를 그냥 내려놓은 상태다.
오늘의 글은 차례대로 문제점을 적고 어떻게 해결했는지 공유하기 위한 글이라고 생각하면 된다.
그리고 혹시나 구조와 코드를 보면서 더 좋은 방법이 있다면 언제든 댓글을 달아주면 감사하겠습니다. ☺️
문제점
세일 기간 및 게임 정보 빈약
겜린더는 기본적으로 게임이 언제 출시하는지 달력으로 정리해 보여주는 게 핵심이다.
그런데 세일 기간 정보는 가지고 있어도 달력에 제대로 표현하지 못했고, 직관적이지 못해 따로 영역을 만들어서 표시할 예정이고
게임 정보가 빈약한 이유는 여태까지 내 손으로 직접 손수 직접 검색해 일일이 추가했던 구조라 정보가 매우 부족했다.
이러한 문제점들이 결국 백엔드를 새롭게 만들게 된 계기가 되었다.
문제점
기존 백엔드는 모든 날짜 정보를 불러와서 달력이 갑자기 초기화되는 현상 발생
이전에 겜린더를 만들고 서비스하면서 위 현상 때문에
"아... 이거 잘 못 만들었다..."
라는 생각을 들게 만들었다.
ㅋㅋㅋㅋㅋㅋㅋㅋㅋ.... 진짜 충격적인 구조
이때는 json-server를 이용해 만들었는데
전혀 DB와 백엔드 자체에 이해도가 없었던 때라 야매로 만들자~ 느낌으로 했다가 이렇게 다시 제작하게 되었다.
예전에는 그냥 통신만 되어도 오오오오! 하면서 신났을 때라 나중에 스케일업까지는 전혀 고려해 보지 못했던 상황이었다...
구조를 하나씩 쪼개서 설명하자면
이미지에 보면 datelist라는 Array가 보일 텐데 이걸 펼치면...
지옥이 펼쳐진다...
저 데이터가 달력에는 12월 7일을 보면 .으로 표시가 된다.
이 리스트 들을 앱을 실행할 때마다 항상 GET 요청을 통해 달력에 표시가 되는 구조인데
이러면 처음 정보가 없을 땐 괜찮지만 나중에 데이터가 쌓이면 대참사가 발생한다.
왜냐면 원하지도 않는 날짜까지 전부다 불러오는 구조라
추후에 서비스를 운영할 때 서버가 불필요한 자원을 소비하기 때문이다.
실제로 저렇게 불러와서 달력을 옆으로 넘기면 오버플로우인지 뭔지는 모르겠지만 다시 초기화가 되어버리는 치명적인 버그가 있었다.. (디버깅 로그에도 안 뜬다...)
게임 정보가 들어있는 Array...
해당 날짜를 이제 누르면 localhost:1234/2021-03-02 이런 식으로 요청을 해 게임 데이터를 가져오는 구조이다
겉보기엔 괜찮아보이지만...
이건 엄청난 노가다를 요구하는 구조가 되어버린다.
한마디로 비효율적인 구조...
이를 위해
Redis와 FastAPI를 사용하였다.
Redis는 DB의 역할을 하고
FastAPI는 RESTAPI 형식으로 GET과 POST 요청 등을 처리하기 위한 미들웨어이다.
게임을 실제로 등록을 하게되면
Redis에선 JSON형식으로 DB에 저장되면서
이런 식으로 DB에 정리가 된다.
저장 형식을 보면
game:test indie 3 로 저장이 되는데
게임 이름으로 저장해서 게임 정보 관리에 더 용이하도록 했다.
그럼 달력에서 게임 정보는 어떻게 불러옴?
이라고 물어본다면 Redis에는 Search 기능이 있어서 Query 검색으로 불러올 수 있게 만들었다.
예를 들어 2022-08-05일에 출시하는 게임을 찾고 싶으면
Redis가 JSON 데이터에서 "date" key를 참조하여 2022-08-05와 일치하는 것을 찾아내 표시하는 방식이다.
또 예를 들어 2022년 8월 게임 정보만 달력에 표시가 되었으면 좋겠다고 가정하면 JSON 데이터에서 "yearmonth" key를 참조하여
이런 식으로 표시가 된다.
이렇게 만들어서 데이터관리와 접근에 훨씬 더 용이해진 것 같다.
애초에 처음부터 이렇게 만드는 게 맞다고 생각한다...
이번 백엔드 작업을 통해서
스케일업이 상당히 편해졌다. 진짜로
자세하게 코드로 보여주고 싶지만...
노출되면 좀 곤란할 것 같아 코드는 생략하겠다...
가독성이 높게 리뉴얼 및 “Push Notification(FCM)”기능 추가
사실 FCM은 이전에 2.0에서 추가했던 내용이라
겜린더 2.0.0 개발 후기를 참고하면 좋을 것 같다.
핵심은 상세페이지를 개선하는 것이 목표인데 이건 아직 구체적인 계획이 없다... UI를 개선해야 할지... 어떤 것을 도입해야 할지 좀 더 고민해 보고 있다.
겜린더 등록 페이지에서 추후 활용
사실 예전 서비스 출시 때부터 겜린더에 자체적으로 등록신청을 해주시는 분들을 위한 이미지 서버가 존재했는데
이걸 제대로 활용하지 못했고 이번에 아예 등록 페이지를 자체적으로 만들어 이미지를 업로드 시 서버에 스토리지에 저장하도록 계획 중에 있다.
React로 제작하고 있고
나름 Figma를 활용해 디자인해봤지만 디자인 하나도 모르는 사람이라 정말 빈약하다.
그래서 요즘 비핸스와 핀터레스트를 미친 듯이 보고있다...(뭐라도 봐야할 것 같아서..)
Q. Redis에선 symbol로 인식한다 어떻게 해결해야 할까..?
A. 파이썬(FastAPI)에서 replace()를 이용해 “-” → “\-” 식으로 백슬래시를 넣으면 string으로 인식한다.
참고내용 Redis query_syntax
TEXT, TAG가 뭔지는
Redis ft.create를 참고해 주세요
TAG로 하면 월/날짜 나눠야 한다
그래서 date와 yearmonth를 만들어 월별 날짜 조회는 yearmonth로 참조하고
yearmonth를 참조해서 나온 결과 값
특정 날짜 조회는 date를 참조하게 만들었다.
TEXT로 index를 만들었는데 연관된 것 까지 검색되고 원하는 결과값이 나오질 않았다.
하지만 TEXT를 잘 이용하여 자동완성 기능도 만들었다
게임 검색 기능에 유용하게 사용될 예정이다.
이거 때문에 반 년 이상을 지체한 것 같은데 너무 간단해서 허무하다...
Docs를 제대로 안 읽어본 잘 못이긴 하다...
(근데 Docs 내용 너무 방대하고 많다..)
Redis search 부분 참고
LIMIT가 뭐냐면
Redis는 FT.SEARCH로 검색 시 표시할 수 있는 데이터의 량을 정할 수가 있다.
Redis CLI에선 LIMIT로 그것을 조절할 수 있다.
하지만 redis-py를 사용할 땐 Query('검색 키워드').paging(0, 10) 이런 형식으로 사용하는데
paging이 LIMIT와 같은 역할을 한다.
저거 해결하려고 참 많이 찾아봤었는데 그냥 Docs 스크롤 하다가 발견해 너무 허무했었다...
일단 지금 로컬 테스트로는 docker를 통해서 사용하고 있지만
추후 서비스할 때는 우분투 서버에 직접 Redis-Stack를 설치할 까 한다..
하드웨어는 역시 언제나 라즈베리파이로 할 예정이다
오래 걸리긴 했지만 백엔드의 기반을 다져놓은 것 같아 뿌듯하다.
드디어 프론트엔드에 집중할 수 있게 되었고, 본격적으로 스케일업을 해도 충분히 대응할 수 있는 구조를 가지게 되어서
앞으로 개발이 많이 수월할 것 같다는 생각과 함께 글을 마치겠다.