옵시디언 위키, 분류 체계 통합
회사에서 QA 자동화 에이전트를 만들면서 하루 종일 삽질한 날이 있었다.
이날 딱 두 가지 큰 작업을 했다.
옵시디언 위키 정리하고 QA Agent 파이프라인을 갈아엎었다.
둘 다
별개 작업인데 하루에 몰아서 하느라 꽤 빡셌다.
그 전까지 옵시디언 노트에 frontmatter를 두 개 필드로 나눠 쓰고 있었다.
type이랑 area. 근데 노트가 쌓이다
보니까 이분법이 잘 안 먹힌다.
하나의 노트가 프로젝트 기록이면서 동시에 journal 성격도 띄고 그러면 type에 뭘 넣어야 할지 애매해진다.
결국 category 단일 필드 하나로 합쳤다.
하나만 쓰는 게 분류하거나 검색할 때 훨씬 직관적이더라. type 필드는 있어야 할 때도 있긴 한데, 내 사용 패턴에서는 오히려 분기를 만들어서 복잡도만 늘렸다.
그리고 같은 날 Linux 서버에 옵시디언 LiveSync 환경을 구축했다.
CouchDB를 올리고 Cloudflare Tunnel로 외부에서 접근 가능하게 만들었다.
이걸로 집 데스크탑이랑 노트북이랑 폰이랑 노트가 실시간으로 동기화된다.
공식 Obsidian 동기화 서비스가 있긴 한데 유료라서 self-hosted로 해결했다.
공식 CLI가 자꾸 비정상 종료돼서 결국 파일 직접 편집으로 fallback했다. 이건 추후에 다시 봐야 할 문제다.
QA Agent 파이프라인 재구성
이건 본업이고, 시간도 더 많이 썼다.
QA Agent는 Slack에서 테스트 대상 URL이랑 시트 정보를 받아서 브라우저로 자동 테스트를 돌리는 에이전트다.
그 전에는 실행 흐름이 좀 난잡했다.
파이프라인 단계가 명확하게 나뉘어 있지 않아서 어디서 문제가 생겼는지 디버깅하기가 어려웠다.
0_intake부터 7_cleanup까지
실행 흐름을 8단계로 재배치했다.
0_intake— Slack 메시지에서 테스트 대상 URL, 시트 정보 수집 -1_normalize— 테스트케이스를 공통 형식으로 변환2_bootstrap— 브라우저 프로필, 런타임 준비 -3_planning— Planner가 실행 계획 수립4_execution— Executor가 실제 테스트 실행 -5_inspection— blocked 케이스 원인 분석6_reporting— 결과 취합, Slack 업데이트 -7_cleanup— 브라우저 세션 정리
각 단계마다 명확한 입력과 출력을 정의해뒀다.
이렇게 하니까 특정 단계에서 실패했을 때 어디서 끊겼는지 바로 알 수 있었다.
그리고 smoke 실행 — 전체 파이프라인 한 번 가볍게 돌려보는 검증 — 이 훨씬 안정적으로 돌아갔다.
Fixture Knowledge를 SQLite로
이날 두 번째 큰 작업. QA Agent가 테스트 돌리면서 얻은 지식 — 예를 들면 특정 URL의 fixture 데이터, 역할, 시트 맥락 — 을 저장하는 시스템을 JSON에서 SQLite로 전환했다.
기존 JSON 구조는 케이스 번호 기준이었다.
그러니까 똑같은 URL이 다른 케이스에서 등장해도, 이전에 학습한 fixture를 재사용할 수가 없다.
매번 새로 학습하는 게 비용이 꽤 컸다.
SQLite로 바꾸면서 URL 기준으로 fixture를 조회하게 만들었다.
같은 URL이면 이전 케이스에서 축적한 fixture knowledge를 그대로 가져다
쓸 수 있다.
qa_lookup_fixture_knowledge라는 도구를 만들어서 Executor가 실행 전에 이전 지식을 조회하도록 했다.
그리고 케이스별 진실 소스(source of truth)는 status.json으로 유지하면서 세션 단위 집계는 fixtures.json으로 분리했다.
무엇이 durable knowledge고 무엇이 임시 기록인지 경계를 명확히 한 게 핵심이다.
마무리
하루에 위키 정리까지, 파이프라인 재구성까지 하려니까 빡세긴 했다.
근데 둘 다
결과적으로 잘한 선택이었다.
category 단일 필드는 이후 노트 관리가 확실히 편해졌고 QA Agent 파이프라인도 8단계 분리 이후로 디버깅과 smoke 실행이 훨씬 나아졌다.
Fixture Knowledge의 SQLite 전환은 특히 체감이 크다.
같은 페이지에 대한 QA를 반복할 때, 이전에 알아낸 걸 매번 다시 학습하지 않아도 되니까 실행 시간도 줄고 토큰도 아낄 수 있었다.