운영 중인 API를 모두 모르면 조직은 무엇을 보호해야 하는지부터 틀리게 된다. 문서에 없는 테스트용 API, 이전 Version, 내부 연동, 임시 Endpoint가 계속 작동하고 있어도 보안 검토·패치·관측·사고 대응·폐기 대상에서는 빠질 수 있다. OWASP API9:2023은 이런 Inventory와 Retirement 관리의 부재가 오래된 API Version을 방치하고 민감정보 노출이나 시스템 침해 위험을 높일 수 있다고 설명한다. (OWASP)
NIST도 정확한 Inventory가 없으면 조직의 API 전체를 일관되게 보호하기 어렵다고 본다. 특히 문서화되지 않았거나 정상적인 검토 절차를 거치지 않은 API를 Shadow API, 교체됐지만 완전히 제거되지 않은 API를 Zombie 또는 Deprecated API로 설명한다. (NIST 기술 시리즈 간행물)
따라서 API Inventory는 URL을 한 번 수집해 만든 스프레드시트가 아니다. 무엇을 만들기로 선언했는지, 실제로 무엇이 배포됐는지, Runtime에서 무엇이 관측됐는지, 누가 어떤 목적으로 책임지는지를 계속 대조하는 운영 Register여야 한다. NIST도 선언된 명세와 Live Traffic을 reconciliation해 “배포된 것”과 “배포돼야 하는 것”의 차이를 찾도록 권고한다. (NIST 기술 시리즈 간행물)
1. 모르는 API가 만드는 다섯 가지 보안 공백
보호 범위에서 빠진다
정책과 점검은 대개 알고 있는 자산을 기준으로 설계된다. Inventory에 없는 API는 적용 대상 선정, 변경 검토, 취약점 대응, 관측 범위에서 빠질 가능성이 높다. 특히 내부·Debug·Test 목적으로 만들어진 Endpoint가 별도 경로로 운영 환경에 남아 있으면, 정식 API보다 약한 절차를 거쳤을 수 있다. (NIST 기술 시리즈 간행물)
오래된 Version이 계속 살아남는다
새 Version을 배포했다고 이전 Version이 자동으로 사라지는 것은 아니다. 기존 Consumer가 남아 있거나 폐기 책임자가 없으면 이전 Endpoint가 계속 호출될 수 있다. 오래된 Version은 현재 개발·검토 흐름에서 벗어나 Patch와 정책 개선을 받지 못하기 쉽다. (OWASP)
어떤 데이터가 어디로 흐르는지 모르게 된다
API Host와 Path만 알아서는 충분하지 않다. 어떤 데이터가 오가고 외부 조직이나 제3자 서비스로 전달되는지, 그 흐름이 현재도 필요한지까지 알아야 한다. OWASP는 제3자 API와 교환하는 데이터, 역할, 민감도, 업무상 필요성을 Inventory에 포함하도록 권고한다. (OWASP)
사고가 발생해도 책임자를 찾기 어렵다
API가 존재하지만 현재 책임자가 없다면 누가 차단·수정·폐기 결정을 내릴지 불명확해진다. Repository의 과거 작성자와 현재 운영 책임자는 다를 수 있다. 팀 이름만 기록돼 있어도 해당 팀이 책임을 수락하지 않았다면 Owner가 지정된 것으로 보기 어렵다.
폐기했다고 생각한 API가 다시 위험해진다
문서에서 삭제했거나 최근 Traffic이 없다는 이유만으로 폐기가 끝난 것은 아니다. DNS, Load Balancer, Runtime Route, Serverless Function, Message Consumer, 배포 Manifest 가운데 하나라도 남아 있으면 다시 호출될 수 있다. 폐기는 “안 보임”이 아니라 더 이상 도달하거나 실행할 수 없다는 Evidence로 확인해야 한다.
2. API Inventory는 네 계층을 대조해야 한다
각 계층은 서로 다른 질문에 답한다.
| 계층 | 답해야 하는 질문 | 주요 Evidence |
|---|---|---|
| Declared | 무엇을 만들고 운영하기로 했는가? | OpenAPI·AsyncAPI·.proto·GraphQL Schema·WSDL, Repository, Catalog, Route 정의, Code |
| Deployed | 실제 환경에 무엇이 배포돼 도달 가능한가? | Gateway Route, Load Balancer, DNS, Kubernetes, Service Mesh, Serverless, Runtime Route, Broker·Topic·Queue 설정 |
| Observed | 실제로 어떤 호출이나 메시지가 관측됐는가? | Access Log, Trace, Network Observation, Runtime Log, Broker Metric, First Seen, Last Seen |
| Governed | 누가 왜 책임지며 어떤 상태로 관리하는가? | Owner, Business Purpose, Data Sensitivity, Authentication Category, Exposure, Version, Lifecycle, Retirement |
4계층 Reconciliation Diagram
구조 다이어그램
API INVENTORY EVIDENCE
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Declared │ │ Deployed │ │ Observed │ │ Governed │
│ │ │ │ │ │ │ │
│ Spec │ │ Gateway / LB │ │ Access Log │ │ Owner │
│ Repository │ │ DNS │ │ Trace │ │ Purpose │
│ Catalog │ │ Kubernetes │ │ Network │ │ Sensitivity │
│ Code / Route │ │ Serverless │ │ Broker / Runtime │ │ Auth / Exposure │
│ │ │ Runtime Route │ │ Last Seen │ │ Version/Lifecycle│
└────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘
│ │ │ │
└─────────────────────┴──────────┬──────────┴─────────────────────┘
▼
┌─────────────────────────┐
│ Normalize & Correlate │
│ Stable API Identity │
│ Evidence + Confidence │
└────────────┬────────────┘
▼
┌─────────────────────────┐
│ API Register │
└────────────┬────────────┘
▼
┌──────────────┬──────────────┬──────────────┬──────────────┐
│ Managed │ Shadow │ Orphan │ Zombie │
│ │ Candidate │ Candidate │ Candidate │
└──────┬───────┴──────┬───────┴──────┬───────┴──────┬───────┘
└───────────────┴───────────────┴───────────────┘
▼
Manage / Migrate / Retire / Verify
어느 한 계층도 단독으로 완전한 Source of Truth가 될 수 없다.
OpenAPI 문서는 HTTP API의 선언을 기술할 수 있지만 실제 배포 여부나 문서에 없는 Endpoint의 부재까지 증명하지는 않는다. 2026년 8월 21일 기준 최신 공식 OpenAPI Version은 3.2.0이다. (OpenAPI Initiative Publications)
마찬가지로 Gateway Log는 해당 Gateway를 통과한 Traffic만 보여준다. 다른 Gateway, 직접 노출된 Origin, 내부 RPC, Message Broker, 관측 기간에 호출되지 않은 Endpoint, Telemetry가 누락된 경로는 보이지 않을 수 있다.
따라서 Scanner나 Discovery 제품의 결과도 하나의 Observation Source로 다뤄야 한다. NIST가 명세·Runtime·소유권·Live Traffic을 함께 대조하도록 요구한다는 점에서, 단일 도구가 100% 완전한 API Inventory를 보장한다고 보는 것은 타당하지 않다는 것이 이 글의 실무적 결론이다. (NIST 기술 시리즈 간행물)
3. REST API만 Inventory에 넣으면 안 된다
API를 HTTP Method + URL Path로만 정규화하면 REST 외 Interface가 빠진다.
| Interface 유형 | Declared Evidence | 권장 Inventory 단위 |
|---|---|---|
| HTTP·REST | OpenAPI, Route Code, Framework Annotation | Host Scope + Method + Normalized Path + Version |
| GraphQL | Schema, SDL, Introspection Snapshot | Endpoint + Operation Type + 중요 Field·Mutation |
| gRPC | Protocol Buffer .proto |
Fully Qualified Service + RPC Method + Version |
| Message-driven API | AsyncAPI, Broker Config, Producer·Consumer Code | Broker Scope + Channel·Topic·Queue + Operation + Message Type |
| SOAP | WSDL, Service Configuration | Service + Operation + Version |
| WebSocket | AsyncAPI 또는 별도 Contract | Connection Endpoint + Message Operation |
OpenAPI는 HTTP API를 위한 명세이고 Message-driven API에는 AsyncAPI 같은 별도 형식이 사용될 수 있다. gRPC는 일반적으로 .proto 파일에 Service와 RPC Method를 선언한다. (OpenAPI Initiative Publications)
이 차이는 단순 형식 문제가 아니다. 예를 들어 GraphQL은 하나의 URL 뒤에 다수의 Query와 Mutation이 존재할 수 있고 Message-driven 시스템은 HTTP Endpoint 없이도 민감한 데이터를 처리할 수 있다. Inventory 단위를 기술 방식에 맞춰 정하지 않으면 “Host는 알고 있지만 실제 Operation은 모르는” 상태가 된다.
4. 네 계층의 불일치는 무엇을 의미하는가
| 발견된 상태 | 1차 해석 | 바로 내리면 안 되는 결론 | 다음 행동 |
|---|---|---|---|
| 네 계층이 일치 | 관리 중인 API일 가능성이 높음 | 안전하다는 의미는 아님 | 현재 Owner·Lifecycle·Evidence 재확인 |
| Deployed 또는 Observed에는 있으나 Declared·Governed에 없음 | Shadow 후보 | 발견 즉시 악성 또는 불법 API라고 단정 | 배포 출처·목적·Owner 확인 후 등록 또는 제거 |
| API는 존재하지만 책임을 수락한 Owner가 없음 | Orphan 후보 | Repository 작성자가 현재 Owner라고 단정 | 업무 책임자와 기술 책임자를 별도로 지정 |
| Deprecated·Retirement Evidence가 있으나 Deployed 또는 Observed에 남음 | Zombie 후보 | 최근 Traffic이 적다는 이유만으로 Zombie 판정 | Consumer·Route·Runtime·폐기 일정 확인 |
| Declared에는 있으나 Deployed·Observed에는 없음 | 계획 중, 폐기 완료, 문서가 오래됐거나 관측 공백 | Shadow라고 판정 | 배포 이력과 문서 최신성 확인 |
| Deployed에는 있으나 Observed되지 않음 | Dormant API 또는 관측 공백 | Traffic이 없으므로 폐기됐다고 판정 | Observation Window와 Telemetry Coverage 검증 |
| Observed됐으나 배포 Source를 찾지 못함 | 알려지지 않은 Route 또는 Source Mapping 실패 | 로그 오류라고 자동 무시 | DNS·Network·Runtime·Proxy 경로까지 역추적 |
| Governed에는 Retired인데 Deployed에 남음 | 폐기 절차 실패 가능성 | 호출이 없으므로 문제없다고 판단 | 도달 가능성 제거와 Consumer Migration 확인 |
Observed와 Lifecycle은 반드시 별도 필드여야 한다.
observed_state: active, dormant, unseen, unknownlifecycle_state: active, deprecated, retiring, retired
최근 호출이 없다는 것은 관측 상태일 뿐, 폐기 의사결정이나 기술적 제거를 증명하지 않는다.
5. Shadow·Orphan·Zombie는 어떻게 구분할까
이 세 용어는 Source와 조직에 따라 범위가 달라질 수 있다. 아래 표는 NIST 문서에서 확인되는 표현과 이 글에서 사용하는 IXC Insights 실무 판정 기준을 분리한 것이다.
| 분류 | Source에서의 상태 | 이 글의 실무 판정 기준 | 판정에 불충분한 Evidence |
|---|---|---|---|
| Shadow API | NIST는 문서화되지 않았거나 정상적인 개발·검토 절차를 거치지 않은 내부·Debug·Test·Ad hoc API 등을 Rogue 또는 Shadow API로 설명한다. (NIST 기술 시리즈 간행물) | Deployed 또는 Observed Evidence가 있지만 승인된 Declared·Governed Record와 연결되지 않은 API | 오래된 Spec 하나, Owner가 잠시 응답하지 않은 상태 |
| Orphan API | NIST의 Reconciliation 권고에는 orphaned endpoint가 열거되지만 이 글에서 검토한 해당 문서에는 별도의 독립 정의가 제시되지 않는다. (NIST 기술 시리즈 간행물) |
API가 존재하지만 현재 변경·사고 대응·폐기를 결정할 책임자가 지정되고 수락한 상태가 아님 | 과거 작성자 퇴사, 팀 이름만 누락, 한 차례 연락 실패 |
| Zombie API | NIST는 교체·대체됐지만 Consumer 미이전이나 책임 부재 등으로 완전히 제거되지 않은 API를 Zombie 또는 Deprecated API로 설명한다. (NIST 기술 시리즈 간행물) | Deprecated·Retirement·Replacement 의도가 확인됐으나 여전히 배포돼 있거나 도달·호출 가능한 API | 최근 Traffic이 적음, last_seen이 오래됨, 문서에서만 삭제됨 |
세 분류는 서로 배타적이지 않다.
- 문서에 없는 API가 Owner도 없다면 Shadow이면서 Orphan일 수 있다.
- 폐기 대상 API가 Owner 없이 남아 있다면 Zombie이면서 Orphan일 수 있다.
- 분류는 자동 삭제 명령이 아니라 조사가 필요한 운영 상태다.
6. API Register의 최소 Schema
URL만 저장하는 Register로는 Reconciliation을 수행할 수 없다. 최소한 다음 정보가 필요하다.
| 그룹 | 최소 필드 | 목적 |
|---|---|---|
| Identity | api_id, name, direction, protocol_style, interface_key, version |
서로 다른 Source의 Record를 같은 API에 연결 |
| Declared | spec_type, spec_ref, repository_ref, spec_digest, declared_at |
기대되는 Contract와 변경 이력 확인 |
| Deployed | environment, exposure, runtime_ref, deployed_version, deployment_state, last_deployed_at |
실제 도달 가능한 Runtime 파악 |
| Observed | observation_sources, first_seen_at, last_seen_at, observation_window, observation_confidence, observed_state |
무엇이 언제 어떤 Source에서 관측됐는지 기록 |
| Ownership | accountable_owner, technical_owner, owner_attested_at |
업무·기술 책임과 확인 시점 분리 |
| Purpose & Data | business_purpose, business_criticality, data_classification, data_flows |
API의 필요성과 데이터 위험 판단 |
| Access Context | authentication_category, expected_access, exposure |
Credential 자체가 아닌 접근 방식과 예상 Caller 범위 기록 |
| Lifecycle | lifecycle_state, deprecation_at, retirement_target, replacement_ref |
Version 교체와 폐기 추적 |
| Reconciliation | reconciliation_status, findings, evidence_refs, checked_at, next_review_at |
불일치, 근거, 후속 검토 관리 |
| Register Security | record_classification, export_policy, credential_material_present |
Inventory 자체의 민감도와 Export 통제 |
OWASP도 Host별 Environment, Network Access, Version과 제3자 서비스의 역할·교환 데이터·민감도를 Inventory에 포함하도록 권고한다. NIST는 Specification, Ownership, Runtime Information을 함께 관리하고 Live Traffic과 대조할 것을 요구한다. (OWASP)
Vendor-neutral YAML 예시
아래 Record는 구조를 설명하기 위한 가상 예시다. 실제 조직의 Host, Endpoint, Credential, 운영 정보와 관계없다.
yaml 예시
api_id: api:fulfillment:inventory-sync:v1
identity:
name: inventory-sync
direction: provided
protocol_style: grpc
interface_key: fulfillment.InventorySyncService
version: v1
declared:
spec_type: protobuf
spec_ref: repo://contracts/fulfillment/inventory_sync.proto
repository_ref: repo://services/fulfillment
spec_digest: sha256:<digest>
declared_at: "<timestamp>"
deployed:
- environment: production
exposure: internal
runtime_ref: platform://production/fulfillment/inventory-sync
deployed_version: v1
deployment_state: running
last_deployed_at: "<timestamp>"
observed:
observation_sources:
- service_mesh_trace
- runtime_log
first_seen_at: "<timestamp>"
last_seen_at: "<timestamp>"
observation_window: "<window>"
observation_confidence: medium
observed_state: active
governed:
accountable_owner: team:fulfillment
technical_owner: team:platform-runtime
owner_attested_at: "<timestamp>"
business_purpose: 재고 동기화
business_criticality: high
data_classification: internal
authentication_category: workload_identity
expected_access: internal-services
lifecycle_state: active
deprecation_at: null
retirement_target: null
replacement_ref: null
reconciliation:
status: managed
findings: []
evidence_refs:
- evidence:declared:<id>
- evidence:deployed:<id>
- evidence:observed:<id>
checked_at: "<timestamp>"
next_review_at: "<timestamp>"
security:
record_classification: restricted
export_policy: approval-required
credential_material_present: false
authentication_category에는 인증 방식의 범주만 기록한다. Token, Secret, Private Key, Cookie 값, Connection String을 Register에 복사해서는 안 된다.
7. Initial Inventory Checklist
처음 API Inventory를 만들 때는 다음 순서로 범위를 닫는 것이 좋다.
- Public·Partner·Internal API를 모두 조사 범위에 넣었는가
- Production뿐 아니라 Staging·Test·Preview·Legacy Environment도 포함했는가
- 제공하는 API와 외부에서 소비하는 API를 모두 포함했는가
- HTTP·REST뿐 아니라 GraphQL·gRPC·SOAP·WebSocket·Message-driven API를 포함했는가
- API를 어떤 단위로 식별할지 정했는가
- Spec, Repository, Catalog, Route Code 등 Declared Source를 수집했는가
- DNS, Load Balancer, Kubernetes, Serverless, Runtime Route 등 Deployed Source를 수집했는가
- Log, Trace, Network, Broker 등 Observed Source와 Observation Window를 기록했는가
- 동일 API의 Environment·Version·Alias를 정규화했는가
- 업무 책임자와 기술 책임자를 분리해 지정했는가
- Business Purpose, Data Sensitivity, Data Flow, Exposure를 분류했는가
- Deprecated·Retiring·Retired 상태와 Replacement를 기록했는가
- Shadow·Orphan·Zombie 후보를 자동 삭제하지 않고 조사 Queue로 보냈는가
- Register 접근 권한·Export 정책·감사 기록을 설정했는가
- Credential Material이 Register에 포함되지 않았음을 확인했는가
- 다음 Reconciliation Trigger와 검토 책임자를 정했는가
8. Continuous Reconciliation Workflow
Inventory는 초기 조사보다 이후 유지가 더 어렵다. 변경이 발생할 때 Register도 함께 갱신되도록 해야 한다.
| Trigger | 대조할 계층 | 자동 또는 수동 확인 |
|---|---|---|
Spec·Schema·.proto 변경 |
Declared ↔ Governed | Version, Owner, Lifecycle, 영향 범위 |
| Repository Merge | Declared ↔ Deployed | Route 추가·삭제가 배포 Manifest와 일치하는지 |
| Deploy·Rollback | Deployed ↔ Declared | 배포 Version과 선언 Version의 차이 |
| DNS·LB·Gateway·Kubernetes·Serverless 변경 | Deployed ↔ Governed | 새 노출 경로와 승인된 Exposure의 차이 |
| 새로운 Runtime Traffic·Trace 관측 | Observed ↔ Declared·Deployed | 미등록 Interface 또는 예상 밖 Caller |
| 조직 개편·Team Ownership 변경 | Governed ↔ 전체 | Owner가 현재도 책임을 수락하는지 |
| Deprecation·Sunset Date 도래 | Governed ↔ Deployed·Observed | 폐기 대상이 여전히 배포·호출되는지 |
| 정기 Attestation | 네 계층 전체 | Purpose, Sensitivity, Version, Owner, Evidence 최신성 |
검토 주기를 모든 API에 똑같이 적용할 필요는 없다. 외부 노출, 높은 데이터 민감도, 변경 빈도, 업무 중요도가 높은 API는 더 빠른 Reconciliation이 필요하다. 반대로 변경이 적고 격리된 API라도 Owner와 Lifecycle Evidence가 영구히 유효한 것은 아니다.
9. 발견에서 관리·폐기까지의 Workflow
1. 발견
새 API 후보와 함께 발견 Source, 시각, Environment, 원시 Evidence를 보존한다.
API가 발견됐다와 API의 정체를 안다는 다른 상태다.
2. 정규화
서로 다른 Source에서 같은 API가 다르게 표현될 수 있다.
- REST: Method + Normalized Path + Host Scope
- GraphQL: Endpoint + Operation Type + 중요 Field
- gRPC: Fully Qualified Service + Method
- Message-driven: Broker Scope + Channel·Topic·Queue + Operation
Environment와 Version은 Identity에서 분리해 비교할 수 있어야 한다.
3. 상관관계 확인
Declared·Deployed·Observed Record가 같은 API를 가리키는지 연결한다. 자동 매칭 결과에는 Confidence를 남기고 서로 충돌하는 Evidence를 조용히 덮어쓰지 않는다.
4. Owner 할당
업무상 필요성을 판단할 accountable_owner와 구현·운영을 담당할 technical_owner를 구분한다.
현재 책임자가 없으면 Orphan 후보로 분류하고 Escalation한다. Owner가 없다는 이유만으로 즉시 삭제하면 여전히 사용하는 Consumer나 업무를 중단시킬 수 있다.
5. 분류
다음을 확인한다.
- 제공·소비 방향
- Public·Partner·Internal Exposure
- Business Purpose
- Data Classification과 외부 Data Flow
- Authentication Category
- Version과 Lifecycle
- Shadow·Orphan·Zombie 후보 여부
6. 관리 또는 전환 결정
정상적으로 필요한 API라면 Register, Spec, Owner, 관측 범위에 편입한다. 중복되거나 오래된 API라면 Consumer Migration, Replacement, Retirement Plan을 만든다.
7. 폐기 실행
폐기는 문서에서 지우는 작업이 아니다.
- 호출 Consumer 이전
- Route와 DNS 제거
- Runtime Resource 중지
- Credential·권한·연동 관계 폐기
- Spec·Catalog·운영 문서 갱신
- 관측 Source에서 예상 밖 호출 확인
- Rollback·예외 계획 종료
를 함께 확인해야 한다.
8. 폐기 검증
last_seen만으로 폐기 완료를 선언하지 않는다. Deployed Evidence에서 도달 가능성이 제거됐고 Governed Record가 Retired로 승인됐으며 필요한 Consumer Migration이 끝났다는 Evidence가 있어야 한다.
10. API Inventory 자체도 민감한 자산이다
잘 만든 API Inventory는 공격자에게도 유용하다. 내부 Host와 Environment, Version, Service 이름, Owner, 인증 범주, Data Classification, 외부 Data Flow, Retirement 상태가 모이면 조직의 공격 표면을 설명하는 지도에 가까워진다.
Register와 공개 API 문서를 같은 것으로 취급해서는 안 된다.
- 역할별 최소 권한으로 접근을 제한한다.
- 조회 권한과 Export 권한을 분리한다.
- Export에는 승인, 감사 기록, 보존 기간을 둔다.
- Public Documentation과 Internal Register를 분리한다.
- Token·Secret·Private Key 등 Credential Material은 저장하지 않는다.
- 필요한 경우 Secret Manager의 비민감 Reference만 연결한다.
- API Record와 첨부 Evidence에 Data Classification을 적용한다.
- 외부 공유본에서는 내부 Runtime Reference와 Owner 정보를 제거한다.
OWASP는 API 문서를 권한 있는 사용자에게만 제공하도록 권고하며 OpenAPI도 문서의 일부를 접근 권한에 따라 감추는 Security Filtering을 명시한다. (OWASP)
API Inventory의 완료 조건
API Inventory는 모든 URL을 한 번 수집했다고 끝나지 않는다.
다음 질문에 Evidence로 답할 수 있어야 한다.
- 무엇이 존재하는가
- 어디에 배포돼 있는가
- 어떤 Protocol과 Version인가
- 최근 무엇이 관측됐는가
- 누가 책임지는가
- 왜 필요한가
- 어떤 데이터를 처리하는가
- 누구에게 노출돼야 하는가
- 현재 Lifecycle은 무엇인가
- 언제 어떻게 폐기할 것인가
- 네 계층이 서로 일치하는가
어떤 Spec도, Gateway Log도, Scanner도 이 질문 전체에 혼자 답할 수 없다. API Inventory의 실체는 목록이 아니라 불일치를 계속 발견하고 해소하는 운영 과정이다.
Inventory가 충분히 완성되고 최신 상태가 유지돼야, 각 API의 위협과 데이터·노출 조건에 맞는 통제를 결정할 수 있다. 그 다음 단계는 상위 Article인 「WAF·API Gateway·Rate Limit·Schema Validation·JWT·mTLS는 각각 무엇을 막는가」에서 다룬다.