Post

⚓ DATT 16 - 인증 및 Place 탐색 기반 UI 구축

⚓ DATT 16 - 인증 및 Place 탐색 기반 UI 구축

개요

DATT는 단순한 장소 검색 서비스가 아니다.

핵심 목표는:

  • 장소 탐색
  • 지역 기반 경험 공유
  • Anchor 큐레이션
  • 게이미피케이션 기반 리텐션

을 하나의 흐름으로 연결하는 것이다.

이번 프론트엔드 작업에서는:

  • JWT 인증 흐름
  • Place 탐색 UI
  • 상태 관리 구조
  • 서버 상태 관리 전략
  • 지도 기반 UX 구조

를 중심으로 구조를 설계했다.


인증 흐름 설계

왜 JWT 기반으로 설계했는가

현재 DATT 백엔드는:

  • Access Token
  • Refresh Token

기반 JWT 인증 구조를 사용한다.

프론트엔드는 다음 흐름으로 동작하도록 구성했다.

1
2
3
4
5
로그인 성공
→ accessToken / refreshToken 저장
→ Zustand 인증 상태 저장
→ Axios Authorization 자동 주입
→ 새로고침 시 로그인 상태 복구

Zustand를 사용한 이유

전역 인증 상태는:

  • 로그인 여부
  • 사용자 닉네임
  • Access Token 상태

정도만 관리하면 된다.

즉:

1
2
3
복잡한 Flux 아키텍처
거대한 reducer
action 분리

까지는 필요하지 않았다.

따라서:

1
2
3
간단한 인증 상태
빠른 개발 속도
낮은 보일러플레이트

에 강한 Zustand를 선택했다.


인증 상태 저장 구조

1
2
3
4
5
6
7
8
9
10
11
type AuthState = {
    accessToken: string | null;
    refreshToken: string | null;

    member: {
        memberId: number;
        nickname: string;
    } | null;

    isLoggedIn: boolean;
};

로그인 성공 시:

1
2
3
localStorage 저장
+
Zustand 상태 저장

두 가지를 동시에 수행한다.


로그인 유지 처리

새로고침 시 Zustand 메모리는 초기화된다.

이를 해결하기 위해:

1
2
AuthProvider
restoreAuth()

구조를 도입했다.

앱 시작 시 localStorage의 토큰 및 사용자 정보를 읽어 인증 상태를 복구한다.


TanStack Query 활용 전략

왜 React Query(TanStack Query)를 선택했는가

Place 검색 / 상세 / Bookmark는 모두:

1
서버 상태(Server State)

이다.

즉:

  • 캐싱 필요
  • 로딩 상태 필요
  • 에러 상태 필요
  • 재조회 필요
  • invalidate 필요

한 구조였다.

이걸 useEffect + useState로 직접 관리하면:

1
2
3
4
로딩 상태 중복
에러 처리 중복
캐싱 부재
데이터 동기화 문제

가 발생한다.


적용 구조

1
2
3
4
usePlaceSearch()
usePlaceDetail()
useAddPlaceBookmark()
useRemovePlaceBookmark()

형태로 API 단위 Hook을 분리했다.

특히 Bookmark는:

1
queryClient.invalidateQueries()

를 활용해:

1
2
상세 페이지
북마크 목록

을 자동 동기화하도록 설계했다.


Place 탐색 UI 설계

초기 문제

초기에는 Place 검색 결과를:

1
Card Grid UI

로 구성했다.

하지만 실제 데이터가 많아지자:

1
2
3
한눈에 보기 어려움
스크롤 피로 증가
정보 밀도 부족

문제가 발생했다.


리스트 기반 UX로 변경

최종적으로는:

1
2
3
1행 리스트 구조
+
페이지네이션

으로 변경했다.

예:

1
2
3
4
[카테고리] 매장명
주소
지역 정보
[상세]

형태.

이 구조의 장점은:

  • 정보 밀도 증가
  • 빠른 탐색
  • 모바일 대응 용이
  • 실제 지도 서비스와 유사한 UX

이다.


PlaceListItem 컴포넌트 설계

기존:

1
PlaceCard

를:

1
PlaceListItem

으로 변경했다.

이유는:

1
2
검색 결과는 "탐색"
상세 페이지는 "집중"

이기 때문이다.

탐색 화면은:

1
2
3
빠른 스캔
빠른 이동
짧은 정보

에 최적화해야 한다.


공통 Async 상태 처리

검색 페이지에서는 반복적으로:

1
2
3
isLoading
isError
empty

분기가 발생했다.

이를 해결하기 위해:

1
AsyncStateView

컴포넌트를 만들었다.

구조:

1
2
3
4
5
6
7
<AsyncStateView
    isLoading={isLoading}
    isError={isError}
    isEmpty={data?.empty}
>
    ...
</AsyncStateView>

이 방식의 장점은:

  • 페이지 코드 간결화
  • 상태 UI 통일
  • 재사용성 증가

이다.


지도 기반 탐색 UX 설계

DATT의 핵심은:

1
지도 기반 경험 탐색

이다.

따라서 단순 리스트 서비스가 아니라:

1
지도 ↔ 장소 ↔ Anchor

가 유기적으로 연결되어야 한다.


Kakao Map 선택 이유

현재 대한민국 지역 데이터와 UX 측면에서:

  • 주소 정확도
  • 로컬 데이터 강점
  • 지도 UX 친숙도

를 고려해 Kakao Map SDK를 선택했다.


지도 UX 핵심 방향

단순 핀 표시가 아니라:

1
2
3
4
현재 위치 기반 탐색
반경 기반 탐색
Anchor 경로 탐색
추천 장소 흐름 탐색

까지 확장 가능한 구조를 목표로 하고 있다.


앞으로의 방향

현재까지는:

1
MVP 탐색 구조

를 구축한 상태다.

다음 단계에서는:

  • Bookmark 페이지
  • 리뷰 시스템
  • Anchor 생성
  • 지도 Overlay
  • 무한스크롤
  • Debounce 검색
  • Skeleton UI
  • 모바일 UX 개선

등을 진행할 예정이다.


마무리

이번 단계에서 가장 중요하게 생각한 것은:

1
2
"기능 구현"보다
"확장 가능한 구조"

였다.

특히:

  • 인증 상태
  • 서버 상태
  • 탐색 UI
  • 지도 UX

를 분리해두면서 이후 기능 확장이 훨씬 쉬워졌다.

이제부터 DATT는 단순한 장소 검색이 아니라:

1
"지역 기반 경험 탐색 플랫폼"

으로 확장될 준비를 갖추게 되었다.

This post is licensed under CC BY 4.0 by the author.