TIL_2024_04_10

이종현·2024년 4월 10일
0

Today_I_Learned

목록 보기
145/145
post-thumbnail

Today 요약

  1. 패캠 강의 (최적화)

1. What I Learned?

패캠 강의 (최적화)

api 통신, SSR

route.ts로 api 생성, 이때 app 폴더 하위에 원하는 api 요청 경로를 폴더 구조로 구조화 할 수 있다.

예를 들어 app/api/videos/search 라면, BASE_URL/api/vidoes/search 라는 엔드포인트로 api 요청을 보내는 걸 해당 폴더 안에 route.ts로 정의하면 된다. 대략 아래와 같다.

export const GET = async (request: NextRequest) => {
  try {
    const queryParams = parseQueryParams(request.nextUrl.searchParams)

    const { data } = await youtubeServerInstance.search.list({
      part: ["snippet"],
      type: ["video"],
      regionCode: "KR",
      maxResults: 20,
      ...queryParams
    })

    const mappedData = mappingResponse(data)

    return Response.json(mappedData)
  } catch {
    return new Response(JSON.stringify({ message: "Internal Server Error" }), {
      status: 500
    })
  }
}

const parseQueryParams = (
  params: URLSearchParams
): GetSearchVideosListRequestParams => {
  return {
    q: params.get("q") ?? "",
    order: (params.get("order") ?? "relevance") as SearchOrder,
    pageToken: params.get("pageToken") ?? undefined
  }
}

const mappingResponse = (
  data: youtube_v3.Schema$SearchListResponse
): GetSearchVideosListResponse => {
  const lists =
    data?.items?.map(({ id, snippet }) => {
      const publishedAt = snippet?.publishedAt ?? ""

      return {
        videoId: id?.videoId ?? "",
        title: snippet?.title ?? "",
        description: snippet?.description ?? "",
        channelId: snippet?.channelId ?? "",
        channelTitle: snippet?.channelTitle ?? "",
        thumbnail: {
          url: snippet?.thumbnails?.medium?.url ?? "",
          width: snippet?.thumbnails?.medium?.width ?? undefined,
          height: snippet?.thumbnails?.medium?.height ?? undefined
        },
        publishedAt,
        publishedAtDisplayText: formatKoreanTextCompareDatesFromNow(publishedAt)
      }
    }) ?? []

  return {
    lists,
    prevPageToken: data.prevPageToken ?? undefined,
    nextPageToken: data.nextPageToken ?? undefined,
    totalResults: data.pageInfo?.totalResults ?? 0
  }
}

그리고 해당 api를 사용할 클라이언트 함수를 정의한다.

export const getSearchVideosList = async (
  params: GetSearchVideosListRequestParams
): Promise<GetSearchVideosListResponse> => {
  const queryParams = queryString.stringify(params)

  const url = `${getSearchVideosListURL}?${queryParams}`

  const response = await fetch(url)

  return await response.json()
}

그리고 그걸 사용할 리액트 쿼리 훅을 만들어서 컴포넌트에서 사용한다.

export const useGetSearchVideosList = ({
  q,
  order,
  initPageToken
}: Params): UseSuspenseInfiniteQueryResult<
  InfiniteData<GetSearchVideosListResponse, Error>
> => {
  return useSuspenseInfiniteQuery({
    queryKey: ["search", q, order, getSearchVideosListURL],
    queryFn: ({ pageParam = initPageToken }) => {
      return getSearchVideosList({ q, order, pageToken: pageParam })
    },
    initialPageParam: initPageToken,
    getNextPageParam: (lastPage) => lastPage.nextPageToken
  })
}
profile
데이터리터러시를 중요하게 생각하는 프론트엔드 개발자

0개의 댓글