맥락은 예산이다 - 보여 줄 것을 고르고 새로 시작하기
이 장에서 배우는 것
앞 장에서 프로젝트 지침 파일에 다음 세션에도 지켜야 할 규칙을 남겼다. 그러나 규칙을 저장했다고 해서 진행 중인 작업의 모든 사정까지 전달되는 것은 아니다. 지금 어떤 기능을 고치는지, 어느 파일이 관련되는지, 무엇을 확인했는지는 따로 골라 보여 주어야 한다. 이 장에서는 혼자 쓰는 메모·할 일 관리 도구의 검색 기능을 고치는 상황에서 그 방법을 익힌다.
맥락(context)은 AI가 현재 답을 만드는 데 참고하는 요청, 대화, 파일 내용 등의 정보다. 맥락은 많이 넣을수록 좋은 자료 창고라기보다 제한된 작업 공간에 가깝다. 필요한 정보를 고르고, 오래된 대화를 정리하고, 기능이 바뀔 때 새로 시작하는 판단이 필요하다. 마지막에는 가상 대화의 글자 수를 세고 오래된 부분을 짧은 요약으로 바꾸는 프로그램을 만든다.
- 긴 대화에서 앞의 요구가 빠지는 현상을 알아보고, 중요한 조건을 다시 제시할 수 있다.
- 작업에 필요한 파일과 줄 위치를 골라 전달할 수 있다.
- 결정 사항과 검증 상태를 요약해 새 세션에 넘길 수 있다.
- 기능별 새 시작과 병렬 작업의 비용을 구분할 수 있다.
- 글자 수 예산을 적용하는 압축기를 실행하고, 요약이 정보를 지켰는지 따로 확인할 수 있다.
문제 상황
메모·할 일 관리 도구에 파일 저장, 완료 항목 숨기기, 검색 기능을 차례로 붙였다고 하자. 처음에는 “검색은 제목만 비교한다”라고 요청했다. 그 뒤 저장 오류를 고치고, 출력 모양을 바꾸고, 할 일의 완료 표시를 손보느라 대화가 길어졌다. 이제 검색 결과의 순서를 고쳐 달라고 했는데 AI가 메모 본문까지 검색하도록 코드를 바꿨다.
답변에는 검색을 개선했다는 설명이 있지만, 처음 정한 조건과는 다르다. 대화 초반에 조건을 썼다는 사실만으로 현재 답에 반영되었다고 판단할 수 없다. 긴 대화에서는 예전 내용이 현재 입력에 온전히 포함되지 않거나, 여러 조건 사이에서 중요한 요구가 충분히 반영되지 않을 수 있다. 사용 중인 도구가 대화를 정리하는 방식에 따라서도 차이가 생긴다.
사용자의 요청: 검색 결과를 입력순으로 보여 주도록 고쳐 달라. 검색 범위는 제목만이다. 이번 작업에서 저장 형식과 완료 항목 숨기기 동작은 바꾸지 않는다.
AI의 답 예시: 제목만 비교하도록 검색 범위를 유지하고, 결과를 별도로 정렬하지 않도록 수정하겠다. 먼저 검색 함수와 그 함수를 호출하는 부분을 확인하겠다.
이렇게 현재 조건을 다시 적는 일은 같은 말을 불필요하게 반복하는 일이 아니다. 이번 변경의 경계를 분명하게 만드는 일이다. 다만 AI의 답에 조건이 들어 있다고 해서 구현까지 맞는 것은 아니다. 변경 전후의 차이를 보여 주는 diff를 읽고, 제목에만 검색어가 있는 경우와 본문에만 있는 경우를 실행해서 확인해야 한다.
반대로 프로젝트 전체를 한꺼번에 붙이는 것도 해결책이 되기 어렵다. 관련 없는 출력 함수, 이미 끝난 저장 오류의 긴 기록, 폐기한 설계까지 섞이면 현재 작업의 조건을 찾기 어려워진다. 필요한 것은 대화를 무조건 줄이는 일이 아니라, 이번 판단에 필요한 정보가 눈에 잘 들어오게 구성하는 일이다.
맥락의 크기와 정보의 중요도는 다르다
AI가 한 번에 참고할 수 있는 입력의 범위에는 제한이 있다. 그 범위를 맥락 창(context window)이라고 부른다. 실제 한도와 긴 대화를 처리하는 방식은 도구마다 다르며 바뀔 수 있다. 여기서는 특정 제품의 수치 대신, 제한된 공간에 어떤 정보를 남길지를 다룬다.
실제 AI 시스템은 흔히 토큰(token)이라는 단위로 텍스트를 처리한다. 토큰은 글자나 단어와 항상 일치하지 않는 처리 단위다. 따라서 한국어 글자 수를 세어 실제 사용량이나 요금을 정확히 계산할 수는 없다. 이 장의 글자 수 예산은 제한된 공간을 다루는 원리를 확인하기 위한 단순한 기준이다.
예산에는 입력 공간만 있는 것도 아니다. 긴 자료를 준비하고 읽는 시간, AI가 답을 만드는 시간, 사람이 변경을 검토하는 시간도 든다. 자료를 덜 보냈더라도 필요한 조건이 빠져 다시 수정해야 한다면 전체 작업은 더 길어진다. 크기를 줄이는 것과 작업 비용을 줄이는 것을 구분해야 한다.
대화가 길어졌을 때 의심할 신호도 있다. AI가 이미 폐기한 방법을 다시 제안하거나, 정해 둔 파일 이름을 바꾸거나, 이번 작업과 관계없는 기능을 수정하면 현재 조건이 제대로 전달되었는지 살펴본다. 같은 조건을 더 강한 표현으로 반복하기보다, 현재 상태와 이번 목표를 짧게 다시 구성하는 편이 유용하다.
| 정보 | 처리 방법 | 이유 |
|---|---|---|
| 제목만 검색한다는 조건 | 현재 요청에 명시한다 | 구현의 맞고 틀림을 가르는 조건이다 |
| 검색 함수와 호출 부분 | 필요한 범위를 보여 준다 | 수정 위치와 연결 관계를 알 수 있다 |
| 폐기한 저장 방식의 논쟁 | 최종 결정만 남긴다 | 과거 선택지를 다시 검토할 필요가 없다 |
| 아직 실행하지 않은 확인 항목 | 미확인 상태로 남긴다 | 추측을 검증 결과로 바꾸지 않는다 |
짧은 요약도 중요한 조건을 빼면 쓸모가 줄어든다. “검색 기능 작업 중”이라는 문장은 짧지만 검색 범위와 결과 순서를 알려 주지 않는다. “제목만 검색하며 결과는 입력순으로 유지한다”는 문장은 조금 길어도 다음 작업의 방향을 잡는다. 좋은 압축의 기준은 짧아진 정도와 필요한 정보의 보존 여부를 함께 보는 것이다.
필요한 파일을 고르고 새 세션에 넘긴다
파일을 보여 줄 때는 경로, 관련 줄 위치, 그 부분을 보여 주는 이유를 함께 적는다. 줄 번호는 탐색의 출발점이지 고정된 주소가 아니다. 코드가 바뀌면 번호도 움직인다. 함수 이름까지 적으면 위치가 달라져도 다시 찾기 쉽다.
이번 목표는 검색 결과를 입력순으로 유지하는 것이다. main.py의 42~58줄에 있는 search_notes 함수와 81~88줄의 호출 부분을 먼저 확인해 달라. 이 줄 위치는 현재 파일 기준이다. 검색 범위는 제목만이다. 함수의 입력 구조를 확인하는 데 다른 부분이 필요하면 그 위치와 이유를 알려 달라.
이 요청의 파일 이름과 줄 위치는 설명을 위한 가상 예시다. 실제로 보낼 때는 현재 파일에서 확인한 위치로 바꾼다. AI가 로컬 파일을 읽을 수 있는 환경이면 위치를 안내하고, 읽을 수 없는 환경이면 해당 함수와 필요한 주변 내용을 직접 전달한다. 경로만 적었다고 파일 내용까지 전달되었다고 생각해서는 안 된다.
필요한 줄만 보여 준다는 말은 함수 몸통의 일부만 잘라 보내라는 뜻도 아니다. 검색 함수가 다른 함수를 부른다면 호출되는 함수의 동작이 필요할 수 있다. 입력 자료의 형태, 관련 상수, 오류가 발생하는 호출 부분도 판단에 영향을 준다. 처음에는 작은 범위를 제시하되, 연결 관계가 부족하면 이유를 확인하고 범위를 넓힌다.
긴 대화를 새 세션에 넘길 때는 대화 전체를 다시 붙이기보다 인계 요약을 만든다. 인계 요약에는 현재 목표, 유지할 조건, 확인한 사실, 남은 작업이 들어간다. “문제없음”처럼 넓은 표현보다 무엇을 실행했고 무엇을 아직 확인하지 않았는지 적는 편이 낫다.
현재 도구는 메모와 할 일을 파일에 저장한다. 완료한 할 일은 기본 목록에서 숨긴다. 이번 목표는 검색 결과를 입력순으로 유지하는 것이다.
검색은 제목만 비교한다. 저장 형식은 이번 작업에서 변경하지 않는다. main.py의 search_notes 함수와 호출 부분을 확인해야 한다.
직접 실행해 메모 저장과 재조회는 확인했다. 본문에만 검색어가 있는 항목을 제외하는 동작과 검색 결과 순서는 아직 확인하지 않았다.
먼저 현재 파일과 요약이 일치하는지 확인하고, 검색 함수의 변경안을 제시해 달라.
새 세션은 새 대화를 시작한 작업 구간을 뜻한다. 이전 대화의 세부 내용이 자동으로 이어진다고 가정하지 않는다. 앞 장에서 만든 프로젝트 지침은 계속 적용할 규칙을 맡고, 인계 요약은 이번 작업의 상태를 맡는다. 모든 진행 기록을 지침 파일에 넣으면 지속할 규칙과 일시적인 상태가 섞인다.
인계 요약을 AI에게 작성하게 할 수는 있다. 그러나 전달 전에 사람이 읽어야 한다. 논의만 한 내용을 완료했다고 썼는지, 실행하지 않은 확인을 통과했다고 썼는지, 남아 있는 문제를 지웠는지 살펴본다. 다음 세션에서도 요약은 출발 자료이며, 실제 파일과 실행 결과가 현재 상태의 근거다.
기능마다 시작하되 공통 조건은 전달한다
검색 기능이 끝났다면 다음 기능은 새 세션에서 시작하는 편이 도움이 될 수 있다. 저장 오류를 논의한 대화와 검색 결과 순서를 논의한 대화를 계속 이어 가면 이번 작업에 필요 없는 선택지가 쌓인다. 기능별로 시작하면 목표와 확인 기준을 다시 좁히기 쉽다.
그렇다고 함수 하나를 수정할 때마다 대화를 끊을 필요는 없다. 같은 기능을 구현하고 확인하는 중에는 바로 앞의 실행 결과가 유용하다. 목표가 바뀌었거나, 오래된 선택지가 반복되거나, 요약으로 현재 상태를 더 분명하게 표현할 수 있을 때 새 시작을 고려한다. 파일 수나 대화 횟수만으로 결정하지 않는다.
병렬 작업은 여러 작업을 동시에 진행하는 방식이다. 예를 들어 한 작업에 검색을 맡기고 다른 작업에 완료 항목 표시를 맡길 수 있다. 그러나 동시에 실행한다고 총비용이 줄어드는 것은 아니다. 두 작업이 같은 파일과 같은 요구를 읽으면 공통 맥락이 각각 전달된다. 결과를 합칠 때 충돌을 해결하고 다시 검증하는 시간도 추가된다.
같은 main.py의 목록 출력 함수를 두 작업이 함께 고치면 변경이 겹치기 쉽다. 반면 독립된 입력 사례를 검토하거나 서로 다른 기능의 요구를 정리하는 작업은 분리하기 쉬울 수 있다. 병렬로 맡기기 전에 수정 대상이 겹치는지, 한 결과가 다른 결과의 전제가 되는지, 합친 뒤 무엇을 확인할지를 먼저 살펴본다.
| 상황 | 선택 | 함께 전달할 정보 |
|---|---|---|
| 같은 검색 오류를 계속 확인한다 | 현재 대화를 이어 간다 | 최신 실행 결과와 실패 사례 |
| 검색을 마치고 삭제 기능으로 옮긴다 | 새 세션을 고려한다 | 현재 상태와 삭제 기능의 조건 |
| 두 작업이 같은 출력 함수를 바꾼다 | 순서대로 진행한다 | 먼저 적용한 변경과 검증 결과 |
| 서로 독립된 사례를 검토한다 | 병렬 진행을 고려한다 | 공통 조건과 각 작업의 범위 |
이제 글자 수로 제한된 맥락 공간을 흉내 낸다. 완성 프로그램은 AI를 호출하지 않는다. 가상 기록마다 사람이 확인한 핵심 문장을 미리 붙이고, 오래된 기록을 그 문장들로 바꾼다. 자동 요약의 품질을 재현하는 프로그램이 아니라, 요약으로 공간을 확보하는 절차와 그 한계를 관찰하는 프로그램이다.
완성 코드
아래 내용을 main.py에 저장한다. 각 기록의 text는 원문이고 fact는 원문에서 남길 핵심이다. 예산은 text 값의 글자 수 합계에만 적용한다. 핵심 문장을 저장하는 공간과 파일 이름 등은 계산에서 제외한다. 최근 세 기록은 원문으로 유지하며, 그 앞의 기록을 하나씩 더 요약해 예산에 들어오는 첫 결과를 선택한다.
HISTORY = [
{"text": "메모를 파일에 저장한다.", "fact": "파일 저장"},
{"text": "완료한 할 일은 숨긴다.", "fact": "완료 숨김"},
{"text": "검색은 제목만 비교한다.", "fact": "제목 검색"},
{"text": "삭제 전에 확인을 받는다.", "fact": "삭제 확인"},
{"text": "검색 결과는 입력순이다.", "fact": "입력순 유지"},
{"text": "이번에는 검색만 고친다.", "fact": "검색만 수정"},
]
BUDGET = 65
KEEP_RECENT = 3
def count_chars(messages):
return sum(len(message) for message in messages)
def make_summary(records):
facts = [record["fact"] for record in records]
return "요약: " + ", ".join(facts) + "."
def compress_history(records, budget, keep_recent):
if budget < 0:
raise ValueError("예산은 0 이상이어야 한다.")
if keep_recent < 1:
raise ValueError("최근 기록은 1개 이상 남겨야 한다.")
original = [record["text"] for record in records]
if count_chars(original) <= budget:
return original, 0, True
max_old_count = max(0, len(records) - keep_recent)
for old_count in range(1, max_old_count + 1):
summary = make_summary(records[:old_count])
recent = original[old_count:]
candidate = [summary] + recent
if count_chars(candidate) <= budget:
return candidate, old_count, True
return original, 0, False
def run_checks():
messages, replaced, fits = compress_history(
HISTORY, BUDGET, KEEP_RECENT
)
assert count_chars([item["text"] for item in HISTORY]) == 79
assert count_chars(messages) == 64
assert replaced == 3 and fits
assert messages[0] == "요약: 파일 저장, 완료 숨김, 제목 검색."
assert messages[-3:] == [item["text"] for item in HISTORY[-3:]]
unchanged, replaced, fits = compress_history(HISTORY, 79, 3)
assert unchanged == [item["text"] for item in HISTORY]
assert replaced == 0 and fits
unchanged, replaced, fits = compress_history(HISTORY, 20, 3)
assert unchanged == [item["text"] for item in HISTORY]
assert replaced == 0 and not fits
empty, replaced, fits = compress_history([], 0, 3)
assert empty == [] and replaced == 0 and fits
assert HISTORY[0]["text"] == "메모를 파일에 저장한다."
def main():
run_checks()
original = [item["text"] for item in HISTORY]
messages, replaced, fits = compress_history(
HISTORY, BUDGET, KEEP_RECENT
)
print(f"원문 글자 수: {count_chars(original)}")
print(f"예산: {BUDGET}")
print(f"압축 후 글자 수: {count_chars(messages)}")
print(f"요약한 기록 수: {replaced}")
print(f"예산 충족: {'예' if fits else '아니오'}")
print("전달할 기록:")
for message in messages:
print(f"- {message}")
print("검사: 통과")
if __name__ == "__main__":
main()
예산에 들어오는 결과를 만들 수 없으면 원문과 실패 상태를 돌려준다. 원문을 몰래 잘라 성공한 것처럼 보이지 않게 하는 선택이다. 이 프로그램은 입력 기록을 수정하지 않으며 파일에도 쓰지 않는다. 같은 원문과 같은 설정으로 실행하면 같은 결과가 나오고 바로 끝난다.
줄별 해설
첫 줄부터 여덟째 줄까지는 가상 대화 기록을 만든다. 중괄호 안의 text와 fact는 각각 원문과 핵심을 가리키는 이름이다. fact는 AI가 생성한 문장이 아니라 이 예제를 위해 미리 작성한 자료다. 실제 작업에서 이런 핵심을 준비한다면 원문과 맞는지 사람이 검토해야 한다.
아홉째 줄의 BUDGET은 글자 수 상한이고, 열째 줄의 KEEP_RECENT는 끝에서부터 유지할 원문 기록 수다. 큰 글자로 적은 이름은 프로그램에서 설정값으로 쓴다는 의도를 나타낸다. Python이 값의 변경을 막아 주는 것은 아니다.
count_chars 함수는 각 문자열에 len을 적용한 뒤 sum으로 더한다. 여기서 len은 저장 용량의 바이트 수나 화면에 보이는 폭을 세는 함수가 아니다. 이 예제의 한글, 공백, 문장 부호는 각각 계산에 포함된다. 줄을 나누어 출력할 때 붙이는 표시와 줄바꿈은 예산에 넣지 않는다.
make_summary 함수는 fact 값만 모으고 쉼표와 공백으로 연결한다. join은 여러 문자열 사이에 지정한 구분자를 넣어 하나로 만드는 문자열 기능이다. 요약 앞의 “요약: ”과 끝의 마침표도 글자 수에 포함된다. 요약 자체가 차지하는 공간을 빼먹으면 예산을 실제보다 넉넉하게 계산하게 된다.
compress_history 함수의 첫 두 조건은 허용하지 않는 설정을 거른다. 음수 예산이나 최근 기록을 하나도 남기지 않는 설정을 받으면 ValueError를 발생시킨다. 이는 함수가 처리할 수 없는 값을 받았음을 알리는 오류다. 정상 실행에서는 유효한 설정만 사용하므로 오류 메시지가 출력되지 않는다.
original을 만드는 줄은 원문의 문자열을 새 목록에 모은다. 이미 예산 이하면 요약하지 않고 반환한다. 반환값 세 개는 전달할 문자열 목록, 요약으로 바꾼 원문 기록 수, 예산 충족 여부다. 호출하는 쪽에서는 같은 순서로 받아야 한다.
max_old_count는 요약해도 되는 최대 기록 수다. 전체 기록이 여섯 개이고 최근 세 개를 남기면 앞의 세 개까지 요약할 수 있다. 기록이 세 개보다 적어도 음수가 되지 않도록 max를 사용한다. 이 경우 반복할 후보가 없으므로 원문이 예산을 넘으면 실패 결과를 반환한다.
반복문은 오래된 기록 한 개, 두 개, 세 개를 바꾼 후보를 차례로 만든다. records[:old_count]는 목록의 앞부분을 꺼내는 슬라이스다. original[old_count:]는 그 뒤의 원문이다. 요약과 남은 원문을 합친 후보 전체를 세므로 아직 요약하지 않은 기록도 예산에 포함된다.
이 자료에서는 첫 후보가 76자, 둘째 후보가 70자, 셋째 후보가 64자다. 따라서 65자 예산에는 셋째 후보가 들어간다. 어떤 자료에서도 요약할 기록을 늘리면 크기가 계속 줄어든다고 가정하지는 않는다. 핵심 문장이 길면 요약이 원문보다 커질 수도 있으므로 후보마다 직접 센다.
run_checks의 assert는 조건이 참인지 확인한다. 예상 글자 수, 요약된 기록 수, 최근 원문의 보존, 이미 예산에 맞는 경우, 예산을 맞출 수 없는 경우, 빈 기록을 검사한다. 실행 결과가 짧아졌다는 사실만 확인하지 않고, 원문을 남기는 동작과 실패 처리도 확인하는 것이다.
마지막 main 함수는 검사를 먼저 실행하고 결과를 출력한다. 검사를 통과한 경우에만 마지막 줄이 출력된다. 다만 이 검사가 요약의 의미까지 보장하지는 않는다. 첫 요약의 “제목 검색”은 원문의 “제목만”이라는 제한을 충분히 드러내지 못한다. 숫자 검사는 통과하더라도 사람이 요약을 읽고 제한 조건을 보완해야 한다.
실행 결과
macOS나 Linux에서 main.py를 저장한 디렉터리로 이동한 뒤 다음 명령을 실행한다. Python 3.12 이상에서 외부 패키지 없이 실행할 수 있다.
python3 main.py
예상 출력은 다음과 같다. 예산 충족 여부는 전달할 문자열의 크기에 대한 판정이며, 요약의 의미가 충분하다는 판정은 아니다.
원문 글자 수: 79
예산: 65
압축 후 글자 수: 64
요약한 기록 수: 3
예산 충족: 예
전달할 기록:
- 요약: 파일 저장, 완료 숨김, 제목 검색.
- 삭제 전에 확인을 받는다.
- 검색 결과는 입력순이다.
- 이번에는 검색만 고친다.
검사: 통과
컴파일 확인은 다음 명령으로 할 수 있다. 정상적으로 끝나면 별도 출력이 없다. 이 명령은 구문과 컴파일 단계의 문제를 확인하며 프로그램의 동작 검사를 대신하지 않는다. 실행 시에는 위의 검사가 수행되고, 수정한 뒤에는 diff에서 의도한 부분만 바뀌었는지도 확인한다.
python3 -W error -m py_compile main.py
실무에서 자주 틀리는 것
오래된 내용을 글자 수만큼 잘라 버린다
문자열 앞부분만 남기면 최근 요청이 먼저 사라진다. 문장 중간에서 끊기면 조건의 의미도 달라질 수 있다. 다음 잘못된 코드는 예산에는 들어가지만 필요한 정보를 보존하지 못한다.
history = ["저장은 유지한다.", "검색은 제목만 비교한다."]
text = "\n".join(history)
budget = 10
clipped = text[:budget]
print(clipped)
고친 코드는 먼저 예산 초과를 드러낸다. 초과 여부를 아는 것과 안전하게 줄이는 것은 다른 작업이다. 원문을 지킨 채 요약 후보를 만들어 검토해야 한다.
history = ["저장은 유지한다.", "검색은 제목만 비교한다."]
text = "\n".join(history)
budget = 10
if len(text) > budget:
print("예산 초과: 핵심 조건을 남길 요약이 필요하다.")
else:
print(text)
요약은 예산에서 제외한다
요약도 다음 작업에 전달하는 문자열이다. 최근 기록만 세면 실제 전달량보다 작게 계산한다. 아래 코드는 요약이 추가한 공간을 빠뜨린다.
summary = "요약: 제목만 검색한다."
recent = ["이번에는 순서를 고친다."]
used = sum(len(message) for message in recent)
print(used)
고친 코드에서는 실제 전달할 목록을 먼저 만들고 그 목록을 센다. 표시용 제목과 구분 기호까지 보내는 방식이라면 그것도 같은 기준에 포함해야 한다.
summary = "요약: 제목만 검색한다."
recent = ["이번에는 순서를 고친다."]
messages = [summary] + recent
used = sum(len(message) for message in messages)
print(used)
시도한 내용을 확인한 사실로 바꾼다
요약에서 상태가 바뀌면 다음 세션은 잘못된 전제를 갖고 시작한다. 다음 코드는 실행하지 않은 일을 검증 완료라고 기록한다. 문자열을 만드는 데는 오류가 없지만 작업 상태가 틀렸다.
check_ran = False
handoff = {"검색 검증": "통과"}
print(handoff["검색 검증"])
고친 코드는 실행하지 않았다는 상태를 남긴다. 실제 작업에서는 실행 여부와 함께 어떤 사례가 통과했는지도 적어야 한다. 실행했다는 사실만으로 모든 동작을 확인한 것은 아니다.
check_ran = False
status = "실행 결과 검토 필요" if check_ran else "미실행"
handoff = {"검색 검증": status}
print(handoff["검색 검증"])
병렬 작업의 공통 입력을 한 번만 센다
두 작업에 같은 요약을 보내면 공통 입력이 두 번 전달된다. 아래 코드는 공통 요약을 한 번만 더하므로 전체 전달량을 작게 계산한다. 이 계산도 글자 수 비교일 뿐 실제 요금 계산은 아니다.
shared = "저장 방식은 유지한다."
search_task = "검색 범위를 확인한다."
display_task = "완료 표시를 확인한다."
total = len(shared) + len(search_task) + len(display_task)
print(total)
고친 코드는 작업별 입력을 각각 만든 뒤 합산한다. 여기에 출력 검토와 결과 통합에 드는 작업까지 고려해야 병렬 진행의 이점을 판단할 수 있다.
shared = "저장 방식은 유지한다."
search_task = "검색 범위를 확인한다."
display_task = "완료 표시를 확인한다."
inputs = [shared + search_task, shared + display_task]
total = sum(len(task_input) for task_input in inputs)
print(total)
한눈에 보기
| 할 일 | 방법 | 확인할 것 |
|---|---|---|
| 현재 조건을 분명하게 한다 | 이번 목표와 유지할 조건을 다시 적는다 | 답과 변경 코드가 조건을 지키는가 |
| 관련 파일을 고른다 | 경로, 줄 위치, 함수 이름을 안내한다 | 입력 구조와 호출 관계가 충분한가 |
| 대화를 인계한다 | 결정, 확인 결과, 남은 일을 요약한다 | 미확인 내용을 완료로 적지 않았는가 |
| 기능별로 새로 시작한다 | 새 목표에 필요한 현재 상태를 전달한다 | 공통 조건과 최신 코드가 이어지는가 |
| 병렬 작업을 선택한다 | 중복 입력과 통합 작업을 함께 고려한다 | 수정 범위가 겹치거나 서로 의존하는가 |
| 압축 결과를 검토한다 | 글자 수 검사와 의미 검토를 나누어 한다 | 최근 요청과 중요한 제한이 남았는가 |
이 장의 압축기는 글자 수, 원문 보존, 실패 처리를 확인하는 작은 도구다. 실제 인계 요약에서는 제한 조건과 미확인 상태를 더 자세히 남겨야 한다. 다음 장에서는 이렇게 고른 파일과 생성 코드를 검토할 때 비밀값, 입력 검증, 패키지 이름을 어떻게 살펴볼지 다룬다.
연습 문제
- BUDGET을 70으로 바꾸면 요약하는 기록 수와 압축 후 글자 수가 어떻게 되는지 예상하라. 그 뒤 기본 설정에 의존하는 검사를 함께 수정하고 실행해 비교하라.
- BUDGET을 20으로 바꾸면 실패 결과로 무엇이 돌아오는지 설명하라. 최근 세 기록의 글자 수를 근거로 사용하라.
- 세 번째 기록의 fact를 “제목만 검색”으로 바꾸어 제한 조건을 더 분명하게 남겨라. 65자 예산에서 어떤 결과가 나오는지 계산하고, 예산을 66으로 바꾼 결과와 비교하라.
- 검색 기능을 마친 뒤 삭제 기능을 새 세션에서 시작한다고 하자. 가상의 인계 요약을 작성하라. 현재 상태, 삭제 조건, 확인한 사실, 아직 확인하지 않은 사실을 구분하라.
정답과 해설
오래된 기록 두 개를 요약하고 70자가 된다. 두 기록의 핵심을 합친 요약은 17자이고, 남은 네 원문은 53자다. 첫 후보는 76자이므로 통과하지 못하고 둘째 후보가 선택된다. 기본 설정을 검사하는 부분의 기대 글자 수를 70, 요약 기록 수를 2로 바꾼다. 첫 메시지는 “요약: 파일 저장, 완료 숨김.”이 된다. 별도로 예산 79와 20을 검사하는 부분은 유지한다.
원문 목록, 요약 기록 수 0, 예산 충족 여부 False가 돌아온다. 최근 세 원문만으로도 40자여서 20자 예산에 들어가지 않는다. 최근 기록을 유지한다는 조건을 지키면 요약으로 해결할 수 없다. 프로그램은 실패를 보고하고 원문을 보존한다. 전달 범위를 줄일지 예산을 바꿀지는 별도 판단이다.
“제목 검색”보다 “제목만 검색”이 한 글자 길다. 세 기록을 요약한 후보는 65자가 된다. 65자 예산에서도 세 기록을 요약해 성공하며, 66자 예산에서도 같은 후보를 선택한다. 검사에서는 기대 글자 수와 첫 요약 문장을 바꿔야 한다. 글자 수가 조금 늘어도 검색 범위를 더 분명하게 보존하므로 인계 자료로는 유용한 수정이다.
가능한 답은 아래와 같다. 완료 상태와 미확인 상태가 구분되어 있고 삭제 작업의 경계가 드러나면 표현은 달라도 된다.
현재 도구는 파일 저장, 완료 항목 숨기기, 제목만 검색하기를 지원한다. 이번 작업은 삭제 기능이다. 삭제 전에는 사용자의 확인을 받아야 한다.
검색 범위와 입력순 결과는 직접 실행해 확인했다. 삭제를 취소했을 때 목록과 파일이 유지되는지는 아직 확인하지 않았다.
현재 main.py에서 삭제 요청을 처리하는 함수와 저장 함수를 먼저 확인해 달라. 이번 변경 뒤에는 삭제 승인과 취소를 각각 실행해 확인한다.
이 답의 검증 결과는 연습용 가정이다. 실제 인계에서는 자신이 실행한 사실로 바꾸어야 한다. AI가 작성한 요약을 그대로 넘기기 전에 현재 파일, 실행 결과, diff와 맞는지 읽어 보는 과정까지가 맥락 관리다.