기존의 소프트웨어 분석 도구 (버그 찾기, 코드 최적화 등) 는 마치 **완벽하게 완성된 건축 도면 (컴파일된 코드)**이 있어야만 일을 시작할 수 있는 건축가들입니다.
문제 1: 개발자가 코드를 다 짜기 전 (진행 중일 때) 에는 도면이 없으므로 분석이 불가능합니다.
문제 2: "이건 좀 다르게 고쳐줘"라고 요청하면, 건축가가 도면 그리는 법 (컴파일러 지식) 을 다시 배워야 하므로 일반 개발자가 직접 수정하기 매우 어렵습니다.
2. AI (LLM) 의 등장과 함정: "상상력이 너무 풍부한 초보자"
최근에는 **거대 언어 모델 (LLM, AI)**이 코드를 이해하는 능력이 뛰어나다고 알려졌습니다. 도면 없이도 코드를 보고 "여기 버그 있겠네!"라고 말해줍니다.
하지만: AI 는 **환각 (Hallucination)**이라는 병을 앓고 있습니다. 없는 것을 있는 것처럼 말하거나, 엉뚱한 버그를 찾아내는 경우가 많습니다. 마치 "이 벽이 무너질 것 같아!"라고 말했는데, 실제로는 튼튼한 벽인 경우죠.
3. NESA 의 해결책: "현장 감독 (파서) 과 AI 의 팀워크"
NESA 는 이 두 가지의 단점을 없애고 장점을 합친 **신비로운 조합 (Neuro-Symbolic)**입니다.
비유: "현장 감독 (Symbolic)"과 "감성적인 설계사 (Neural/AI)"의 협업
NESA 는 복잡한 분석 작업을 **작은 조각 (하위 문제)**으로 나누어 처리합니다.
Step 1: 작업 분할 (Datalog 정책)
사용자가 "이 코드에서 어떤 변수가 어디서 영향을 받는지 찾아줘"라고 요청하면, NESA 는 이를 작은 미션으로 쪼갭니다.
예: "1. 변수 이름 찾기", "2. 변수가 어디에 있는지 찾기", "3. 두 변수가 서로 영향을 주는지 AI 가 판단하기".
Step 2: 확실한 것은 '현장 감독'이 처리 (Symbolic Relations)
변수 이름, 코드 줄 번호, 문법 구조 같은 것은 AI 가 추측할 필요가 없습니다. **파서 (Parser)**라는 기계적인 도구가 100% 정확하게 찾아냅니다.
비유: "이 벽이 몇 번째 줄에 있는지?"는 AI 가 상상할 필요 없이 자자로 재면 됩니다.
Step 3: 어려운 것은 'AI'가 처리하되, 조건을 붙임 (Neural Relations)
데이터 흐름, 의미론적 관계 같은 복잡한 것은 AI 에게 맡깁니다.
핵심 기술 1: 게으른 프롬핑 (Lazy Prompting)
AI 에게 "전체 코드를 봐서 버그를 찾아줘"라고 하면 AI 는 헷갈려서 엉뚱한 말을 합니다.
대신, 현장 감독이 먼저 "A 변수는 10 줄에 있고, B 변수는 20 줄에 있어"라고 정보를 준 뒤, AI 에게 "그럼 A 와 B 가 서로 영향을 주니?"라고 물어봅니다.
비유: "전체 도시를 다 봐서 범죄자를 찾아줘"라고 하면 AI 는 망연자실하지만, "범인은 3 번 건물에 있을 거야"라고 범위를 좁혀주면 AI 는 정확하게 찾아냅니다.
핵심 기술 2: 점진적 프롬핑 (Incremental Prompting)
같은 일을 AI 에게 여러 번 시키지 않습니다. 이미 찾아낸 정보는 기억해두고, 새로운 정보만 찾아오게 합니다.
비유: "이미 찾은 실수 목록은 다시 확인하지 마. 새로운 실수만 찾아와."라고 지시하여 시간과 비용을 아낍니다.
4. 실제 성과: "현장에서 통하는 분석가"
NESA 는 실제 실험에서 놀라운 결과를 보여주었습니다.
버그 찾기: 기존 산업용 도구보다 더 많은 버그를 찾아냈고, 특히 컴파일 (완성) 이 안 된 코드에서도 잘 작동했습니다.
실제 적용: Uber 의 실제 프로젝트 (h3) 에서 개발자가 놓친 메모리 누수 (돈을 버리는) 버그 13 개를 찾아내어 수정하게 했습니다.
사용 편의성: 개발자가 복잡한 코드를 직접 짤 필요 없이, 자연어와 간단한 예시만 제공하면 원하는 분석을 바로 할 수 있습니다.
💡 한 줄 요약
NESA는 "AI 의 직관력"과 "기계의 정확성"을 결합하여, 컴파일 없이도 개발자가 원하는 대로 정확하고 유연하게 코드의 버그를 찾아내는 새로운 방식의 분석 도구입니다.
마치: "완벽한 도면이 없어도, 현장 감독이 기초 정보를 제공하고 AI 가 그 정보를 바탕으로 지능적으로 문제를 찾아내는, 최고의 건설 팀"이라고 생각하시면 됩니다.
1. 문제 정의 (Problem)
정적 프로그램 분석 (Static Program Analysis) 은 코드 최적화, 버그 탐지, 디버깅 등에 필수적이지만, 실제 산업 현장에서의 채택은 다음과 같은 두 가지 주요 한계로 인해 제한받고 있습니다.
컴파일 의존성 (Reliance on Compilation): 기존 주요 분석 도구들 (FlowDroid, Infer 등) 은 소스 코드를 중간 표현 (IR) 으로 변환하는 컴파일 과정에 의존합니다. 이로 인해 개발 환경에서 코드가 불완전한 상태일 때 분석이 불가능하며, 다양한 빌드 시스템과 컴파일러 버전 호환성 문제로 인해 IR 접근이 어렵습니다.
커스터마이징의 부재 (Lack of Customization): 개발자의 특정 요구사항에 맞춰 분석 도구를 수정하거나 새로운 버그 패턴을 탐지하려면, 도메인 특화 언어 (DSL) 나 IR 내부 구조에 대한 깊은 전문 지식이 필요합니다. 이는 분석 도구의 진입 장벽을 높여 사용성을 떨어뜨립니다.
최근 대규모 언어 모델 (LLM) 은 컴파일 없이 코드 의미론을 이해할 수 있는 잠재력을 보였으나, 할루시네이션 (Hallucination, 거짓 정보 생성) 이라는 본질적인 문제로 인해 정적 분석과 같은 정밀도가 요구되는 작업에서 오검출 (False Positive) 또는 누락 (False Negative) 이 빈번하게 발생합니다.
2. 방법론 (Methodology: NESA)
저자들은 NESA (Neuro-Symbolic Static Program Analysis) 라는 새로운 프레임워크를 제안합니다. 이는 LLM 의 의미론적 이해 능력과 전통적인 파싱 기반의 결정론적 분석을 결합한 관계형 신경 - 심볼릭 (Relational Neuro-Symbolic) 접근법입니다.
핵심 아이디어
문제 분해 (Problem Decomposition): 복잡한 분석 문제를 더 작은 하위 문제 (서브 - 문제) 로 분해합니다.