정적 분석 + LLM에 관하여
Source: Dev.to
정적 분석
정적 분석은 코드를 실행하기 전에 코드를 이해하는 것입니다.
def add(a, b):
return a + b
def main():
return add(1, 3)위는 사소한 프로그램입니다.
한눈에 main()을 호출하면 4가 반환된다는 것을 알 수 있습니다.
생각해 볼 질문들
add를 숫자가 아닌 타입으로 호출하면 어떻게 될까요? 예를 들어add("foo", "bar")는 무엇을 반환할까요?- 위 내용에 대해 어떻게 알 수 있을까요?
정적 분석은 코드를 실제로 실행하지 않고 이러한 질문에 답하는 것을 목표로 합니다.
인간 프로그래머는 언어와 런타임에 대한 친숙함을 통해 이러한 질문에 쉽게 답할 수 있습니다.
그렇다면 기계는 어떻게 답을 찾아낼 수 있을까요?
Source: …
프로그램 표현
프로그램은 여러 가지 표현 방식을 가지고 있습니다(인간에게 친숙한 구문은 그 중 하나일 뿐). 아래는 같은 파이썬 프로그램에 대한 몇 가지 대체 표현입니다.
AST
Module(
body=[
FunctionDef(
name='add',
args=arguments(
args=[
arg(arg='a'),
arg(arg='b')]),
body=[
Return(
value=BinOp(
left=Name(id='a'),
op=Add(),
right=Name(id='b')))]),
FunctionDef(
name='main',
args=arguments(),
body=[
Return(
value=Call(
func=Name(id='add'),
args=[
Constant(value=1),
Constant(value=3)]))])])바이트코드
Disassembly of :
1 RESUME 0
2 LOAD_FAST 0 (a)
3 LOAD_FAST 1 (b)
4 BINARY_OP 0 (+)
5 RETURN_VALUE
Disassembly of :
1 RESUME 0
2 LOAD_GLOBAL 1 (add)
3 LOAD_SMALL_INT 1
4 LOAD_SMALL_INT 3
5 CALL 2
6 RETURN_VALUE이러한 표현은 “기계에 더 가깝다”고 할 수 있습니다. 컴파일러나 CPU가 프로그램을 실행하려 할 때 필요한 세부 정보를 담고 있습니다. 대부분의 인간 프로그래머는 이러한 저수준 세부 사항에 신경 쓰지 않지만, 필요할 때는 유용할 수 있습니다.
호출 그래프
example.py
[D] add
[D] main
main
[U] add[D]는 “정의된 위치”를, [U]는 “사용된 위치”를 의미합니다.
위 내용을 “add와 main은 example.py에 정의되어 있고, add는 main에서 사용된다”라고 읽을 수 있습니다.
호출 그래프는 프로그램 내 의존 관계와 데이터 흐름을 이해하는 데 매우 유용합니다. 수십만 줄의 코드, 수천 개의 함수, 다수의 파일로 이루어진 대규모 시스템에서는 다음과 같은 질문에 답하는 데 도움이 됩니다:
- 특정 데이터가 어떤 함수와 파일을 거쳐 흐르는가?
- 데이터 흐름을 리팩터링하거나 재고해야 할 경우, 어떤 파일과 함수를 수정해야 하는가?
정적 분석은 복잡한 시스템을 다루는 엔지니어에게 강력한 도구입니다. 이러한 시스템은 처음부터 다시 작성하기 어려운 경우가 많으며, 흔히 불안정한 기반 위에 점점 커져갑니다. 따라서 그 기반을 이해하는 것이 필수적입니다.
정적 분석 및 LLM(대형 언어 모델) 2026년
우리는 이제 대형 언어 모델(LLM)을 보유하고 있습니다.
LLM만을 사용해 리팩터링과 재작성 작업을 할 수 있을까요?
LLM으로 “진지한” 엔지니어링을 할 수 없다는 인식이 있습니다. 그 이유는:
- 컨텍스트 윈도우가 너무 작다.
- 결과물이 “엉성”하게 나오는 경향이 있다.
저는 동의하지 않습니다. 저는 능력 과잉이 존재한다고 믿습니다. 순수한 프롬프트와 부실한 컨텍스트 관리가 모델의 능력을 크게 제한하는데, 이는 유능한 엔지니어에게 코드를 1초만 보고 문제를 해결하라고 하는 것과 같습니다.
Claude Code, Codex, Opencode 같은 도구들은 모델에 테스트와 반복을 위한 손과 환경을 제공하지만, 여전히 우리가 부여하는 권한과 프롬프트에 인코딩하는 패턴에 제한됩니다. 궁극적으로 모델 + 하네스는 엔지니어 자신의 역량에 의해 제한됩니다.
훌륭한 엔지니어는 마법사가 아니다.
그들은 훌륭한 도구를 사용하는 좋은 엔지니어이다.
실행하거나 프로파일링하지 않고도 수행할 수 있는 분석이 많이 있습니다: 호출 그래프 분석, 제어 흐름 분석 등. 이러한 도구에 모델이 접근하도록 하면—시니어 엔지니어가 이미 사용하는 도구—대규모 리팩터링을 개선할 수 있는 “쉽게 얻을 수 있는 과일”을 제공합니다.
제 경험에 따르면, 정적 분석을 통해 코드베이스를 분석할 수 있게 하면 모델이 더 큰 리팩터링을 보다 능숙하게 계획하고 실행할 수 있습니다. 모델은 시니어 엔지니어와 비교할 만한 수준으로 코드베이스를 추론할 수 있습니다.
저는 현재 파이썬용 정적 분석 도구를 개선하고 있습니다. 파이썬은 동적 언어이며(많은 사용자가 프로그래머가 아니기 때문에) C/LLVM 같은 언어에 비해 도구가 덜 성숙하지만, LLM이 여기서 개발을 가속화하고 있습니다. 저는 이미 LLM이 호출 그래프와 제어 흐름 그래프만을 보고 10 k LOC 파이썬 프로젝트를 리팩터링하고 개선하는 것을 보았습니다.
제 생각에는 최첨단 모델이 적절한 정적 분석 데이터를 갖추면 시니어 엔지니어만큼 능숙할 가능성이 높습니다.
As a senior or staff‑level engineer, given the right prompt, tools, and enough time to reason, getting this right will “just” be a matter of building tools, formats, and representations that are highly amenable to LLM reasoning.