BUILT & IMPROVED · 2025.12
조건 판단, 화면 데이터 구성, 라우팅 실행이 한곳에 섞여 있던 초기화 로직을 분리했습니다. 조건을 순수 함수와 배열 기반 전략으로 재구성해 흐름을 짧고 선언적으로 만들었습니다.
모바일 SDK 약관 동의 페이지에는 가입 여부, 국가, 연령 인증 상태에 따라 첫 화면을 결정하는 로직이 있었습니다. 시나리오가 늘면서 초기화 함수는 108줄의 if-else 블록으로 커졌습니다.
각 분기 안에는 조건 판단뿐 아니라 화면 데이터 구성과 서비스 호출, 라우터 실행까지 함께 들어 있어 작은 변경도 전체 흐름을 다시 확인해야 했습니다.
라우팅 조건과 목적지를 배열 기반 Strategy로 정의하고, 현재 상태를 전달하면 목적지만 반환하는 순수 함수를 만들었습니다. 목적지별 화면 데이터도 별도의 설정 객체로 분리했습니다.
export const RoutingDestination = {
INFO_CONFIRM_SIGNUP: 'INFO_CONFIRM_SIGNUP',
INFO_CONFIRM_SIGNIN: 'INFO_CONFIRM_SIGNIN',
TERMS_LIST: 'TERMS_LIST'
} as const;
// 우선순위 순서대로 평가되는 전략 배열
const ROUTING_STRATEGIES: Array<RoutingStrategy> = [
{
// 신규 가입 동선
condition: ({termsQuery, isStoveJoin}) =>
!isStoveJoin && checkJoinTerms(termsQuery) && checkInfoEnable(termsQuery),
destination: RoutingDestination.INFO_CONFIRM_SIGNUP
},
{
// 기존 회원의 잔여 약관 동선
condition: ({termsQuery, isVerifiedAge}) => {
const {nation, disagreeTerms} = termsQuery;
return (
!checkJoinTerms(termsQuery) &&
(nation || '').toLowerCase() !== 'kr' &&
!isVerifiedAge &&
(disagreeTerms || []).length === 0
);
},
destination: RoutingDestination.INFO_CONFIRM_SIGNIN
},
{
// default fallback
condition: () => true,
destination: RoutingDestination.TERMS_LIST
}
];
// 상태를 받아 목적지만 반환 — 컴포넌트 없이 테스트 가능
export function determineInitialRoute(context: RoutingContext): RoutingDecision {
const strategy = ROUTING_STRATEGIES.find((s) => s.condition(context));
if (!strategy) {
throw new Error('No routing strategy matched.');
}
return {destination: strategy.destination};
}컴포넌트 메서드를 참조해야 하는 콜백과 실제 서비스·라우터 호출만 컴포넌트에 남겼습니다. 초기화 함수는 컨텍스트 생성, 목적지 결정, 데이터 생성, 콜백 주입, 실행의 다섯 단계만 조율합니다.
protected init(): void {
// 1. 라우팅 컨텍스트 구성
const context: RoutingContext = {
termsQuery: this.termsQuery,
isStoveJoin: this.isStoveJoin,
isVerifiedAge: this.isVerifiedAge,
isDefaultNation: this.isDefaultNation,
// ...
};
// 2. 순수 함수로 목적지 결정
const decision = determineInitialRoute(context);
// 3. 목적지에 맞는 화면 데이터 생성
const baseData = ROUTING_DATA_CONFIGS[decision.destination](context);
// 4. 컴포넌트가 관리하는 콜백 주입
const callback = this.ROUTING_CALLBACKS[decision.destination];
const completeData = callback ? {...baseData, onSubmit: callback} : baseData;
// 5. 서비스 설정과 라우팅 실행
this.setServiceData(decision.destination, completeData);
this.navigateToRoute(decision.destination);
}복잡한 분기에서 먼저 분리해야 할 것은 코드의 길이가 아니라 ‘판단’과 ‘실행’의 경계였습니다. 이 경계를 나누자 테스트와 시나리오 확장이 함께 단순해졌습니다.