1. 한 일 - 카카오맵 코드 리팩토링
1.1 ReactKakaoMapSDK 사용
카카오맵 api 공식문서의 바닐라 자바스크립트 문법을 단순히 리액트로만 바꾸기 보다, 처음부터 리액트에 맞게 만들어진 라이브러리를 사용하는 것이 좋겠다 판단하여 기존 코드를 전부 걷어내고 해당 라이브러리를 사용하여 useEffect 훅 안에서 검색 결과에 해당하는 마커를 지도에 표시해주며 검색 결과의 디테일한 정보가 나타나는 리스트를 map으로 화면에 렌더링하도록 하였다.
1.2 바닐라 자바스크립트 코드 제거
기존 방식에서 document.createElement, addEventListener, appendChild 등 바닐라 자바스크립트 방식으로 DOM 조작을 굉장히 많이 사용하고 있었고 검색 결과로 리턴하는 태그들을 템플릿 리터럴로 생성하고 있어 스타일링이나 함수를 붙이는 데에 많은 애를 먹고 있었다. 오늘 해당 코드들을 전부 걷어내고 리액트에 적합한 방식으로 최대한 개선했다.
비동기 처리나 redux 사용 등 더 개선할 수 있는 방안이 있을걸로 생각되나 현재 수준과 남은 프로젝트 기간 상 나머지 미비된 기능 구현으로 넘어가야 할 것 같다.
기존 코드
// 기존에 검색결과를 화면에 렌더링한 방식
// 검색결과 항목을 Element로 반환하는 함수
function getListItem(index, places) {
const el = document.createElement('li');
let itemStr = `
<div class="info">
<a href="${places.place_url}" target="_blanck">
<span class="marker marker_${index + 1}">
${index + 1}
</span>
<h5 class="info-item place-name">${places.place_name}</h5>
${
places.road_address_name
? `<span class="info-item road-address-name">
${places.road_address_name}
</span>
<span class="info-item address-name">
${places.address_name}
</span>`
: `<span class="info-item address-name">
${places.address_name}
</span>`
}
<span class="info-item tel">
${places.phone}
</span>
</a>
</div>
`;
el.innerHTML = itemStr;
el.className = 'item';
return el;
}
개선한 코드
- 검색한 키워드 props 상속: AlertContents.jsx → KakaoMap.jsx → SearchResults.jsx
- 검색어 입력을 AlertContents 컴포넌트의 input의 onChange 시 감지
- onSubmit 시 검색어에 앱의 목적에 부합하는 추가 키워드를 붙인 값으로 검색 키워드를 setState.
- AlertContents 컴포넌트에서 자식인 KakaoMap 컴포넌트로 검색 키워드를 props로 내려줌.
- 상속받은 검색 키워드를 의존성 배열의 요소로 갖는 KakaoMap 컴포넌트의 useEffect 훅에서 지도를 생성하며 상속받은 검색 키워드에 따라 지도에 마커를 표시하고 자식 컴포넌트인 SearchResult에게 검색결과를 담는 state를 빈배열로 생성해두었다가 검색 결과로 setState하며 해당 state를 props로 내려줌.
- SearchResults 컴포넌트에서 검색결과의 리스트를 담는 state를 빈배열로 생성해두었다가 부모인 KakaoMap 컴포넌트에게 상속받은 검색결과의 값으로 해당 값을 setState하는 useEffect 훅 사용. 이때 의존성 배열의 요소는 부모에게 받은 props로 주었음.
- map 메서드로 렌더링
// kakaoMap.jsx
useEffect(() => {
if (!map) return;
let markers = [];
ps.keywordSearch(keyword, async (data, status, _pagination) => {
if (status === kakao.maps.services.Status.OK) {
// 검색된 장소 위치를 기준으로 지도 범위를 재설정하기위해
// LatLngBounds 객체에 좌표를 추가합니다
for (var i = 0; i < data.length; i++) {
// @ts-ignore
markers.push({
position: {
lat: data[i].y,
lng: data[i].x,
},
content: data[i].place_name,
});
// @ts-ignore
bounds.extend(new kakao.maps.LatLng(data[i].y, data[i].x));
}
setMarkers(markers);
// 검색된 장소 위치를 기준으로 지도 범위를 재설정합니다
map.setBounds(bounds);
}
setPlaces([...data]);
console.log(places);
});
}, [keyword]);
import React, { useState, useEffect } from 'react';
import * as S from './SearchResultStyle';
function SearchResults({ places }) {
const [placeList, setPlaceList] = useState([]);
useEffect(() => {
setPlaceList(places);
}, [places]);
return (
<div>
<S.ResultsLayouyUl>
{placeList.map((place) => (
<li key={Math.random()}>{place.place_name}</li>
))}
</S.ResultsLayoutUl>
</div>
);
}
export default SearchResults;
리뷰
이미지와 텍스트가 함께 있는 multiparts/form-data 형태의 데이터를 post하고 get 하는 걸 이번에 모두가 처음 해보면서 여러 시행착오가 있었는데 새벽 1시 반에 결국 테스트에 성공했다.
나는 지도 api 사용하는 파트 구현에 집중하고 있어서 다른 팀원분들께 기존에 토이프로젝트에서 내가 구현했던 방식만 간단하게 설명드리고 많은 신경을 쓰지 못하고 있었는데, 결국 이미지 업로드를 빼야 할지 고민이 될 정도로 안풀리다가 끝까지 붙들어서 해결해내는 열정넘치는 팀원분들의 모습에, 많이 지쳐있었던 요즘 다시 동기부여가 되었고 감사했다.
나도 오늘은 지도 기능 때문에 하루종일 골머릴 싸맸고 가장 문제였던 부분중 일부는 해결이 되어서 나름의 보람을 느꼈다. 팀 프로젝트 기간에 들어가며 정말 예전처럼 될때까지 씨름하기보다 일정한 기한 안에 해결하지 못하면 기능을 축소하거나, 빼거나, 그다지 좋지 않은 방식의 나쁜 코드로 때우고 넘기는 일이 많았는데 오랜만에 나도 다른 팀원분들도 풀리지 않는 문제를 될 때까지 붙잡고 제대로 해결 할 수 있었던 하루였다.
'기록 > 코드스테이츠 프론트엔드' 카테고리의 다른 글
10.4 화 - 메인프로젝트 데일리 회고 (3) | 2022.10.05 |
---|---|
10.3 월 - 메인프로젝트 데일리 회고(멘토 미팅) (1) | 2022.10.03 |
9.27 화 - 메인프로젝트 데일리 회고 (0) | 2022.09.29 |
9.25 월 - 메인프로젝트 데일리 회고(멘토 미팅) (2) | 2022.09.27 |
9.24 토 - 메인프로젝트 데일리 회고 (1) | 2022.09.25 |