Feature Chain — operationId 하나로 풀스택을 추적한다

기능 하나를 수정하려면 어떤 파일들을 건드려야 하는가? operationId 하나를 입력하면 답이 나온다.


문제

풀스택 애플리케이션에서 “기능 하나"는 하나의 파일에 없다.

“제안 수락(AcceptProposal)“이라는 기능을 수정해야 한다고 해보자. 이 기능은 API 스펙에도 있고, 서비스 로직에도 있고, 데이터베이스 스키마에도 있고, 인가 정책에도 있고, 상태 전이 다이어그램에도 있고, 외부 함수 호출에도 있고, 테스트 시나리오에도 있고, 프론트엔드에도 있다.

기존에 이 전체 범위를 파악하는 방법은 두 가지였다:

  1. Grep을 수십 번 돌린다
  2. 코드를 수동으로 추적한다

둘 다 느리고, 둘 다 누락이 생긴다. 특히 레이어를 넘나드는 참조 — API 스펙에서 서비스로, 서비스에서 DB 스키마로, 서비스에서 인가 정책으로 — 를 사람이 빠짐없이 추적하는 것은 현실적으로 어렵다.

그런데 만약 각 레이어의 소스가 다른 레이어를 심볼릭하게 참조하고 있다면, 그 참조를 따라가는 것만으로 전체 범위가 자동으로 드러난다.


Feature Chain이란

Feature Chain은 하나의 API 기능(operationId)에 연결된 모든 소스 노드를 추출한 것이다.

operationId 하나를 시작점으로, 소스 간 심볼 참조를 따라가며 관련된 모든 파일과 라인 번호를 한 번에 출력한다. Grep 수십 번이 한 번의 명령어로 대체된다.

fullend chain AcceptProposal specs/
── Feature Chain: AcceptProposal ──

  OpenAPI    api/openapi.yaml:296                          POST /proposals/{id}/accept
  SSaC       service/proposal/accept_proposal.ssac:19      @get @empty @auth @state @put @call @post @response
  DDL        db/gigs.sql:1                                 CREATE TABLE gigs
  DDL        db/proposals.sql:1                            CREATE TABLE proposals
  DDL        db/transactions.sql:1                         CREATE TABLE transactions
  Rego       policy/authz.rego:3                           resource: gig
  StateDiag  states/gig.md:7                               diagram: gig → AcceptProposal
  StateDiag  states/proposal.md:6                          diagram: proposal → AcceptProposal
  FuncSpec   func/billing/hold_escrow.go:8                 @func billing.HoldEscrow
  Gherkin    scenario/gig_lifecycle.feature:4              Scenario: Happy Path - Full Gig Lifecycle
  Gherkin    scenario/gig_lifecycle.feature:42             Scenario: Unauthorized Access

기능 하나의 전체 구조가 한 화면에 보인다. 연결되지 않는 레이어는 출력하지 않는다.


왜 가능한가

이것은 마법이 아니다. 소스가 이미 서로를 참조하고 있기 때문에 가능하다.

fullend 프레임워크에서 각 SSOT(Single Source of Truth) 레이어는 다른 레이어를 심볼릭하게 가리킨다:

  • SSaC@get Model.Method → DDL 테이블
  • SSaC@auth action resource → Rego 인가 정책
  • SSaC@state diagramID → Mermaid 상태 다이어그램
  • SSaC@call pkg.Func → Func Spec 구현체
  • OpenAPI의 operationId → SSaC 파일명
  • Gherkin의 action step → operationId
  • STML의 endpoint → OpenAPI path

이 참조들은 원래 crosscheck — SSOT 간 정합성을 검증하는 도구 — 를 위해 설계됐다. crosscheck가 이미 이 참조들을 파싱하고 있으므로, 같은 인프라를 재활용하면 그래프 탐색만으로 feature chain이 추출된다.


탐색 경로

operationId를 시작점으로 잡으면, 참조 그래프는 이렇게 펼쳐진다:

operationId (시작점)
├── OpenAPI → path + method
├── SSaC → 서비스 함수 파일
│   ├── @get → DDL 테이블들
│   ├── @auth → Rego 정책 규칙
│   ├── @state → Mermaid stateDiagram 전이
│   ├── @call → Func Spec 구현체
│   └── @publish → 큐 구독자
├── Gherkin → operationId를 참조하는 시나리오들
└── STML → endpoint를 참조하는 프론트엔드 파일

각 가지는 한 단계의 심볼 참조만 따라간다. 깊이가 아니라 너비가 넓은 탐색이다. 하나의 기능이 어떤 레이어에 흔적을 남기는지가 전부 드러난다.


이것이 바꾸는 것

수정 범위 파악

“이 기능을 고치려면 어디를 건드려야 하지?”

이 질문에 대한 답을 얻기 위해 우리는 코드를 읽고, grep을 돌리고, 동료에게 물어본다. Feature Chain은 이 질문을 명령어 하나로 대체한다. 빠져나간 파일이 없다 — 심볼 참조가 있는 한.

AI 코드 수정

AI에게 기능 수정을 맡길 때 가장 어려운 것은 “수정 범위를 알려주는 것"이다. 컨텍스트 윈도우에 관련 파일을 모두 넣어야 AI가 정확하게 수정할 수 있는데, 어떤 파일이 관련되는지를 사람이 판단해야 한다.

Feature Chain이 있으면 다르다. operationId 하나만 알려주면 전체 수정 범위가 자동으로 식별된다. AI에게 넘길 컨텍스트가 누락 없이 준비된다.

코드 리뷰

PR을 리뷰할 때 “이 기능을 수정했으면 저 파일도 바뀌어야 하는 거 아닌가?“라는 의심을 chain과 대조하면 바로 확인할 수 있다. 레이어 간 불일치를 사람 대신 구조가 잡아준다.

온보딩

새로 합류한 개발자가 “AcceptProposal이 어떻게 동작하는지 알고 싶어요"라고 할 때, Feature Chain 하나를 보여주면 된다. API부터 DB까지, 인가 정책부터 테스트 시나리오까지 — 기능의 전체 지형이 한눈에 보인다.


왜 operationId인가

시작점을 무엇으로 잡느냐가 중요하다. Feature Chain은 operationId를 선택했다.

이유는 간단하다. 풀스택 애플리케이션에서 기능의 단위는 API 엔드포인트다. 사용자가 버튼을 누르면 API가 호출되고, 그 API가 서비스 로직을 실행하고, DB를 읽고, 인가를 확인하고, 상태를 전이시킨다. 이 모든 흐름의 시작점이 operationId다.

operationId는 이미 OpenAPI 스펙에 정의되어 있고, 팀 전체가 공유하는 이름이다. “AcceptProposal을 수정해야 한다"고 말하면 백엔드 개발자도, 프론트엔드 개발자도, QA도 같은 것을 떠올린다. 이 보편적인 이름 하나로 전체 스택을 관통하는 것이 Feature Chain의 설계다.


전제 조건

Feature Chain이 작동하려면 전제가 있다:

  1. 소스가 심볼릭하게 서로를 참조해야 한다. SSaC의 @get, @auth, @state, @call 디렉티브가 다른 SSOT를 명시적으로 가리키고 있어야 한다. 참조가 암묵적이면 — 예를 들어 DB 테이블명이 코드 안에 문자열로만 존재하면 — 추적할 수 없다.

  2. crosscheck를 통과해야 한다. Feature Chain은 심볼 참조를 따라가므로, 참조가 유효하지 않으면 잘못된 결과가 나온다. crosscheck가 참조의 정합성을 보장하고, Feature Chain은 그 위에서 탐색한다.

이것이 Feature Chain이 범용 도구가 아닌 이유다. 아무 프로젝트에나 적용할 수 없다. 소스 간 참조가 설계된 프로젝트 — fullend처럼 SSOT가 서로를 명시적으로 가리키는 구조에서만 작동한다.


미래: GEUL + SILK

현재 Feature Chain은 각 SSOT 파서를 순회하며 탐색한다. SSaC 파서, DDL 파서, Rego 파서, Mermaid 파서를 각각 호출하고 결과를 조합한다.

모든 SSOT가 GEUL 그래프로 변환되면, Feature Chain은 단일 인덱스 쿼리가 된다. SILK의 SIDX 비트와이즈 AND 연산으로, operationId에 연결된 모든 노드를 한 번의 쿼리로 추출할 수 있다.

파서별 순회에서 그래프 쿼리로. Feature Chain의 인터페이스는 같지만, 내부는 근본적으로 달라진다.


정리

풀스택 애플리케이션에서 “기능"은 하나의 파일에 있지 않다. 여러 레이어에 걸쳐 있고, 그 레이어들은 서로를 참조한다. Feature Chain은 이 참조를 따라가서 기능 하나의 전체 범위를 자동으로 추출한다.

operationId 하나를 입력하면, API 스펙부터 DB 스키마까지, 인가 정책부터 테스트 시나리오까지 — Grep 수십 번이 명령어 하나로 대체된다.

코드: github.com/park-jun-woo/fullend