Conversation
./gradlew test --tests '…security.SecurityConfigTest' 가 혼자 돌면 빨갰다. CLAUDE.md 가
그 명령 형태를 공식으로 적어 뒀고, 정책 파일을 만지는 사람이 가장 먼저 치는 것이 그
명령이라 자기 변경과 무관한 빨강을 본다.
Dev.permitsEverything 이 /products/{id}/risk-items 를 친다
→ 그 경로는 저장된 추출이 DB 에 있어야 200 이다(#478 이 MockData 폴백을 걷은 뒤)
→ 전체 실행에서는 앞선 테스트가 H2 에 남긴 것 덕에 초록
→ 단독 실행에서는 404
실측 단독 실행 전: Status expected:<200> but was:<404>
후: BUILD SUCCESSFUL
❗바로 옆 Prod.allowsAuthenticated 가 같은 이유로 이미 고쳐져 있었다(#478) —
"인증을 재는 테스트가 카탈로그 상태 때문에 빨개지면 재는 것과 깨지는 이유가 달라진다".
형제 쪽만 안 따라왔다.
- Dev 는 이제 Prod.rejectsAnonymous 와 같은 세 경로를 보고, 거기서 401 이 아닌 것만
단정한다. 상태를 200 으로 못 박지 않는 이유는 404 든 200 이든 인증 때문이 아니면
통과가 이 테스트의 뜻이기 때문이다
- 체인이 아예 안 서는 것(전부 500)과 구별하려고 /products 200 을 하나 남겼다 — 목록은
비어도 200 이라 데이터에 안 걸린다
- 경로 목록을 GUARDED_PATHS 한 벌로 뒀다. 대조는 짝으로만 성립한다 — prod 에서 401 인
것과 dev 에서 401 이 아닌 것이 같은 경로여야 "프로파일이 가른다" 가 증명되고, 따로
적으면 한쪽만 늘어난 것을 아무도 모른다
역검증:
dev 체인이 인증을 요구하게 한다 permitsEverything 빨강
기준선 초록
server 전체 830건 · 실패 0 · skip 0
Closes #611
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
junseo2323
left a comment
There was a problem hiding this comment.
승인합니다. 이 빨강을 저는 오늘 실제로 밟았습니다 — #610 을 리뷰하면서 --tests '…security.*' 를 친 것이 처음 한 일이었고, 나온 것이 정확히 그 줄이었습니다.
(이 PR 전) SecurityConfigTest$Dev "전면 허용 — 프론트가 인증 없이 개발할 수 있다"
java.lang.AssertionError: Status expected:<200> but was:<404>
본문이 "정책 파일을 만지는 사람이 가장 먼저 치는 것" 이라고 한 자리가 바로 그것이라, 이 PR 의 값을 제가 증인으로 서겠습니다. #610 리뷰에도 「이 PR 것이 아닌 빨강」으로 적어 뒀습니다.
재현 — 브랜치에서 사라집니다
단독 실행 (e6a24bb) ./gradlew test --tests '…security.SecurityConfigTest' BUILD SUCCESSFUL
전체 ./gradlew test BUILD SUCCESSFUL · 830건
base origin/main 뒤처짐 0커밋
❗변이 둘 — 느슨해지지 않았는지가 이 PR 의 급소입니다
단정이 isOk() 에서 not(401) 로 약해졌으므로, 「약해진 만큼 안 잡히는 것이 생겼나」를 봤습니다.
| 변이 | 결과 |
|---|---|
dev 체인을 anyRequest().authenticated() 로 |
permitsEverything 빨강 |
dev 체인을 anyRequest().denyAll() 로 |
permitsEverything 빨강 |
둘째가 제가 걱정한 자리입니다 — denyAll 은 401 이 아닌 것으로 떨어질 수 있어서 not(401) 만으로는 통과할 수 있는데, /products 200 앵커가 그걸 뭅니다. 본문은 그 줄을 "체인이 아예 안 서는 것과 구별한다" 로만 적었는데, 실제로는 「전면 허용」이 「401 만 아님」으로 무너지는 것까지 막고 있습니다. 그 줄이 생각보다 일을 더 합니다.
모양 — 형제와 짝이 맞습니다
경로를 GUARDED_PATHS 한 벌로 둔 것이 이 PR 에서 제일 좋은 부분이라고 봅니다. 대조는 짝으로만 성립한다는 것이 맞고, 따로 적혀 있었으면 Prod 에만 경로가 하나 늘어난 날 아무도 모릅니다. #478 이 Prod.allowsAuthenticated 에서 이미 내린 판단을 형제 쪽에 마저 적용한 것이라 새 규칙을 만들지도 않았습니다.
곁 — CI 가 못 잡는다는 정리에 동의합니다
클래스 하나만 도는 잡을 따로 두는 것은 값에 비해 비싸다는 데 동의합니다. 다만 남는 갈래를 한 줄 적어 두면, 이 테스트가 다시 데이터에 걸리는 날(누가 GUARDED_PATHS 에 「저장된 것이 있어야 200」인 경로를 하나 더 넣는 날) 그 사람이 여기 주석을 읽게 됩니다 — 지금 javadoc 이 그 역할을 이미 하고 있어서 따로 요청하지는 않겠습니다.
Closes #611 걸려 있는 것 확인했습니다.
#611입니다. 제 파일이고 제가 밟히게 만든 자리입니다.재현
Dev.permitsEverything이/products/{id}/risk-items를 치는데, 그 경로는 저장된 추출이 DB 에 있어야 200 입니다(#478이 MockData 폴백을 걷은 뒤로). 전체 실행에서는 앞선 테스트가 H2 에 남긴 것 덕에 초록이고, 혼자 돌리면 404 입니다.CLAUDE.md가 그 명령 형태를 공식으로 적어 뒀고, 정책 파일을 만지는 사람이 가장 먼저 치는 것이--tests '…security.*'라 이 자리에서 유독 자주 밟힙니다.❗바로 옆 형제가 같은 이유로 이미 고쳐져 있었습니다
그 판단이 옳았는데 형제 쪽만 안 따라왔습니다. 제안하신 ⓐ 가 그 주석과 같은 결론이라 그대로 받았습니다.
고친 모양
상태를 200 으로 못 박지 않습니다 — 404 든 200 이든 인증 때문이 아니면 통과가 이 테스트의 뜻입니다. 「전면 허용」의 반대말은 401 이지 404 가 아니라는 정리를 그대로 씁니다.
체인이 아예 안 서는 것(전부 500)과 구별하려고
/products200 하나를 남겼습니다. 목록은 비어도 200 이라 데이터에 안 걸립니다.경로 목록을 한 벌로 뒀습니다 — 대조는 짝으로만 성립합니다. prod 에서 401 인 것과 dev 에서 401 이 아닌 것이 같은 경로여야 「프로파일이 가른다」가 증명되고, 따로 적으면 한쪽만 늘어난 것을 아무도 모릅니다.
역검증
permitsEverything빨강전에는 이 테스트가 「인증」과 「데이터」 둘에 걸려 있었습니다. 이제 인증만 재므로, 다음에 진짜로 인증이 깨지면 원인을 한 번 더 가릴 필요가 없습니다.
검증
곁 — CI 에서는 안 보인다는 지적이 맞습니다
ci.yml이 전체를 돌리므로 CI 는 언제나 초록이었습니다. 단독 실행은 사람 손에서만 일어나서 각자 한 번씩 밟고 각자 넘어갑니다. 이 PR 이후로도 그 갈래를 자동으로 막지는 못합니다 — 클래스 하나만 도는 잡을 따로 두는 것은 값에 비해 비싸다고 봅니다. 대신 이 테스트가 데이터에 안 걸리게 된 것이 그 갈래를 좁힙니다.Closes #611