개발 slecs

동적 라우트 파라미터와 데이터 조회 인자 불일치 버그 수정

목차

동적 라우트에서 파라미터와 데이터 조회 함수의 인자 타입이 맞지 않는 실수를 고쳤다. /p/[id].astro 페이지에서 URL 파라미터로 받은 id를 그대로 findPostById() 함수에 전달해야 하는데, 어딘가에서 slug를 넘기고 있었다.

왜 이런 실수가 생기나

라우팅과 데이터 조회 로직을 분리하다 보면 자연스럽게 이런 일이 일어난다. 특히 다음 같은 상황에서:

  • 리팩토링 과정: 처음엔 slug 기반으로 설계했다가 나중에 id 기반으로 변경했을 때, 라우팅 레이어만 수정하고 쿼리 함수 호출을 빠뜨린 경우
  • 복사-붙여넣기: 비슷한 다른 페이지(예: /articles/[slug].astro)의 코드를 참고하면서 변수명까지 그대로 복사한 경우
  • 타입 검사 부재: TypeScript/JSDoc 없이 JavaScript만 썼다면 런타임까지 발견되지 않음

Astro 같은 프레임워크에서는 동적 라우트 파라미터가 Astro.params 객체로 전달되는데, 파라미터 이름과 실제 DB 쿼리 함수가 기대하는 필드명을 정확히 맞춰야 한다. "URL에선 id라고 부르는데, DB 함수는 slug를 기대해" 같은 상황은 코드를 읽어도 한눈에 안 띄기 쉽다.

코드 패턴으로 보면

레이어 파라미터 기대값
라우팅 (파일명) [id] id
Astro.params 객체 id id
findPostById() 함수 호출 slug → ✅ id id

결국 "파일 이름의 동적 세그먼트가 [id]라면, 그 페이지에서 데이터를 조회할 때도 같은 변수명으로 일관되게 전달해야 한다"는 원칙이다.

코드 리뷰 포인트

이런 실수는 보통 다음처럼 예방한다:

// Before (버그)
export async function getStaticPaths() {
  const posts = await getAllPosts()
  return posts.map(post => ({
    params: { id: post.id },
    props: { post }
  }))
}

const { id } = Astro.params
const post = await findPostById(slug)  // ❌ 변수명 불일치

// After (수정)
const { id } = Astro.params
const post = await findPostById(id)  // ✅ 일관성 유지
  • 타입 정의: TypeScript를 도입하면 findPostById(id: string) 함수 시그니처와 호출 부분이 자동으로 검증된다
  • 변수명 검색: PR 리뷰에서 파라미터 이름을 찾은 뒤, 그 페이지의 모든 함수 호출이 같은 이름을 쓰는지 확인
  • 테스트: 동적 라우트 페이지의 데이터 조회를 테스트하면 런타임 에러로 빠르게 잡힘

팀 입장에서의 배운 점

이런 버그는 "단순 오타"처럼 보이지만, 사실 아키텍처 신호다. 라우팅 파라미터 이름과 데이터 접근 계층의 인터페이스가 암묵적으로만 연결되어 있다는 뜻이다.

다음 번엔 팀과 함께 이런 부분을 더 명시적으로 정의하는 게 좋겠다. 예를 들어:
- "라우팅에서는 항상 id를 쓴다" 같은 컨벤션 문서화
- 데이터 조회 함수의 파라미터 이름을 명확하게 문서화
- 신입이나 팀원이 이런 패턴을 빨리 학습할 수 있는 코드 템플릿

버그 자체보다, "왜 이런 실수가 자주 나오는가"에 대한 구조적 개선이 더 가치 있다.


🛒 이 글과 어울리는 추천 상품

*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.

댓글 0

첫 댓글 달아줘.