[아웃소싱 프로젝트] 이번에도 해냈네?

안현희·2024년 12월 3일
0

React를 배워보자!

목록 보기
28/30

우선 먼저 좀 볼까?

  • 진짜 군수골고개에 살고 있는거 아닙니다...
    생전 처음 들어보는곳입니다...

업데이트 목록

1. UI 구성
2. 코드분리
3. 키워드검색 ➡️ 카테고리 검색


1. UI

퍼블리싱이 끝났고 해당 스타일을 가지고 리팩토링을 진행했다.
gif에 나와있듯이 이전과는 다르게 깔끔하고 보기 좋은 디자인이다.

 <SerchListWrap>
        {/* 검색 및 필터 UI */}
        <SerchTabWrap>
          <SelectWrap>
            <RegionSelector
              selectedRegion={selectedRegion}
              selectedCity={selectedCity}
              setSelectedRegion={setSelectedRegion}
              setSelectedCity={setSelectedCity}
              onRegionChange={handleRegionChange}
            />
          </SelectWrap>
          <SearchTabUl>
            <SearchTabLi
              isActive={selectedCategory === 'CE7' ? 'true' : 'false'}
              onClick={() => setSelectedCategory('CE7')} // 선택된 카테고리 업데이트
            >
              <i className="fa-solid fa-mug-saucer"></i>
              <p>카페</p>
            </SearchTabLi>
            <SearchTabLi
              isActive={selectedCategory === 'AD5' ? 'true' : 'false'}
              onClick={() => setSelectedCategory('AD5')} // 선택된 카테고리 업데이트
            >
              <i className="fa-solid fa-hotel"></i>
              <p>펜션</p>
            </SearchTabLi>
          </SearchTabUl>
        </SerchTabWrap>

        <SearchButton onClick={searchByCategory}>현 위치로 검색</SearchButton>

        <ListWrap>
          {places.map((place, index) => (
            <ListItem
              key={index}
              onClick={() => {
                const marker = markers[index];
                if (marker) {
                  infowindow.setContent(createInfoWindowContent(place)); // 유틸리티 함수 사용
                  infowindow.open(map, marker);
                  map.panTo(marker.getPosition());
                }
              }}
            >
              <ListLine>
                <div style={{ display: 'flex', alignItems: 'center' }}>
                  <i
                    className={`fa-solid ${
                      place.category_name?.includes('카페')
                        ? 'fa-mug-saucer'
                        : 'fa-hotel'
                    }`}
                    style={{ color: '#ff6732', marginRight: '8px' }}
                  ></i>
                  <TitleP isListTitle="true">{place.place_name}</TitleP>
                </div>
                <ListBookmark>
                  <HeartIcon className="fa-regular fa-heart" />
                </ListBookmark>
              </ListLine>
              <AddressP isListTitle="true">
                {place.road_address_name || place.address_name}
              </AddressP>
              <PhoneP isListTitle="true">{place.phone || '정보 없음'}</PhoneP>
            </ListItem>
          ))}
        </ListWrap>
      </SerchListWrap>

      <div style={{ flex: 1 }}>
        <div id="map" style={{ width: '100%', height: '100%' }}></div>
      </div>
      <MapControls location={location} />
  • 스타일드 컴포넌트를 사용해서 그런지 많이 깔끔하다.

2. 코드분리

우선 분리된 코드부터 볼까?

  // 검색 결과 마커 표시
  const displayPlaces = (places) => {
    const bounds = new window.kakao.maps.LatLngBounds();
    markers.forEach((marker) => marker.setMap(null));
    setMarkers([]);

    const newMarkers = places.map((place) => {
      const position = new window.kakao.maps.LatLng(place.y, place.x);
      const marker = new window.kakao.maps.Marker({ position });

      marker.setMap(map);
      bounds.extend(position);

      window.kakao.maps.event.addListener(marker, 'click', () => {
        infowindow.setContent(createInfoWindowContent(place));
        infowindow.open(map, marker);
      });

      return marker;
    });

    setMarkers(newMarkers);
    map.setBounds(bounds);
  };
  • 그렇게 어지러운 코드로 보이지는 않는다.

그런데 이것이 이전에는 어땠냐면


분리하기전 코드

  // 검색 결과 마커 표시
  const displayPlaces = (places) => {
    const bounds = new window.kakao.maps.LatLngBounds();
    markers.forEach((marker) => marker.setMap(null));
    setMarkers([]);

    const newMarkers = places.map((place) => {
      const position = new window.kakao.maps.LatLng(place.y, place.x);
      const marker = new window.kakao.maps.Marker({ position });

      marker.setMap(map);
      bounds.extend(position);

      window.kakao.maps.event.addListener(marker, 'click', () => {
        infowindow.setContent(`
      <div style="
        padding: 10px; 
        font-size: 14px; 
        line-height: 1.6; 
        display: flex; 
        align-items: flex-start; 
        gap: 10px; 
        max-width: 250px; 
        width: auto; 
        border-radius: 8px; 
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); 
        background-color: #fff; 
        color: #333;
      ">
        <!-- 아이콘 -->
        <div style="flex-shrink: 0; font-size: 20px;">
          <i class="fa-solid ${iconClass}" style="color: #ff6732;"></i>
        </div>
        <!-- 텍스트 -->
        <div>
          <strong style="font-size: 16px; color: #4b74c6; font-weight:bold; display: block; margin-bottom: 5px;">
            ${place.place_name}
          </strong>
          <span style="font-size: 14px; color: #555; display: block; margin-bottom: 3px;">
            ${place.road_address_name || place.address_name}
          </span>
          <span style="font-size: 13px; color: #999;">
            ${place.phone || '전화번호 없음'}
          </span>
        </div>
      </div>
    `;
        infowindow.open(map, marker);
      });

      return marker;
    });

    setMarkers(newMarkers);
    map.setBounds(bounds);
  };
  • 대략 이런 느낌이었는데 보기만해도 어지러운데
    이 로직이 두 군데서나 사용되고 있었기에 매우 지저분한 코드였다.

그래서 다음과 같이 로직을 분리시켰다.


//utils/infoWindowUitl.js
export const createInfoWindowContent = (place) => {
  const iconClass = place.category_name?.includes('카페')
    ? 'fa-mug-saucer'
    : 'fa-hotel';
  return `
      <div style="
        padding: 10px; 
        font-size: 14px; 
        line-height: 1.6; 
        display: flex; 
        align-items: flex-start; 
        gap: 10px; 
        max-width: 250px; 
        width: auto; 
        border-radius: 8px; 
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); 
        background-color: #fff; 
        color: #333;
      ">
        <!-- 아이콘 -->
        <div style="flex-shrink: 0; font-size: 20px;">
          <i class="fa-solid ${iconClass}" style="color: #ff6732;"></i>
        </div>
        <!-- 텍스트 -->
        <div>
          <strong style="font-size: 16px; color: #4b74c6; font-weight:bold; display: block; margin-bottom: 5px;">
            ${place.place_name}
          </strong>
          <span style="font-size: 14px; color: #555; display: block; margin-bottom: 3px;">
            ${place.road_address_name || place.address_name}
          </span>
          <span style="font-size: 13px; color: #999;">
            ${place.phone || '전화번호 없음'}
          </span>
        </div>
      </div>
    `;
};
  • 이렇게 분리한 뒤, 로직을 접목시키니 가독성유지보수 측면에서 아주 좋아졌다.

3. 키워드검색 ➡️ 카테고리 검색

사실 이것은 가장 망설이던 부분인데 바꾸기로 결심하게된 포인트가 있다.

우리 프로젝트는 반려동물 동반 가능한 맛집 및 숙박업소 추천 서비스였기 때문에, 항상 그 조건이 만족을 해야만 한다.

  • 그래서 공공데이터포털의 reponse를 참고했는데, 결과를 보고는 조금 허탈했다.

  • 대부분의 데이터가 카페아니면 펜션이었기 때문이다.
    한가지 더 중요한것은, 높은확률로 가게 이름에 애견이라는 말이 붙는다는것...


🤔 근데 나중에 생각해보니 그럴만도 하겠다 싶었다.

  • 우리는 강아지를 참 좋아하지만!
    음식점에는 안내견빼고는 입장하기 힘들지 않은가?

왜 상식적으로 생각하지 못했나 싶었다.


그래서 결론이 뭐냐?

  1. 반려동물 동반 가능한 맛집은 높은확률로 애견카페다.
  2. 반려동물 동반 가능한 숙박업소는 애견펜션이다.
  • 여기서 높은확률은 99%이상을 얘기한다...

뒤늦은 자기반성 :
API리서치를 하라고 했을때 조금 더 자세히 했어야됐다...


어쨌든 바꿔야겠지?

  1. 이제는 카테고리만 눌러도 검색이 되고!
  2. 지도를 옮겨서 현 위치에서 검색을 누르면 해당 위치에서의 결과값이 검색이 된다!

이렇게 오늘의 결과물을 기록해보았다.


회고

  • 참 쉽지않다.

  • 캠프에 호기롭게 도전하긴 했지만 이렇게 난이도가 급상승 할줄은 예상도 하지 못했기에 어려움이 많은것은 사실이다.

  • 그렇지만 많은 과제들을 통해 스스로 어느정도인지 파악하고 또 학습해가면서 성장하는 그 시간들이 참 소중하다고 느낀다.

  • 이제 발표까지 이틀남았으니까 조금 더 힘내서 완성도 높은 결과물을 보여주도록 하자!!! 화이팅!!!

그럼이만

profile
모든 순간에 최선을 다합니다.

0개의 댓글

관련 채용 정보