Skip to content

[Issue & TroubleShooting]

SEUNGUN CHAE edited this page Jul 26, 2024 · 19 revisions

구현 과정에서 다루어야 할 이슈, 추후 해결방안까지 담을 공간입니다.

Front-End

스크롤 기반 단일 페이지이며, 대부분의 내용이 정적임을 감안하여 SSG를 도입하고자 합니다. 이를 통해 빌드 시 html을 미리 렌더링하여 유저의 컨텐츠 접근 속도를 극대화하고, 검색 엔진(SEO)를 최적화하여 사용자 유입을 높일 것입니다.

인터랙션 컴포넌트 - 추첨 이벤트 플로우 모달 간 상호작용

저희 서비스는 5개의 인터랙션 컴포넌트가 있고, 인터랙션 컴포넌트를 추첨 이벤트 플로우 모달이 감싸는 형태로 구성되어 있어요. 추첨 이벤트 플로우 모달에서는, 다음의 기능이 인터랙션 컴포넌트의 종류에 상관없이 들어가요.

  • 인터랙션 컴포넌트가 어떠한 방식으로도 “상호작용”된다면, 추첨하기 버튼이 활성화되어요.
  • 리셋 버튼을 클릭하면 인터랙션 컴포넌트의 초기 상태가 리셋되어요.

처음에는 각각의 컴포넌트를 감싸는 각각의 모달이 인터랙션 컴포넌트의 상태를 관리하는 것을 고려했었으나, 인터랙션의 방식이 제각기 다르고, 향후 여러 개의 인터랙션이 더 추가될 수 있으며, 인터랙션 자체를 독립적으로 구성할 수 있어야 한다고 생각했어요.

그래서 각각의 인터랙션 컴포넌트에서 reset이라는, 모든 상태를 리셋할 수 있는 함수를 외부에 노출하면 어떨까? 라고 생각했어요. 이렇게 구성하면, 인터랙션 컴포넌트는 자신이 갖고 있는 상태에만 집중할 수 있고, 인터페이스를 통해 외부와 상호작용을 할 수 있어서 응집도가 향상돼요.

하지만, 리액트에서 컴포넌트의 인터페이스를 노출하는 것은 쉬운 일이 아니었어요. 저희는 다음의 4가지의 방식을 생각해 봤어요.

  1. forwardRef와 useImperativeHandle을 사용하는 방법
  2. trigger 상태를 들고, 트리거가 호출될 때 trigger 상태를 변경시켜서 trigger 변경에 따라 useEffect로 값을 리셋시키는 방법
  3. 상위 컴포넌트에서 setReset 함수를 props로 내려주고, 하위 컴포넌트에서 리셋 함수를 등록시키는 방법
  4. 리액트 버리고 웹 컴포넌트를 쓰는 방법

이 4개 중 어떤 것을 사용해야, 가장 리액트스럽게, 가장 유지보수가 쉽게 문제를 해결할 수 있을까요?

모달 관리

저희 서비스는 모달이 많아요. 모달은 독립적으로 열고, 닫을 수 있는 UI적 관심사를 가지고 있으며, 닫기 버튼을 따로 가지고 있어요. 하지만, 모달 안에는 특정한 내용이 들어가야 하며, 모달 내부 컴포넌트에서 어떠한 행동을 하면서 모달을 닫아야 하는 경우도 있어요. 문제는, 모달에 들어가는 요소마다 스타일이 다르고, 닫기 버튼 옆에 기능 버튼이 표시되는 경우도 있으며, 닫기 버튼이 x자로 표시되고 위치가 이동되는 경우도 있었어요.

우리가 직면해야 하는 과제는 크게 2개에요.

  1. 어디까지를 UI적 요소로 보아서, 모달 자체 컴포넌트가 무엇까지 가지고 있어야 하는가?
  2. 모달을 여는 상태를 어떻게 관리할 것인가?

1번의 경우, 모달의 열고 닫는 동작 자체는 UI적 관심 요소라고 생각했어요. 하지만, '닫기 버튼'의 경우, 모달 내부 요소마다 닫기 버튼의 스타일과 위치가 상이한데, 닫기 버튼까지 모달 안에 들어갈 내부 요소에서 관리해야 하는지, 모달 자체에서 관리해야 하는지가 고민이에요.

2번의 경우, 모달을 여는 위치가 여러 개라서, 각 컴포넌트 밑에 모달 컴포넌트를 두는 것은 과도하게 컴포넌트가 많아질 수 있을 것이라고 생각했어요. 가장 이상적인 것은 모달을 여는 함수를 호출하면 모달이 열리는 것인데, 현업에서는 모달 상태를 어떻게 관리하는지가 궁금해요.

Back-End

선착순 이벤트의 객관적이고 설득력 있는 테스트

순간적으로 요청이 몰리는 선착순 이벤트의 여러 가지 구현 방안을 조사하고 실제로 가볍게 구현하고 있습니다. 크게 다음과 같습니다.

  1. Redis의 분산 락을 활용한 상호 배제 요청 처리
  2. RabbitMQ 큐잉을 활용한 대기열 기반 요청 처리
  3. Redis의 SortedSet을 활용한 대기열 기반 요청 처리

여러 가지 구현 방안 중 어떤 방안이 최적인지 개략적으로 평가한 후 기능 구현을 시작하고자 하며, 최근엔 SortedSet 방식을 로컬에서 초당 n번의 요청을 가하는 부하 테스트로 성능을 파악하고 있습니다.

이렇게 다양한 구현 전략의 성능을 객관적으로 평가하기 위한 "설득력 있는 테스트"를 위해서는 백엔드 개발진으로서 메모리, 네트워크 외 어떤 요소를 추가적으로 신경써야 할지 여쭙고 싶습니다.

추첨 이벤트의 구현

image

추첨 시스템이 유저의 행동을 기반으로 계산되는 가중치를 고려해야 하기 때문에, 기본적으로 유저의 총 응모점수를 산출한 뒤 누적 합 알고리즘을 활용하여 유저를 추첨할 계획입니다. 더 효율적인 알고리즘 역시 조사 중입니다.

추첨 이벤트의 확장성

현재 저희에 요구사항에 따르면 유저가 추첨 이벤트에 참여할 때 단순 응모권 외에도 "기대평 작성" 시 응모 가산점을 추가로 부여하고 있습니다.

그러나 "링크 공유" 등 다른 액션으로 응모 가산점을 받을 수 있는 이벤트도 충분히 존재할 수 있습니다.

저희 팀은 애플리케이션 전반적으로 "재사용 가능한 시스템"을 구축하는 것을 목표로 하여, 유저의 다양한 액션을 고려하여 확장성 있는 시스템을 설계하고자 합니다.

다만 현재로서는 이러한 부분을 DB에서 처리해야 할 지, 애플리케이션에서 처리해야 할 지 혼란이 있습니다.

이렇게 응모 가산점 정책과 같은 변동 가능성이 있는 부분은 애플리케이션에서 처리하는 것이 바람직한지, 테이블 자체를 더 확장성 있게 설계하는 것에 집중하는 게 바람직한지 조언을 구하고 싶습니다.