Claude Code가 BrassCoders의 Findings File을 읽는 방식
요약
Claude Code가 BrassCoders의 Findings File(.brass/ai_instructions.yaml)을 활용하여 효율적으로 코드를 리뷰하는 메커니즘을 설명합니다. 심각도와 줄 번호 정보를 활용해 모델이 소스 코드를 전체적으로 읽지 않고도 우선순위에 따라 정확한 수정을 수행하는 워크플로우를 다룹니다.
핵심 포인트
- 심각도(Severity) 기반 정렬로 우선순위 높은 보안 취약점 우선 처리
- 줄 번호(Line Number)를 통해 특정 코드 위치로 즉시 접근 가능
- Remediation 필드로 소스 코드 전체 탐색 없이 수정 방향 제시
- 가공된 데이터 입력을 통해 AI의 판단 비용 절감 및 효율적 Triage 실현
Claude Code는 .brass/ai_instructions.yaml을 미리 소화된 작업 대기열(work queue)로 읽습니다. severity(심각도) 필드는 검토 순서를 결정하고, line number(줄 번호) 필드는 각 finding(결과물)을 특정 코드 위치에 고정하며, remediation(수정) 필드는 모델이 소스 코드를 단 한 줄도 읽기 전에 수정 방향을 제공합니다. BrassCoders가 이 파일을 작성하고, Claude Code가 이를 읽습니다. 이러한 역할 분담이 전체 워크플로우의 핵심입니다.
각 필드가 어떤 역할을 하는지 이해하면, 왜 이 구조가 개방형 코드 리뷰 프롬프트보다 더 나은 triage(분류) 세션을 만들어내는지 알 수 있습니다.
실제 파일의 모습
BrassCoders는 매 스캔이 끝난 후 스캔된 프로젝트 디렉토리에 .brass/ai_instructions.yaml을 생성하며, critical-severity(심각도: 매우 높음) 결과물이 high-severity(심각도: 높음)보다 먼저, high-severity가 medium-severity(심각도: 중간)보다 먼저 나타나도록 정렬합니다. 이 파일은 각 finding당 하나의 항목을 포함하며, 각 항목은 id, severity, file path(파일 경로), line number(줄 번호), title(제목), description(설명), 그리고 remediation(수정) 필드를 가집니다.
api/views.py에 있는 SQL injection(SQL 인젝션)에 대한 finding은 다음과 같은 모습입니다:
issues:
- id: bandit-B608-001
severity: critical
...
Claude Code는 이 항목을 읽고 다음과 같은 사실을 알게 됩니다: 해당 finding은 critical(매우 높은) 우선순위이며, api/views.py의 47번 줄에 위치하고, 수정 방법은 parameterized queries(매개변수화된 쿼리)라는 점입니다. 문제를 이해하기 위해 파일 전체를 읽을 필요가 없습니다. Claude Code는 표시된 줄과 그 주변의 좁은 범위를 읽어 finding이 실제인지 확인하고, 수정 사항을 생성합니다.
Severity가 세션을 주도하는 방식
BrassCoders는 파일을 작성하기 전에 finding을 severity(심각도) 순으로 먼저 정렬합니다. 이는 Claude Code가 별도의 우선순위 지정 지침 없이도, medium-severity(중간 심각도)의 missing-timeout(타임아웃 누락)이나 low-severity(낮은 심각도)의 style note(스타일 참고 사항)를 접하기 전에 critical(매우 높은 심각도)의 SQL injection을 먼저 마주하게 된다는 것을 의미합니다.
이는 분류 (triage) 세션에서 중요합니다. 정렬된 입력이 없다면, 가공되지 않은 소스 코드를 읽는 AI 어시스턴트는 각 발견 사항 (finding)의 중요성을 스스로 평가해야 하며, 보안 취약점보다 스타일 문제를 먼저 처리할 수도 있습니다. 정렬된 파일은 그러한 판단 과정을 제거합니다. 세션은 심각도(critical)가 높은 발견 사항부터 시작하여, 높은(high) 수준을 거쳐, 위험한 발견 사항들이 모두 처리된 후에야 낮은(low) 수준에 도달하게 됩니다.
BrassCoders는 파일을 작성할 때 2차 심각도 필터 (secondary severity filter)를 적용합니다. 만약 전체 발견 사항의 개수가 제한치를 초과하면, high 슬롯을 채우기 전에 critical 슬롯을 먼저 채우고, 그 다음 medium 슬롯을 채웁니다. 1,500개의 가공되지 않은 스캐너 발견 사항 (raw scanner findings)이 있는 코드베이스라도, 낮은 심각도의 발견 사항을 위한 공간을 만들기 위해 높은 심각도의 발견 사항이 누락되는 파일은 절대 생성되지 않습니다.
줄 번호 (Line Number)의 역할
BrassCoders는 줄 번호가 있는 모든 발견 사항에 대해 line_number 필드를 작성합니다. Claude Code는 이를 사용하여 파일 전체를 읽는 대신, 플래그가 지정된 위치 주변의 좁은 코드 창 (code window)을 가져오는 데 사용합니다.
줄 번호가 없다면, 코드 리뷰는 파일 수준에서 시작됩니다. 즉, 파일을 읽고, 패턴을 스캔하며, 무엇이 잘못되었을지에 대한 가설을 세우는 방식입니다. 줄 번호가 있다면, 정확한 위치에서 시작합니다. 예를 들어 44~50행을 읽고, 47행이 SQL 문자열에 사용자 입력을 보간 (interpolate) 하는지 확인하여 취약점을 확정합니다. 이 차이는 대략 20줄의 컨텍스트 (context) 대 200줄의 컨텍스트 차이와 같습니다.
400줄짜리 Flask 뷰 (view)나 600줄짜리 데이터 처리 모듈과 같은 대용량 파일의 경우, 줄 고정점 (line anchor)은 세션이 발견 사항과 관련 없는 코드 속에서 길을 잃지 않도록 도와줍니다. 모델은 중요한 부분만을 읽습니다.
수정 (Remediation) 필드의 역할
BrassCoders는 수정 방향을 결정론적으로 명시할 수 있는 발견 사항에 대해 remediation 필드를 작성합니다. Claude Code는 이 필드를 읽고, 제1원칙 (first principles)으로부터 올바른 접근 방식을 도출하는 대신 명시된 패턴으로부터 수정 사항 생성 (fix generation)을 시작합니다.
SQL 인젝션 (SQL injection)의 경우, 해결책은 항상 "매개변수화된 쿼리 (parameterized queries)를 사용하라"입니다. shell=True subprocess 호출의 경우, "쉘 문자열 대신 리스트를 전달하라"입니다. 루프 내의 문자열 연결 (string concatenation)의 경우, "리스트로 수집한 뒤 ''.join()을 사용하라"입니다. 이러한 수정 방향은 해당 수정 사항이 일치하는 구조적 패턴 (structural pattern)에 대해 정확합니다. 모델은 해결책 (remediation)을 읽고, 그것이 특정 코드에 적용되는지 확인한 뒤, 패치 (patch)를 작성합니다.
모델이 여전히 가치를 더하는 발견 (finding)은, 명시된 해결책은 맞지만 적용 방식이 복잡할 때입니다. 매개변수화가 필요한 다중 테이블 SQL 쿼리는 단순히 %s를 값 튜플 (values tuple)로 교체하는 것이 아니라, 쿼리 자체를 재구성해야 할 수도 있습니다. 모델은 해결책을 지침으로 읽고, 코드를 제약 조건 (constraint)으로 읽으며, 이 두 가지를 모두 만족하는 수정 사항을 생성합니다. 해결책 필드는 솔루션 공간 (solution space)을 좁혀주며, 모델은 구체적인 구현 (implementation)을 처리합니다.
Claude Code가 BrassCoders가 할 수 없는 것을 제공하는 지점
BrassCoders는 공개된 벤치마크에서 Claude Code가 잡아낸 한 가지 발견을 놓쳤습니다: 빈 리스트에 대한 방어 코드(guard)가 없는 sum(readings) / len(readings) — 이는 규칙이 매칭될 구조적 마커 (structural marker)를 남기지 않는 ZeroDivisionError입니다.
이것은 사전 검사 (pre-pass) 여부와 상관없이 Claude Code가 승리하는 유형의 발견입니다. 해피 패스 (happy path)가 아닌 언해피 패스 (unhappy path)에서 함수가 무엇을 받는지에 대한 추론 — "readings가 비어있을 때는 어떤 일이 발생하는가?" — 이 필요한 버그는 결정론적 규칙 (deterministic rule)으로 표현될 수 없습니다. .brass 파일은 일치하는 패턴이 없기 때문에 이를 플래그 (flag)하지 못합니다. Claude Code는 함수를 읽고 엣지 케이스 (edge cases)를 생각함으로써 이를 찾아냅니다.
사전 검사는 구조적 계층 (structural layer)을 정리하고, Claude Code는 추론 계층 (reasoning layer)을 커버합니다. 어느 쪽의 공백도 상대방이 존재하지 않는 척할 필요를 요구하지 않습니다.
pip install brasscoders
brasscoders --offline scan /path/to/your/project
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기