배경
외부 레이팅 시스템 연동을 계정 연결부터 경기 결과 제출까지 만들었습니다. 약 2개월 반이 걸린 작업이었고, 두 달 뒤 신규 서비스에 같은 기능이 필요해졌을 때 5일 만에 붙었습니다.
처음에 어디에 둘지
빠르게 붙은 이유는 이식할 때 잘해서가 아니라 처음 만들 때 어디에 둘지를 정해뒀기 때문입니다.
자연스러운 배치는 이벤트 페이지 폴더 안이었지만, 그러면 나중에 꺼내는 리팩토링부터 해야 하고 그게 이식 비용의 대부분이 됩니다. 처음부터 공용 위치에 두고 화면과 로직을 분리했습니다.
흐름은 안에, 트리거는 밖에
여섯 개의 다이얼로그를 오가는 흐름(계정 종류에 따라 단일 경로로는 최대 네 단계)은 한 컴포넌트에 캡슐화하되, 트리거 버튼의 모양과 위치는 쓰는 쪽이 정하도록 Render Props로 열었습니다. 흐름은 어디서 쓰든 같지만 트리거는 화면마다 다르기 때문입니다.
type ConnectProps = {
connectButton: ({ onClick, onOpenClubSelect }) => ReactNode; // 밖에서 정함
onComplete?: (type: 'standard' | 'premium' | 'club') => void;
onClose?: () => void;
shouldCheckPremium?: boolean;
};
밖에서 받는 건 트리거 UI와 완료 콜백뿐이고, 단계 전이와 계정 종류 분기는 전부 안에 있습니다. 다이얼로그는 모두 동적 import라 연동을 쓰지 않는 화면에서는 0KB입니다.
도메인이 늘 때 손댈 곳 좁히기
- API 훅은 중앙에 두고 도메인별 함수만 추가합니다.
- 쿼리 정의는 팩토리로 공유해 키만 바꿉니다.
- 도메인 분기는
never로 강제해, 새 도메인을 추가하고 어느 분기를 빠뜨리면 빌드가 깨집니다. - 폼은 필요한 최소 타입만 요구하도록 제네릭으로 열었습니다.
- 번역 키도 특정 도메인이 아닌 공통 네임스페이스에 뒀습니다.