[바이브 코딩] 3. 리뷰 : AI가 짠 코드 믿어도 되나

바이브 코딩 실전 3편 - AI 코드 믿어도 되나

작성자

카테고리:

* 이 게시물은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

(바이브 코딩 ③) 리뷰

AI 코드의 제일 위험한 특성은 “틀린 티가 안 난다”는 거다. 대놓고 깨지면 차라리 낫다. 문제는 그럴듯하게 잘 짠 것 같은데 미묘하게 어긋난 경우다. 이걸 걸러내는 게 바이브 코딩에서 사람이 하는 핵심 일이다.

자주 나오는 함정 몇 가지. AI가 존재하지 않는 라이브러리나 함수를 자신 있게 부른다. 학습 시점 기준의 오래된 API를 써서 지금은 안 도는 코드를 준다. 겉보기엔 멀쩡한데 경계값이나 예외 처리가 비어 있다. 그리고 은근히 잦은 게, 입력 검증을 건너뛰어 보안 구멍을 남기는 거다.

예를 들어 AI가 이런 걸 자신 있게 준다. 얼핏 멀쩡해 보인다.

# 빈 리스트가 들어오면 ZeroDivisionError
def average(nums):
    return sum(nums) / len(nums)

# requests에 없는 인자를 있는 것처럼 쓴다
requests.get(url, retries=3)   # retries 인자는 존재하지 않는다

그래서 검수 요령은 뻔하지만 확실하다. 첫째, 일단 돌려봐라. 눈으로 읽고 “맞네” 하지 말고 실제로 실행하고 테스트를 통과시켜라. 둘째, 의존성을 확인하라. import한 게 진짜 있는 패키지인지, 버전이 맞는지 본다. 셋째, 경계와 실패 경로를 물어라. “입력이 비어 있으면?”, “네트워크가 끊기면?”을 직접 확인한다.

채용 공고에서도 “AI가 생성한 코드를 평가하는 능력”을 요구 역량으로 적는 곳이 눈에 띄게 늘었다. 코드를 짜는 것보다, 짜여진 코드가 맞는지·안전한지 판단하는 쪽으로 무게가 옮겨간 거다.

AI 코드를 PR처럼 대하라

가장 안전한 태도는 AI가 낸 코드를 동료가 올린 Pull Request로 보는 것이다. 통째로 믿고 머지하지 말고, 무엇을 하려는지 읽고 코드베이스와 대조하며 버그·중복·불필요한 패턴을 찾는다. 요즘은 아예 다른 AI에게 그 코드를 리뷰시켜 1차로 훑게 하기도 한다. 그래도 최종 판단은 사람이 한다.

비밀키는 프롬프트에도, 코드에도 두지 마라

특히 API 키·DB 비밀번호·토큰은 프롬프트나 코드에 절대 넣지 않는다. 시크릿 매니저나 환경변수로 빼두고, AI에겐 YOUR_API_KEY 같은 자리표시자만 준다. 기억할 것 하나 — 보안 결함은 프롬프트를 잘 쓴다고 사라지지 않는다. 생성 이후의 리뷰와 테스트에서 잡아야 한다.

테스트가 안전망이다

여러 조사에서 바이브 코딩이 가장 자주 건너뛰는 단계로 QA를 꼽는다. 표준 체크리스트가 없어서다. 그런데 사람이 한 줄씩 치지 않았을수록 자동 테스트는 더 중요하다. 핵심 경로부터 테스트를 깔아두면, AI가 다음에 코드를 고쳐도 무엇이 깨졌는지 즉시 드러난다. 이게 바이브 코딩을 지속 가능하게 만드는 안전망이다. 이어서 무너지는 지점을 본다.

해부 — ‘멀쩡해 보이는’ 코드 하나

전형적인 예를 하나 해부하자. AI에게 “URL에서 JSON 받아서 저장해줘”라고 하면 이런 코드가 온다.

# AI가 낸 첫 버전 — 얼핏 완벽하다
def fetch_and_save(url, path):
    data = requests.get(url).json()
    with open(path, "w") as f:
        json.dump(data, f)

돌아는 간다. 문제는 실패 경로가 전부 비어 있다는 것 — ① 타임아웃이 없어 서버가 늘어지면 영원히 매달린다 ② 404·500에도 .json()을 시도해 엉뚱한 예외가 난다 ③ 쓰다 실패하면 파일이 반쯤 깨진 채 남는다. “타임아웃·상태코드·부분 쓰기 처리해줘”라고 되물으면 이렇게 바뀐다.

def fetch_and_save(url, path):
    r = requests.get(url, timeout=10)
    r.raise_for_status()                      # 404/500이면 여기서 실패
    tmp = path + ".tmp"
    with open(tmp, "w") as f:
        json.dump(r.json(), f)
    os.replace(tmp, path)                     # 원자적 교체 — 반쯤 깨진 파일 없음

두 버전의 차이가 곧 리뷰 포인트다 — AI는 행복 경로는 잘 짜고 실패 경로는 시키기 전까지 안 짠다. 그래서 리뷰의 절반은 “안 되는 경우”를 묻는 일이다.

리뷰 체크리스트

매번 무엇을 볼지 헷갈리면 이 순서로 훑는다. 짧지만 대부분의 사고를 여기서 막는다.

  • 비밀키·토큰이 코드나 프롬프트에 노출됐나?
  • 입력 검증·이스케이프가 있나? (주입 공격 여지)
  • 빈 값·null·큰 입력 같은 경계 조건을 다뤘나?
  • 존재하지 않는 라이브러리·함수를 부르지 않았나?
  • 핵심 경로에 테스트가 있나?
  • 기존 코드와 중복되거나, 불필요하게 복잡하지 않나?

팁 하나. AI한테 검수까지 시킬 거면 “문제 있으면 다 말해, 사소한 것도, 확신 없는 것도”라고 넉넉하게 풀어주는 게 낫다. “중요한 것만 말해”라고 하면 요즘 모델은 그 지시를 곧이곧대로 따라서 애매한 걸 스스로 걸러버린다. 일단 다 꺼내게 하고, 거르는 건 그다음이다. 그래야 놓치는 게 준다.

자주 묻는 질문 (FAQ)

AI가 짠 코드는 어디를 먼저 봐야 하나요?

경계 조건·에러 처리·보안(입력 검증, 비밀키 노출), 그리고 ‘그럴듯하지만 틀린’ 로직을 우선 확인하고 테스트로 검증하세요.

AI가 짠 코드도 테스트가 필요한가요?

오히려 더 필요합니다. 사람이 한 줄씩 치지 않았을수록 자동 테스트가 안전망 역할을 합니다.

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다