Static Badge

관련문서

getServerSideProps with HOC

프로젝트 특성상 각 페이지별 seo 최적화 및 페이지 랜더링 전 서버로 부터 필요한 data fetch 가 필요함
getServerSideProps로 각 페이지별 필요 데이터를 page props 전달 코드 존재


const Page = (props) => {
  return (
    <CommonSeo {...props}>
      <Page {...props} />
    </CommonSeo>
   )
}

export const getServerSideProps = async (context) => {
  /** 필요한 data fetch 하는 곳 */
  /** 중복된 코드도 엄청 많음 */
  return { props }
}

이런식으로 getServerSideProps 가 사용되는 페이지가 다수 존재
중복되는 코드를 수행하는 부분도 다수 존재했음

문제 발생

각 페이지에 페이지 활성화를 체크하는 로직이 생김
서버 요구사항은 /site api 호출후 return 되는 status 값에 따라
HTTP 상태 코드를 416 (Requested Range Not Satisfiable) 변경해주고
불필요한 랜더링 하지 말기 원했음

AWS 에서 변경된 416 코드를 받고 안내 페이지로 리다이렉트 시키는 작업

문제는 getServerSideProps 페이지가 다수 존재했고 일일히 다 복붙 넣어야하는 상황 발생

HOC 패턴으로 공통로직 추가 + 확장성

getInitialProps 를 통해서 app.jsx 한번만 선언하고 말까 하다가 여러 글을 읽고 getServerSideProps 를 공통 HOC 로 만들어 보기로 결정

  • getInitialPropsgetServerSideProps 차이

    항목 getInitialProps getServerSideProps
    사용 위치 Pages, _app.tsx, _document.tsx Pages only
    실행 시점 서버 or 클라이언트 모두 서버에서만 실행
    Static Optimization 영향 ❌ 비활성화됨 ✅ 필요 시 SSR만 동작
    데이터 노출 가능성 클라이언트에서도 실행되므로 API 경로 노출 위험 서버에서만 실행되어 안전함
    권장 여부 ❌ (구버전, 비추천) ✅ (Next.js 권장 방식)

withServerSideProps

getServerSideProps를 인자로 받아 각 페이지별 로직 + 공통 로직 실행하는 컴포넌트

/** server side props 공통 */
const withServerSideProps = (getServerSideProps) => {
  return async (context) => {
    let props ={}

    /** page 별 추가 server side props */
    const pageProps =
      typeof getServerSideProps === 'function'
        ? await getServerSideProps(context)
        : {}

    /** 사이트 활성화 체크 + sites props */
    const site = await fetch(context, `/sites`)
    if (site?.publishStatus === 'inactive') {
      context.res.statusCode = 416
      context.res.end() // 응답 종료
      return { props: {} }
    }

    /** 그 밖에 중복으로 계속 작성되었던 로직들 */
    ...

    return { props: { ...props, ...pageProps } }
  }
}

page 별 적용

const Home = (props) => {
  return (
    <CommonSeo {...props}>
      <Page {...props}/>
    </CommonSeo>
  )
}

export const getServerSideProps = withServerSideProps()

export default Home

페이지별 추가 로직이 필요한 경우


export const getServerSideProps = withServerSideProps(async (context: any) => {
  /** 추가 로직 후 props에 포함될 객체 리턴 */
  return { board: context.params }
})

export default Home