Devin.KR

타이핑보다 읽기 - 남이 쓴 코드를 따라가는 훈련

개발자KR 조회 0

이 장에서 배우는 것

코드를 읽는다는 것은 화면에 적힌 문장을 눈으로 훑는다는 뜻이 아니다. 어떤 줄이 실행되고, 그 줄을 지나면서 값이 어떻게 바뀌며, 마지막에 무엇이 남는지 따라가는 일이다. 직접 입력한 코드도 시간이 지나면 낯설어진다. 다른 사람이 작성했거나 AI가 제안한 코드는 더욱 그렇다. 익숙한 단어가 몇 개 보인다는 이유만으로 이해했다고 판단하기 쉽다.

앞 장에서 AI에게 설명을 요청하는 때와 일을 맡기는 때를 구분했다. 어느 쪽으로 사용하더라도 결과를 확인하는 책임은 남는다. 이 장에서는 작은 학습 점수 계산 함수를 읽으며 그 확인을 연습한다. 함수는 이름을 붙여 다시 사용할 수 있게 묶은 코드다. 계산에 필요한 값을 건네면 정해진 순서로 처리하고 결과를 돌려준다.

목표는 긴 프로그램을 빠르게 읽는 것이 아니다. 짧은 코드에서 자신의 예상과 실제 실행을 연결하는 것이다. 예제에 나오는 학습 시간과 점수는 설명용 가상값이다. 점수가 학습 능력이나 이해 수준을 나타내는 것은 아니다.

  • 개발자가 자신이 쓰지 않은 코드를 읽어야 하는 이유를 설명한다.
  • 줄 번호와 변수 값의 변화를 실행 추적표에 적는다.
  • 실행 전에 예상 결과를 적고 실제 결과와 비교한다.
  • 이해하지 못한 줄을 구체적인 질문으로 바꾼다.
  • 짧은 함수를 읽고, 실행 기록을 근거로 자신의 설명을 고친다.

문제 상황

한 팀이 학생용 학습 기록 도구를 만든다고 생각해 보자. 전날 기록한 공부 시간을 합산하고, 복습 여부에 따라 작은 점수를 더하는 기능이 있다. 담당자는 기존 코드의 계산 방식이 안내 문구와 맞는지 확인해야 한다. 코드는 다른 사람이 작성했고, 일부 수정은 AI가 제안했다. 담당자는 새 코드를 많이 입력하지 않아도 이 일을 수행할 수 있다. 그러나 계산 과정을 읽지 못하면 수정안을 받아들여도 되는지 판단하기 어렵다.

화면에 결과가 6이라고 표시되었다고 하자. 숫자 하나만 보고는 계산이 맞는지 알 수 없다. 공부 시간의 합이 얼마였는지, 나눗셈에서 소수 부분을 어떻게 처리했는지, 복습 점수가 어느 시점에 더해졌는지 알아야 한다. 같은 결과가 나왔더라도 중간 과정은 다를 수 있다.

학생이 혼자 연습할 때도 비슷한 일이 생긴다. AI에게 학습 기록 계산 코드를 요청하고 실행했더니 오류 없이 종료된다. 여기서 “잘 돌아간다”라고 기록하면 확인한 범위가 너무 넓어 보인다. 실제로 확인한 것은 특정 입력에서 프로그램이 끝났다는 사실뿐이다. 그 입력의 계산 과정을 설명할 수 있는지는 별도로 살펴봐야 한다.

이번 예제는 공부 시간 두 개와 복습 여부를 받아 점수를 계산한다. 계산 도중의 값을 표로 출력하므로, 눈으로 예상한 순서와 컴퓨터가 수행한 순서를 나란히 확인할 수 있다. 독자는 먼저 계산을 따라가고, 그다음 프로그램을 실행한다.

쓰는 코드보다 읽는 코드가 많아지는 이유

프로그램을 만드는 일은 빈 파일에 처음부터 문장을 입력하는 일만으로 이루어지지 않는다. 이미 있는 기능을 살펴보고, 다른 사람이 고친 부분을 확인하고, 문제가 생긴 위치를 찾는 시간이 함께 들어간다. 짧은 수정 하나를 하려면 그 앞뒤의 여러 줄을 읽어야 할 수도 있다. 자신이 오늘 입력하는 줄보다 이해해야 하는 줄이 많아지는 상황이 자연스럽게 생긴다.

AI가 초안을 빠르게 제안하면 이런 상황은 더 자주 생길 수 있다. 코드가 만들어지는 속도와 사람이 의미를 확인하는 속도는 같지 않다. 입력을 줄인 시간만큼 결과를 읽고 실행하며 판단하는 일이 중요해진다. 이것을 모든 개발자의 읽기 시간이 일정한 비율로 늘어난다는 뜻으로 받아들일 필요는 없다. 작업의 종류에 따라 다르지만, 직접 작성하지 않은 코드를 다룰 준비는 필요하다.

이 변화는 개발자가 할 일이 없어졌다는 뜻이 아니다. 해야 할 일의 무게가 달라지는 것이다. 무엇을 계산하는지 설명하고, 예상 밖의 결과가 나온 이유를 찾고, 제안된 수정이 의도에 맞는지 판단하는 일은 남는다. 코드를 읽는 능력은 이런 판단을 구체적인 줄과 값에 연결해 준다.

읽기에는 두 가지 질문이 함께 필요하다. 첫째는 “이 코드가 무엇을 하려는가”이고, 둘째는 “이 줄이 실제로 무엇을 하는가”다. 함수 이름과 설명은 첫 번째 질문에 도움을 준다. 실제 연산과 값의 변화는 두 번째 질문에 답한다. 이름이 학습 점수 계산이라고 해도 내부에서 어떤 계산을 하는지는 본문을 읽어야 알 수 있다.

코드의 의도는 설명에서 찾고 실제 동작은 줄과 값의 변화로 확인한다

처음 읽을 때 모든 기호를 외울 필요는 없다. 이 코드에 들어오는 값, 계산 중 바뀌는 값, 마지막에 나가는 값부터 찾는다. 그다음 결과에 영향을 주는 줄을 좁혀 간다. 이렇게 읽으면 모르는 문법이 한 줄 나타났다고 해서 프로그램 전체를 이해할 수 없는 것은 아니라는 점도 알게 된다.

실행 추적표로 줄과 값을 연결하기

변수는 값에 붙인 이름이다. 실행 추적표는 코드가 실행되는 순서에 따라 그 이름이 가리키는 값을 적은 표다. 코드의 줄 번호는 위치를 알려 주고, 표의 위아래 순서는 실행 시간을 알려 준다. 이 둘은 같지 않다. 반복문에서는 같은 줄로 돌아오므로 하나의 줄 번호가 표에 여러 번 나타난다.

예제에서는 공부 시간 15분과 25분을 차례로 더한다. 시간을 담은 목록은 여러 값을 순서대로 모은 자료다. 반복문은 그 목록에서 값을 하나씩 꺼내 같은 계산을 수행한다. 첫 번째 반복이 끝났을 때 합계는 15이고, 두 번째 반복이 끝났을 때 합계는 40이다. 두 번의 계산은 같은 코드 줄에서 일어나지만 계산에 쓰이는 값은 다르다.

반복문은 같은 줄을 서로 다른 값으로 실행한다
실행 순서코드 줄이번 공부 시간더한 뒤 합계
첫 번째 반복101515
두 번째 반복102540

표의 값을 적는 시점도 정해야 한다. 이번 장에서는 대입이 끝난 직후의 값을 기록한다. 대입은 계산한 값을 변수 이름에 연결하는 일이다. 예를 들어 total = total + minutes_today는 오른쪽의 기존 합계와 이번 시간을 먼저 더한 뒤, 그 결과를 왼쪽의 total에 연결한다. 두 번째 반복에서는 오른쪽 계산이 15 + 25이고, 대입 후 total은 40이다.

아직 만들어지지 않은 값과 0은 구분해야 한다. 합계가 0이라는 것은 값이 존재하고 그 값이 0이라는 뜻이다. 점수를 계산하기 전에는 points라는 이름에 아직 값이 연결되지 않았다. 추적표에서는 이 상태를 하이픈으로 표시한다. 이 하이픈은 계산에 사용하는 숫자가 아니라, 사람이 표를 읽기 위한 표시다.

조건문은 조건에 따라 실행할 부분을 고른다. reviewed가 True이면 복습했다는 뜻으로 보고 점수에 2를 더한다. False이면 그 계산을 건너뛴다. True와 False는 참과 거짓을 나타내는 값이다. 파일에 적혀 있는 모든 줄이 매번 실행되는 것은 아니다.

완성 코드는 Python의 실행을 자동으로 감시하는 도구가 아니다. 관찰하려는 위치에 기록 함수를 직접 넣은 예제다. 중요한 계산 한 단계가 끝날 때마다 그때의 값을 기록하고, 계산이 끝난 뒤 모아 둔 행을 출력한다. 따라서 표에는 모든 문법 줄이 아니라 이번 읽기 연습에 필요한 지점만 나타난다.

예상하고 비교한 뒤 모르는 줄을 질문으로 바꾸기

실행 전 예상은 정답을 맞히는 시험이 아니다. 자신이 코드를 어떻게 이해했는지 남기는 기록이다. 실행 결과를 먼저 보면 그 숫자를 이미 알고 있었다고 느끼기 쉽다. 예상 값을 먼저 적으면 어떤 생각을 바꾸어야 하는지 분명해진다.

이번 계산은 공부 시간을 모두 더하고, 그 합계를 10으로 나눈 몫을 기본 점수로 삼는다. 여기서 //는 두 정수의 나눗셈 결과를 아래쪽 정수로 내리는 연산이다. 예제처럼 음수가 아닌 공부 시간에서는 10분 묶음이 몇 개 들어가는지 세는 것으로 이해할 수 있다. 40 // 10은 4이고, 45 // 10도 4다. 복습했다면 여기에 2를 더한다.

코드를 실행하기 전에 종이나 메모장에 합계 40, 기본 점수 4, 복습 후 점수 6을 적는다. 최종 점수만 적는 것보다 중간 값을 함께 적는 편이 좋다. 결과가 다르면 처음 어긋난 지점부터 찾아갈 수 있기 때문이다. 합계부터 다르면 반복과 더하기를 보고, 합계는 같은데 점수가 다르면 나누기와 조건을 본다.

예상과 실행이 다르면 최종 숫자보다 처음 어긋난 중간 값을 찾는다

이해하지 못한 줄에는 물음표를 남긴다. 다만 “전체를 모르겠다”에서 멈추지 않고 질문에 줄과 값을 넣는다. 질문의 범위가 좁아지면 답을 받은 뒤 직접 확인할 수 있다. AI의 설명도 이 과정에서 확인할 대상이다. 설명이 자연스러워도 실제 연산과 맞는지는 실행해 봐야 한다.

막연한 의문을 실행으로 확인할 수 있는 질문으로 바꾼다
표시한 부분처음 든 의문바꾼 질문
10줄의 대입같은 이름이 왜 두 번 나오나두 번째 반복에서 오른쪽 total은 얼마이고, 대입 후에는 얼마가 되는가
12줄의 //나누기 기호가 왜 두 개인가합계가 45일 때 /와 //의 결과는 각각 무엇인가
14줄의 조건언제 점수가 더해지나reviewed가 False이면 16줄을 실행하는가
20줄의 return출력과 무엇이 다른가이 줄의 값은 화면에 바로 나타나는가, 함수를 부른 곳으로 돌아가는가

AI에게 설명을 요청할 때는 다음처럼 읽고 있는 지점과 자신의 예상을 함께 적을 수 있다.

12줄의 total // 10을 이해하지 못했다. total이 45이면 points가 4가 된다고 예상했다. 이 예상이 맞는 이유를 설명하고, /를 썼을 때와 어떻게 다른지 알려 달라. 전체 코드를 다시 작성하지 말고 이 연산만 설명해 달라.

답을 받으면 필요한 부분을 짧게 실행하거나 완성 코드의 입력을 바꾸어 확인한다. AI가 “소수 부분을 버린다”라고만 설명했다면 이번 양수 예제에서는 결과를 이해하는 데 도움이 된다. 다만 음수까지 포함한 일반적인 설명은 아래쪽 정수로 내린다는 표현이 더 정확하다. 자신이 확인한 입력 범위와 더 넓은 규칙을 구분하는 것도 읽기 연습이다.

완성 코드

아래 전체를 main.py라는 파일에 저장한다. macOS나 Linux의 Python 3.12 이상에서 외부 패키지 없이 실행할 수 있다. 입력을 묻거나 현재 시각을 읽지 않으므로, 코드를 바꾸지 않으면 같은 결과가 나온다. 공부 시간 15와 25, 나누는 기준 10, 복습 점수 2는 모두 설명용 가상값이다.

줄 번호는 첫 번째 def를 1줄로 세며 빈 줄도 포함한다. 코드 안의 기록용 숫자는 이 파일에서 관찰 대상이 되는 줄 번호다. 코드를 수정하면서 줄을 추가하거나 삭제하면 이 숫자도 함께 고쳐야 한다.

def record(rows, line, change, total, points):
    rows.append([line, change, total, points])


def study_points(minutes, reviewed, rows):
    total = 0
    record(rows, 6, "합계 시작", total, "-")
    for minutes_today in minutes:
        record(rows, 8, f"이번 시간={minutes_today}", total, "-")
        total = total + minutes_today
        record(rows, 10, "시간 더하기", total, "-")
    points = total // 10
    record(rows, 12, "기본 점수 계산", total, points)
    if reviewed:
        record(rows, 14, "복습 조건=True", total, points)
        points = points + 2
        record(rows, 16, "복습 점수 더하기", total, points)
    else:
        record(rows, 14, "복습 조건=False", total, points)
    return points


def main():
    minutes = [15, 25]
    reviewed = True
    expected = 6
    rows = []
    actual = study_points(minutes, reviewed, rows)
    print("학습 점수 실행 추적표")
    print("줄 | 실행 내용 | 합계 | 점수")
    print("--- | --- | --- | ---")
    for row in rows:
        print(f"{row[0]} | {row[1]} | {row[2]} | {row[3]}")
    print(f"예상 점수: {expected}")
    print(f"실제 점수: {actual}")
    if actual == expected:
        print("비교: 일치")
    else:
        print("비교: 불일치")


if __name__ == "__main__":
    main()

줄별 해설

1줄은 record라는 기록 함수를 정의한다. 괄호 안의 이름은 함수를 부를 때 받을 값을 가리킨다. rows는 기록을 모을 목록이고, line은 관찰한 줄 번호다. change는 실행 내용을 설명하는 글이며, total과 points는 기록할 값이다. 함수 정의를 읽었다고 해서 그 안의 작업이 바로 실행되는 것은 아니다. 함수를 부를 때 본문이 실행된다.

2줄의 append는 목록 끝에 항목을 추가하는 기능이다. 대괄호로 묶은 네 값을 하나의 행으로 만들어 rows에 붙인다. 이 줄에서 화면 출력은 하지 않는다. 기록을 모으는 일과 보여 주는 일이 별도로 이루어진다는 점을 기억한다. 3줄과 4줄은 함수를 구분하기 위한 빈 줄이다.

5줄은 점수 계산 함수 study_points를 정의한다. minutes는 공부 시간 목록, reviewed는 복습 여부, rows는 기록 목록이다. 6줄은 합계를 0에서 시작한다. 7줄은 6줄을 수행한 직후의 상태를 기록한다. 점수는 아직 계산하지 않았으므로 숫자 대신 하이픈을 넣는다.

8줄은 minutes에서 시간을 하나씩 꺼내 minutes_today에 연결한다. 첫 번째에는 15, 두 번째에는 25가 들어간다. 9줄은 이번 시간과 더하기 전 합계를 기록한다. 이때 합계가 바로 바뀌지는 않는다. 시간을 꺼내는 작업과 더하는 작업은 서로 다른 줄에서 일어난다.

10줄은 기존 합계에 이번 시간을 더한다. 11줄은 그 결과를 기록한다. 9줄부터 11줄까지는 들여쓰기되어 있으므로 반복문의 본문에 속한다. 들여쓰기는 줄 앞의 공백으로 코드의 묶음을 표시하는 방식이다. 두 번째 시간이 처리된 뒤에는 더 꺼낼 값이 없으므로 반복이 끝난다.

12줄은 합계 40을 10으로 나눈 몫 4를 points에 연결한다. 이 줄은 반복문 본문보다 왼쪽에 있으므로 반복이 모두 끝난 뒤 한 번 실행된다. 13줄은 이제 만들어진 points의 값을 기록한다. 표에서 점수 열이 하이픈에서 4로 바뀌는 지점이다.

14줄은 복습 여부를 확인한다. 현재 입력은 True이므로 15줄부터 17줄까지 실행한다. 15줄은 조건이 참일 때의 상태를 기록한다. 16줄은 점수에 2를 더하고, 17줄은 바뀐 점수 6을 기록한다. 조건을 확인한 시점과 점수를 더한 시점을 나누어 관찰할 수 있다.

18줄의 else는 조건이 거짓일 때 실행할 부분을 시작한다. 현재 실행에서는 19줄을 건너뛴다. 입력을 False로 바꾸면 반대로 15줄부터 17줄까지 건너뛰고 19줄에서 조건이 거짓이었다고 기록한다. 따라서 두 갈래의 기록이 한 번의 실행에 모두 나타나지는 않는다.

20줄의 return은 결과를 함수를 부른 곳에 돌려준다. 화면에 글자를 보여 주는 print와 역할이 다르다. 여기서는 점수 6을 돌려주고 함수 실행을 끝낸다. 21줄과 22줄은 빈 줄이다.

23줄은 전체 실행 순서를 묶은 main 함수를 정의한다. 24줄은 공부 시간 목록을 만들고, 25줄은 복습 여부를 정한다. 26줄의 expected는 실행 전에 적어 둔 예상 점수다. 27줄의 빈 대괄호는 아직 기록이 없는 목록을 만든다.

28줄은 계산 함수를 호출한다. 호출은 함수 이름과 괄호를 써서 그 작업을 실행하는 것이다. 계산하는 동안 rows에 기록이 쌓이고, 20줄에서 돌아온 점수는 actual에 연결된다. minutes와 reviewed는 계산할 입력이고, rows는 계산 중 기록을 담는 용도로 함께 전달한다.

29줄부터 31줄까지는 표 제목과 열 이름을 출력한다. 32줄은 모아 둔 기록을 한 행씩 꺼낸다. 33줄에서 row[0]은 행의 첫 번째 값인 줄 번호다. 목록의 위치는 0부터 센다. row[1], row[2], row[3]은 차례로 실행 내용, 합계, 점수다. 따옴표 앞의 f와 중괄호는 글 안에 값을 넣는 형식 문자열 문법이다.

34줄과 35줄은 예상 점수와 실제 점수를 출력한다. 36줄의 ==는 두 값이 같은지 비교한다. 값을 연결하는 =와 기호도 역할도 다르다. 같으면 37줄이, 다르면 39줄이 실행된다. 38줄은 두 번째 갈래를 시작하고, 40줄과 41줄은 빈 줄이다.

42줄과 43줄은 이 파일을 직접 실행했을 때 main을 호출하는 시작 부분이다. __name__은 Python이 정하는 이름이며, 직접 실행한 파일에서는 "__main__"이라는 값을 갖는다. 처음에는 이 두 줄을 프로그램을 시작하는 약속으로 읽어도 된다. 함수들이 파일 위쪽에 정의되어 있어도 실제 계산은 여기서 main을 호출한 뒤 시작된다.

실행 결과

터미널은 명령을 입력해 프로그램을 실행하는 창이다. main.py를 저장한 폴더에서 다음 명령을 입력한다.

python3 main.py

코드를 그대로 저장했을 때의 예상 출력은 다음과 같다. 각 행은 관찰 대상으로 정한 지점의 상태를 나타낸다.

학습 점수 실행 추적표
줄 | 실행 내용 | 합계 | 점수
--- | --- | --- | ---
6 | 합계 시작 | 0 | -
8 | 이번 시간=15 | 0 | -
10 | 시간 더하기 | 15 | -
8 | 이번 시간=25 | 15 | -
10 | 시간 더하기 | 40 | -
12 | 기본 점수 계산 | 40 | 4
14 | 복습 조건=True | 40 | 4
16 | 복습 점수 더하기 | 40 | 6
예상 점수: 6
실제 점수: 6
비교: 일치

줄 번호가 10에서 8로 돌아오는 부분을 먼저 살펴본다. 이것은 코드의 위치를 잘못 적었다는 뜻이 아니다. 반복문이 다음 공부 시간을 꺼내러 돌아간 것이다. 반면 표의 행은 위에서 아래로 계속 진행한다. 줄 번호만 오름차순으로 정렬하면 이 실행 순서를 잃게 된다.

“비교: 일치”는 예상 점수 6과 실제 점수 6이 같다는 뜻이다. 모든 입력에서 계산이 맞다는 뜻은 아니다. 또 expected를 실행 결과에 맞춰 고치면 비교의 의미가 줄어든다. 예상과 실제가 다를 때는 먼저 자신의 계산과 추적표를 대조하고, 어느 쪽 설명을 고쳐야 하는지 판단한다.

실무에서 자주 틀리는 것

예상 값을 실제 결과에서 가져오기

아래의 틀린 예에서는 실제 계산 뒤에 예상 값을 같은 값으로 정한다. 어떤 결과가 나오든 비교는 참이 된다. 두 코드는 따로 실행할 수 있는 짧은 예다.

틀린 코드다.

actual = (15 + 25) // 10 + 2
expected = actual
print(actual == expected)

고친 코드다.

expected = 6
actual = (15 + 25) // 10 + 2
print(actual == expected)

예상은 코드를 읽고 독립적으로 계산한 값이어야 한다. 자동으로 같은 값을 복사하는 것은 자신의 이해를 확인하는 비교가 아니다.

매번 합계를 새 시간으로 바꾸기

반복문의 대입을 빠르게 읽으면 값을 쌓는지 바꾸는지 놓치기 쉽다. 틀린 코드는 이전 시간을 보존하지 않아 마지막 시간 25만 남는다.

틀린 코드다.

total = 0
for minutes_today in [15, 25]:
    total = minutes_today
print(total)

고친 코드다.

total = 0
for minutes_today in [15, 25]:
    total = total + minutes_today
print(total)

고친 코드에서는 40이 출력된다. 오른쪽에 기존 total이 들어 있는지 확인하면 누적 계산을 읽는 데 도움이 된다.

값이 바뀌기 전에 바뀐 뒤라고 기록하기

추적표도 코드가 만드는 결과이므로 잘못 작성할 수 있다. 아래 틀린 코드는 0을 보여 주면서 더한 뒤의 값이라고 설명한다.

틀린 코드다.

total = 0
print("더한 뒤 합계:", total)
total = total + 15

고친 코드다.

total = 0
total = total + 15
print("더한 뒤 합계:", total)

고친 코드에서는 15가 표시된다. 기록의 설명과 실제 기록 시점이 맞아야 한다. AI가 만든 추적표에서도 표 제목만 믿지 않고 출력문이 계산 앞에 있는지 뒤에 있는지 읽는다.

화면에 출력한 값을 반환한 값으로 생각하기

함수가 화면에 6을 출력해도 그 함수를 부른 곳으로 6이 돌아오는 것은 아니다. 다음 틀린 코드의 마지막 출력은 None이다. None은 여기서 돌려받은 결과가 없음을 나타내는 값이다.

틀린 코드다.

def score():
    print(6)

actual = score()
print(actual)

고친 코드다.

def score():
    return 6

actual = score()
print(actual)

고친 코드는 반환받은 6을 actual에 연결한 뒤 한 번 출력한다. 함수를 읽을 때는 화면에 보이는 글과 다음 계산에 전달되는 값을 구분한다.

한눈에 보기

코드를 읽을 때 남길 근거와 확인할 지점
읽기 행동남기는 기록확인할 지점
입력 찾기시간 목록과 복습 여부어떤 값으로 실행하는가
먼저 예상하기합계 40, 기본 점수 4, 결과 6실행 전에 계산했는가
실행 따라가기줄 번호와 그 시점의 값반복과 조건의 순서가 보이는가
결과 비교하기처음 달라진 중간 값최종 결과만 보고 판단하지 않았는가
질문 만들기모르는 줄, 현재 값, 자신의 예상답을 실행으로 확인할 수 있는가
기록 점검하기기록 위치와 줄 번호추적표 자체가 코드와 맞는가

읽기를 마친 뒤에는 “이 프로그램은 점수를 계산한다”보다 조금 더 구체적으로 설명해 본다. “시간을 차례로 더한 뒤 10분 묶음 수를 구하고, 복습 여부가 참이면 2를 더해 반환한다”라고 말할 수 있으면 주요 흐름을 따라간 것이다. 다음 장에서는 이렇게 읽어 낸 동작을 입력과 출력, 예시로 분명하게 표현하는 방법을 다룬다.

연습 문제

  1. 완성 코드에서 minutes를 [12, 23]으로 바꾸고 reviewed는 True로 둔다. 실행 전에 각 반복 직후의 합계, 기본 점수, 최종 점수를 적는다. expected도 자신의 예상으로 바꾼 뒤 실행해 비교한다.
  2. 원래 시간 목록 [15, 25]를 사용하고 reviewed를 False로 바꾼다. 어떤 기록 행이 사라지고 어떤 행이 나타날지 예상한다. 최종 점수와 함께 그 이유를 설명한다.
  3. 원래 코드의 10줄을 total = minutes_today로 바꾸었다고 가정한다. 첫 번째 반복과 두 번째 반복 직후의 합계, 기본 점수, 최종 점수를 적는다. 예상 점수를 6으로 유지하면 비교 결과가 무엇인지 설명한다.
  4. “20줄을 이해하지 못했다”라는 메모를 구체적인 질문으로 바꾼다. 질문에는 함수가 돌려주는 값과 그 값을 받는 위치를 포함한다. 이어서 print와 return을 혼동하지 않는 답을 자신의 말로 적는다.

정답과 해설

  1. 첫 번째 반복 직후 합계는 12이고, 두 번째 반복 직후에는 35다. 기본 점수는 35 // 10으로 계산한 3이다. 복습 점수 2를 더하므로 최종 점수는 5다. expected를 5로 정했다면 비교는 일치한다. 나눈 결과가 3.5라고 예상했다면 12줄의 연산 기호를 다시 읽는다.
  2. 기본 점수는 4이고 최종 점수도 4다. “복습 조건=True” 행과 “복습 점수 더하기” 행이 사라진다. 대신 줄 번호 14에 “복습 조건=False”가 기록된 행이 나타나며, 그때 합계는 40이고 점수는 4다. 복습 조건이 거짓이므로 16줄은 실행되지 않는다. expected도 4로 바꾸면 비교가 일치한다.
  3. 첫 번째 반복 직후 합계는 15이고, 두 번째 반복 직후에는 25다. 기존 값을 더하지 않고 새 값으로 바꾸기 때문이다. 기본 점수는 25 // 10인 2이고, 복습 점수를 더한 최종 점수는 4다. expected가 6이면 비교는 불일치다. 원래 코드와 처음 다른 값은 두 번째 반복의 10줄 직후에 나타난다.
  4. 질문은 “20줄의 return points가 돌려주는 6은 28줄의 actual에 어떻게 연결되는가. 이때 20줄 자체가 화면에 6을 출력하는가”처럼 쓸 수 있다. 답은 “20줄은 점수를 돌려주고 함수 실행을 끝낸다. 28줄이 그 결과를 actual에 연결한다. 화면에 실제 점수를 보여 주는 것은 35줄의 print다”가 된다. 질문과 답을 연결한 뒤 코드에서 각 위치를 다시 찾는다.

예상이 틀렸다면 그 기록을 지우기보다 옆에 이유를 덧붙인다. 어느 줄을 어떻게 잘못 읽었는지가 다음 읽기 연습의 출발점이 된다. 코드 읽기의 성과는 정답 숫자를 기억하는 데 있지 않다. 그 숫자가 만들어지는 순서를 값의 변화로 설명하고, 자신의 설명을 실제 실행과 대조할 수 있는 데 있다.

댓글 0

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

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