URL은 곧 상태다 ("Your URL Is Your State")

okorion·2025년 12월 3일

1. 핵심 요약

  • URL은 단순한 리소스 주소가 아니라 애플리케이션 상태(State)를 담는 1급 객체다.

  • 좋은 URL은:

    • 공유(Share)
    • 북마크(Bookmark)
    • 뒤로 가기(History)
    • 깊은 링크(Deep Linking)
      를 모두 해결한다.
  • 많은 프론트엔드 개발자가 Redux·Context·전역 스토어에만 집중하지만,
    URL은 1991년부터 동작해온 원조 상태 관리 시스템이다.

  • URL을 설계하는 순간, “어떤 상태를 공유·저장·복원 가능한가?”를 결정하는 것과 같다.

  • 사례: PrismJS 설정 URL, GitHub 라인 하이라이트, Google Maps 좌표, Figma 링크 등
    → 모두 URL을 state container로 활용.


2. URL이 제공하는 “무료 UX 기능”

URL을 상태로 저장하면 아래가 자동으로 따라온다.

  • Shareability: 링크 보내면 그대로 재현
  • Bookmarkability: 저장하면 상태가 기억
  • Back/Forward History: 히스토리 기반 탐색
  • Deep Linking: 특정 상태로 즉시 이동
  • Caching: 같은 URL → 같은 리소스 캐시 사용
  • Analytics: URL만으로도 사용자 흐름 분석 가능

→ URL은 자연스럽고 예측 가능한 상태 저장소다.


3. URL 구조와 상태 설계

URL은 여러 부분으로 상태를 담을 수 있다.

3-1. Path

계층 구조·리소스 위치 표현

/users/123/posts
/docs/api/authentication
/dashboard/analytics

3-2. Query Parameters

구체적 상태(필터·옵션·모드 등)를 저장하는 데 가장 적합

?theme=dark&lang=en
?page=2&limit=20
?status=active&sort=date
?from=2025-01-01&to=2025-12-31

3-3. Fragment (#)

문서 내 특정 위치/선택 상태를 표현

#L20-L35 (GitHub 코드 하이라이트)
#features

3-4. Text Fragments

페이지 내부 텍스트로 직접 링크
→ URL이 “문서 내 컨텍스트”까지 저장 가능해짐


4. Query 패턴 예시

여러 값 담기

?languages=javascript+typescript+python

Key–Value 시리얼라이즈

?filters=status:active,owner:me

Base64 직렬화(복잡하지만 안전)

?config=eyJyaWNrIjoicm9sbCJ9==

Boolean flag

?debug=true
?mobile

배열 (Bracket Notation)

?tags[]=react&tags[]=hooks

→ 중요한 건 일관성.


5. URL을 State로 사용하는 실전 사례

PrismJS 설정 URL

https://prismjs.com/download.html#themes=prism&languages=markup+css+scss+sql&plugins=line-numbers

→ UI 전체 설정을 URL 하나에 담아 공유·복원 가능.

GitHub 코드 라인 링크

...#L108-L136

Google Maps

좌표, 줌 레벨, 지도 모드까지 모두 URL에 포함.

Figma

캔버스 위치, 확대 비율, 선택 노드 등 전체 컨텍스트를 URL로 저장.

E-commerce 필터

?brand=dell+hp&price=500-1500&sort=price-asc

→ 필터링 상태를 공유·저장·복원하기 쉬움.


6. 어떤 상태를 URL에 담아야 하는가?

URL에 넣어야 하는 상태

  • 필터
  • 정렬
  • 페이지네이션
  • 날짜 범위
  • 보기 모드(list/grid)
  • feature flag
  • 활성 탭

URL에 넣으면 안 되는 상태

  • 비밀번호·토큰·개인정보
  • 모달 열림/닫힘
  • 입력 중이던 Form 값
  • 매우 복잡하고 거대한 JSON
  • 고빈도 상태(마우스 좌표 등)

판단 기준:
“이 URL을 누군가에게 보내면 동일한 상태를 보여야 하는가?”
Yes → URL
No → 메모리/스토어


7. JavaScript/React에서의 URL 상태 관리

기본 JS: URLSearchParams

const params = new URLSearchParams(window.location.search);
const view = params.get('view') || 'grid';

window.history.pushState({}, '', `?${params.toString()}`);

popstate(뒤로/앞으로)

window.addEventListener('popstate', () => {
  // URL → UI 복원
});

React Router / Next.js

const [searchParams, setSearchParams] = useSearchParams();
const sort = searchParams.get('sort') || 'price';

setSearchParams(prev => {
  const params = new URLSearchParams(prev);
  params.set('sort', newSort);
  return params;
});

8. URL 상태 관리 Best Practices

8-1. 기본값은 URL에 넣지 말 것

?theme=dark  // OK
?theme=light // light가 기본이면 불필요

8-2. Debounce 적용

실시간 검색에서 URL 남용 방지:

history.replaceState({}, '', `?q=${value}`);

8-3. push vs replace

  • pushState: 새로운 상태 → 히스토리 추가
  • replaceState: 미세 조정 → 히스토리 덮어쓰기

9. URL은 “계약(Contract)”이다

좋은 URL은 UI·백엔드·사용자·검색엔진이 모두 이해할 수 있는 규약이 된다.

9-1. 의도 전달

/products/laptop?color=silver&sort=price

→ URL만 읽어도 상태가 드러난다.

9-2. 캐싱 최적화

URL = 캐시 키

  • 동일 URL = 동일 응답
  • 쿼리 조합이 캐시 분기

9-3. A/B 실험·버저닝

?v=2
?beta=true
?experiment=new-ui

10. Anti-patterns

10-1. 메모리 전용 SPA

새로고침 → 상태 초기화 → UX 파괴

10-2. URL에 민감 데이터 포함

절대 금지.

10-3. 난해한 파라미터명

?foo=true&x=1 → No
?theme=dark&page=2 → Yes

10-4. Base64 거대 JSON

URL은 구성 옵션 쓰레기통이 아니다.

10-5. Back 버튼 무시

replaceState 남용 → 사용자 분노


11. 결론

  • URL은 단순한 주소가 아니라 가장 강력하고 오래된 상태 저장 시스템이다.
  • 새로고침·뒤로 가기·북마크·공유가 모두 상태 관리의 일부다.
  • 잘 설계된 URL은 사용자 경험을 강화하고, 개발 흐름을 단순화하며, 캐싱·추적·디버깅을 손쉽게 만든다.

프런트엔드 상태 관리 전에 항상 물어봐야 한다.

“이 상태, URL에 담으면 훨씬 낫지 않을까?”

원문 - Your URL Is Your State

profile
Tech Blog

0개의 댓글