[ 공모전 ] 지도 페이지 : Generic & HashMap

최문길·2024년 6월 25일
0

공모전

목록 보기
20/46

저번 시간에 API 두개를 병렬 호출 글을 써봤다.

이제 남은건 API 1개인데, 산책로 API 호출만 하면 된다.

GetStaticProps

<산책로/>
서울시 주요 공원현황
http://openAPI.seoul.go.kr:8088/process.env.NEXT_PUBLIC_SEOUL_PARK/json/SearchParkInfoService/1/132/

서울시 주요 공원 현황 API는 데이터가 132개로 제한 되어있어서 GetStaticProps로 데이터를 받기로 결정했다.

export const getStaticProps = (async () => {
  const results = await searchSeoulParkInfo('SearchParkInfoService/1/135/');
  const data: I_SearchParkInfoService = results.data;

  return { props: { seoulParkInfo: data.SearchParkInfoService.row } };
}) satisfies GetStaticProps<{
  seoulParkInfo: I_SeoulParkAPI[];
}>;

const MapPage = ({ seoulParkInfo }: { seoulParkInfo: I_SeoulParkAPI[] }) => { ... }

Build 할 때 정량 데이터(132개)를 받는 것은 좋은 것 같다.

하나의 샘플 데이터를 받아오면

이렇게 객체 데이터가 들어있다.
여기서 고민할 거리가 생기는데, 이전 블로그에서 각 지역구별 데이터 처리를 위한 UI는 tab형식으로 한다고 결정하였다.

따라서 객체배열을 조작하여 중구 , 도봉구 등으로 데이터를 정제해줘야 한다.

여기서, 선택지는 2가지이다.

  • 객체 배열을 객체로 변환시키거나,
  • HashMap으로 정제하거나

무엇을 선택하던, 상관없다는 생각이 막연하게 든다. 그러나, 왜 HashMap이 떠올랐는지를 다시 한번 더 생각 해본 결과

데이터를 관리할 때 HashMap으로 관리 할 수도 있다고 공부했었고, 요번 프로젝트에서는 다양한 것을 사용하고, 경험 하는 것이 나 자신만의 프로젝트의 당위성이기에 익숙한 것보단, 새로운 것을 사용하여 배우고, 학습, 공부하기로 마음을 잡아 , HashMap으로 관리 하기로 하였다.

formattedGroupByKey

각 객체 배열을 HashMap으로 바꾸려면 조건이 위의 사진에서 형광펜칠한 것과 같이
P_ZONE 을 기준으로 HashMap으로 변경 하고자 하여 util 함수를 만들어 봤다.

export function formattedGroupByKey<T extends { [key: string | number]: unknown }>(array: T[], key: keyof T) {
  return array.reduce((acc, cur) => {
    const stringkey = cur[key] as string;// unknown이다.
    if (acc.get(stringkey)) {
      acc.get(stringkey)?.push(cur);
    } else {
      acc.set(stringkey, [cur]);
    }
    return acc;
  }, new Map<keyof T, T[]>());
}

formattedGroupByKeyGeneric에 내가 정의한 타입을 넣어주면,
2번째 인자값에 첫 번째 인자값의 key 이 자동 추론 되도록 코드를 짰다.

typeError

// types/map/seoul-api/api.d.ts
interface I_SeoulParkAPI {
  //... 생략,
   P_ZONE: string; // 지역
}

// src/pages/map/map.tsx
const MapPage = ({ seoulParkInfo }: { seoulParkInfo: I_SeoulParkAPI[] }) => {
  const formattedData = formattedGroupByKey<I_SeoulParkAPI>(seoulParkInfo, 'P_ZONE');
 //...생략

이렇게 해줬는데 Error가 발생 하였다.

요지는
string type에 대한 인덱스 시그니쳐는 I_SeoulParkAPI 에 없다는 문구다.

Why...

뭐지 ?? 내가 정의한 타입도 { [key:string|number] : unknown} 이 조건에 되는 것 아닌가??

interface I_Constraint {
  [key: string]: string | number | boolean
}

type T_TypeAlias = {
  str: string
  num: number
  bool: boolean
}

interface I_SameInterface {
  str: string
  num: number
  bool: boolean
}

type T_IsToBeTrue = T_TypeAlias extends I_Constraint ? true : false // true

type T_ButFalse = I_SameInterface extends I_Constraint ? true : false // false

Stack Overflow

어떻게 구글링을 해야 할지 몰라서 stack overflow에 Question을 했다.

어제(20240624) 질문을 올리고 난 후
오늘 확인해보니 중복된 질문이라는 알람이 있어서 들어가서 확인 해 보았다.

Type Alias에 대해서는 암묵적으로 인덱스 시그니처가 추론되지만, 인터페이스에 대해서는 추론 되지 않는 이슈가 있는데 이것은
RyanCavanaugh(Microsoft의 TypeScript 팀 개발 리드)에 따르면 의도된 것이라고 한다.

의도된 것이라는 것에 주목할 수 있다.

HashMap의 키 값을 다른 이름으로 변경하기

다시 돌아와서,
객체 데이터는 가공되지 않은 상태다.
동물병원&동물약국 그리고 산책로 라는 탭에서 동일하게 사용하려면 데이터, 정확히는 key 값을 바꿔줘야 한다.

SubTabs에 들어가는 각 지역구의 이름들이 들어가 있는 상수(객체 배열데이터)가 아래와 같이 정의 되어있다.

/*
* @explain 
  { 
    location: 탭에 보일 UI
    api_query : 동물병원&동물약국 API에 사용 할 쿼리
  }
*/
export const SEOUL_LOCATION: { location: string; api_query: T_LocationType }[] = [
  {
    location: '중구',
    api_query: 'JG', 
  },
//... 생략

API를 통해서 받아온 서울근교 산책로 데이터를 HashMap 처리한 상태이다.
위의 상수 값들을 이용해서 객체 배열의 데이터를 내가 원하는 식으로 가공해보자.

export function replaceLocationToApiQuery<T extends { [key: string | number]: unknown }>(
  seoulParkInfo: Map<keyof T, T[]>,
) {
  SEOUL_LOCATION.forEach(({ location, api_query }) => {
    const values = seoulParkInfo.get(location);
    seoulParkInfo.delete(location);
    seoulParkInfo.set(api_query, values as T[]);
  });

  return seoulParkInfo;
}

replaceLocationToApiQuery 함수를 통해 가공된 데이터를 보면

key 값이 한글영어 로 처리 되었다.
값들의 차이가 있는 이유는 사용할 수 없는 데이터들이 있기에 제거 해줬었다. 일을 ... 안하네?

마무리

이제 key 값의 가공은 끝났고 카카오 맵에서 각 데이터 UI(=마커로 표기)를 보여주려면 데이터를 가공 해야 하는데 또 다시 고민할 거리에 부딛혔다.

0개의 댓글

관련 채용 정보