ast.NodeVisitor
ast.NodeVisitor
ast.NodeVisitor는 Python의 내장 ast 모듈에서 제공하는 클래스로, 추상 구문 트리(Abstract Syntax Tree, AST)를 순회(traverse)하고 각 노드를 방문하여 특정 작업을 수행하는 데 사용됩니다. 이 클래스는 정적 분석, 코드 리팩터링, 코드 생성, 보안 분석 등 다양한 소프트웨어 개발 도구에서 핵심적인 역할을 합니다.
개요
Python 코드는 파싱되어 추상 구문 트리(AST) 형태로 변환될 수 있습니다. AST는 소스 코드의 구조를 계층적으로 표현한 트리 구조로, 각 노드는 변수, 함수, 조건문, 반복문 등의 문법 요소를 나타냅니다. ast.NodeVisitor는 이러한 트리 구조를 체계적으로 탐색할 수 있도록 도와주는 기본 클래스입니다.
이 클래스는 방문자 패턴(Visitor Pattern)을 기반으로 설계되어 있으며, 사용자는 특정 노드 타입에 대한 처리 로직을 메서드 오버라이딩을 통해 정의할 수 있습니다.
기본 사용법
ast.NodeVisitor는 직접 인스턴스화하기보다는, 상속을 통해 서브클래스를 정의하고 필요한 메서드를 재정의하는 방식으로 사용됩니다.
예제: 함수 정의 탐지
import ast
class FunctionVisitor(ast.NodeVisitor):
def visit_FunctionDef(self, node):
print(f"함수 발견: {node.name} (라인 {node.lineno})")
self.generic_visit(node) # 하위 노드 탐색 계속
# 예제 코드 파싱
code = """
def hello():
print("안녕")
def world():
return 42
"""
tree = ast.parse(code)
visitor = FunctionVisitor()
visitor.visit(tree)
출력 결과:
함수 발견: hello (라인 2)
함수 발견: world (라인 5)
주요 메서드
[visit](/doc/%EA%B8%B0%EC%88%A0/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%20%EA%B0%9C%EB%B0%9C/visit)(node)
- 모든 노드에 대해 호출되는 기본 메서드.
- 노드의 타입에 따라 적절한
visit_*메서드를 자동으로 호출합니다.
[generic_visit](/doc/%EA%B8%B0%EC%88%A0/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%20%EA%B0%9C%EB%B0%9C/generic_visit)(node)
- 특정
visit_*메서드가 정의되지 않은 경우, 이 메서드가 호출되어 자식 노드들을 순회합니다. - 명시적으로 호출하지 않으면 하위 노드 탐색이 중단됩니다.
visit_* 메서드
ast모듈의 각 노드 타입에 대응하는 메서드.- 예:
[visit_FunctionDef](/doc/%EA%B8%B0%EC%88%A0/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/%EC%86%8C%EC%8A%A4%EC%BD%94%EB%93%9C/visit_FunctionDef),[visit_Call](/doc/%EA%B8%B0%EC%88%A0/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/%EC%86%8C%EC%8A%A4%EC%BD%94%EB%93%9C/visit_Call),[visit_Assign](/doc/%EA%B8%B0%EC%88%A0/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/%EC%86%8C%EC%8A%A4%EC%BD%94%EB%93%9C/visit_Assign),[visit_If](/doc/%EA%B8%B0%EC%88%A0/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/%EC%86%8C%EC%8A%A4%EC%BD%94%EB%93%9C/visit_If),[visit_For](/doc/%EA%B8%B0%EC%88%A0/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/%EC%86%8C%EC%8A%A4%EC%BD%94%EB%93%9C/visit_For)등. - 공식 문서에서 전체 목록 확인 가능.
활용 사례
1. 정적 분석 도구 개발
NodeVisitor는 코드 내 잠재적 버그, 보안 취약점, 스타일 위반 등을 탐지하는 데 사용됩니다. 예를 들어, [eval](/doc/%EA%B8%B0%EC%88%A0/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/%EB%B3%B4%EC%95%88%20%EC%B7%A8%EC%95%BD%EC%A0%90/eval)() 또는 [exec](/doc/%EA%B8%B0%EC%88%A0/%EB%B3%B4%EC%95%88/%EB%8D%B0%EC%9D%B4%ED%84%B0%20%EB%B3%B4%ED%98%B8/exec)() 사용을 감지하여 보안 경고를 발생시킬 수 있습니다.
class DangerousCallVisitor(ast.NodeVisitor):
def visit_Call(self, node):
if isinstance(node.func, ast.Name):
if node.func.id in ('eval', 'exec'):
print(f"위험한 호출 발견: {node.func.id} (라인 {node.lineno})")
self.generic_visit(node)
2. 코드 메트릭 측정
함수 복잡도, 코드 줄 수, 변수 사용 빈도 등을 분석할 수 있습니다.
3. 코드 변환 및 리팩터링
ast.[NodeTransformer](/doc/%EA%B8%B0%EC%88%A0/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%20%EA%B0%9C%EB%B0%9C/NodeTransformer)와 함께 사용하면 AST를 수정하고, 코드를 자동으로 리팩터링할 수 있습니다. 예: 함수 이름 자동 변경, 로깅 삽입 등.
주의사항
generic_visit()을 명시적으로 호출하지 않으면, 하위 노드가 탐색되지 않습니다.- 모든 노드 타입에 대해 메서드를 정의할 필요는 없으며, 필요한 경우에만 오버라이드하면 됩니다.
NodeVisitor는 읽기 전용 분석에 적합하며, AST를 수정하려면ast.NodeTransformer를 사용해야 합니다.
관련 클래스 및 모듈
| 클래스 / 모듈 | 설명 |
|---|---|
ast.NodeTransformer |
NodeVisitor를 상속하며, AST 노드를 수정할 수 있음 |
[ast.parse](/doc/%EA%B8%B0%EC%88%A0/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/%ED%8C%8C%EC%9D%B4%EC%8D%AC%20%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC/ast.parse)() |
소스 코드를 AST로 변환 |
[ast.dump](/doc/%EA%B8%B0%EC%88%A0/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/%EB%94%94%EB%B2%84%EA%B9%85/ast.dump)() |
AST 구조를 문자열로 출력 (디버깅용) |
[ast.walk](/doc/%EA%B8%B0%EC%88%A0/%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B3%BC%ED%95%99/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98/ast.walk)() |
모든 노드를 깊이 우선으로 순회 (단순 순회용) |
참고 자료
- Python 공식 문서: ast 모듈
- Green Tree Snakes – 파이썬 AST 이해하기
- AST를 활용한 파이썬 도구 만들기, Real Python 블로그
ast.NodeVisitor는 파이썬의 동적 특성에도 불구하고 정적 분석이 가능하도록 해주는 강력한 도구이며, 고급 개발 도구 및 린터, IDE 기능 구현에 없어서는 안 될 존재입니다.
이 문서는 AI 모델(qwen-3-235b-a22b-instruct-2507)에 의해 생성된 콘텐츠입니다.
주의사항: AI가 생성한 내용은 부정확하거나 편향된 정보를 포함할 수 있습니다. 중요한 결정을 내리기 전에 반드시 신뢰할 수 있는 출처를 통해 정보를 확인하시기 바랍니다.