수영장(Sooyoung Archive)
홈개발일지이번캠App소개
전체보기
프로젝트
블로그 만들기그림톡캠핑 인스타
개발

© 2026 수영장 (Sooyoung Archive). All rights reserved.

개인정보처리방침연락처
개발일지 목록
캠핑 인스타

캠핑 인스타 만들기 3편

2026년 2월 12일약 7분 소요44회 조회
목차
1. UI/UX 대수술: "랜딩 사이트" 느낌 주기📱 하단 네비게이션 (Bottom Navigation) 개편🛎️ 상단 헤더 통일화📸 스토리(Stories) 영역 추가2. 오늘의 트러블 슈팅 (Troubleshooting) 🔥🐛 이슈 1: Hydration Error "서버와 클라이언트가 달라요"🐛 이슈 2: "저장이... 된 줄 알았는데요?" (Silent Failure)🐛 이슈 3: Missing Table (PGRST205)3. 소셜 기능 완성 (Social Features)🚀 앞으로의 계획

🏕️ Next.js + Supabase로 캠핑 소셜 앱 만들기: UI 리팩토링과 트러블 슈팅 로그

오늘은 기존의 단순한 캠핑 로그 앱을 인스타그램 스타일의 소셜 플랫폼으로 고도화하는 작업을 진행했다. 단순히 기능만 붙이는 것이 아니라, 사용자 경험(UX)을 고려해 UI를 대대적으로 리팩토링하고, 그 과정에서 마주친 몇 가지 기술적인 문제들을 해결했다.

1. UI/UX 대수술: "랜딩 사이트" 느낌 주기

기존 앱은 기능 위주로 투박하게 구성되어 있었다. 사용자가 앱에 들어왔을 때 "와, 요즘 앱 같다!"라는 느낌을 주기 위해 전반적인 레이아웃을 손봤다.

📱 하단 네비게이션 (Bottom Navigation) 개편

  • 기존: 4개 탭 (피드, 검색, 글쓰기, 프로필)
  • 변경: 5개 탭 (피드, 검색, 작성, 저장, 프로필)
  • 이유: 사용자가 자주 찾는 '저장(찜)한 캠핑장' 메뉴의 접근성을 높이고, 아이콘 배치를 균형 있게 맞췄다. 글쓰기 버튼(PlusCircle)을 중앙에 배치하여 행동 유도(CTA)를 강조했다.

🛎️ 상단 헤더 통일화

  • 페이지마다 제각각이던 모바일 헤더를 제거하고, MainNav 컴포넌트 하나로 통일했다.
  • 우측 상단에 알림(Bell) 아이콘을 추가해 향후 알림 기능을 위한 공간을 마련했다.
  • Radix UI의 DropdownMenu를 활용해 프로필 메뉴를 깔끔하게 정리했다.

📸 스토리(Stories) 영역 추가

  • 인스타그램의 상징인 '스토리' 영역을 피드 최상단에 배치했다.
  • 현재는 레이아웃(StoriesPlaceholder)만 잡혀있지만, 가로 스크롤(ScrollArea)을 적용해 나중에 실제 데이터만 연동하면 바로 동작하도록 구현했다.

2. 오늘의 트러블 슈팅 (Troubleshooting) 🔥

기능 구현보다 더 값진 것은 버그를 잡는 과정이었다. 오늘 해결한 주요 이슈 3가지를 정리해 본다.

🐛 이슈 1: Hydration Error "서버와 클라이언트가 달라요"

증상: 새로고침만 하면 콘솔에 빨간색 Hydration Error가 발생했다. 원인: SearchCampsiteDialog 컴포넌트에서 trigger prop으로 버튼(Button)을 넘겨주고 있었는데, Radix UI의 DialogTrigger 내부에서 ID 생성 로직(aria-controls)이 서버와 클라이언트 간에 불일치를 일으켰다. 해결:

  • trigger prop 대신 **children**을 사용하는 방식(Composition 패턴)으로 변경했다.
  • 부모 컴포넌트(MainNav)에서 <SearchCampsiteDialog><Button>...</Button></SearchCampsiteDialog> 형태로 감싸주니 깔끔하게 해결되었다. 역시 React는 합성이 답이다.

🐛 이슈 2: "저장이... 된 줄 알았는데요?" (Silent Failure)

증상: 캠핑장 찜하기(하트)를 눌렀는데, 버튼 색은 바뀌는데 실제로 '저장됨' 페이지엔 아무것도 없었다. 원인:

  1. **낙관적 업데이트(Optimistic Update)**의 함정: UI는 즉시 바뀌게 해놓고, 실제 API 요청 결과를 제대로 확인하지 않았다.
  2. 에러 핸들링 누락: Supabase의 .insert()나 .delete()가 실패해도 에러를 throw 하지 않고 조용히 지나가고 있었다. 해결: API 요청의 error 객체를 확인해서, 실패 시 에러를 던지고 UI를 롤백(Rollback) 하도록 수정했다.

🐛 이슈 3: Missing Table (PGRST205)

증상: "Could not find the table 'public.bookmarks'" 에러 발생. 원인: 마이그레이션 파일(002_bookmarks.sql)은 만들었지만, 실제 DB에 적용(Apply)하는 것을 깜빡했다. 😅 해결: Supabase SQL Editor에서 테이블 생성 쿼리와 RLS(Row Level Security) 정책을 수동으로 실행해 해결했다.


3. 소셜 기능 완성 (Social Features)

  • 좋아요(Like): 게시글 좋아요 기능 구현. 낙관적 업데이트를 적용해 클릭 즉시 반응하도록 했다.
  • 댓글(Comment): Sheet(Drawer) UI를 사용해 모바일 친화적인 댓글 창을 구현했다.
  • 프로필(Profile): 댓글이나 글 작성 시 프로필이 없으면 자동으로 생성해주는 Self-healing 로직을 추가해 UX 끊김을 방지했다.

🚀 앞으로의 계획

  • 검색 기능 고도화 (지역 필터 + 검색어 조합)
  • 스토리 기능 실제 데이터 연동
  • 알림 센터 구현

오늘의 작업으로 앱의 뼈대는 거의 완성되었다. 이제 "예쁜" 앱을 넘어 "잘 돌아가는" 앱으로 다듬어 나갈 차례다.

클릭할 때마다 작가에게 따뜻한 응원이 전달됩니다 ❤️

이 글이 유익하셨나요?
동료 개발자들과 경험과 노하우를 공유해 보세요.
이전 글캠핑 인스타
캠핑인스타 만들기 2편
캠핑 인스타다음 글
캠핑인스타 만들기 4편

함께 읽으면 좋은 다른 개발일지

'캠핑 인스타' 및 추천 아카이브 글 모음

캠핑인스타 만들기 5편: '이번캠(MyCamp)' 리브랜딩과 Capacitor로 Apple App Store 심사 통과한 이야기
캠핑 인스타
캠핑인스타 만들기 5편: '이번캠(MyCamp)' 리브랜딩과 Capacitor로 Apple App Store 심사 통과한 이야기
캠핑인스타를 '이번캠(MyCamp)'으로 리브랜딩하고, Capacitor를 활용해 Next.js 웹 서비스를 Apple App Store(iOS)에 공식 출시하며 겪은 심사 통과와 트러블슈팅 기록.
2026. 8. 26.

댓글

목차
1. UI/UX 대수술: "랜딩 사이트" 느낌 주기📱 하단 네비게이션 (Bottom Navigation) 개편🛎️ 상단 헤더 통일화📸 스토리(Stories) 영역 추가2. 오늘의 트러블 슈팅 (Troubleshooting) 🔥🐛 이슈 1: Hydration Error "서버와 클라이언트가 달라요"🐛 이슈 2: "저장이... 된 줄 알았는데요?" (Silent Failure)🐛 이슈 3: Missing Table (PGRST205)3. 소셜 기능 완성 (Social Features)🚀 앞으로의 계획
4회
캠핑인스타 만들기 4편
캠핑 인스타
캠핑인스타 만들기 4편
OG 이미지 구현 과정에서 겪은 삽질과 Supabase 연동 이슈를 정리한 캠핑인스타 개발 기록.
2026. 3. 3.48회
캠핑인스타 만들기 2편
캠핑 인스타
캠핑인스타 만들기 2편
게시글 삭제, 권한 처리, 이미지 정리까지 포함해 캠핑인스타의 기본 CRUD 경험을 다듬은 작업 기록.
2026. 2. 12.44회