본문 바로가기
C.W.K.
Stream
Lesson 04 of 06 · published

코드 생성 평가

~18 min · systems, code, execution

Level 0추측자
0 XP0/55 lessons0/10 achievements
0/150 XP to next level150 XP to go0% complete

코드는 평가하기 가장 쉬우면서도 가장 어려운 출력이야

쉬운 이유는 직접 실행할 수 있기 때문이야. 어려운 이유는 코드가 실행된다는 사실만으로는 충분하지 않기 때문이지. 테스트를 통과한다고 해서 좋은 코드라는 뜻은 아니야. 세 가지 품질 계층을 모두 살펴야 해.

계층 1: 실행 정확성

생성된 코드를 실행하고 단위 테스트 결과를 확인해. pass@k는 k개 표본 가운데 하나 이상이 모든 테스트를 통과할 확률을 측정해. HumanEval과 SWE-bench가 이 방식을 사용해.

계층 2: 코드 품질

  • 정적 분석 — 린터, 유형 검사기, 보안 검사기를 사용해. Bandit과 Semgrep이 대표적이야.
  • 스타일 — Ruff, Prettier, Black으로 확인해. 버그를 직접 찾지는 않지만 "사람이 이 PR을 받아들일까?"를 판단하는 신호가 돼.
  • 복잡도 — 순환 복잡도와 중첩 깊이를 측정해.
  • 문서화 — 문서 문자열, 주석, 유형 주석을 확인해.

계층 3: 테스트 너머의 동작 정확성

생성된 코드가 테스트를 통과하더라도 실제 의도와 일치하는지 확인해야 해. LLM 판정 모델로 구현과 자연어 명세를 비교할 수 있어. "올바르게 보이지만 실제로는 틀린" 버그 대부분이 이 계층에 숨어 있어.

원칙: 생성된 코드는 항상 격리 환경에서 실행해. 린터도 반드시 실행하고, 판정 모델로 구현과 의도가 일치하는지도 확인해. 계층 하나라도 건너뛰면 잡을 수 있었던 버그가 배포될 수 있어.

코드에 특화된 안전성 점검

생성된 코드에는 명령 주입, SQL 주입, 하드코딩된 비밀값, 안전하지 않은 역직렬화, 안전하지 않은 의존성 문제가 있을 수 있어. Semgrep, Bandit, npm audit 같은 보안 검사를 코드 평가에 포함해야 해. 나중에 덧붙일 일이 아니야.

Code

pass@k 계산·python
import math
import itertools

def pass_at_k(n, c, k):
    """Standard HumanEval-style pass@k. n=samples, c=correct, k=evaluation k."""
    if n - c < k:
        return 1.0
    return 1.0 - math.comb(n - c, k) / math.comb(n, k)

# Generate n samples for each problem; run tests; count correct.
# Then compute pass@1, pass@10, pass@100 from the same data.
results = []
for problem in benchmark:
    samples = [model.generate(problem) for _ in range(20)]
    n_correct = sum(run_tests(s, problem.tests) for s in samples)
    results.append({
        "problem": problem.id,
        "pass@1": pass_at_k(20, n_correct, 1),
        "pass@10": pass_at_k(20, n_correct, 10),
    })
코드 평가에 보안 검사 포함하기·python
import subprocess, tempfile, os

def security_scan(code: str):
    with tempfile.NamedTemporaryFile(suffix=".py", delete=False) as f:
        f.write(code.encode())
        path = f.name
    try:
        # bandit for Python security antipatterns
        result = subprocess.run(
            ["bandit", "-q", "-f", "json", path],
            capture_output=True, text=True,
        )
        # also: semgrep, ruff, mypy --strict
    finally:
        os.unlink(path)
    return result.stdout
격리된 환경에서 테스트 실행하기·python
import subprocess, tempfile, os, signal

def run_in_sandbox(code: str, test_code: str, timeout=10):
    """Run with subprocess timeout. For real safety use Docker/firejail."""
    with tempfile.TemporaryDirectory() as d:
        with open(f"{d}/sol.py", "w") as f:
            f.write(code)
        with open(f"{d}/test.py", "w") as f:
            f.write(test_code)
        try:
            r = subprocess.run(
                ["python", f"{d}/test.py"],
                capture_output=True, text=True, timeout=timeout,
                cwd=d,
            )
            return r.returncode == 0, r.stdout + r.stderr
        except subprocess.TimeoutExpired:
            return False, "timeout"

External links

Exercise

한 소규모 도메인에서 20개 과제로 구성된 코드 평가 모음을 만들어. 생성된 해결책마다 실행 정확성, 정적 검사 및 보안 검사 통과 여부, 의도 일치 여부를 평가해. 의도 일치는 LLM 판정 모델로 확인하고, 과제마다 세 점수를 각각 보고해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.