프론트엔드/RN

RN(React-Native) 스크롤 스냅 구현 예시코드 (릴스&숏츠 UI)구현

순코딩 2025. 9. 13. 15:49

성능최적화 X

const QuizPlayer = () => {
  const { open, setOpen, selectedQuizIndex } = useQuizPlayerStore()
  const { quizList } = useQuizStore()

  // 화면 높이 계산
  const { height: SCREEN_HEIGHT } = Dimensions.get('window')
  // 스테이터스바 높이 계산
  const STATUSBAR_HEIGHT = StatusBar.currentHeight || 0
  // 바텀 네비게이션 바 높이 계산
  const insets = useSafeAreaInsets()
  // 컨텐츠 높이 계산(상단 스테이터스바, 하단 바텀 네비게이션 바 제외)
  const CONTENT_HEIGHT = SCREEN_HEIGHT - STATUSBAR_HEIGHT - insets.bottom

  return (
    <Modal visible={open} transparent animationType='fade' onRequestClose={() => setOpen(false)}>
      <ModalContainer>
        <FlatList
          ///// 렌더링 관련
          // 렌더링할 배열
          data={quizList}
          // 렌더링할 아이템 컴포넌트
          renderItem={({ item: quizData, index }) => (
            <QuizContainer height={CONTENT_HEIGHT}>
              <Quiz quiz={quizData} index={index} />
            </QuizContainer>
          )}
          ///// 페이징 관련
          // 페이징 사용 여부
          pagingEnabled={true}
          // 시작할 아이템 인덱스
          initialScrollIndex={selectedQuizIndex}
          // 아이템 크기/위치 정보
          getItemLayout={(_, index) => ({
            length: CONTENT_HEIGHT,
            offset: CONTENT_HEIGHT * index,
            index,
          })}
          ///// 뷰 트래킹 관련
          // 뷰 트래킹 판단 기준 설정
          viewabilityConfig={{
            itemVisiblePercentThreshold: 70,
          }}
          // 보이는 아이템 변경 핸들러
          onViewableItemsChanged={({ viewableItems }) => {
            if (viewableItems.length > 0) {
              console.log('현재 퀴즈:', viewableItems[0].item)
            }
          }}
          // 스크롤바 숨김 여부
          showsVerticalScrollIndicator={false}
        />
      </ModalContainer>
    </Modal>
  )
}

 

성능최적화 O

const QuizPlayer = () => {
  const { open, setOpen, selectedQuizIndex } = useQuizPlayerStore()
  const { quizList } = useQuizStore()

  // 화면 높이 계산
  const { height: SCREEN_HEIGHT } = Dimensions.get('window')
  // 스테이터스바 높이 계산
  const STATUSBAR_HEIGHT = StatusBar.currentHeight || 0
  // 바텀 네비게이션 바 높이 계산
  const insets = useSafeAreaInsets()
  // 컨텐츠 높이 계산(상단 스테이터스바, 하단 바텀 네비게이션 바 제외)
  const CONTENT_HEIGHT = SCREEN_HEIGHT - STATUSBAR_HEIGHT - insets.bottom

  return (
    <Modal visible={open} transparent animationType='fade' onRequestClose={() => setOpen(false)}>
      <ModalContainer>
        <FlatList
          ///// 렌더링 관련
          // 렌더링할 배열
          data={quizList}
          // 렌더링할 아이템 컴포넌트
          renderItem={({ item: quizData, index }) => (
            <QuizContainer height={CONTENT_HEIGHT}>
              <Quiz quiz={quizData} index={index} />
            </QuizContainer>
          )}
          ///// 페이징 관련
          // 페이징 사용 여부
          pagingEnabled={true}
          // 시작할 아이템 인덱스
          initialScrollIndex={selectedQuizIndex}
          // 아이템 크기/위치 정보
          getItemLayout={(_, index) => ({
            length: CONTENT_HEIGHT,
            offset: CONTENT_HEIGHT * index,
            index,
          })}
          ///// 뷰 트래킹 관련
          // 뷰 트래킹 판단 기준 설정
          viewabilityConfig={{
            itemVisiblePercentThreshold: 70,
          }}
          // 보이는 아이템 변경 핸들러
          onViewableItemsChanged={({ viewableItems }) => {
            if (viewableItems.length > 0) {
              console.log('현재 퀴즈:', viewableItems[0].item)
            }
          }}
          // 스크롤바 숨김 여부
          showsVerticalScrollIndicator={false}
        />
      </ModalContainer>
    </Modal>
  )
}