Devin.KR

혼자가 아닌 작업 - 버전 관리·리뷰·문서의 기본기

개발자KR 조회 0

이 장에서 배우는 것

앞 장에서 프로그램을 입력부터 출력까지 이어지는 흐름으로 살펴보았다. 이제 그 프로그램을 다른 사람과 함께 바꾸는 상황을 생각해 본다. 혼자 만든 작은 학습 기록장도 시간이 지나면 이전의 내가 쓴 코드, 오늘의 내가 고친 코드, AI가 제안한 코드가 뒤섞인다. 변경 이유를 기억하지 못하면 잘 동작하던 부분까지 다시 확인해야 한다. 함께 일한다는 것은 여러 사람이 동시에 키보드를 두드리는 일만 뜻하지 않는다. 변경을 남기고, 서로 읽고, 다음 사람이 이어서 작업할 수 있게 만드는 일이다.

변경을 기록하고 돌아갈 지점을 마련하면 새로운 방법을 시도하기가 쉬워진다. 실패한 시도를 없었던 일로 숨기는 대신 무엇을 바꿨고 왜 되돌렸는지 설명할 수 있다. AI가 코드 작성을 돕는 상황에서도 이 역할은 남는다. 개발자의 일은 코드 입력뿐 아니라 변경의 범위를 정하고, 결과를 확인하고, 다른 사람이 이해할 근거를 남기는 방향으로 바뀐다.

  • 버전 관리가 변경 기록과 되돌리기에 어떤 도움을 주는지 설명한다.
  • 커밋, 브랜치, 변경 비교를 서로 다른 역할로 구분한다.
  • 리뷰에서 의도, 동작, 위험을 나누어 질문한다.
  • 사람과 AI가 함께 읽는 지침 문서와 README의 역할을 구분한다.
  • 두 코드의 바뀐 줄을 출력하는 프로그램을 실행하고, 그 출력만으로 알 수 없는 점도 찾는다.

문제 상황

한 팀이 학생용 학습 기록장을 만든다고 하자. 학생이 하루 학습 시간을 입력하면 짧은 안내 문장을 보여 주는 프로그램이다. 원래는 60분 이상 공부했을 때 “오늘 목표 달성”이라고 표시했다. 팀에서 목표 시간을 45분으로 바꾸기로 했고, 한 사람이 AI에게 수정을 요청했다. 이 숫자들은 설명을 위한 가상값이며, 적절한 학습 시간을 권하는 기준이 아니다.

학습 기록 함수에서 목표 시간을 60분에서 45분으로 바꿔 줘. 함수 이름과 출력 문장은 유지해 줘.

AI가 내놓은 코드는 목표 시간만 바꾼 것이 아니었다. 음수 시간을 넣으면 오류를 내는 처리도 추가했다. 잘못된 입력을 막겠다는 의도는 이해할 만하다. 하지만 기존 화면은 오류가 나면 사용자에게 안내하지 못하고 멈추도록 만들어져 있었다. 함수 안에서는 합리적으로 보이는 수정이 전체 사용 흐름에서는 문제가 될 수 있다.

수정한 사람이 파일 전체를 덮어쓰고 “개선 완료”라는 말만 남겼다면 동료는 무엇이 달라졌는지 처음부터 찾아야 한다. 반대로 이전 버전과 수정 버전을 비교하고, 목표 시간 변경과 입력 처리 변경을 구분해 적었다면 확인할 대상이 분명해진다. 지금 필요한 것은 더 긴 코드가 아니라 변경을 설명하는 방법이다.

리뷰를 맡은 동료도 답을 대신 정해 주는 사람이 아니다. “45분이 요청한 기준인가”, “음수 입력에서 달라지는 동작을 화면이 처리할 수 있는가”, “이 두 변경을 함께 반영해야 하는가”를 묻는 사람이다. 코드를 쓴 사람과 읽는 사람이 판단 근거를 나누면 혼자서는 놓치기 쉬운 가정을 발견할 수 있다.

변경을 남기는 세 가지 단위

버전 관리(version control)는 파일이 어떻게 바뀌었는지 기록하고 여러 작업의 관계를 관리하는 방법이다. 널리 쓰이는 도구인 Git을 예로 개념을 살펴보되, 이 장에서는 설치나 명령어 암기를 요구하지 않는다. 먼저 무엇을 남기고 무엇을 비교하는지 이해하면 이후에 도구를 배울 때 목적을 놓치지 않는다.

커밋은 설명할 수 있는 변경의 묶음이다

커밋(commit)은 선택한 파일의 상태를 기록에 남기는 단위다. 파일을 저장하는 것과는 다르다. 저장은 작업 중인 파일 내용을 바꾸는 일이고, 커밋은 그중 어떤 상태를 기록으로 삼을지 정하는 일이다. 저장했다고 모든 변화가 버전 관리 기록에 들어가는 것은 아니다.

좋은 커밋은 한 가지 이유로 설명하기 쉽다. 목표 시간을 바꾸는 일과 화면 색상을 바꾸는 일을 한꺼번에 묶으면, 목표 시간만 되돌리고 싶을 때 처리가 번거로워진다. 반대로 함께 바뀌어야 동작하는 함수와 그 사용 부분은 같은 변경으로 묶는 편이 이해하기 쉽다. 줄 수가 작다는 이유만으로 잘 나눈 커밋이 되는 것은 아니다.

기록에는 무엇을 바꿨는지뿐 아니라 왜 바꿨는지도 남긴다. “수정”보다는 “학습 목표 기준을 45분으로 조정”이 읽는 사람에게 도움이 된다. 음수 입력 처리까지 포함했다면 그 이유와 확인 결과도 적어야 한다. 제목에 적지 못한 별도 목적이 계속 생긴다면 변경을 나눌 필요가 있는지 살펴본다.

브랜치는 작업의 흐름을 나누는 이름이다

브랜치(branch)는 특정 기록을 가리키며 별도의 변경 흐름을 이어 가게 하는 이름이다. 기본 작업 흐름에서 새 방법을 시험하는 흐름을 나누면, 현재 사용 중인 버전과 실험 중인 버전을 구분하기 쉽다. 브랜치를 폴더 전체의 독립적인 복사본으로 생각하기보다는 기록의 출발점과 진행 방향을 표시하는 이름으로 이해하면 좋다.

실험이 끝나면 변경을 기본 흐름에 합칠지 결정한다. 같은 부분을 서로 다르게 바꿨다면 도구가 사람에게 선택을 요구할 수 있다. 이때 필요한 것은 더 최근에 입력한 글을 무조건 고르는 일이 아니라 두 수정의 의도를 이해하는 일이다. 브랜치가 판단을 대신해 주지는 않는다.

되돌리기도 같은 관점으로 본다. 개인 실험에서는 이전 상태로 돌아가 다시 시도할 수 있다. 이미 동료와 공유한 기록에서는 기존 기록을 지우기보다 변경을 취소하는 새 기록을 남기는 방법이 협업에 유용하다. 또 기록에 넣지 않은 파일이나 외부에 저장한 데이터는 코드의 기록만으로 복구되지 않는다. 시도하기 전에 무엇이 기록 대상인지 확인해야 한다.

브랜치는 공통 기록에서 작업 흐름을 나누며, 검토한 변경을 합칠 때 새 기록을 남길 수 있다

변경 비교는 질문할 위치를 보여 준다

변경 비교(diff)는 두 상태의 차이를 보여 주는 표현이다. 파일 전체를 다시 읽는 대신 추가된 줄과 삭제된 줄을 중심으로 살펴볼 수 있다. 앞에 붙은 빼기 표시는 이전 버전에서 빠진 줄, 더하기 표시는 수정 버전에 들어간 줄을 뜻한다. 내용이 같은 주변 줄도 함께 나오는데, 변경이 어느 위치에 놓였는지 이해하도록 돕는다.

비교 결과는 변경 이유나 올바름까지 알려 주지는 않는다. 숫자 하나를 바꾼 수정도 사용자에게 큰 영향을 줄 수 있고, 긴 주석 수정은 실행 결과에 영향을 주지 않을 수 있다. 비교는 읽을 위치를 좁혀 주는 자료다. 판단하려면 요청한 내용과 실제 동작을 연결해야 한다.

커밋, 브랜치, 변경 비교가 답하는 질문
개념답하는 질문학습 기록장 예시
커밋어떤 상태를 어떤 이유로 남겼는가목표 시간을 조정한 상태를 기록한다.
브랜치어느 기록에서 어떤 작업을 이어 가는가새 입력 처리 방법을 별도로 시험한다.
변경 비교두 상태에서 어느 줄이 달라졌는가기준 변경과 오류 처리 추가를 찾아낸다.

리뷰는 의도·동작·위험을 함께 읽는 일이다

코드 리뷰(code review)는 다른 사람이 변경을 읽고 질문하며 반영 여부를 검토하는 과정이다. 오타를 찾는 일도 포함하지만, 읽기 좋은 모양만 확인하는 활동은 아니다. 무엇을 하려는 변경인지, 실제로 어떻게 동작하는지, 주변에 어떤 영향을 주는지를 함께 살핀다.

먼저 의도를 확인한다. 요청한 것은 목표 시간 조정인데 음수 입력 처리까지 들어갔다면 범위가 넓어진 것이다. 그 수정이 도움이 되더라도 별도 설명이 필요하다. “좋은 기능이니까 넣는다”는 판단보다 “지금 합의한 변경에 포함되는가”라는 질문이 먼저다. 요청에 없는 수정은 분리해서 검토하는 방법도 있다.

다음으로 동작을 확인한다. 45분 이상이라는 조건이라면 44분, 45분, 46분에서 어떤 문장이 나오는지 실행해 본다. 조건의 바로 아래와 같은 값, 바로 위의 값은 비교 기호를 잘못 쓴 경우를 드러내기 쉽다. 음수 입력을 처리한다면 실제로 어떤 오류가 발생하는지도 확인한다. AI가 “검사를 마쳤다”고 말했더라도 실행한 입력과 관찰한 결과가 있어야 판단할 수 있다.

마지막으로 위험을 확인한다. 여기서 위험은 막연한 걱정이 아니라 변경으로 영향을 받는 구체적인 지점이다. 안내 문장만 받던 화면이 새 오류를 처리할 수 있는지, 다른 곳에서도 같은 함수를 부르는지, 목표 기준을 설명하는 문서도 함께 바뀌어야 하는지 살펴본다. 앞 장에서 보았던 흐름을 변경 전후에 다시 따라가는 셈이다.

리뷰 의견은 사람의 성격이나 실력을 평가하는 문장보다 확인할 수 있는 질문으로 쓴다. “생각 없이 바꿨다”는 말 대신 “음수 입력에서 새 오류가 발생하는데 호출 화면에 처리 코드가 있는가”라고 묻는다. 작성자는 이유를 설명하거나 수정할 수 있고, 리뷰한 사람도 새로운 근거를 보고 의견을 바꿀 수 있다.

45분 기준으로 바뀐 부분은 요청과 일치한다. 음수 입력 처리는 별도 동작 변경이다. 이 함수를 부르는 화면이 오류를 처리하는지 확인한 결과를 남겨 달라.

같은 변경을 의도, 동작, 위험이라는 세 질문으로 읽으면 확인 근거를 구체화할 수 있다

AI에게도 같은 질문으로 검토를 요청할 수 있다. 다만 AI의 리뷰 의견은 확인할 후보이지 승인 근거 전체가 아니다. 실제로 없는 호출 부분을 있다고 가정하거나, 요청에 없는 개선을 권할 수 있다. 사람은 관련 코드를 읽고 예시 입력을 실행하며 의견이 이 프로그램에 맞는지 확인한다.

이 변경을 의도, 동작, 위험으로 나누어 검토해 줘. 확인할 수 있는 사실과 추가 자료가 필요한 판단을 구분해 줘. 특히 목표 기준 변경 외에 추가된 동작을 찾아 줘.

지침 문서와 README는 다음 작업을 돕는다

지침 문서는 이 작업에서 지켜야 할 약속을 적는 문서다. 예를 들어 “외부 패키지를 추가하지 않는다”, “요청 범위 밖의 동작 변경은 따로 설명한다”, “실행 명령과 확인 결과를 남긴다” 같은 내용을 담을 수 있다. 사람과 AI가 같은 약속을 읽으면 매번 대화에서 조건을 반복하는 부담이 줄어든다.

약속은 실행할 수 있을 만큼 구체적으로 쓴다. “좋은 코드를 작성한다”는 문장은 무엇을 확인해야 할지 알려 주지 않는다. “함수의 입력이나 출력이 바뀌면 그 함수를 사용하는 곳을 확인한다”는 문장은 확인 대상을 제시한다. 지침은 길게 적는 것보다 현재 작업에 필요한 기준을 찾기 쉽게 유지하는 것이 중요하다.

README는 프로젝트를 처음 여는 사람에게 목적과 사용 방법을 안내하는 문서다. 무엇을 하는 프로그램인지, 어떤 환경이 필요한지, 어떻게 실행하는지, 어떤 결과가 나와야 하는지 적는다. 이 장의 도구라면 “코드 두 버전의 줄 차이를 보여 주는 예시이며, Git 기록을 만들거나 함수의 동작을 자동 검증하지 않는다”는 한계도 설명해야 한다.

두 문서는 역할이 다르지만 연결된다. 지침 문서에는 변경할 때의 약속을 두고, README에는 현재 프로그램의 사용 정보를 둔다. 실행 방식이 바뀌면 README도 수정한다. 지침과 실제 코드가 어긋나면 어느 쪽이 현재 합의인지 확인하고 고친다. 문서를 읽었다는 사실만으로 코드가 그 약속을 지켰다고 판단하지 않는다.

사람과 AI가 함께 읽는 문서의 역할
문서담을 내용이 예시에서의 문장
지침 문서작업 범위와 확인 약속요청 외 동작 변경은 이유와 영향 범위를 설명한다.
README목적, 환경, 실행법, 한계Python 3.12 이상에서 main.py를 실행한다.
변경 기록이번 수정의 이유와 확인 결과목표 기준을 바꾸고 경계값의 결과를 확인했다.

AI가 어떤 파일을 자동으로 읽는지는 사용하는 환경에 따라 다르다. 파일을 만들었다고 전달되었다고 가정하지 말고, 작업에 필요한 지침이 실제 입력에 포함되었는지 확인한다. 여기서 제시하는 요청문은 2026년 10월 기준 예시다. 특정 제품의 자동 읽기 기능에 기대지 않고 약속을 전달하고 결과를 확인하는 원리를 연습한다.

완성 코드

다음 코드를 main.py로 저장한다. macOS나 Linux에서 Python 3.12 이상으로 실행할 수 있으며 표준 라이브러리만 사용한다. 표준 라이브러리는 Python에 함께 들어 있는 도구 모음이다. 그중 difflib는 글이나 코드의 차이를 비교하는 기능을 제공한다.

이 프로그램은 학습 기록 함수의 이전 코드와 수정 코드를 문자열, 즉 글자 데이터로 보관한다. 두 문자열의 문법을 확인한 뒤 바뀐 줄과 리뷰 질문을 출력하고 끝난다. 비교 대상 함수를 실행하거나 파일을 되돌리는 기능은 없다. 예시의 60분과 45분은 설명용 가상값이다.

import difflib

before_lines = [
    "def learning_message(minutes):",
    "    if minutes >= 60:",
    '        return "오늘 목표 달성"',
    '    return "조금 더 학습"',
]
after_lines = [
    "def learning_message(minutes):",
    "    if minutes < 0:",
    '        raise ValueError("학습 시간은 음수일 수 없음")',
    "    if minutes >= 45:",
    '        return "오늘 목표 달성"',
    '    return "조금 더 학습"',
]

before = "\n".join(before_lines) + "\n"
after = "\n".join(after_lines) + "\n"
compile(before, "이전/main.py", "exec")
compile(after, "수정/main.py", "exec")

questions = [
    "의도: 목표 기준을 45분으로 바꾸기로 합의했는가?",
    "동작: 44분, 45분, 46분의 결과를 실행해 확인했는가?",
    "위험: 음수 입력의 오류를 호출 화면이 처리하는가?",
    "문서: 목표 기준과 입력 처리 설명을 함께 바꿨는가?",
]

print("학습 기록 함수 변경 검토")
print("구문 검사: 두 버전 통과")
print()
changes = list(
    difflib.unified_diff(
        before.splitlines(),
        after.splitlines(),
        fromfile="이전/main.py",
        tofile="수정/main.py",
        lineterm="",
    )
)
for line in changes:
    print(line)
print()
print("리뷰 질문")
for number, question in enumerate(questions, start=1):
    print(f"{number}. {question}")

코드 안에 들어 있는 이전 함수와 수정 함수는 모두 새로 작성한 예시다. 이번 비교에서는 수정안에 요청 밖의 변경을 일부러 포함했다. 출력이 나왔다는 이유로 수정안을 곧바로 채택하지 않고, 어디까지 확인했는지 구분하는 연습을 하기 위해서다.

줄별 해설

아래 줄 번호는 빈 줄도 포함한다. 따옴표 안의 코드는 비교할 자료이며, 그 바깥의 코드가 비교 도구를 실행한다. 이 둘을 구분하면 함수가 왜 바로 실행되지 않는지 이해할 수 있다.

완성 코드의 각 줄이 하는 일
줄하는 일읽을 때 확인할 점
1difflib를 가져온다.외부 설치 없이 Python에 포함된 기능을 사용한다.
2빈 줄이다.가져오기와 자료 준비를 나누어 보여 준다.
3이전 코드의 줄 목록을 시작한다.대괄호는 여러 값을 순서대로 담는 목록을 만든다.
4함수를 정의하는 줄을 글자로 담는다.minutes는 함수가 받을 학습 시간의 이름이다.
5기존 조건을 담는다.60 이상인지 묻는 조건이며 앞 공백도 자료에 포함된다.
6조건을 만족했을 때 돌려줄 문장을 담는다.바깥 작은따옴표와 안쪽 큰따옴표를 구분한다.
7조건을 만족하지 않을 때의 문장을 담는다.들여쓰기가 앞 줄보다 얕다.
8이전 코드 목록을 닫는다.여기까지가 비교할 첫 번째 자료다.
9수정 코드 목록을 시작한다.이전 목록과 별도로 유지한다.
10같은 함수 정의를 담는다.함수 이름과 입력 이름은 유지한다.
11음수인지 묻는 새 조건을 담는다.요청한 목표 시간 변경과 다른 목적의 조건이다.
12음수일 때 오류를 발생시키는 줄을 담는다.ValueError는 적절하지 않은 값임을 알리는 오류 종류다.
13수정한 목표 조건을 담는다.기준이 60에서 45로 달라졌다.
14목표 달성 문장을 담는다.기존 문장은 그대로다.
15추가 학습 문장을 담는다.이 문장도 그대로다.
16수정 코드 목록을 닫는다.음수 처리로 전체 줄 수가 늘어났다.
17빈 줄이다.줄 목록과 문자열 변환을 나눈다.
18이전 목록을 하나의 문자열로 합친다.\n은 줄바꿈이며 마지막에도 줄바꿈을 붙인다.
19수정 목록도 같은 방식으로 합친다.두 자료를 같은 방식으로 준비한다.
20이전 문자열의 구문을 검사한다.구문은 코드 작성 규칙이며 함수의 결과까지 검사하지 않는다.
21수정 문자열의 구문을 검사한다.exec는 여러 문장으로 된 코드를 검사할 모드 이름이다.
22빈 줄이다.구문 검사와 질문 준비를 나눈다.
23리뷰 질문 목록을 시작한다.질문을 순서대로 출력할 자료다.
24의도에 관한 질문을 담는다.목표 기준이 합의와 일치하는지 묻는다.
25동작에 관한 질문을 담는다.조건의 경계 주변에서 실행했는지 묻는다.
26위험에 관한 질문을 담는다.함수 밖의 호출 화면까지 확인하게 한다.
27문서에 관한 질문을 담는다.실제 동작과 설명이 함께 바뀌었는지 묻는다.
28질문 목록을 닫는다.질문은 자동 판정 결과가 아니다.
29빈 줄이다.자료 준비와 출력을 나눈다.
30출력 제목을 표시한다.무엇을 검토하는 출력인지 알려 준다.
31구문 검사 통과를 표시한다.앞의 검사에서 오류가 나면 이 줄에 도달하지 않는다.
32빈 줄을 출력한다.제목과 비교 결과 사이를 띄운다.
33비교 결과를 목록으로 모으기 시작한다.여러 줄의 결과를 차례로 보관한다.
34주변 줄을 포함하는 비교 기능을 호출한다.unified_diff가 두 자료의 줄 차이를 만든다.
35이전 문자열을 줄 단위로 나눈다.splitlines는 줄 안의 들여쓰기를 유지한다.
36수정 문자열도 줄 단위로 나눈다.이전과 수정의 순서를 유지해야 표시 방향이 맞다.
37이전 자료의 표시 이름을 정한다.실제 파일을 여는 경로가 아니라 출력에 쓰는 이름이다.
38수정 자료의 표시 이름을 정한다.어느 쪽이 수정본인지 알려 준다.
39비교 표시 줄의 끝에 줄바꿈을 추가하지 않게 한다.print가 붙이는 줄바꿈과 중복되지 않도록 한다.
40비교 기능 호출을 닫는다.여러 줄로 나눈 호출의 끝이다.
41목록으로 모으는 호출을 닫는다.changes에 비교 결과가 담긴다.
42비교 결과에서 한 줄씩 꺼낸다.for는 같은 출력을 각 줄에 반복한다.
43꺼낸 비교 줄을 출력한다.앞의 공백과 더하기·빼기 표시도 그대로 출력한다.
44빈 줄을 출력한다.비교 결과와 질문을 나눈다.
45리뷰 질문 제목을 출력한다.이후 내용이 확인할 질문임을 알린다.
46질문과 번호를 함께 꺼낸다.enumerate는 번호를 붙이며 여기서는 1부터 시작한다.
47번호와 질문을 한 줄로 출력한다.f로 시작하는 문자열의 중괄호에 값을 넣는다.

compile은 문자열을 Python이 이해할 수 있는 코드로 바꿀 수 있는지 확인한다. 이 프로그램은 그 결과를 실행하지 않는다. 따라서 “구문 검사 통과”는 함수의 조건이나 출력이 요구에 맞는다는 뜻이 아니다. AI가 만들어 준 비교 도구를 읽을 때도 이 차이를 확인해야 한다.

실행 결과

main.py를 저장한 폴더에서 다음 명령을 실행한다.

python3 main.py

예상 출력은 다음과 같다. 비교 자료와 질문이 고정되어 있어 실행할 때마다 같은 내용을 출력한다.

학습 기록 함수 변경 검토
구문 검사: 두 버전 통과

--- 이전/main.py
+++ 수정/main.py
@@ -1,4 +1,6 @@
 def learning_message(minutes):
-    if minutes >= 60:
+    if minutes < 0:
+        raise ValueError("학습 시간은 음수일 수 없음")
+    if minutes >= 45:
         return "오늘 목표 달성"
     return "조금 더 학습"

리뷰 질문
1. 의도: 목표 기준을 45분으로 바꾸기로 합의했는가?
2. 동작: 44분, 45분, 46분의 결과를 실행해 확인했는가?
3. 위험: 음수 입력의 오류를 호출 화면이 처리하는가?
4. 문서: 목표 기준과 입력 처리 설명을 함께 바꿨는가?

처음 두 줄의 세 개짜리 빼기·더하기 표시는 자료 이름을 보여 주는 머리말이다. 코드 삭제와 추가 표시는 그 아래 코드 줄 앞에 하나씩 붙는다. 골뱅이 두 개로 둘러싸인 줄은 비교한 구간을 나타낸다. 이전 자료는 첫 줄부터 네 줄, 수정 자료는 첫 줄부터 여섯 줄이 해당 구간이라는 뜻이다.

이 출력에서 목표 기준을 바꾼 줄과 음수 처리를 추가한 줄을 함께 찾을 수 있다. 그렇다고 화면이 새 오류를 처리한다고 판단할 수는 없다. 화면 코드는 비교 자료에 없기 때문이다. 리뷰 질문 목록도 사람이 정해 둔 문장을 출력한 것이며, 프로그램이 질문의 답을 조사한 결과가 아니다.

실행한 출력이 예상과 다르면 먼저 복사한 코드의 들여쓰기와 문자열을 확인한다. 예상과 같다면 비교 도구가 이 자료에서 원하는 표시를 했다는 근거가 생긴다. 수정 함수의 동작을 확인하려면 그 함수를 실제로 호출하는 별도 실행이 필요하다.

실무에서 자주 틀리는 것

줄 비교 전에 공백을 지워 버린다

다음 코드는 비교 자료를 준비하면서 글을 공백 기준으로 나눈다. split은 여기서 단어 사이 공백과 줄바꿈을 구분하지 않고 조각을 만든다. Python에서는 들여쓰기가 실행할 문장의 묶음을 정하므로 중요한 정보를 잃는다. 코드는 실행되지만 리뷰 자료로는 부적절하다.

source = "if True:\n    print('확인')\n"
pieces = source.split()
print(pieces)

줄 차이를 보고 싶다면 줄을 기준으로 나눈다. 다음 코드는 각 줄 안의 공백을 유지한다. 목록 출력에 보이는 두 번째 값의 앞 공백을 확인한다.

source = "if True:\n    print('확인')\n"
lines = source.splitlines()
print(lines)

보기 편하게 만들겠다는 이유로 모든 줄에 앞뒤 공백을 없애는 처리를 붙이는 것도 주의해야 한다. 비교 도구가 읽을 정보를 먼저 지우면 변경이 보이지 않을 수 있다.

구문 검사 통과를 동작 확인으로 보고한다

다음 코드의 함수는 구문상 문제가 없다. 하지만 45분을 목표 달성으로 보는 요구에는 맞지 않는다. 검사 뒤에 “동작 확인 완료”라고 출력하면 수행한 확인보다 큰 주장을 하게 된다.

source = 'def learning_message(minutes):\n    return "오늘 목표 달성"\n'
compile(source, "검토 대상", "exec")
print("동작 확인 완료")

구문 검사 결과는 구문 검사라고 표시한다. 실제 동작은 입력을 넣고 결과를 관찰한다. 다음 예시는 목표 기준 주변의 입력을 실행한다. 이 함수는 목표 조건만 확인하기 위한 짧은 예시다.

def learning_message(minutes):
    if minutes >= 45:
        return "오늘 목표 달성"
    return "조금 더 학습"

for minutes in [44, 45, 46]:
    print(minutes, learning_message(minutes))

44분에서는 “조금 더 학습”, 45분과 46분에서는 “오늘 목표 달성”이 나와야 한다. 이 확인을 했다고 음수나 다른 입력까지 확인한 것은 아니다. 기록에는 실행한 범위를 그대로 적는다.

리뷰 질문을 칭찬 문장으로 바꾼다

다음 목록은 출력할 수 있지만 다음 행동을 정하는 데 도움이 적다. “좋다”라는 결론에 확인 대상과 근거가 빠져 있다.

questions = ["코드가 좋다", "문제가 없어 보인다"]
for question in questions:
    print(question)

질문을 바꾸면 무엇을 읽고 실행해야 하는지가 드러난다. 함수 밖에 관한 질문은 관련 자료가 더 필요하다는 사실도 알려 준다.

questions = [
    "45분 입력에서 목표 달성 문장이 나오는가?",
    "음수 입력의 오류를 호출 화면이 처리하는가?",
]
for question in questions:
    print(question)

AI의 답에도 같은 기준을 적용한다. “잘 작성되었다”는 평가보다 어떤 줄을 근거로 어떤 입력을 확인했는지 묻는다. 자료가 없어서 판단할 수 없는 부분은 그 상태로 남기고 필요한 코드를 추가로 읽는다.

한눈에 보기

변경을 함께 다룰 때 남겨야 할 근거
활동남길 것확인할 한계
변경 기록설명 가능한 변경 묶음과 이유기록하지 않은 파일까지 복구하지는 못한다.
작업 흐름 나누기출발 기록과 실험 목적브랜치가 합칠 내용을 판단하지는 않는다.
변경 비교추가·삭제된 줄과 주변 문맥줄 차이만으로 요구 충족을 알 수 없다.
리뷰의도·동작·위험에 관한 질문과 근거관련 자료가 없으면 확인 범위가 제한된다.
문서 유지작업 약속과 현재 사용 방법문서 내용이 실제 코드와 일치하는지 확인해야 한다.

작은 도구라도 변경 전 상태를 남기고, 바뀐 줄을 읽고, 예시 입력을 실행하고, 확인 범위를 설명하면 다음 작업이 쉬워진다. 이 장의 프로그램은 그중 변경 비교와 질문 준비를 눈으로 보여 준다. 질문에 답하는 작업은 코드를 읽는 사람에게 남아 있다.

연습 문제

  1. 완성 코드의 수정 버전에서 45분 기준을 50분으로 바꾼다고 하자. 리뷰 질문 목록의 어떤 문장을 함께 바꿔야 하는지 적고, 실행해 볼 세 입력을 고른다.
  2. 변경 비교에 음수 입력 오류가 추가되었다. 출력 자료만으로 호출 화면의 안전한 처리를 확인할 수 있는지 설명하고, 추가로 읽을 자료를 하나 적는다.
  3. 목표 기준 변경, 화면 색상 변경, 실행 방법 문서 수정을 함께 하려고 한다. 설명 가능한 변경 묶음으로 어떻게 나눌지 제안하고 그 이유를 적는다.
  4. 이 도구를 처음 받는 동료를 위해 README에 들어갈 목적, 환경, 실행 방법, 한계를 각각 한 문장으로 쓴다.

정답과 해설

  1. 의도 질문의 기준을 50분으로 바꾸고, 동작 질문의 입력을 49분, 50분, 51분으로 바꾼다. 49분은 목표 미달, 50분과 51분은 목표 달성이어야 한다. 비교 대상만 바꾸고 질문을 그대로 두면 오래된 기준으로 확인하게 된다.
  2. 확인할 수 없다. 출력에는 두 함수의 코드만 있고 호출 화면의 처리는 없다. 함수를 호출하는 부분과 오류를 받아 사용자에게 안내하는 부분을 추가로 읽어야 한다. 그 경로에 음수 입력을 넣어 실제 안내가 나오는지도 확인한다.
  3. 예를 들어 목표 기준 변경과 그 기준을 설명하는 문서 수정은 함께 묶고, 화면 색상 변경은 별도로 묶는다. 실행 방법 자체가 바뀌었다면 그 변경과 실행 방법 문서 수정을 함께 묶는다. 문서라는 이유로 전부 따로 떼기보다 같은 목적에 필요한 변경끼리 묶는 것이 핵심이다.
  4. 목적은 “두 코드의 줄 차이와 리뷰 질문을 출력한다”다. 환경은 “macOS 또는 Linux의 Python 3.12 이상에서 외부 패키지 없이 실행한다”다. 실행 방법은 “main.py를 저장한 폴더에서 python3 main.py를 실행한다”다. 한계는 “비교 대상 함수의 동작을 자동 검사하거나 Git 기록을 만들지는 않는다”다.

변경의 이유와 확인 결과를 남기는 습관은 결과물에 대한 설명을 가능하게 한다. 다음 장에서는 이 기록을 바탕으로 AI에게 맡긴 일과 자신이 판단한 일을 어떻게 정직하게 밝힐지 살펴본다.

댓글 0

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

댓글을 남기려면 로그인이 필요합니다.