본문으로 건너뛰기

23.08.12

오늘 한 일

  • 프로그라피 팀 모임
  • 카공실록 개발

카공실록

오늘 프로그라피 팀 모임에서 api 연결 테스트를 진행했다.

만나서 작업하니까 확실히 빠르게 진행되는 것 같다.

백엔드에게 변경 요청

기존의 방식: 장소 데이터를 받음 -> 이 데이터의 이미지 id를 이용해 백엔드에 이미지 요청 -> 이미지를 받아서 렌더링

변경 요청: 장소 데이터를 받음 -> 이미지 id 대신 이미지 url로 렌더링

prefetch 시 데이터 겹치는 이슈 해결

저번 TIL에서 prefetch 시 데이터 겹치는 이슈가 있었는데, 이를 해결했다.

문제

처음에는 리액트 쿼리의 문제인가 싶었지만 아니었다. ky의 문제였다.

해결하기 위해 여러가지 테스트를 진행해본 결과, ky의 커스텀 인스턴스에서 header에 content-type: application/json을 넣어주면 데이터가 겹치는 현상이 발생했다.

get 요청에는 헤더에 content-type을 넣지 않아도 된다. 하지만 넣어도 별 문제가 되지 않는다.

테스트 1 - ky

RSC(server side)에서 ky로 get 요청 시 헤더에 content-type을 넣었을 때 데이터 겹치는 현상이 발생

const { data } = await ky
.get(process.env.NEXT_PUBLIC_API_URL + 'api/v1/tags/all', {
headers: {
'Content-Type': 'application/json',
},
})
.json<APIResponse<{ tags: PlaceCondition[] }>>();

테스트 2 - axios

RSC(server side)에서 axios로 get 요청 시 헤더에 content-type을 넣었을 때 데이터 겹치는 현상이 발생하지 않음

const { data } = await axios.get<APIResponse{ tags: PlaceCondition[] }>(
process.env.NEXT_PUBLIC_API_URL + 'api/v1/tags/all',
{
headers: {
'Content-Type': 'application/json',
},
}
);

테스트 3 - fetch API

fetch API 역시 헤더에 content-type을 넣었을 때 데이터 겹치는 현상이 발생하지 않음

const { data } = await fetch(process.env.NEXT_PUBLIC_API_URL + 'api/v1/tags/all', {
headers: {
'Content-Type': 'application/json',
},
}).then(res => res.json());

해결

ky의 커스텀 인스턴스에서 헤더에 content-type을 제거하여 해결했다.

결론

ky 라이브러리의 이슈라고 판단했다. 내일 이슈 적어서 올려야겠다..

카카오 맵

문제 - api 연결

서버에게 보내야하는 데이터는 다음과 같다.

  • latitude: 위도
  • longitude: 경도
  • latitudeBound: 위도 범위
  • longitudeBound: 경도 범위

하지만 카카오 맵에서는 getBounds를 하면 남서쪽, 북동쪽 좌표를 반환한다.

그래서 서버에게 보내야하는 데이터를 계산해야했다.

해결

const map = mapRef?.current as kakao.maps.Map;
const center = map.getCenter();

const latitude = center.getLat();
const longitude = center.getLng();
const latitudeBound = map.getBounds().getNorthEast().getLat() - latitude;
const longitudeBound = map.getBounds().getNorthEast().getLng() - longitude;

리팩토링

이전에는 KakaoMap이라는 컴포넌트를 만들어두었는데, 어차피 react-kakao-maps-sdk를 사용하는 컴포넌트기에 따로 공통으로 분리할 필요가 없어보였다.

그래서 KakaoMap 컴포넌트를 사용하지 않고 Map 컴포넌트를 사용하도록 변경했다.

MapSection 코드
export default function MapSection() {
const { coordinates } = useCenterCoordinateStore();
const { refetch } = useGetPlacesAround(coordinates);
const mapRef = useRef<kakao.maps.Map>(null);

useEffect(() => {
refetch();
}, [coordinates]);

return (
<section>
<Map
className="h-screen w-full min-w-[360px]"
ref={mapRef}
center={{
lat: DEFAULT_COORDINATES.latitude,
lng: DEFAULT_COORDINATES.longitude,
}}
isPanto={true}
level={6}
>
<SearchCTAButton mapRef={mapRef} />
<Suspense.CSROnly>
<Markers />
</Suspense.CSROnly>
<LocationCTAButton mapRef={mapRef} />
</Map>
</section>
);
}

Sheet 상태를 context로 관리

Sheet 상태에 따라 달라지는 곳이 많아서 context로 관리하기로 했다. 이 때 zustand를 사용했다.

SheetProvider 코드
'use client';
import { createContext, useContext } from 'react';
import { createStore, useStore } from 'zustand';

interface SheetStore {
isBottomSheetUp: boolean;
setIsBottomSheetUp: (isBottomSheetUp: boolean) => void;
}

const sheetStore = createStore<SheetStore>(set => ({
isBottomSheetUp: false,
setIsBottomSheetUp: isBottomSheetUp => set({ isBottomSheetUp }),
}));

const sheetContext = createContext<typeof sheetStore | null>(null);

export const SheetProvider = ({ children }: { children: React.ReactNode }) => {
return <sheetContext.Provider value={sheetStore}>{children}</sheetContext.Provider>;
};

export function useSheetContext<T>(selector: (state: SheetStore) => T): T {
const store = useContext(sheetContext);
if (!store) {
throw new Error('Cannot find SheetProvider');
}

return useStore(store, selector);
}

사용 결과

// app/(home)/page.tsx
export default function HomePage() {
return (
<QueryAsyncBoundary
rejectedFallback={<div>에러가 발생했습니다.</div>}
pendingFallback={<Loading />}
>
<SheetProvider>
<HydrationProvider queryFn={() => getPlaceConditions()} queryKey={Keys.placeConditions()}>
<Header />
</HydrationProvider>
<MapSection />
<HomeBottomSheet />
</SheetProvider>
</QueryAsyncBoundary>
);
}

내일 할 일

  • gloddy 디자인 시스템 컴포넌트 구현
  • 카공실록
    • 카카오 맵 마커 클릭 시 중앙으로 이동
    • 마커 아이콘 변경
    • Modal 구현