2025년 7월 24일 목요일

IP를 제대로 읽지 못할때

String ip = request.getHeader("X-Forwarded-For"); if (ip == null || ip.isEmpty()) { ip = request.getRemoteAddr(); }

2025년 7월 20일 일요일

하이드레이션 체크 코드

데이터 조회 코드

import { useHydrationTest } from './useHydrationTest'

const SectionGridFilterHeritageList = ({}) => {
  const {
    data: listData,
    // error,
    isLoading,
    isFetching,
    fetchStatus,
    isPlaceholderData,
  } = useQuery(listQueryParam)

  // 데이터 소스 확인 (내부에서 로그 출력)
  useHydrationTest(
    isLoading, // 로딩 상태
    isFetching, // fetch 상태
    fetchStatus, // fetch 상태
    !!listData, // 데이터 존재 여부
    isPlaceholderData, // placeholder 데이터 여부
    listQueryParam.queryKey, // 쿼리 키
  )

  return (
  )
}

export default SectionGridFilterHeritageList

훅 코드

import { useEffect, useRef } from 'react'

/**
 * 어디서 fatch한(서버/클라이언트) 데이터인지 체크
 * @param isLoading - React Query의 isLoading
 * @param isFetching - React Query의 isFetching
 * @param fetchStatus - React Query의 fetchStatus
 * @param hasData - 데이터 존재 여부
 * @param enableLogging - 로그 출력 여부 (기본값: true)
 */
export const useHydrationTest = (
  isLoading: boolean,
  isFetching: boolean,
  fetchStatus: string,
  hasData: boolean,
  isPlaceholderData?: boolean,
  queryKey?: any[],
  enableLogging: boolean = true,
) => {
  // 이전 상태를 추적하기 위한 ref
  const prevHasData = useRef(hasData)
  const prevQueryKey = useRef('')
  const isFirstLoad = useRef(true)

  useEffect(() => {
    const currentQueryKey = queryKey ? JSON.stringify(queryKey) : ''

    // 🎯 핵심: 데이터가 즉시 보이는지 확인 (가장 확실한 하이드레이션 증거)
    if (hasData && !isLoading && isFirstLoad.current) {
      console.log(
        '🎉 useHydrationTest => 성공! => 데이터가 즉시 표시됨\n',
        '   📊 서버에서 prefetch한 데이터가 클라이언트에서 복원됨\n',
        '   📊 로딩 지연 없이 즉시 렌더링됨',
      )
      isFirstLoad.current = false
      return
    }

    // 로딩 상태 확인
    if (isLoading && fetchStatus === 'fetching' && isFirstLoad.current) {
      console.log('🔄 useHydrationTest => 첫 로딩 중... (서버 prefetch 또는 클라이언트 fetch)')
      isFirstLoad.current = false
    } else if (isLoading && fetchStatus === 'fetching' && !isFirstLoad.current) {
      console.log('📡 useHydrationTest => 클라이언트에서 추가 fetch 중...')
    } else if (hasData && !isLoading) {
      if (isPlaceholderData) {
        console.log('✅ useHydrationTest => Placeholder 데이터 사용 (이전 캐시된 데이터)')
      } else {
        console.log('✅ useHydrationTest => 정상 데이터 사용')
      }
    } else if (isFetching && !isLoading) {
      console.log('⏳ useHydrationTest => 백그라운드 업데이트 중...')
    } else {
      console.log('❌ useHydrationTest => 데이터 없음')
    }

    // 이전 상태 업데이트
    prevHasData.current = hasData
    prevQueryKey.current = currentQueryKey
  }, [isLoading, isFetching, hasData, enableLogging])
}