Skip to content

Troubleshooting

JEONG edited this page Sep 7, 2026 · 1 revision

트러블슈팅

증상별로 정리했습니다. 대부분은 경로·글로브·git 히스토리 셋 중 하나입니다.


스캔이 시작도 못 함

메시지 원인 조치
--openapi-url or --openapi-file required 스펙 소스를 안 줬습니다 둘 중 하나를 넘기세요. 둘 다 주면 --openapi-file 이 이깁니다
at least one of --app-product / --umc-app required 스캔할 프로젝트가 없습니다 최소 한 개는 필요합니다
auth-env vars not set: A:B --auth-env 가 가리킨 환경변수가 비어 있습니다 --auth-env 는 값이 아니라 변수 이름 두 개를 받습니다. export A=... B=... 후 다시 실행

스펙을 못 읽음

HTTP 상태 오류 — 2xx 가 아니면 바로 끊습니다. 인증이 필요한 스펙이면 --auth-env USER_VAR:PASS_VAR 로 Basic 인증을 붙이세요.

export UMC_API_USER=... UMC_API_PASS=...
swift run apicov scan --openapi-url https://.../docs-json --auth-env UMC_API_USER:UMC_API_PASS ...

파싱 실패 — 파서는 JSON 만 받습니다. openapi.yaml 은 못 읽으니 JSON 으로 변환해서 주세요. info.title · info.version · paths 중 하나라도 없으면 missingField 로 끊습니다.

네트워크가 불안하면 스펙을 한 번 내려받아 --openapi-file 로 고정하는 편이 재현하기 좋습니다.

curl -u "$UMC_API_USER:$UMC_API_PASS" https://.../docs-json -o spec.json
swift run apicov scan --openapi-file spec.json ...

커버리지가 0% 이거나 결과가 텅 빔

거의 항상 Router 파일이 글로브에 안 걸린 경우입니다. 걸리지 않은 파일은 "매치 안됨"에도 안 나오고 그냥 없는 셈이 됩니다.

프로젝트 glob
--app-product **/Router/*Router.swift
--umc-app **/Data/Sources/*Router.swift

직접 세어보세요.

find ../umc-product-iOS/AppProduct -path "*/Router/*Router.swift" | wc -l
find ../umc-product-iOS/UMCApp -path "*/Data/Sources/*Router.swift" | wc -l

0 이 나오면 경로가 틀렸거나 파일 이름이 ...Router.swift 로 끝나지 않는 겁니다. 패턴 자체를 바꿔야 한다면 개발 가이드 를 보세요.

숨김 디렉터리 안의 파일은 탐색에서 제외됩니다.

case 는 있는데 "매치 안됨"으로 빠짐

unmatchedRouterCases[].reason 이 어느 쪽인지 먼저 확인하세요.

missing path or method arm

pathmethod 의 해당 갈래를 못 읽었습니다. 파서는 갈래가 return 문 하나로 문자열 리터럴을 돌려주는 형태만 읽습니다.

// 읽힙니다
case .detail: return "/notices/\(id)"

// 안 읽힙니다 — 중간 변수, 삼항 연산자, 함수 호출
case .detail:
    let base = "/notices"
    return base + "/\(id)"

var path: String 은 타입이 정확히 String 이어야 하고 var method 는 타입 이름이 Method 로 끝나야 합니다. enum 이름도 Router 로 끝나거나 TargetType/BaseTargetType 을 상속해야 인식합니다.

코드를 못 고치는 상황이면 overrides.yml 로 직접 지정하세요.

no OpenAPI entry for GET /some/path

정규화까지는 됐는데 스펙에 같은 엔드포인트가 없습니다. 메시지에 찍힌 경로가 정규화 후 값이라는 점이 중요합니다.

  • 서버 프리픽스가 빠졌거나 (/api/v1 등) 붙었거나
  • 스펙과 코드의 파라미터 이름이 다르면 — 이건 템플릿 매칭이 흡수합니다. {id} vs {noticeId} 는 통과합니다
  • 진짜로 스펙에 없는 외부 API 라면 overrides.yml 에서 ignore 로 빼세요
- routerCase: KakaoRouter.searchAddress
  ignore: 외부 API — 스펙에 없음

ignored: ...

의도적으로 제외한 항목입니다. 문제가 아닙니다. 다만 summary.unmatched 에는 함께 잡히니 수치를 볼 때 감안하세요.

작성자가 전부 Unknown

git blame 이 실패하면 연결은 남고 작성자만 Unknown, SHA 는 빈 문자열, 날짜는 1970 년이 됩니다. 스캔은 멈추지 않으므로 조용히 지나갑니다.

원인 확인
CI 가 얕은 클론을 함 actions/checkoutfetch-depth: 0 이 있는지
--blame-root 가 git 레포가 아님 해당 디렉터리에서 git rev-parse --show-toplevel
파일이 아직 커밋 안 됨 git status
--blame-root 와 프로젝트 경로가 다른 레포 blame 은 --blame-root 에서 실행되고 filePath 도 그 기준입니다

커버리지 숫자가 너무 후함

summary.matched매치된 Router case 수입니다. 연결된 엔드포인트 수가 아닙니다. 서로 다른 case 두 개가 같은 엔드포인트에 매치되면 matched 는 2 로 잡히고 missing 이 그만큼 줄어듭니다. HTML 리포트의 퍼센트도 이 값을 그대로 씁니다.

중복 매핑이 의심되면 스냅샷에서 직접 세어보세요.

python3 -c "
import json,collections
d=json.load(open('coverage.json'))
c=collections.Counter()
for e in d['endpoints']:
    for p,conn in e['connections'].items():
        if conn: c[p]+=1
print('실제 연결된 엔드포인트 수:', dict(c))
print('summary.matched:', {k:v['matched'] for k,v in d['summary'].items()})
"

두 숫자가 다르면 그 차이만큼 중복입니다.

YAML 을 안 먹음

로더가 실패하면 invalidYAML 과 함께 사유를 던집니다.

사유
missing routerCase overrides.yml 항목에 routerCase 키가 없음
routerCase must be 'Enum.case': ... NoticeRouter.detail 처럼 점 하나로 구분해야 합니다
openAPI override requires method and path remap 대상에 둘 다 필요합니다
unsupported HTTP method: ... GET·POST·PUT·PATCH·DELETE 만 됩니다

파일 자체를 못 찾으면 fileNotFound 입니다. 상대 경로는 현재 작업 디렉터리 기준으로 풀립니다.

Fixtures/overrides.yml 은 비어 있는 게 정상입니다. 여기에 운영 규칙을 넣으면 테스트가 깨집니다 — 레포 루트의 overrides.yml 에 넣으세요.

Stella 앱 문제

경로가 이상한 값으로 채워져 있음 — 앱의 기본 경로는 아직 레포를 분리하기 전 배치(<루트>/Stella/*.yml)를 가정합니다. 첫 실행 때 설정 화면에서 네 경로(AppProduct · UMCApp · blame 루트 · YAML) 를 직접 잡아주세요. 한 번 고치면 UserDefaults 에 남습니다.

에러 메시지가 StellaCore.StellaError error 3. 같이 나옴StellaErrorLocalizedError 를 채택하지 않아서입니다. 같은 스캔을 CLI 로 돌리면 원인이 그대로 보입니다.

토큰이 안 남음 — 토큰은 UserDefaults 가 아니라 Keychain 에 들어갑니다 (서비스 kr.it.umc.apicoverage, 계정 bearerToken). 키체인 접근 권한을 거부했으면 저장이 안 됩니다.

앱이 안 열림 / 손상됐다고 나옴scripts/build-app.sh 는 ad-hoc 서명만 합니다. 로컬 실행용이라 다른 기기로 복사하면 Gatekeeper 에 걸립니다. 받는 쪽에서 직접 빌드하는 게 빠릅니다.

diff 가 아무것도 안 잡음

apicov diffold 를 먼저, new 를 나중에 받습니다. 순서를 바꾸면 부호가 뒤집힙니다.

비교하는 건 connectionsnull ↔ 값 전환뿐입니다. 같은 엔드포인트가 다른 case 로 옮겨간 경우, 작성자만 바뀐 경우는 변화로 잡히지 않습니다.

빌드가 안 됨

swift package reset && swift build

Swift 6.0 이상, macOS 15 이상이 필요합니다. swift --version 으로 확인하세요. CI 에서는 Xcode 26.4 이상을 명시적으로 선택합니다.


여기 없는 문제라면 이슈 에 스캔 명령줄과 unmatchedRouterCases 일부를 붙여 올려주세요.


관련: CLI 레퍼런스 · 매칭 파이프라인 · 매핑 YAML