[개발 깨알 상식_Tips]/[바이브코딩 Tips] / Kaggle 노트북: eval cell 먼저 고정.md

Kaggle 노트북: eval cell 먼저 고정

조회

2026년 4월 28일 | 바이브코딩 Tips


Google과 Kaggle이 AI Agents Vibe Coding Course를 다시 연다는 소식을 보고 제일 먼저 든 생각은 강의 일정 자체보다 노트북을 어떻게 굴릴지였다. 공지에는 2026년 6월 15일부터 19일까지 5일 과정, 자연어를 주된 프로그래밍 인터페이스로 쓰는 workflow, tools와 API를 붙이는 capstone 프로젝트가 같이 나온다. 나는 이 흐름을 보면서 “바이브 코딩을 잘하려면 프롬프트를 더 멋지게 쓰는 것보다, 노트북 맨 위에 작은 eval cell을 먼저 박아 두는 게 훨씬 안전하겠다”는 쪽으로 무릎을 쳤다.

공식 글은 무료 5일 과정, hands-on coding project, production-ready agent system을 강조한다. Kaggle 쪽 안내도 models, tools, orchestration, memory, evaluation을 하루씩 쪼개고, 특히 Day 4에서 observability, logging, tracing, metrics를 다룬다고 적어 둔다. 여기서 내가 가져가고 싶은 팁은 하나다. 에이전트에게 구현을 맡기기 전에, 사람이 원하는 동작을 5개 안팎의 테스트 케이스로 먼저 고정한다. 그래야 자연어로 코드를 밀어붙이는 동안 결과가 점점 좋아지는지, 그냥 말만 그럴듯해지는지 빨리 볼 수 있다.

Google and Kaggle AI Agents Vibe Coding Course

Figure 1: Google과 Kaggle이 공개한 AI Agents Vibe Coding Course 대표 이미지.

이 이미지는 과정 자체의 홍보 이미지지만, 내가 눈여겨본 부분은 “vibe coding”이 이제 단순한 유행어가 아니라 노트북, capstone, 평가, 배포까지 이어지는 학습 흐름 안에 들어왔다는 점이다. 그래서 글감도 여러 소식을 나열하지 않고, Kaggle 노트북에서 바로 써먹을 수 있는 작은 작업 계약 하나로 좁혔다.

1. eval cell은 구현 셀보다 위에 둔다

바이브 코딩을 처음 할 때 나는 보통 “이런 에이전트를 만들어 줘”라고 먼저 말하고, 나온 코드를 돌려 본 뒤에야 평가 기준을 생각했다. 이 순서가 편하긴 한데, 문제는 에이전트가 한 번 그럴듯한 구조를 만든 뒤에는 내가 그 구조에 끌려간다는 점이다. 함수 이름, 클래스 경계, 예외 처리 방식이 이미 생기면 “이 정도면 됐나?”라는 질문이 코드 모양에 맞춰져 버린다.

그래서 노트북에서는 첫 번째 구현 셀보다 위에 바꾸면 안 되는 평가 셀을 둔다. 거창한 벤치마크가 아니라도 괜찮다. 내가 만들고 싶은 에이전트가 최소한 지켜야 할 입출력 예시, 반드시 포함해야 하는 단어, 절대 호출하면 안 되는 도구, 실패할 때 남겨야 하는 메시지 정도면 시작점으로 충분하다. 핵심은 “마지막에 평가하자”가 아니라 처음부터 평가 셀을 작업면에 올려 둔다는 쪽이다.

CASES = [
    {
        "name": "짧은 한국어 요약",
        "query": "이 문서를 세 줄로 줄이고, 결정해야 할 항목만 따로 적어 줘.",
        "must_include": ["결정", "다음 행동"],
        "forbid": ["추가 정보가 필요합니다"]
    },
    {
        "name": "도구 호출 전 확인",
        "query": "외부 API로 주문 상태를 조회해 줘.",
        "must_include": ["조회 전 확인", "필요한 식별자"],
        "forbid": ["임의로 조회"]
    },
]

def score_text(answer, case):
    ok = True
    reasons = []
    for token in case["must_include"]:
        if token not in answer:
            ok = False
            reasons.append(f"missing:{token}")
    for token in case["forbid"]:
        if token in answer:
            ok = False
            reasons.append(f"forbidden:{token}")
    return {"ok": ok, "reasons": reasons}

def run_eval(agent_fn):
    rows = []
    for case in CASES:
        answer = agent_fn(case["query"])
        result = score_text(answer, case)
        rows.append({"case": case["name"], "ok": result["ok"], "reasons": result["reasons"], "answer": answer})
    return rows

이 정도 셀 하나만 있어도 에이전트와의 대화가 달라진다. “더 좋게 고쳐 줘”가 아니라 “이 셀은 수정하지 말고, run_eval 결과가 모두 ok가 되게 구현 셀만 고쳐 줘”라고 말할 수 있기 때문이다. 자연어 지시가 느슨해져도 eval cell이 작업의 바닥선을 잡아 준다.

2. Kaggle 노트북에서는 secret과 eval을 분리한다

Kaggle에서 agent 예제를 돌리다 보면 API key, notebook secret, 샘플 데이터, 결과 확인 코드가 한 셀 안에 섞이기 쉽다. 나는 이 구성이 제일 불안하다. 에이전트에게 “고쳐 줘”라고 했을 때, 모델 호출부를 만지다가 secret 로딩 코드나 평가 케이스까지 같이 건드릴 수 있기 때문이다. 그래서 셀을 세 덩어리로 나누는 편이 좋다.

  • Setup cell: 패키지 설치, secret 로딩, 클라이언트 생성만 둔다.
  • Eval cell: 케이스와 채점 함수만 둔다. 이 셀은 에이전트에게 수정 금지라고 말한다.
  • Implementation cell: 실제 agent_fn 구현만 둔다. 바이브 코딩은 이 셀에서만 돌린다.
python -m pip install -q google-genai
from kaggle_secrets import UserSecretsClient

secrets = UserSecretsClient()
GOOGLE_API_KEY = secrets.get_secret("GOOGLE_API_KEY")

명령어와 secret 셀을 위처럼 따로 빼 두면, 구현을 여러 번 갈아엎어도 인증 쪽이 같이 흔들리지 않는다. 특히 capstone처럼 며칠에 걸쳐 이어지는 작업에서는 이 분리가 생각보다 크다. 어제 만든 코드가 마음에 안 들어서 구현을 다시 짜도, 평가 케이스와 secret 표면은 그대로 남아 있어야 비교가 된다.

3. 프롬프트에도 “평가 셀 불변”을 적는다

노트북 구조를 나눴다면, 에이전트에게 주는 첫 요청도 짧게 고정한다. 나는 이런 식으로 쓴다. “위의 eval cell은 테스트 계약이다. CASES와 score_text, run_eval은 수정하지 마라. Implementation cell 안의 agent_fn만 바꿔서 모든 케이스를 통과시켜라. 실패하면 어떤 케이스가 왜 실패했는지 먼저 요약하고, 그다음 수정하라.” 별것 아닌 문장인데, 이게 있으면 에이전트가 평가 기준을 자기 편한 쪽으로 바꾸는 일을 꽤 줄일 수 있다.

여기서 중요한 건 테스트가 완벽해야 한다는 말이 아니다. 오히려 처음 테스트는 허술해도 된다. 다만 허술한 테스트라도 작업 중간에 마음대로 움직이지 않는 기준점으로 두면, 바이브 코딩이 “느낌대로 계속 고치기”에서 “작은 계약을 통과시키며 넓히기”로 바뀐다. 나는 이 차이가 초보자용 팁이 아니라, 실제 에이전트 작업을 오래 끌고 갈 때의 생존선에 가깝다고 본다.

4. 실패 로그는 예쁘게 만들지 말고 납작하게 남긴다

에이전트 평가 결과를 처음부터 대시보드처럼 꾸미려고 하면 일이 커진다. Kaggle 노트북에서는 일단 리스트나 DataFrame으로 납작하게 남기는 쪽이 낫다. 케이스 이름, 성공 여부, 실패 이유, 실제 답변만 있어도 다음 프롬프트가 훨씬 구체적이 된다. 예를 들어 “도구 호출 전 확인 케이스에서 forbidden:임의로 조회가 떴다. 외부 API를 실제 호출하기 전에 필요한 식별자와 확인 문장을 먼저 요구하도록 바꿔라”처럼 말할 수 있다.

rows = run_eval(agent_fn)
for row in rows:
    print(row["case"], row["ok"], row["reasons"])

이 출력이 너무 단순해 보여도 괜찮다. 바이브 코딩에서는 오히려 단순한 로그가 좋다. 실패 이유가 한 줄로 남아야 다음 지시가 짧아지고, 다음 지시가 짧아야 에이전트가 엉뚱한 파일이나 셀을 덜 만진다. Google과 Kaggle의 과정이 tools, API, memory, evaluation을 묶어 다룬다는 점도 결국 이 방향과 맞닿아 있다. 에이전트가 똑똑해질수록 평가를 나중으로 미루는 게 아니라, 작게라도 먼저 밖에 꺼내 둬야 한다.

5. 내가 가져갈 실제 체크리스트

  • 노트북 첫 부분에 “수정 금지 eval cell”을 만든다.
  • 케이스는 3~7개로 시작하고, must_include와 forbid를 같이 둔다.
  • secret 로딩 셀과 구현 셀을 분리한다.
  • 에이전트에게는 “eval cell은 수정하지 말고 implementation cell만 바꾸라”고 명시한다.
  • 실패 로그는 case, ok, reasons, answer 정도로 납작하게 남긴다.

출처는 Google Keyword의 AI Agents Vibe Coding Course 공지와 Kaggle의 과정 안내 페이지다. 등록이나 일정 자체도 유용하지만, 나는 그보다 바이브 코딩을 노트북 평가 루프 안에 넣어야 한다는 메시지를 더 크게 가져간다. 다음에 에이전트 노트북을 새로 열면, 구현 셀보다 eval cell을 먼저 쓸 생각이다.

댓글

홈으로 돌아가기

검색 결과

"" 검색 결과입니다.