llm 포트폴리오 노트
메인 인덱스 | Shield4U | 오버뷰 | GitHub
이 문서는 제가
llm레포를 조금 더 길게 설명하려고 남긴 심층 메모입니다. 빠르게 훑어보실 때는 오버뷰부터 보시고, 구현 판단이나 한계까지 보고 싶으실 때 이 문서로 내려오시면 됩니다.
왜 이 레포를 앞에 두는가
llm은 제가 AI를 제품 안에서 어떻게 위치시키는지 설명할 수 있는 레포입니다. 모델을 붙이는 데서 끝내지 않고, 분석 게이트와 보고서 생성이 파이프라인 안에서 어떤 역할을 하는지까지 보여드릴 수 있습니다.
개요
이 문서는 제가 llm 레포를 포트폴리오에서 설명할 때 쓰는 기준 정리입니다. Shield4U 보안 플랫폼의 AI 통합 서비스로, 웹 애플리케이션 취약점 탐지와 전문 보고서 생성을 담당하는 마이크로서비스 아키텍처 기반 시스템이며 analyzeLLM과 reportLLM 두 모듈로 구성됩니다.
1. 기능 (Functions)
1.1 크롤러 데이터 기반 지능형 취약점 탐지 분석
analyzeLLM 모듈은 웹 크롤러가 수집한 구조화된 JSON 데이터를 입력받아 다층적 분석 파이프라인을 실행합니다. analyzeLLM.py의 build_raw_findings() 함수는 6개의 전문 감지기(Detector)를 순차적으로 실행하여 DOM 구조, 메타데이터, 스크립트, 폼 데이터 등 다차원적 정보를 분석합니다. 각 감지기는 특정 패턴을 인식하여 Panel/Login 페이지(detect_panel_login), CMS 스택(detect_cms_stack), 기술 스택(detect_tech), 민감 정보 노출(detect_exposure), OSINT 정보(detect_osint), 폼 기반 취약점(detect_form_vulnerabilities) 등을 식별합니다. 이후 add_universal_web_templates() 함수를 통해 모든 웹 애플리케이션에 대해 SQL Injection, XSS, LFI, RFI, Directory Traversal, CSRF, Auth Bypass 등 8가지 핵심 취약점에 대한 기본 템플릿을 자동으로 추가하여 포괄적 스캔 범위를 보장합니다.
1.2 LLM 게이트 기반 동적 스캔 의사결정 메커니즘
OpenAI GPT-5/GPT-4o 모델을 활용한 call_llm_gate() 함수는 탐지된 취약점 후보들에 대해 스캔 가치와 심각도를 지능적으로 판정합니다. LLMGateOutput과 LLMFindingDecision Pydantic 모델을 통해 구조화된 출력을 강제하며, 각 finding에 대해 run_template (실행 여부), severity (심각도), rationale (근거)를 결정합니다. 특히 SYSTEM_PROMPT에 정의된 “EXTREME AGGRESSION POLICY”는 모든 웹 애플리케이션을 잠재적으로 취약한 것으로 간주하고, 폼 존재 시 SQL Injection/XSS/CSRF, 동적 콘텐츠(.php, .asp 등) 존재 시 RCE/SQLI/LFI, 관리자 패턴(/admin, /login 등) 존재 시 Brute-force/Auth Bypass 스캔을 강제합니다. 이는 기존 정적 규칙 기반 스캐너의 한계를 극복하여 놓칠 수 있는 취약점을 포착합니다.
1.3 동적 Nuclei YAML 템플릿 생성 및 출력
findings_to_nuclei_yaml() 함수는 LLM 게이트의 판정 결과를 바탕으로 실제 실행 가능한 Nuclei 스캐너용 YAML 템플릿을 동적으로 생성합니다. 각 템플릿은 id, info (name, author, severity, description, tags), http (method, path, matchers) 섹션으로 구성되며, 태그 유형에 따라 적절한 matcher 조건을 자동으로 설정합니다. 예를 들어 panel/login 태그는 status 코드 200/302/401/403과 body 내 “login”/“admin” 키워드 매칭을, wordpress 태그는 /wp-content/ 경로나 “WordPress” 문자열 매칭을 사용합니다. 생성된 템플릿들은 yaml.dump_all()을 통해 단일 YAML 파일로 직렬화되어 Nuclei 스캐너에서 즉시 실행 가능한 형태로 제공됩니다.
1.4 전문 보안 평가 보고서 자동 생성
reportLLM 모듈은 Nuclei 스캔 결과를 입력받아 generate_security_report() 함수를 통해 다섯 가지 섹션(Executive Summary, Technical Details, Risk Assessment, Recommendations, Methodology)으로 구성된 전문 보고서를 생성합니다. build_report_schema() 함수는 OpenAI Function Calling을 위한 JSON Schema를 정의하여 LLM이 일관된 구조의 출력을 생성하도록 강제합니다. 각 취약점은 strategic_tag (panel, login, wordpress, exposure 등 13개 분류)로 분류되며, exploitability (Easy/Moderate/Difficult)와 severity (Critical/High/Medium/Low/Info)가 평가됩니다. 생성된 보고서는 기술자와 경영진 모두가 이해할 수 있는 양방향 커뮤니케이션 형태로 작성됩니다.
1.5 데이터 시각화 및 차트 생성
create_all_tags_summary_chart() 함수는 Matplotlib과 Pandas를 활용하여 전체 태그별 취약점 발견 건수를 막대 차트로 시각화합니다. 취약점이 발견된 태그는 빨간색(#ef9a9a), 발견되지 않은 태그는 녹색(#c8e6c9)으로 구분하여 시각적 직관성을 높입니다. create_tag_severity_chart() 함수는 태그별 심각도 분포를 누적 막대 차트로 생성하며, Critical(빨강), High(주황), Medium(노랑), Low(파랑), Info(연파랑) 색상으로 심각도를 구분합니다. 이러한 시각화 자료는 render_final_report() 함수에 의해 최종 Markdown 보고서에 삽입되어 보고서의 가독성과 설득력을 향상시킵니다.
1.6 REST API 기반 마이크로서비스 아키텍처
analyzeLLM과 reportLLM은 각각 독립적인 Flask 기반 REST API 서비스로 구현되어 있습니다. analyzeLLM 서비스(app.py, 포트 5003)는 /analyze 엔드포인트를 통해 크롤러 결과를 받아 분석하고 YAML 템플릿을 반환하며, reportLLM 서비스(app.py, 포트 5004)는 /generate-report 엔드포인트를 통해 보고서 생성을 수행합니다. 각 서비스는 /health 엔드포인트로 헬스체크를 제공하고, /status 엔드포인트로 OpenAI API 설정 상태를 확인할 수 있습니다. Docker 컨테이너화를 통해 독립적인 배포와 확장이 가능하며, 환경 변수(OPENAI_API_KEY, FLASK_HOST, FLASK_PORT 등)를 통한 유연한 설정을 지원합니다.
2. 특징 (Characteristics)
2.1 공격적 스캐닝 정책(Aggressive Policy)을 통한 포괄적 취약점 커버리지
기존 보안 스캐너가 “증거 기반” 접근법을 사용하는 것과 달리, 이 시스템은 “가정 기반” 공격적 정책을 채택했습니다. SYSTEM_PROMPT에 명시된 “EXTREME AGGRESSION POLICY”는 “Consider EVERY URL as potentially vulnerable until proven otherwise”(증명되기 전까지 모든 URL을 잠재적으로 취약한 것으로 간주)라는 철학을 기반으로 합니다. heuristic_gate() 함수는 모든 웹 취약점에 대해 기본적으로 run=True와 severity="medium"을 설정하며, run_pipeline_from_report() 함수는 findings가 5개 미만일 경우 “comprehensive-scan” 강제 템플릿을 추가합니다. 또한 LLM이 3개 미만의 템플릿만 실행하도록 판정할 경우 휴리스틱 정책으로 강제 오버라이드하는 “SAFETY NET” 메커니즘이 구현되어 있습니다. 이는 실제 환경에서 놓칠 수 있는 0-day 취약점이나 비표준 취약점을 탐지할 확률을 극대화합니다.
2.2 휴리스틱 폴백 메커니즘을 통한 LLM 독립적 동작 보장
시스템은 OpenAI API 의존성으로 인한 단일 장애점(SPOF)을 방지하기 위해 우아한 폴백(Graceful Fallback) 메커니즘을 구현했습니다. _get_openai_client() 함수는 API 키 미설정, 패키지 미설치, 클라이언트 생성 실패 등 다양한 오류 상황을 처리하며, call_llm_gate() 함수는 LLM 호출 실패 시 자동으로 heuristic_gate() 함수로 전환됩니다. heuristic_gate()는 태그 기반 규칙 엔진으로, exposure/sqli/xss/rce/lfi/rfi 태그는 “high” 심각도와 실행 설정, panel/login/wp-plugins 등은 “medium” 심각도로 분류하는 등의 휴리스틱을 적용합니다. 이는 API Rate Limiting, 네트워크 장애, 비용 제약 등 다양한 상황에서도 시스템이 중단 없이 동작할 수 있게 합니다.
2.3 Pydantic 기반 타입 안전성 및 데이터 검증
analyzeLLM.py는 LLMFindingDecision과 LLMGateOutput 클래스를 통해 Pydantic 기반의 엄격한 스키마 검증을 구현했습니다. tag, looks_vulnerable, severity, rationale, run_template 등의 필드는 타입 힌팅과 Field(..., description=...)을 통해 문서화되며, severity 필드는 "none|low|medium|high|critical" Enum으로 제한됩니다. _postprocess_and_fill_missing() 함수는 LLM이 일부 태그에 대해서만 응답했을 경우 누락된 태그를 자동으로 채워 스키마 완전성을 보장합니다. 이는 동적 타입 언어인 Python에서도 컴파일 타임 수준의 타입 안전성을 확보하고, 런타임 오류를 예방하며, 코드 가독성과 유지보수성을 향상시킵니다.
2.4 전략적 태깅 시스템을 통한 취약점 분류 및 관리
시스템은 13개의 전략적 태그(ALLOW_TAGS_ALL)를 정의하여 취약점을 체계적으로 분류합니다. 태그는 기능적 특성(panel, login), 기술 스택(wordpress, joomla, cms), 정보 노출 유형(exposure, info-leak, logs, debug), OSINT 정보(osint, osint-social, listing) 등으로 그룹화됩니다. 각 태그는 suggest_templates_for() 함수를 통해 Nuclei 템플릿 태그로 매핑되며(예: wordpress 태그 → “tags:wordpress”, “tags:wp”, “tags:wp-plugin”), 이는 Nuclei의 방대한 템플릿 라이브러리와의 효율적인 연동을 가능하게 합니다. reportLLM 모듈의 ALLOWED_TAGS는 이와 동일한 분류 체계를 사용하여 분석-보고 일관성을 유지합니다.
2.5 배치 처리 및 자동화 워크플로우 지원
batch_analyze.py 스크립트는 디렉토리 내 모든 JSON 파일을 자동으로 처리하는 배치 분석 기능을 제공합니다. glob.glob()을 통해 input_dir (./tmp) 내의 모든 .json 파일을 검색하고, 순차적으로 analyzeLLM.main()을 호출하여 분석을 수행한 후, 결과를 output_dir (./yaml_output)에 자동 저장합니다. 이는 대규모 웹 애플리케이션 포트폴리오의 정기적 스캔이나 CI/CD 파이프라인 통합에 적합하며, os.makedirs(output_dir, exist_ok=True)를 통해 디렉토리 자동 생성 및 중복 실행 안전성을 보장합니다.
2.6 Docker 컨테이너화 및 헬스체크 메커니즘
두 서비스 모두 Python 3.11 slim 기반 Dockerfile을 통해 컨테이너화되어 있으며, 프로덕션 환경에서의 안정적인 배포를 지원합니다. Dockerfile은 curl을 통한 헬스체크 의존성 설치, requirements.txt 기반 의존성 관리, PYTHONPATH 설정, FLASK_ENV=production 설정 등을 포함합니다. 특히 HEALTHCHECK 지시문은 30초 간격으로 /health 엔드포인트를 체크하여 서비스 가용성을 모니터링하며, Kubernetes나 Docker Swarm과 같은 오케스트레이션 환경에서 자동 복구를 가능하게 합니다.
3. 부족한 점 (Limitations)
3.1 OpenAI API 단일 제공자에 대한 강한 의존성
시스템은 OpenAI GPT 모델에 대한 하드코딩된 의존성을 가지고 있습니다. analyzeLLM.py와 reportLLM.py 모두 from openai import OpenAI를 통해 OpenAI SDK에 직접 의존하며, _get_openai_client() 함수는 OpenAI API 키만을 검증합니다. Azure OpenAI, Anthropic Claude, Google Gemini, Cohere, Llama 등 다른 LLM 제공자로의 마이그레이션이나 멀티 제공자 전략을 지원하지 않습니다. 이는 OpenAI의 가격 정책 변경, API 가용성 문제, 지역적 제한, 기업의 벤더 종속성 회피 정책 등 다양한 리스크에 노출될 수 있습니다. 특히 gpt-5 모델 지정은 현재 미리보기/제한적 접근 상태일 수 있어 실제 운영 환경에서의 안정성에 의문이 제기됩니다.
3.2 API 호출 최적화 및 비용 관리 메커니즘 부재
LLM API 호출 비용은 처리하는 데이터 양에 따라 선형적으로 증가하며, 현재 시스템은 비용 최적화를 위한 메커니즘이 거의 없습니다. call_llm_gate() 함수는 max_candidates_per_call 파라미터를 통해 배치 처리를 지원하나, 이는 메모리/컨텍스트 제한 대응 목적이며 비용 절감 목적은 아닙니다. 중복 요청 캐싱, 유사 보고서 재사용, 토큰 사용량 모니터링, 예산 기반 스로틀링, 온디맨드 vs 배치 처리 전략 등이 구현되어 있지 않습니다. 대규모 웹사이트(수천 페이지) 스캔 시 예상치 못한 API 비용이 발생할 수 있으며, AGGRESSIVE POLICY는 더 많은 LLM 판정을 유발하여 비용을 증가시킵니다.
3.3 실시간 스트리밍 및 진행 상황 모니터링 미지원
현재 시스템은 요청-응답 동기 패턴으로만 동작하며, 장시간 분석 작업의 진행 상황을 실시간으로 클라이언트에 전달하는 스트리밍 메커니즘이 없습니다. analyze() 또는 generate-report API 호출은 모든 처리가 완료될 때까지 블로킹되며, 대상 웹사이트가 크거나 복잡할 경우 타임아웃이 발생할 수 있습니다. WebSocket, Server-Sent Events(SSE), 또는 progressive JSON 스트리밍을 통한 중간 결과 전달, 진행률 업데이트, 청크 단위 처리 등이 구현되어 있지 않아 사용자 경험(UX)이 제한적입니다.
3.4 병렬 처리 및 비동기 아키텍처 미적용
batch_analyze.py의 배치 처리는 순차적 for 루프로 구현되어 있으며, threading이나 asyncio, multiprocessing을 활용한 병렬 처리가 적용되지 않았습니다. analyzeLLM.py의 여러 감지기(detect_panel_login, detect_cms_stack 등)도 순차적으로 실행되며, 각각은 독립적이므로 병렬 실행이 가능함에도 불구하고 순차 실행됩니다. 대규모 데이터 처리 시 CPU와 I/O 리소스를 효율적으로 활용하지 못하며, Flask의 threaded=True 설정만으로는 GIL(Global Interpreter Lock)로 인한 실제 병렬성 확보가 제한적입니다.
3.5 오탐(False Positive) 관리 및 검증 메커니즘 부재
“AGGRESSIVE POLICY”는 높은 커버리지를 달성하지만, 그 대가로 오탐률이 증가할 수 있습니다. 현재 시스템은 탐지된 취약점의 실제 존재 여부를 검증하는 메커니즘이 없으며, 모든 결과를 동일한 신뢰도로 보고합니다. Nuclei 템플릿 생성 후 실제 실행 결과를 피드백하여 LLM 게이트의 판정 정확도를 개선하는 학습 루프, 사용자 피드백 수집 및 모델 파인튜닝, 오탐 필터링 규칙 등이 구현되어 있지 않습니다. 이는 보안 담당자가 많은 오탐을 수동으로 필터링해야 하는 부담을 초래할 수 있습니다.
3.6 보고서 형식 및 다국어 지원 한계
reportLLM.py는 Markdown 형식의 보고서만 생성하며, PDF, HTML, DOCX 등 다른 형식으로의 변환을 지원하지 않습니다. 기업 환경에서 요구되는 브랜딩(로고, 색상, 레이아웃) 커스터마이징, 보고서 템플릿 선택, 다국어(영어, 한국어, 일본어 등) 동시 생성 등이 불가능합니다. 또한 보고서의 품질이 LLM 프롬프트에 크게 의존하며, 산업별 규제 요구사항(PCI-DSS, GDPR, HIPAA 등)에 맞춘 컴플라이언스 중심 보고서 생성은 지원되지 않습니다.
4. 개선 방향 (Improvements)
4.1 다중 LLM 제공자 지원 및 추상화 계층 도입
OpenAI SDK에 대한 직접 의존성을 제거하고, BaseLLMClient 추상 클래스를 정의하여 다양한 LLM 제공자를 플러그인 형태로 지원해야 합니다. 구현체로 OpenAIClient, AnthropicClient, GoogleGeminiClient, AzureOpenAIClient, OllamaLocalClient 등을 개발하고, 환경 변수 LLM_PROVIDER=anthropic 설정으로 제공자를 전환할 수 있게 합니다. 각 제공자별로 모델 매핑 설정(gpt-4o ↔ claude-3-opus ↔ gemini-pro)을 지원하며, 멀티 제공자 폴백 체인(Primary: OpenAI → Secondary: Anthropic → Tertiary: Local LLM)을 구현하여 가용성을 극대화합니다. 이는 벤더 종속성 리스크를 분산하고, 비용/성능 최적화를 위한 제공자별 워크로드 분배도 가능하게 합니다.
4.2 로컬 LLM 및 하이브리드 아키텍처 지원
민감한 데이터 처리나 비용 민감한 환경을 위해 Ollama, vLLM, Text Generation Inference(TGI) 등을 활용한 로컬 LLM 지원을 추가해야 합니다. LocalLLMClient 구현체는 HTTP REST API로 로컬 LLM 서버와 통신하며, llama3, mistral, codellama 등 오픈소스 모델을 활용할 수 있습니다. 하이브리드 아키텍처로는 민감도가 낮은 휴리스틱 판정은 로컬 LLM으로, 복잡한 보고서 생성은 클라우드 LLM으로 분리하여 비용과 품질의 균형을 맞출 수 있습니다. analyzeLLM은 경량화된 로컬 모델(phi-3, gemma-2b)로 마이그레이션하여 API 비용을 90% 이상 절감할 수 있습니다.
4.3 지능형 캐싱 및 비용 최적화 시스템 구현
Redis나 in-memory 캐시를 활용하여 동일하거나 유사한 크롤러 결과에 대한 LLM 응답을 캐싱해야 합니다. URL 정규화 및 해싱 기반 캐시 키 생성, 유사도 기반 캐시 매칭(SimHash, MinHash), TTL 기반 캐시 만료 정책을 구현합니다. 또한 토큰 사용량 모니터링 대시보드를 구축하여 프로젝트/사용자/시간대별 비용을 추적하고, 예산 알림(예: $100 도달 시 Slack 알림), 하드 예산 리밋(초과 시 처리 중단) 기능을 추가합니다. 프롬프트 압축 기법(prompt compression)과 few-shot 예제 최적화로 토큰 사용량을 30-50% 절감할 수 있습니다.
4.4 비동기 아키텍처 및 실시간 스트리밍 지원
Flask를 FastAPI로 마이그레이션하고 async/await 패턴을 도입하여 비동기 I/O 처리를 구현해야 합니다. analyze() 엔드포인트는 SSE(Server-Sent Events)를 통해 중간 결과를 스트리밍하고, 클라이언트는 {"status": "analyzing", "progress": 45, "current_page": "https://..."} 형태의 진행 상황을 실시간으로 수신합니다. Celery + Redis 기반의 분산 태스크 큐를 도입하여 장기 실행 작업을 백그라운드로 오프로드하고, 작업 상태 조회 API(/tasks/{task_id}/status)를 제공합니다. 이는 대규모 웹사이트 분석 시 사용자 경험을 크게 개선하며, 웹소켓을 통한 양방향 통신으로 분석 중 사용자 피드백(예: “이 페이지는 무시해주세요”) 수신도 가능하게 합니다.
4.5 피드백 루프 및 지속적 학습 시스템 구축
Nuclei 스캔 결과와 LLM 판정의 정확성을 연계하는 피드백 루프를 구현해야 합니다. nuclei_execution_results 테이블에 LLM 판정 태그, 실제 Nuclei 매칭 여부, 사용자 검증 결과를 저장하고, 정기적으로 이 데이터를 수집하여 OpenAI의 Fine-tuning API나 LoRA 기반 로컬 모델 파인튜닝을 수행합니다. llm_decision_feedback API를 통해 보안 담당자가 “이 판정은 오탐입니다” 피드백을 제출할 수 있게 하며, 오탐 패턴 분석을 통해 휴리스틱 규칙과 LLM 프롬프트를 지속적으로 개선합니다. A/B 테스트 프레임워크를 도입하여 새로운 프롬프트나 모델 버전의 오탐률을 측정하고, 통계적으로 유의미한 개선이 확인될 때만 프로덕션에 배포합니다.
4.6 확장 가능한 보고서 엔진 및 다국어 지원
Jinja2 템플릿 엔진을 도입하여 templates/professional.md, templates/executive.md, templates/technical.md 등 다양한 보고서 템플릿을 지원해야 합니다. WeasyPrint나 Puppeteer를 활용한 PDF 변환, HTML + CSS 커스터마이징, DOCX 생성 기능을 추가합니다. i18n 모듈을 통해 다국어 지원을 구현하고, report_locale=ko|en|ja 파라미터로 언어를 선택할 수 있게 합니다. 산업별 컴플라이언스 템플릿(PCI-DSS 점검 보고서, GDPR 영향 평가 보고서 등)을 프리셋으로 제공하며, 기업 브랜딩(로고, 색상 팔레트, 푸터) 커스터마이징 설정을 지원합니다. 보고서 스케줄링 및 자동 이메일 전송 기능도 추가하여 정기 보고 워크플로우를 자동화합니다.
분석 파일 목록
총 15개 핵심 파일 분석:
| 파일 경로 | 라인 수 | 설명 |
|---|---|---|
analyzeLLM/analyzeLLM.py | 914 | 메인 분석 엔진, 감지기 파이프라인, LLM 게이트 |
analyzeLLM/app.py | 168 | Flask REST API 서비스 |
analyzeLLM/batch_analyze.py | 39 | 배치 처리 스크립트 |
analyzeLLM/readme.md | 108 | 입력/출력 형식 문서화 |
analyzeLLM/requirements.txt | 5 | Python 의존성 |
analyzeLLM/Dockerfile | 33 | 컨테이너 설정 |
reportLLM/reportLLM.py | 503 | 보고서 생성 엔진, 시각화 |
reportLLM/app.py | 204 | Flask REST API 서비스 |
reportLLM/requirements.txt | 7 | Python 의존성 (matplotlib, pandas 포함) |
reportLLM/Dockerfile | 33 | 컨테이너 설정 |
analyzeLLM/crawler_report_sample.json | 38 | 샘플 입력 데이터 |
reportLLM/nuclei_output.md | 48 | 샘플 Nuclei 스캔 결과 |
analyzeLLM/yaml_output/*.yaml | 다수 | 생성된 Nuclei 템플릿 예시 |
reportLLM/nuclei_output2.md | - | 추가 스캔 결과 샘플 |
reportLLM/nuclei_output3.md | - | 추가 스캔 결과 샘플 |