728x90
Braze Feature flag 로딩 타임 아웃 처리로 UX 개선하기
문제 상황
Braze 툴로 A/B 테스트를 구현하는데, braze initialize
후 getFeatureFlag()
호출 시점에서 featureFlag
데이터가 준비되지않아 undefined
가 반환되는 이슈가 발생했다. 이로인해 FeatureFlagProvider
내부에서 children이 null로 반환되어 페이지 전체가 렌더링되지 않는 문제가 있었다.
접근/해결 방식
- 재시도 로직 추가: feature flag가 없을 경우 refreshFeatureFlags 메서드로 한번 더 호출
- 타임아웃 설정: 네트워크 지연으로 인한 무한 대기를 방지하기 위해 최대 대기 시간 설정
- 로딩 상태 관리: 사용자에게 로딩 중임을 알리고, 타임아웃 후에는 기존 컨텐츠 표시
// AS-IS
export function FeatureFlagProvider({
children,
id,
}: PropsWithChildren<{ id: FeatureFlagId }>) {
const brazeInitState = useBrazeInitStateContext()
const [featureFlagEntity, setFeatureFlagEntity] =
useState<FeatureFlagEntity | null>()
useEffect(() => {
if (brazeInitState && id) {
const braze = window.braze
const featureFlag = braze.getFeatureFlag(id)
if (!featureFlag) {
setFeatureFlagEntity(null)
return
}
braze.logFeatureFlagImpression(id)
}
}, [brazeInitState, id])
if (featureFlagEntity === undefined) {
return null
}
return (
<FeatureFlagContext.Provider value={featureFlagEntity}>
{children}
</FeatureFlagContext.Provider>
)
}
// TO-BE
const FEATURE_FLAG_TIMEOUT = 3000
export function FeatureFlagProvider({
children,
id,
}: PropsWithChildren<{ id: FeatureFlagId }>) {
const brazeInitState = useBrazeInitStateContext()
const [isLoading, setIsLoading] = useState(true)
const [featureFlagEntity, setFeatureFlagEntity] =
useState<FeatureFlagEntity | null>()
useEffect(() => {
if (brazeInitState && id) {
const timeoutId = setTimeout(() => {
setIsLoading(false)
}, FEATURE_FLAG_TIMEOUT)
const braze = window.braze
const featureFlag = braze.getFeatureFlag(id)
if (!featureFlag) {
setFeatureFlagEntity(null)
window.braze.refreshFeatureFlags(() => {
const newFeatureFlag = window.braze.getFeatureFlag(id)
if (newFeatureFlag) {
handleFeatureFlagInit(newFeatureFlag)
} else {
setIsLoading(false)
}
clearTimeout(timeoutId) // setTimeout이 더 이상 필요없고, 브라우저에게 더 이상 추적하지 말라는 의미를 주기위해 추가
})
return
}
handleFeatureFlagInit(featureFlag)
clearTimeout(timeoutId)
return () => {
clearTimeout(timeoutId)
}
}
}, [brazeInitState, id, isLoading, handleFeatureFlagInit])
if (isLoading) {
return <>{LoadingComponent}</>
}
return (
<FeatureFlagContext.Provider value={featureFlagEntity}>
{children}
</FeatureFlagContext.Provider>
)
}
추가 고려사항
향후에는 이 코드를 다음과 같이 개선해볼 수 있다.
- 에러 바운더리 처리: refreshFeatureFlags 혹은 네트워크 요청 실패등의 에러 발생시 에러 바운더리로 위임한다.
- 재시도 횟수 제한: 지금은 1번만 재시도를 하게되는데 재시도 횟수를 임의로 설정하도록 개선이 가능하겠다
반응형
'Frontend > React' 카테고리의 다른 글
[ 리액트(React) ] Higher Order Component 사용하기 (0) | 2023.04.13 |
---|---|
[ 리액트(React) ] && 대신 삼항연산자 사용하기 (0) | 2022.11.07 |
[ 리액트(React) ] 불필요한 prop drilling 제거하기 (0) | 2022.07.27 |
[ 리액트(React) ] Uncaught SyntaxError: Unexpected token '<’ 오류 해결하기 (0) | 2022.03.15 |
[ 리액트(React) ] useLayoutEffect, useEffect의 차이점 실험으로 쉽게 알아보기 (0) | 2021.08.19 |
댓글