[Hot-Dealicious #3] Hot-Dealicious 중간 피드백

Hot-Dealicious Project의 중간 피드백과 개선점을 고민합니다.

🌱 Hot-Dealicious의 구조적 문제

Hot-Dealicious의 프로젝트는 기능적으로는 동작하지만, 전체적으로는 잘못된 기획과 구조를 가지고 있었다는 결론에 도달하였습니다. 서비스 기획과 구현을 소홀히 한 대가였습니다.

….

지금은 라이더가 언제 서버와 WebSocket 커넥션을 맺어 실시간 통신을 하는지, Scale out된 WebSocket 서버에서 어떻게 소비자 클라이언트가 자신과 매칭된 라이더의 위치를 지속적으로 받을 수 있는지에 대한 고민이 미흡한 상태에서 코드를 구현했기 때문에, 어떤 Flow로 전체 프로세스가 진행되는지 파악할 수 없을 지경에 이르렀습니다.

첫 백엔드 프로젝트로써 서버 구축과 WebSocket 통신, Scale out을 고려한 서버 확장 등 많은 것들을 신경쓰면서 작업했기 때문에 많은 스터디를 할 수 있었지만, 복잡한 기능일 수록 탄탄한 기획과 아키텍쳐가 단단하게 받쳐줘야 한다는 것을 다시한번 깨닫게 되었습니다.


🌱 아키텍쳐를 ReBuilding 해봅니다.

  • 기존의 아키텍쳐

web-Socekt-architecture

이 아키텍쳐의 의도는 이러합니다.

  1. 라이더는 Scale out된 서버와 WebSocket을 통해 한번 커넥션을 맺은 서버와 지속적으로 통신해야합니다. 마치 “sticky session”과 같은 방식으로 routing table에 라이더가 한번 통신 맺은 서버의 URL을 저장합니다.

  2. URL을 가지고 있는 라이더는 이미 자신의 위치를 커넥션 맺은 서버에게 제공하고 있는 중이기 때문에 라우팅 테이블에 저장한 서버 URL에 지속적으로 자신의 위치를 업데이트합니다.

  3. 만일 라우팅 테이블에 라이더 자신과 커넥션을 맺은 서버 URL이 없다면 LB를 통해 하나의 서버 URL가 매칭된다면 그 URL을 라우팅 테이블에 저장하고 이후 지속적으로 서버와 통신합니다.

하지만 이 의도는 많은 것들을 간과하고 구성된 아키텍쳐를 만들게 되었습니다.

  1. WebSocket으로 한번 커넥션을 맺은 서버와 라이더는 이후 별도의 처리가 필요없이 지속적으로 커넥션을 맺고 있습니다. WebSocket 자체가 서버와 실시간 통신을 위해 한번 맺은 커넥션을 끊지 않고 유지시키기 때문에 한번 LB를 통해 맺어진 라이더-서버 간의 커넥션은 누구 하나의 종료가 없다면 계속 이어집니다.

  2. WebSocket의 라우팅 테이블이 필요한 기능은 바로 소비자 클라이언트와 라이더 간의 매칭입니다. 라이더는 서버와 WebSocket 커넥션을 맺고 지속적으로 통신하지만, 소비자 클라이언트는 배달을 한번 매칭된 이후 라이더의 위치를 조회해야하기 때문입니다.


🥲️ 위의 기술적 동작 방식을 다시 고려하여 새롭게 아키텍쳐를 구성하고 실시간 위치 조회 기능 Flow를 재정의하보았습니다.

hot-dealicious-real-architecture

  1. 라이더는 출근 시 서버와 WebSocket 커넥션을 맺고 지속적으로 위치 정보를 갱신합니다.
  2. 매장에서 라이더를 호출 시 매장 주변으로 라이더가 존재하는지 탐색합니다.
  3. 2번 성공 / 실패
    • 매칭 성공 시 라우팅 테이블에 주문에 대한 소비자 아이디를 Key값으로 저장, Key에 대한 Value로 매칭된 라이더 아이디를 저장합니다.
    • 매칭 실패 시 매장에게 안내합니다.
  4. 매칭 성공하게 되면 매장, 소비자에게 각각 안내합니다.
  5. 소비자는 라이더를 조회하는 특정 페이지에서 Polling 방식으로 매칭된 라이더 아이디를 조회합니다. 조회한 후 라이더의 위치 정보를 조회하여 소비자 클라이언트에게 반환합니다.

위치 정보를 제공하는 기능 Flow가 보다 명확해졌습니다. 이와 함께 Scale out을 고려한 아키택쳐도 재정의해보려합니다.

Screenshot-2023-09-25-at-2-38-05-PM

다소 Redis를 맹신(?)하는 것처럼 보일 수 있을 것 같습니다. Redis는 In-Memory 기반으로 사용할 수 있는 캐시 스토리지이기 때문에 일반적으로 File I/O를 하는 DB보다 빠르게 저장하고 데이터를 조회할 수 있습니다.

❗️ 다만, Redis는 메인 메모리에 값을 저장하기 때문에 영구적인 데이터 저장이 어려워 중요한 데이터를 보관하는데 적합하지 않습니다. 그렇기에 라이더의 위치를 조회하는 것은 배달에 아무런 영향을 끼치지 않으므로 Redis를 사용하기에 적합하다고 판단했습니다.


🌱 중간 피드백 정리

전 직장에서도 고민이 많았던 기획에 대해 다시 생각해보는 프로젝트였습니다.

탄탄하게 설계된 기획과 기능 Flow는 명확하게 의사를 전달할 수 있다는 것입니다. 이는 구두 전달이나 팀 미팅 뿐만 아니라 코드 레벨에서도 적용될 수 있다는 점입니다.

팀 미션이었다면 마음이 많이 어려웠을 것 같습니다. 그만큼 팀들과 생산성 있는 작업을 함께하기 위해서 명확하게 전달할 수 있는 도구나 메모가 꼭 필요하다고 느꼈습니다. 이번 프로젝트는 일단 여기에서 Break을 걸려고 합니다. 아무래도 전체적인 부분을 수정하기 위해서는 새로운 Repository를 만들어 구현하는 것이 더욱 빠를 것 같다고 예상됩니다.

다만, 그동안 2개정도의 프로젝트를 진행해보면서 익힌 TDD, JPA 등의 효율적인 개발 방법론과 기술들을 도입해서 리뉴얼할 예정입니다.

완벽한 프로젝트가 아니라 성장하는 프로젝트를 위해 더욱 고민하며 힘써야겠습니다. 💪🏻


© 2021. All rights reserved.