ADR-27: 커밋 기반 분석 조회
| 날짜 | 작성자 | 리포지토리 |
|---|---|---|
| 2026-02-03 | @KubrickCode | web |
Context
문제 상황
사용자는 리포지토리의 최신 분석 결과만 조회 가능. 그러나 데이터베이스에는 특정 커밋 SHA에 연결된 여러 분석 기록 존재. force-push 작업(git reset --hard && git push -f) 후 "Up to date" 메시지만 표시되고, 이전에 분석된 커밋 접근 불가.
사용자 요구사항
| 요구사항 | 설명 |
|---|---|
| 히스토리 조회 | 이전에 분석된 모든 커밋의 결과 조회 |
| 시간별 비교 | 테스트 명세 변화 추적 |
| 회귀 디버깅 | 특정 테스트 명세 변경 시점 식별 |
| 공유 가능한 분석 상태 | 특정 커밋 분석 결과 링크 공유 |
기존 제약사항
| 제약사항 | 출처 | 영향 |
|---|---|---|
| nuqs URL 상태 | Web ADR-16 | 커밋 선택에 URL 파라미터 사용 필요 |
| Zustand 범위 | Web ADR-26 | 임시 상태 전용; 네비게이션 상태에 부적합 |
| TanStack Query | Web ADR-04 | 분석 데이터 fetching 패턴 확립 |
| Next.js App Router | Web ADR-07 | URL 상태에 대한 SSR 고려 필요 |
Decision
nuqs를 사용한 URL 기반 커밋 선택과 CommitSelector UI 컴포넌트 도입.
핵심 원칙:
- URL을 진실의 원천으로: 커밋 선택이 URL에 유지 (
?commit=abc1234) - 점진적 개선: 파라미터 없을 시 최신 커밋으로 기본 설정
- nuqs 통합: SHA 형식 검증과 함께
parseAsString사용 - 복합 상태: 커밋 선택과 기존 필터 조합
URL 구조
/repos/{owner}/{repo}/analysis?commit=abc1234
/repos/{owner}/{repo}/analysis?commit=abc1234&view=starred&q=authOptions Considered
Option A: nuqs를 통한 URL 기반 커밋 선택 (채택)
기존 nuqs 패턴을 사용하여 선택된 커밋 SHA를 URL 쿼리 파라미터에 저장.
장점:
- 정확한 분석 상태를 담은 공유 가능한 URL
- 브라우저 히스토리 통합 (뒤로/앞으로 네비게이션)
- SSR 호환으로 사전 fetching 가능
- 기존 필터 패턴과 일관성 (ADR-16)
- 다른 URL 상태와 조합 가능
단점:
- URL 길이 증가 (7자 SHA 축약으로 완화)
- 유효하지 않은 커밋 처리 필요
- 커밋 삭제 시 오래된 북마크 처리 필요
Option B: Zustand를 통한 클라이언트 측 상태
선택된 커밋을 임시 클라이언트 상태로 Zustand 스토어에 저장.
장점:
- 깔끔한 URL
- 빠른 상태 변경
- 크로스 컴포넌트 접근
단점:
- 공유 불가
- 페이지 새로고침 시 상태 손실
- 브라우저 히스토리 미지원
- ADR-26 범위 위반 (Zustand는 임시 상태 전용)
기각: 확립된 패턴과 모순; 공유 가능한 링크에 대한 불량 UX.
Option C: 경로 세그먼트 기반 선택
커밋 SHA를 URL 경로에 인코딩 (/analysis/{commit}).
장점:
- RESTful 시맨틱
- 깔끔한 URL 계층 구조
단점:
- 라우팅 복잡성 증가
- 쿼리 기반 필터와 불일치
- 컴포넌트 업데이트가 아닌 페이지 전환 발생
기각: 구현 노력 증가; 필터 조합 불가.
Option D: 드롭다운만 (상태 지속성 없음)
로컬 상태만 있는 UI 컴포넌트.
기각: 수용 불가한 UX; 모든 네비게이션에서 선택 손실.
Implementation Details
API 엔드포인트
| 엔드포인트 | 목적 |
|---|---|
GET /api/analyze/{owner}/{repo}/history | 분석된 커밋 목록 (최대 50개) |
GET /api/analyze/{owner}/{repo}?commit={sha} | 특정 커밋의 분석 결과 조회 |
데이터 구조
typescript
interface AnalysisHistoryItem {
id: string;
commitSha: string;
commitDate: string | null;
completedAt: string;
branchName: string | null;
testCount: number;
isHead: boolean;
}URL 상태 Hook
typescript
import { parseAsString, useQueryState } from "nuqs";
const commitParser = parseAsString.withDefault("");
export const useCommitSelect = () => {
const [commit, setCommit] = useQueryState("commit", commitParser);
const validated = /^[a-f0-9]{7,40}$/.test(commit ?? "") ? commit : null;
return { commit: validated, setCommit } as const;
};CommitSelector 컴포넌트
- 축약된 SHA (7자) 표시 드롭다운
- 현재 HEAD 커밋에
[HEAD]배지 - 테스트 수, 브랜치명, 날짜 표시
- 히스토리 항목이 2개 미만일 경우 정적 텍스트로 폴백
TanStack Query 통합
typescript
export const useAnalysisData = (owner: string, repo: string) => {
const { commit } = useCommitSelect();
return useQuery({
queryKey: ["analysis", owner, repo, commit],
queryFn: () => fetchAnalysis(owner, repo, commit),
});
};Consequences
Positive
- 공유 가능한 분석 상태:
/analysis?commit=abc1234&view=starred같은 URL로 협업 가능 - 브라우저 네비게이션: 뒤로/앞으로 버튼으로 커밋 히스토리 자연스럽게 탐색
- SSR 최적화: URL 파라미터에서 서버가 올바른 분석 사전 fetch 가능
- 패턴 일관성: ADR-16의 nuqs 패턴 확장
- 디버깅 용이성: 지원팀이 정확한 상태를 위해 "URL 보내주세요" 요청 가능
Negative
- URL 복잡성: 커밋 파라미터로 URL 길어짐 (SHA 축약으로 완화)
- 유효하지 않은 상태 처리: 삭제된/사용 불가한 커밋 우아하게 처리 필요
- 쿼리 무효화: 커밋 변경 시 TanStack Query 캐시 무효화 (예상된 동작)
References
Internal
- ADR-04: TanStack Query 선택 - 서버 상태 관리
- ADR-16: nuqs URL 상태 관리 - URL 상태 패턴
- ADR-26: Zustand 클라이언트 상태 관리 - 상태 관리 삼위일체
- ADR-12: Worker 중심 분석 라이프사이클 - 분석 데이터 모델
External
- GitHub Issue #300 - 기능 요청 및 설계
- Release v1.6.0 - 초기 구현
