문제 정의
블로그 목록에서 검색어와 카테고리를 선택했는데 새로고침하면 상태가 사라진다면 사용자는 같은 탐색을 다시 해야 합니다. 뒤로가기를 눌렀을 때 필터가 초기화되거나, 링크를 공유했는데 상대방이 같은 결과를 보지 못하는 것도 같은 문제입니다.
프론트엔드 상태는 화면 안에만 머물면 편하지만, 공개 탐색 경험에서는 URL에 남아야 할 상태가 있습니다.
상황과 배경
검색과 카테고리는 단순 UI 컨트롤이 아니라 사용자가 콘텐츠를 고르는 의도입니다. 이 의도를 URL에 남기면 브라우저 기본 기능과 제품 경험이 맞물립니다. 반대로 모든 상태를 컴포넌트 내부에만 두면 새로고침, 공유, analytics, SEO route shell이 서로 다른 페이지를 보는 문제가 생깁니다.
공개 URL을 계약처럼 다루는 원칙은 SEO가 깨지지 않는 공개 라우트 계약 설계에서 더 넓게 다룹니다.
URL 상태 계약의 핵심
- 공유 가능한 상태: 검색어, 카테고리, 페이지, 정렬처럼 다른 사람에게 보여 줄 수 있는 조건은 URL에 둡니다.
- 임시 상태: 드롭다운 열림, hover, 입력 중 임시값처럼 공유할 필요가 없는 상태는 컴포넌트에 둡니다.
- 기본값 생략: 기본 카테고리나 빈 검색어는 URL을 지저분하게 만들지 않습니다.
- 뒤로가기 보존: 사용자가 이동한 순서가 브라우저 기록에 자연스럽게 남아야 합니다.
실제 적용 방법
먼저 URL query의 schema를 정합니다. 예를 들어 ?lang=ko&category=devops&q=deploy&page=2처럼 의미가 분명한 키를 사용합니다. 프론트엔드는 query를 읽어 초기 상태를 만들고, 사용자가 필터를 바꾸면 URL을 갱신합니다. API 요청도 같은 query를 기준으로 만들면 화면과 데이터가 어긋나지 않습니다.
글 목록 API의 page와 limit 계약은 글 목록 API pagination 계약에서 이어서 정리했습니다. URL과 API가 같은 기준을 공유해야 운영이 쉽습니다.
운영 체크리스트
- 새로고침 후에도 검색어와 카테고리가 유지되는지 확인합니다.
- 공유한 URL이 같은 결과 목록을 보여 주는지 확인합니다.
- 빈 검색어, 전체 카테고리, 첫 페이지는 URL에서 생략할지 결정합니다.
- 잘못된 query 값은 안전한 기본값으로 되돌립니다.
- 홈, /posts, /categories의 route shell이 같은 URL 기준을 쓰는지 봅니다.
결론
URL은 프론트엔드 구현의 부산물이 아니라 사용자가 탐색을 저장하고 공유하는 인터페이스입니다. 콘텐츠 허브 큐레이션과 URL 상태 계약을 함께 설계하면 글을 찾고 이어 읽는 흐름이 훨씬 강해집니다.