JOURNAL ENTRY Engineering

기록을 많이 남겼는데 더 찾기 어려워졌다 — 파일을 옮기지 않고 Retrieval Layer를 만든 이유

History가 커지자 기록 부족보다 검색 비용이 문제가 됐다. 원문을 프로젝트별로 재배치하는 대신 provenance를 보존하고 catalog, query, purpose-specific projection을 위에 얹은 과정을 정리한다.

개발 기록을 남기기 시작했을 때 문제는 단순했다.

기억하지 못하는 일이 너무 많았다.

왜 이런 구조를 선택했는지, 어떤 실험이 실패했는지, 어느 시점의 설계가 현재 authority인지 아니면 과거 snapshot인지, 여러 AI session이 무엇을 했는지 등을 사람이 계속 머릿속에 들고 있기 어려웠다.

그래서 기록을 늘렸다.

History repository에 chronicle, project evidence, research, AI artifact를 나누고, 설계와 구현 과정에서 중요한 판단을 Git provenance와 함께 남기기 시작했다.

그런데 기록이 충분히 쌓이자 반대 문제가 나타났다.

기록이 부족하다
→ 더 이상 주된 문제가 아님

기록은 있는데 필요한 것을 빠르게 찾기 어렵다
→ 새 문제

당시 연도별 long-form 기록은 119개까지 늘어 있었다. 중요한 evidence를 잃어버리는 문제는 줄었지만, 필요한 정보를 찾기 위해 2026/ 디렉터리의 긴 파일 목록을 훑거나 큰 문서를 여러 개 다시 읽는 일이 늘었다.

처음에는 프로젝트별 디렉터리로 파일을 옮기면 해결될 것처럼 보였다.

2026/
  photogram/
  charaweave/
  paas/
  workspace/

하지만 실제로 검토해보니 문제는 storage보다 retrieval에 가까웠다.

파일 위치가 틀린 것이 아니라 보고 싶은 관점이 여러 개였다

History record 하나는 하나의 프로젝트에만 속하지 않을 수 있다.

예를 들어 어떤 기록은 Workspace Ops의 문제를 다루면서 동시에 PhotoGram에서 발생한 incident를 evidence로 사용할 수 있다. 어떤 문서는 PaaS 운영 기록이면서 블로그 글감이 될 수도 있다.

사람이 찾는 질문도 매번 다르다.

PhotoGram에서 최근 무슨 일이 있었나?
현재 accepted baseline의 provenance는 무엇인가?
architecture 관련 기록만 보고 싶다.
이 기록은 primary인가 supporting인가?
블로그로 풀 만한 chronicle은 무엇인가?
지난주에 추가된 evidence는 무엇인가?

하나의 physical directory tree가 이 모든 질문에 동시에 최적화되기는 어렵다.

파일을 프로젝트별로 옮기면 project view는 좋아질 수 있다. 대신 chronological browsing, cross-project record, 기존 locator, 과거 prompt와 handoff에서 사용한 path가 불편해질 수 있다.

그래서 문제를 다시 정의했다.

PHYSICAL STRUCTURE IS NOT IDEAL FOR EVERY VIEW
!=
PHYSICAL STRUCTURE MUST BE REWRITTEN

먼저 source가 아직 가치 있는지 봤다

기존 구조를 유지할 이유는 단순히 이동 작업이 귀찮아서가 아니었다.

History의 physical path에는 이미 provenance 가치가 있었다.

기존 Git history
과거 문서에서 참조한 path
session / handoff의 locator
날짜 기반 탐색
cross-project record
기존 blame / rename context

이걸 모두 무시하고 현재 사용하기 편한 directory taxonomy로 재배치하면 retrieval 한 종류를 개선하는 대신 다른 provenance를 약화시킬 수 있었다.

그래서 기준을 하나 세웠다.

SOURCE STRUCTURE STILL HAS PROVENANCE VALUE
+ RETRIEVAL FRICTION IS REPEATED
→ SOURCE를 먼저 보존한다

그리고 source를 바꾸지 않고 원하는 view를 만들 수 있는지를 먼저 확인했다.

선택한 구조: Normalize → Filter → Project

결국 History 위에 작은 read-only retrieval layer를 추가했다.

Markdown records
+ embedded frontmatter
+ legacy metadata overlays
        ↓
normalized catalog
        ↓
query / filter
        ↓
purpose-specific projection

원문은 그대로 둔다.

신규 문서는 Markdown frontmatter를 metadata source로 사용하고, 과거 문서는 기존 METADATA.yaml과 CLASSIFICATION.yaml overlay를 유지한다. 둘을 query 시점에 하나의 catalog로 normalize한다.

그 위에서 다음과 같은 질문을 바로 할 수 있게 했다.

history-query axis photogram
history-query primary workspace
history-query class chronicle
history-query role supporting
history-query tag architecture-atlas
history-query find 'refresh token'
history-query blog photogram

중요한 점은 catalog를 새로운 source of truth로 만들지 않았다는 것이다.

CATALOG != SOURCE
QUERY RESULT != CURRENT AUTHORITY
GENERATED VIEW != ACCEPTANCE

catalog는 원문을 선택하고 배열하기 위한 projection일 뿐이다.

INDEX도 전체 목록에서 entry point로 바꿨다

예전 INDEX.md는 사람이 읽을 수 있는 전체 목록과 class count를 직접 유지했다.

문서가 빠르게 늘어나자 이 방식은 곧 stale해졌다.

MANUAL EXHAUSTIVE INVENTORY
+ FREQUENT DOCUMENT GROWTH
= STALE NAVIGATION

그래서 INDEX의 역할도 바꿨다.

전체 파일 개수와 schema 분포 같은 기계적 정보는 CI가 계산한다. 사람이 읽는 INDEX는 어디서부터 탐색할지를 알려주는 curated navigation에 집중한다.

큰 프로젝트는 다음 순서로 읽도록 했다.

project entry point
→ accepted / operational baseline
→ architecture overview
→ question-specific supporting detail
→ evidence / chronicle / research

모든 문서를 한 번에 context에 넣는 대신 작은 overview에서 시작하고, 필요한 경우에만 아래로 내려간다.

이건 사람뿐 아니라 AI retrieval에서도 중요했다.

Git에 옮겼다고 context 비용이 사라지는 것은 아니었다

이전에 AI context를 줄이면서 비슷한 문제를 경험했다.

긴 prompt 내용을 Git 문서로 옮기면 Human이 전달하는 payload는 줄어든다. 하지만 agent가 매번 Git 문서를 처음부터 전부 다시 읽으면 실제 retrieval cost는 그대로이거나 더 커질 수 있다.

CONTEXT MOVED TO GIT
!=
CONTEXT COST ELIMINATED

History도 같았다.

기록을 잘 보존하는 것과 매번 모든 기록을 읽는 것은 다른 문제다.

그래서 목표를 다음처럼 잡았다.

PRESERVE RICH PROVENANCE
+
REDUCE DEFAULT RETRIEVAL SURFACE

정보를 덜 남기는 것이 아니라 기본적으로 읽어야 하는 정보량을 줄이는 것이다.

CI는 의미를 결정하지 않고 구조만 감시한다

retrieval layer를 붙이면서 metadata와 link가 다시 흐트러지지 않도록 CI도 추가했다.

여기서도 automation의 범위를 제한했다.

CI가 잘할 수 있는 것은 기계적인 검사다.

필수 metadata 누락
filename / date mismatch
허용하지 않는 class / role
broken curated link
너무 큰 primary 문서
한 프로젝트에 primary atlas가 과도하게 많은 상태

하지만 어떤 기록이 정말 primary인지, 어떤 설계 판단이 중요한지는 자동화가 결정하지 않는다.

MECHANICAL OBSERVATION
!= ARCHIVAL JUDGMENT

예를 들어 primary architecture document가 너무 크면 CI는 warning을 낼 수 있다. 그렇다고 자동으로 supporting으로 강등하지는 않는다.

관측과 판단을 분리하기 위해서다.

이 패턴은 Workspace에서도 이미 나타났었다

History를 정리하다 보니 흥미로운 점이 하나 있었다.

WSP에서도 이미 비슷한 원칙을 사용하고 있었다.

PHYSICAL_TREE != LOGICAL_TREE

실제 repository와 directory 구조는 그대로 존재하지만, 사용자가 보고 싶은 논리 구조는 semantic relation을 통해 별도로 projection한다.

History에서도 결과적으로 같은 모양이 나왔다.

PHYSICAL HISTORY TREE
!= RETRIEVAL VIEW

둘을 일반화하면 현재 내 작업에서는 이런 형태가 반복된다.

SOURCE / PHYSICAL STATE
        ↓ preserve
NORMALIZED SEMANTIC MODEL
        ↓
PURPOSE-SPECIFIC PROJECTION

이 패턴이 모든 시스템에 맞는다고 주장할 생각은 없다.

다만 내 작업에서는 provenance를 유지해야 하는 source가 있고, 동시에 같은 source를 여러 관점에서 봐야 하는 상황이 자주 발생한다. 그런 환경에서는 physical structure를 질문마다 다시 만드는 것보다 projection을 추가하는 방식이 잘 맞았다.

그렇다고 불편할 때마다 도구를 만드는 것은 아니다

이 방식에도 위험은 있다.

작은 불편 하나마다 CLI, catalog, index를 추가하면 retrieval을 편하게 하려다 또 다른 maintenance system을 만들 수 있다.

그래서 tooling으로 올리는 조건도 같이 정했다.

RETRIEVAL FRICTION IS REPEATED
+ SAME MANUAL RECONSTRUCTION HAPPENS AGAIN
+ SOURCE STRUCTURE STILL HAS PROVENANCE VALUE
→ SMALL READ-ONLY PROJECTION

ONE-OFF INCONVENIENCE
→ DO NOT BUILD TOOLING

그리고 새 도구는 가능한 한 다음 경계를 가진다.

READ-ONLY FIRST
NO NEW AUTHORITY
NO IMPLICIT MUTATION
NO DUPLICATE SOURCE OF TRUTH

History query CLI가 원문을 수정하지 않고 ephemeral catalog만 만드는 이유도 여기에 있다.

Projection first는 restructure never가 아니다

파일을 절대로 옮기지 않는다는 규칙도 아니다.

physical structure 자체가 correctness나 security 문제를 만들거나, build/runtime boundary가 실제 layout에 의존하거나, repository 규모 때문에 명확한 성능 문제가 생긴다면 source restructuring이 맞을 수 있다.

그래서 최종 rule은 더 좁다.

STORAGE PROBLEM
→ STORAGE CHANGE를 검토한다

RETRIEVAL PROBLEM
→ PROJECTION을 먼저 검토한다

즉:

PROJECTION FIRST
!= RESTRUCTURE NEVER

이다.

기록이 많아진 다음에야 보인 두 번째 문제

처음 History를 만들 때는 기록 부족을 해결하고 싶었다.

이제는 그 단계를 지나 기록을 얼마나 잘 검색하고 필요한 만큼만 읽을 것인가가 더 중요한 문제가 됐다.

기록 시스템의 성숙 과정도 어쩌면 다음과 비슷한 것 같다.

1. 기록이 없다
2. 기록을 남긴다
3. 기록이 많아진다
4. 찾기 어려워진다
5. source와 retrieval view를 분리한다

현재 나에게 가장 유용한 원칙은 이 문장으로 압축된다.

하나의 view가 불편해졌다는 이유만으로 provenance가 있는 source를 먼저 뜯어고치지 않는다. 문제를 storage와 retrieval로 나누고, retrieval 문제라면 작은 semantic projection부터 추가한다.

이건 아직 보편적인 engineering law가 아니다.

하지만 여러 프로젝트의 workspace와 History라는 서로 다른 영역에서 같은 방식이 반복됐다는 점에서, 적어도 내 개발 환경에서는 계속 써볼 만한 operating rule이 됐다.