지도검색 기능 구현하기: 클라이언트 편

조성철 (JoSworkS)·2020년 2월 17일
0

이번 로그에서는 바로 전 로그에 이어 지도검색 기능에 대해 클라이언트 측면에서 다뤄보도록 하겠다.

클라이언트 고려사항

지도 검색을 위해서는 클라이언트에서 유저에게 시각적으로 쾌적하게 보여주는 것이 가장 중요한 점이라고 생각했다.

그러기 위해서는 검색창을 가장 위에 두고 검색창 하단 부분을 전체를 화면에 맞게 지도로 크게 보여주기로 하였고, 이를 위해 Dimensions을 아래와 같이 이 'window'의 사이즈를 이용하는 방법으로 진행했다.

먼저 Dimensions을 import하고 Dimensions.get()을 이용하여 window의 높이와 넓이를 StyleSheet의 height와 width로 주었다.

const styles = StyleSheet.create({
  mapStyle: {
    height: Dimensions.get('window').height,
    width: Dimensions.get('window').width,
  },
});

두 번째로는 지도 위에 각각의 하우스가 하우스의 좌표에 맞게 위치할 수 있도록 하였다. 이를 통해 유저는 자신이 원하는 지역에 위치한 하우스를 간단히 파악할 수 있다.

이를 구현하기 위해서는 지도위에 마커 컴포넌트를 이용하여 렌더하는 방법을 이용하였다.

먼저, 검색하기 전에는 모든 하우스의 위치를 서버로 부터 받아 렌더 되게 하고, 검색 한 후에는 검색된 하우스만 지도 위에 렌더되도록 하였다.

  const [markers, setMarkers] = useState(housesData);

마지막으로는 렌더된 마커를 통해 바로 하우스의 상세정보에 접근할 수 있도록 하였습니다. 지도 위에 렌더된 마커를 터치하면 onPress() 메소드를 통해 해당 마커의 하우스 정보를 서버로부터 받아와 하우스 상세 페이지에 구현하는 방식을 이용하였다.

              <Marker
                key={marker.id}
                coordinate={marker.coordinate}
                title={marker.title}
                identifier={String(marker.id)}
                onPress={(e) => {
                  axiosInstance
                    .get(`houses/${e.nativeEvent.id}`)
                    .then((res) => {
                    props.navigation.navigate('HouseDetail', {data: res.data});
                }}
              />

구동 테스트

소스코드

import React, { useState } from 'react';
import { View, StyleSheet, Dimensions } from 'react-native';
import MapView, { Marker } from 'react-native-maps';
import { Input, Button } from 'react-native-elements';
import { withNavigation } from 'react-navigation';
import axiosInstance from '../../util/axiosInstance';

const LATITUDE = 35.39673755350146;
const LONGITUDE = 127.71844625473022;
const LATITUDE_DELTA = 4;
const LONGITUDE_DELTA = 4;

const styles = StyleSheet.create({
  mapStyle: {
    height: Dimensions.get('window').height,
    width: Dimensions.get('window').width,
  },
});

function MapSearchForm(props: any): JSX.Element {
  const { data } = props;

  const housesData = data.map((house: any) => {
    return {
      id: house.id,
      title: house.title,
      coordinate: {
        latitude: Number(house.location[0]),
        longitude: Number(house.location[1]),
      },
    };
  });

  const [searchWord, setSearchWord] = useState('');
  const [markers, setMarkers] = useState(housesData);

  return (
    <View>
      <View>
        <Input
          placeholder="검색할 내용을 입력해 주세요. 예: 강남 시티뷰가 좋은 집"
          label="검색"
          labelStyle={{ alignSelf: 'center' }}
          onChangeText={(text): void => setSearchWord(text)}
        />
        <Button
          title="검색하기"
          type="solid"
          onPress={(): void => {
            axiosInstance
              .post('houses/search', {
                searchWord,
              })
              .then((res) => {
                const searchHouse = res.data.map((house: any) => {
                  return {
                    id: house.id,
                    title: house.title,
                    coordinate: {
                      latitude: Number(house.location[0]),
                      longitude: Number(house.location[1]),
                    },
                  };
                });
                setMarkers(searchHouse);
              });
          }}
        />
      </View>
      <View>
        <MapView
          style={styles.mapStyle}
          provider="google"
          showsUserLocation
          initialRegion={{
            latitude: LATITUDE,
            longitude: LONGITUDE,
            latitudeDelta: LATITUDE_DELTA,
            longitudeDelta: LONGITUDE_DELTA,
          }}
          {markers.map(
            (marker: {
              key: number;
              id: number;
              coordinate: { latitude: number; longitude: number };
              title: string;
            }) => (
              <Marker
                key={marker.id}
                coordinate={marker.coordinate}
                title={marker.title}
                identifier={String(marker.id)}
                onPress={(e) => {
                  axiosInstance
                    .get(`houses/${e.nativeEvent.id}`)
                    .then((res) => {
                    props.navigation.navigate('HouseDetail', {data: res.data});
                }}
              />
            ),
          )}
        </MapView>
      </View>
    </View>
  );
}
export default withNavigation(MapSearchForm);

0개의 댓글