현재 위치 정보 hook 만들기

이효범·2022년 4월 6일
0

React Hooks

목록 보기
1/2
post-thumbnail

다음과 같이 유저의 위치 정보를 가져올 수 있는 훅을 만들어보자.

const { latitude, longitude } = useCoords();

useCoords 훅

우선 latitude와 longitude를 담을 state를 하나 만들면서 시작하자.

import React from 'react';

interface UseCoordsState {
  latitude: number | null;
  longitude: number | null;
}

export default function useCoords() {
  const [coords, setCoords] = React.useState<UseCoordsState>({
    latitude: null,
    longitude: null,
  });

  return coords;
}

이 훅이 정상적으로 mount되면 네비게이터를 호출하자.

 useEffect(() => {
    navigator.geolocation.getCurrentPosition()
  },[])

getCurrentPosition 함수는 successCallback과 errorCallback을 넣어주어야 한다.

(method) Geolocation.getCurrentPosition(successCallback: PositionCallback, errorCallback?: PositionErrorCallback | null | undefined, options?: PositionOptions | undefined): void

errorCallback은 옵셔널이다. 여기서는 successCallback만 만들어서 보내도록 한다.
successCallback 함수에는 coords 오브젝트가 들어오게 된다.

// useCoords.ts
import React, { useEffect } from 'react';

interface UseCoordsState {
  latitude: number | null;
  longitude: number | null;
}

export default function useCoords() {
  const [coords, setCoords] = React.useState<UseCoordsState>({
    latitude: null,
    longitude: null,
  });

  const onSuccess = (coords: GeolocationPosition) => {
    console.log(coords);  
  }
  useEffect(() => {
    navigator.geolocation.getCurrentPosition(onSuccess)
  },[])

  return coords;
}

이 훅을 Write.tsx에서 사용해보면 다음과 같이 브라우저가 권한을 요청하는 알림 모달이 뜬다.

/// Write.tsx
const Write: NextPage = () => {
  const { latitude, longitude } = useCoords();
  
  return null;
};

export default Write;


이를 허용해주게되면 위에서 작성한 것과 같이 콘솔에 위치 정보를 표시해주며 잘 작동을 하고 있음을 알 수 있다.

coords도 있고, latitude와 longitude 또한 잘 들어오는 것을 알 수 있다.

그럼 이제 코드를 다듬고 원하는 정보를 리턴하도록 하자.
setState를 이용하여 우리의 state인 coords에 위의 정보를 저장하자.

// ...  
  const onSuccess = ({
      coords: { latitude, longitude },
  }: GeolocationPosition) => {
      setCoords({ latitude, longitude });
  };

  // ...
  return coords;
}

이렇게 간단하게 유저의 위치 정보를 가져올 수 있는 훅을 완성했다.
주인장 같은 경우에는 이 훅을 이용하여 색다른 채팅 어플리케이션 만들어 보고자 한다.
실시간으로 달라지는 유저의 위치에 따라 UI/UX와 대화 상대가 변화하는 어플리케이션을 만들어 볼 수 있을 것 같다.


특정한 위치에서만 보이는 채팅 서비스

그러면 실제로 특정 좌표 범위 내에 있는 채팅만 보이게끔 해보자.
만약 우리가 강남역 한복판에 있다고 하자.

여기가 현재 우리의 좌표다.
일단 기본적인 반경을 어떻게 만들어야 할지에 대해 얘기해보자.
위의 이미지에서 보이듯 강남역의 좌표는 37.498095, 127.027610 라고 나와있다.
단순하게 37을 38로 바꾸면 사실 엄청나게 큰 범위다. 너무 큰 반경이다.
실제로 바꾸면 북한의 어느 부근이 지도에 표시되게 된다.

1의 자리는 너무 커서 소수점 자리 첫번째를 바꿔본다.
그래도 서울에서 안양까지의 반경이 생긴다. 이 또한 너무 멀기 때문에 소수점 둘째 자리를 수정해보자.
교대역과 남부터미널 사이의 좌표가 찍힌다. 이 정도면 우리가 원하는 정도에 어느정도 도달했다고 볼 수 있다.

그래서 우리가 사용할 알고리즘은 latitude와 longitude에 각각 0.01씩을 더하고 빼주는 식으로 반경을 만드는 것으로 한다.

이제 이를 기반으로 실제로 유저가 어플리케이션을 들어왔을 때의 위치 정보를 확인 후
그 위치 반경 내의 채팅 대화 내용만 유저에게 보내주도록 해보자.

이를 위해서 데이터를 받아오기 위한 url에 우리의 latitude와 longitude를 담아서 보내주자.

// Entrance.tsx
cosnt Entrance: NextPage = () => {
  const {latitude, longitude} = useCoords();
  const { data } = useSWR<ChatRoomsResponse>(`/api/chats?latitude=${latitude}&longitude=${longitude}`);
  
  // ...
  return <LocalChatRoom data={data} />;
}

이제 server.js에서 확인해보자.

// server.js
async function handler(
  req: NextApiRequest,
  res: NextApiResponse<ResponseType>,
) {
  const {
    body: { question, latitude, longitude },
    session: { user },
    query,
  } = req;
  console.log(query);
// { latitude: 'your geo', longitude: 'your geo' }
// ...

위와 같이 req.query를 이용하여 해당 데이터를 잘 받아오는 것을 확인할 수 있다. 'your geo' 부분에 유저의 위치 정보가 기록된다.

이제 위에서 받아온 데이터를 필터링을 통해 가공하는 과정을 거치면서 유저의 위치 정보에서 latitude와 longitude에 각각 0.01을 더하고 빼주면서 유저의 현재 위치의 반경을 구한 후, 클라이언트에 보내주면 된다.

이러한 유저의 위치 기반 데이터를 필터링하여 새롭게 가공하는 과정부터는 서버에 영역에 치우쳐져 있으므로 여기서는 생략하도록 한다.

우리는 더욱 나아가서 유저의 주요 위치 정보를 데이터 베이스의 유저 프로필 오브젝트에 저장을 해보거나
혹은 반경은 0.01을 가지고 하는 것이 아닌, 유저가 직접 반경의 범위를 키로미터 단위로 정할 수 있게끔 해보는 것은 어떨까?
추후에 기회가 된다면 포스팅을 해보도록 하자.

profile
I'm on Wave, I'm on the Vibe.

0개의 댓글