AI가 쓴 코드를 이해하는 연습, 고장 난 지점을 좁혀 보기

노트 위 분기 회로 한 곳을 램프로 비추는 코드 진단 학습 삽화

AI가 코드를 길게 만들어 주면 읽어야 할 문서도 함께 늘어난다. 모든 줄을 혼자 다시 작성할 필요는 없을 것이다. 그렇다고 실행 결과가 이상할 때 어디를 봐야 하는지도 모르면 판단을 통째로 맡기게 된다. 나는 “코드를 이해했다”는 말을 작은 진단 문제로 바꿔 보는 편이 학습 목표를 잡는 데 도움이 된다고 생각한다.

노트 위 분기 회로 한 곳을 램프로 비추는 코드 진단 학습 삽화
주제를 표현한 개념 삽화. Google Gemini 이미지 기능을 사용했습니다.

10월 29일 GeekNews에서 발견한 Adrian Quiroga의 글은 에이전트가 구현을 맡더라도 개발자에게 어떤 지식이 필요한지 묻는다. 작성자가 제시한 경험과 견해이지 모든 개발자의 경력 전망을 검증한 연구는 아니다. 그 글에서 가져올 질문은 지식을 얼마나 외웠느냐보다 이상한 동작을 알아보고 필요한 깊이로 들어갈 수 있느냐에 가깝다.

참고 원문: 관련 원문을 직접 읽기

읽기 과제를 관찰 과제로 바꾸기

가상의 프로그램 하나를 생각해 보자. 입력 목록에서 중복을 제거한 뒤 결과를 저장하는 작은 도구다. AI가 구현을 만들었고 정상 예제에서는 기대한 결과가 나온다고 가정한다. 이때 함수를 처음부터 끝까지 설명할 수 있다는 것 외에 무엇을 이해했다고 말할 수 있을까. 여기서는 실제 생성 도구나 서비스를 시험한 것이 아니라 학습 과제를 설계한다.

첫 과제는 입력을 두 배로 늘렸을 때 어떤 부분이 오래 걸릴지 예상하는 것이다. 예를 들어 자료 수가 10, 20, 40일 때 비교 횟수가 대략 100, 400, 1,600으로 늘어나는 가상의 중첩 반복을 놓아 보자. 이것은 실측 시간이나 특정 구현의 성능 수치가 아니다. 입력 크기와 작업량의 관계를 설명하기 위한 계산이다.

예상과 관찰이 다르면 코드를 전부 고치기 전에 시간을 나눠 볼 수 있다. 파일을 읽는 구간, 중복을 검사하는 구간, 저장하는 구간이다. 어디서 느려졌는지부터 구분하면 “AI 코드가 느리다”는 넓은 설명을 더 작은 질문으로 바꿀 수 있다. 측정 방법도 실제 실행 환경에 맞게 정해야 하며 제안과 실행 기록을 혼동하지 않는다.

한 가지 고장에 두 가지 설명 세우기

두 번째 과제는 틀린 결과의 원인을 두 개 이상 생각하는 일이다. 중복이 남는다면 비교 기준이 다른 것일 수도 있고, 같은 항목을 두 번 읽는 것일 수도 있다. 전자는 값의 의미를, 후자는 입력 경로를 살펴야 한다. 가설을 나누지 않고 함수를 다시 생성하면 문제가 사라져도 왜 사라졌는지 알기 어렵다.

이때 작은 반례가 유용하다. 문자열 앞뒤의 공백이 다른 두 값을 같은 것으로 볼지, 대문자와 소문자를 구분할지 결정해 보자. 이 결정은 언어 문법만으로 나오지 않는다. 도구를 쓰는 사람의 기대와 자료의 성격을 읽어야 한다. 코드 학습과 업무 규칙 학습이 만나는 자리다.

세 번째 과제는 실패를 알아보는 신호를 정하는 것이다. 저장 공간이 부족하거나 입력을 읽을 수 없을 때 정상 결과와 구분되는 상태가 나오는지 묻는다. 성공 화면을 본 것만으로 실패 처리를 이해했다고 할 수는 없다. 별도 시험 환경에서 어떤 오류를 안전하게 재현할 수 있는지 계획하는 과정 자체가 이해의 빈틈을 드러낸다.

모르는 것을 없애기보다 위치를 알기

이 연습에서 모든 내부 구현을 외울 필요는 없다. 대신 지금 모르는 것이 자료 구조인지, 파일 시스템인지, 외부 API의 응답 규칙인지 이름을 붙일 수 있어야 한다. 그래야 문서와 도구에 구체적으로 질문한다. “전체 코드를 설명해 줘”보다 “이 입력에서 비교 기준이 달라지는 위치가 어디인가”라는 질문이 다음 행동으로 이어지기 쉽다.

AI에게 설명을 요청할 때도 같은 입력과 기대 결과를 함께 준다고 제안할 수 있다. 다만 설명을 정답으로 저장하지 말고 원래 문서와 실제 관찰에 대조한다. 그럴듯한 호출 경로를 말해도 현재 실행 중인 코드와 버전이 다르면 소용이 없다. 답변이 아니라 확인할 가설 목록을 얻는다고 생각하면 역할이 분명해진다.

학습 기록은 길지 않아도 된다. 내가 예상한 원인, 그것을 가릴 입력, 관찰한 결과, 아직 모르는 점을 남긴다. 한 번의 연습에서 네 칸을 채우는 것이 수십 개의 새 용어를 모으는 것보다 목표가 분명할 수 있다. 물론 이 방법이 모든 학습자의 성과를 높인다는 실험 결과를 주장하는 것은 아니다. 실천 가능한 진단 과제의 예시다.

개발을 막 시작했다면 작은 함수와 공개 예제에서 연습할 수 있다. 이미 큰 시스템을 다룬다면 평소 고장이 자주 생기는 경계 하나를 고를 수 있다. 범위를 작게 잡아야 예상과 관찰을 연결할 여유가 생긴다. 운영 중인 서비스를 일부러 망가뜨리는 식의 연습은 필요하지 않다.

학습 난도를 조절할 때는 설명할 수 없는 경계를 하나만 남겨 본다. 처음부터 네트워크와 저장소, 병렬 처리를 모두 넣으면 어느 부분에서 예상이 틀렸는지 가리기 어렵다. 작은 입력으로 원인을 가려 본 뒤 다음 경계를 추가하는 편이 피드백을 읽기 쉽다. 자료가 부족하면 답을 빨리 얻는 일보다 다음에 무엇을 관찰할지 정하는 데서 연습을 끝내도 된다.

나는 다음에 코드를 이해했는지 자문할 때 줄마다 설명하는 시험만 하지는 않으려 한다. 이상한 입력 하나를 넣으면 어디가 달라질지, 그 예상이 틀리면 무엇을 먼저 확인할지도 물어보고 싶다. 오늘 읽은 코드에서 그런 질문을 던질 수 있는 가장 작은 부분은 어디일까?

함께 읽기: 작은 프로그램을 읽는 연습