Devin.KR

시스템으로 보기 - 부분이 아닌 흐름과 실패 지점

개발자KR 조회 0

이 장에서 배우는 것

학습 기록장의 저장 함수가 잘 작동해도 기록 전체가 정확하다는 뜻은 아니다. 저장할 내용이 비어 있을 수 있고, 같은 기록이 두 번 들어갈 수 있으며, 저장한 뒤 화면에 보여 주는 단계에서 문제가 생길 수도 있다. 함수는 일을 나누는 단위다. 시스템은 그 일들이 연결되어 하나의 결과를 만드는 전체다.

앞 장에서 반례를 찾아 예상과 실제를 비교했다면, 이번에는 비교할 범위를 넓힌다. 한 함수의 입력과 출력뿐 아니라 데이터가 들어와서 나가기까지의 흐름을 살핀다. 공부를 시작한 학생도 이 관점을 연습할 수 있다. 자신이 만든 작은 도구에 “어디까지 끝났는가”, “여기서 멈추면 무엇이 남는가”를 묻는 것이다.

이번 예시는 주문 처리다. 접수, 재고 확인, 결제, 알림이라는 익숙한 순서로 전체 흐름을 관찰한다. 학생은 이 프로그램을 코드 추적 연습 도구로 사용한다. 실행 전에 멈출 위치를 예상하고, 실행 뒤 실제 출력과 비교한다. 주문 서비스를 만드는 것이 목표는 아니다. 서로 이어진 단계의 관계를 읽는 것이 목표다.

  • 함수 하나의 정답과 전체 흐름의 정답을 구별한다.
  • 입력, 단계, 저장된 상태, 출력을 연결해 흐름을 그린다.
  • 입력 누락, 저장 실패, 중복 요청이 남기는 결과를 설명한다.
  • 이미 끝난 일을 반복하지 않고 남은 일을 이어 가는 방법을 읽는다.
  • AI가 작성한 코드를 전체 흐름에 맞춰 실행하고 확인한다.

문제 상황

작은 온라인 판매 도구를 맡았다고 생각해 보자. 주문을 받으면 물건이 있는지 확인하고, 결제한 뒤 구매자에게 알림을 보낸다. 각 담당자는 자기 함수가 잘 작동한다고 말한다. 재고 확인 함수는 남은 수량을 정확히 읽고, 결제 함수는 결제 성공을 반환하며, 알림 함수는 메시지를 전송한다.

그런데 구매자가 같은 주문을 다시 보내자 결제가 한 번 더 실행된다. 첫 요청에서 결제는 끝났지만 알림이 실패했고, 구매자는 주문이 접수되지 않았다고 생각한 것이다. 알림 함수의 실패를 고쳤더라도 이미 발생한 두 번의 결제가 저절로 정리되지는 않는다. 문제는 함수 안의 계산보다 함수 사이의 연결에 있다.

다른 상황도 있다. 주문 번호가 없는 요청을 결제 단계까지 보내면 나중에 어떤 주문의 결제였는지 연결하기 어렵다. 주문 저장이 실패했는데 다음 단계로 진행하면 돈은 받았지만 주문 목록에는 아무것도 없는 상태가 생길 수 있다. 각 단계가 자기 일을 수행했다는 사실만으로 전체 결과를 설명할 수 없는 이유다.

학습 기록장에서도 비슷한 일이 생긴다. 저장 버튼을 두 번 눌렀을 때 공부 시간이 두 번 더해지는지, 기록 저장은 끝났는데 완료 안내가 나오지 않았을 때 재시도하면 어떻게 되는지 확인해야 한다. 주문 예시에서 읽은 질문을 자신의 학습 도구에 옮겨 볼 수 있다.

함수의 결과를 연결해서 읽는다

함수는 입력을 받아 일을 수행하는 코드 묶음이다. 시스템을 읽을 때는 각 함수가 무엇을 반환하는지에 더해, 다음 단계가 무엇을 전제로 움직이는지 살핀다. “결제가 성공하면 알림을 보낸다”에는 결제 성공을 어디에 기억할지, 알림이 실패하면 성공 기록을 유지할지라는 결정도 포함되어 있다.

여기서 상태란 현재 어디까지 진행했는지를 나타내는 정보다. 이 장에서는 주문 번호와 함께 “접수”, “결제 완료”, “완료”를 저장한다. 상태가 있으면 같은 주문이 다시 들어왔을 때 처음부터 실행할지, 알림만 이어 갈지 판단할 수 있다. 출력 문장만 보고 판단하는 방식과 달리, 프로그램이 읽을 수 있는 근거를 남기는 것이다.

흐름은 성공 경로부터 그린다. 시작점에는 주문 번호와 수량이 있고, 끝에는 처리 결과와 알림이 있다. 가운데에는 입력 확인, 주문 저장, 재고 확인, 결제, 알림이 놓인다. 각 화살표는 단순한 실행 순서가 아니라 “앞 단계에서 무엇이 확인되어야 다음으로 갈 수 있는가”를 뜻한다.

주문은 앞 단계의 조건을 통과해야 다음 단계로 진행한다

이 그림을 읽을 때는 칸의 이름보다 칸 사이의 조건에 주목한다. 입력 확인이 끝났다면 주문 번호와 양의 정수 수량이 있어야 한다. 저장이 끝났다면 주문 번호로 진행 상태를 찾을 수 있어야 한다. 결제가 끝났다면 다시 요청을 받아도 결제를 반복하지 않을 근거가 있어야 한다.

전체가 맞다는 말에는 마지막 출력뿐 아니라 중간에 남은 정보도 포함된다. “알림 실패”라는 출력이 같아도 결제까지 끝났는지, 결제 전에 멈췄는지는 다르다. 같은 실패 문장을 보더라도 대응이 달라지는 이유다. 코드 추적표에는 출력 옆에 주문 상태와 남은 재고를 함께 적는 편이 좋다.

실패한 위치와 남은 일을 구별한다

실패 지점은 실행이 기대한 방식으로 이어지지 못한 위치다. 실패를 만났다고 해서 모든 일이 취소되었다고 가정해서는 안 된다. 입력 확인에서 멈췄다면 아직 주문을 저장하지 않았지만, 알림에서 멈췄다면 결제와 재고 반영은 이미 끝났을 수 있다.

멈춘 단계에 따라 남은 정보와 대응이 달라진다
멈춘 단계남은 정보대응
입력 확인새 주문 기록 없음누락되거나 잘못된 입력을 고친다
접수 저장새 주문 기록 없음결제로 진행하지 않는다
재고 확인접수 상태수량이나 재고 조건을 확인한다
결제접수 상태, 재고 유지결제 실패 원인을 확인한다
알림결제 완료 상태, 재고 감소결제를 반복하지 않고 알림을 재시도한다

중복 요청은 같은 일을 다시 해 달라는 요청이다. 이를 구별하려면 요청마다 새 번호를 만드는 대신, 같은 주문을 다시 보낼 때 같은 주문 번호를 사용해야 한다. 번호가 달라지면 프로그램은 두 요청을 다른 주문으로 볼 수 있다. 번호만 같고 수량이 달라진 경우도 조용히 넘겨서는 안 된다. 같은 주문의 재시도인지, 다른 내용으로 바꾸려는 요청인지 구별해야 한다.

이 예시에서는 이미 완료된 주문은 다시 처리하지 않는다. 결제까지 끝나고 알림만 실패한 주문은 알림부터 이어 간다. 같은 요청을 반복해도 결제나 재고 감소 같은 효과가 추가로 발생하지 않게 하는 성질을 멱등성(idempotency)이라고 한다. 용어를 외우기보다 “두 번 요청했을 때 한 번 처리한 결과를 유지하는가”를 먼저 물으면 된다.

알림 실패 뒤 재시도는 결제를 반복하지 않고 알림부터 이어 간다

저장에도 범위가 있다. 이번 프로그램은 사전이라는 자료 구조에 주문 상태를 넣는다. 사전은 이름표에 해당하는 키로 값을 찾는 저장 공간이다. 여기서는 주문 번호가 키다. 이 정보는 프로그램이 실행되는 동안만 남고 종료하면 사라진다. 따라서 이 예시의 저장 성공은 파일이나 별도 저장 서비스에 안전하게 보관되었다는 뜻이 아니다.

또한 실패를 넣는 위치를 정해 둔다. 접수 저장 실패, 결제 실패, 알림 실패만 흉내 낸다. 결제 성공 직후 프로그램이 종료되거나, 여러 요청이 동시에 재고를 읽는 상황은 다루지 않는다. 실제 시스템에서 그런 상황까지 대응하려면 결제 결과 확인, 오래 남는 기록, 동시에 들어온 요청의 조정이 필요하다. 작은 예시가 보여 주는 범위를 알고 읽는 것도 전체를 보는 연습이다.

AI에게 코드를 맡겨도 흐름의 기준은 사람이 정한다

AI에게 “주문 처리 함수를 만들어 달라”고만 요청하면 성공 경로가 자연스럽게 이어지는 코드를 받을 수 있다. 하지만 알림 실패 뒤 재시도할 때 결제를 반복해도 되는지, 같은 번호에 다른 수량이 들어오면 어떻게 할지는 요청에 드러나지 않는다. 이런 결정은 코드 작성 속도보다 업무의 의미와 관련된다.

사람이 쥐고 있어야 하는 전체 그림은 모든 코드 줄을 직접 작성한다는 뜻이 아니다. 무엇을 입력으로 받고, 언제 상태를 남기며, 어떤 단계부터 다시 시작할지를 설명할 수 있어야 한다는 뜻이다. AI는 이 기준을 코드로 옮기고 가능한 누락을 찾는 데 도움을 줄 수 있다. 기준의 타당성은 실제 목적과 실행 결과를 함께 보며 판단한다.

다음은 특정 제품의 기능에 의존하지 않는 요청문이다. AI 활용 대화는 2026년 10월 기준 예시이며, 제품 이름이나 모델보다 요청에 담긴 조건을 읽는 데 초점을 둔다.

주문 번호와 수량을 받는 짧은 Python 프로그램을 작성하라. 접수 저장, 재고 확인, 결제, 알림 순서로 처리하라. 저장 실패 때는 결제를 시작하지 말라. 결제 실패 때는 재고를 줄이지 말라. 알림 실패 때는 결제 완료 상태를 남기고, 같은 주문을 재시도하면 알림만 실행하라. 같은 번호에 다른 수량이 들어오면 중단하라. 외부 서비스 없이 실패를 흉내 내고, 각 단계와 마지막 상태를 출력하라.

답을 받은 뒤에는 요청문이 코드에 반영되었는지 읽는다. 특히 상태를 저장하는 줄과 재고를 줄이는 줄의 위치를 확인한다. 그다음 실패 사례를 실행해 본다. AI가 “중복 처리를 방지했다”고 설명해도, 알림 재시도에서 결제 출력이 다시 나타나거나 재고가 더 줄었다면 기준을 만족하지 못한 것이다.

학습할 때는 AI에게 실행 전 예상 결과를 먼저 말하게 할 수도 있다. 자신의 예상, AI의 예상, 실제 실행을 비교하면 어느 단계의 관계를 잘못 읽었는지 드러난다. 개발자가 맡는 일도 이렇게 달라진다. 코드를 작성하는 일과 함께, 연결된 작업의 의미를 정하고 결과를 판별하는 일이 필요하다.

완성 코드

다음 내용을 main.py에 저장한다. 재고 5개와 각 주문 수량은 설명용 가상값이다. 실패 이름도 실제 오류를 발생시키는 장치가 아니라 정해진 위치에서 멈추게 하는 연습용 입력이다. 시간, 난수, 네트워크를 사용하지 않아 매번 같은 결과가 나온다.

stock = 5
orders = {}

def process(order, failure=""):
    global stock
    order_id = order.get("id")
    quantity = order.get("quantity")
    label = order_id or "번호 없음"
    print(f"[{label}] 시작")
    if not isinstance(order_id, str) or not order_id.strip():
        print("중단: 입력 누락 또는 오류")
        return
    if type(quantity) is not int or quantity <= 0:
        print("중단: 수량 오류")
        return
    saved = orders.get(order_id)
    if saved is not None and saved["quantity"] != quantity:
        print("중단: 같은 번호의 수량이 다름")
        return
    if saved is not None and saved["status"] == "완료":
        print("중단: 이미 완료한 주문")
        return
    if saved is None:
        if failure == "저장":
            print("중단: 접수 저장 실패")
            return
        saved = {"quantity": quantity, "status": "접수"}
        orders[order_id] = saved
        print("접수: 저장 완료")
    else:
        print(f"재개: {saved['status']}")
    if saved["status"] == "접수":
        if quantity > stock:
            print("중단: 재고 부족")
            return
        print("재고: 확인 완료")
        if failure == "결제":
            print("중단: 결제 실패")
            return
        print("결제: 성공")
        stock -= quantity
        saved["status"] = "결제 완료"
    if failure == "알림":
        print("중단: 알림 실패")
        return
    print("알림: 발송 완료")
    saved["status"] = "완료"
    print("완료: 주문 처리 끝")

cases = [
    ({"quantity": 1}, ""),
    ({"id": "A", "quantity": 1}, "저장"),
    ({"id": "B", "quantity": 9}, ""),
    ({"id": "C", "quantity": 1}, "결제"),
    ({"id": "D", "quantity": 2}, "알림"),
    ({"id": "D", "quantity": 2}, ""),
    ({"id": "D", "quantity": 2}, ""),
    ({"id": "D", "quantity": 1}, ""),
]
for order, failure in cases:
    process(order, failure)
    print(f"남은 재고: {stock}")
    print()
print("최종 주문 상태")
for order_id, saved in orders.items():
    print(f"{order_id}: {saved['status']}")

줄별 해설

빈 줄을 포함해 첫 줄부터 번호를 센다. 코드는 66줄이다. 길어 보이는 부분도 같은 질문을 반복한다. “입력이 맞는가”, “이미 기록이 있는가”, “어디까지 끝났는가”를 순서대로 읽으면 된다.

코드의 각 줄이 전체 흐름에서 맡는 역할
줄코드에서 하는 일읽을 때 확인할 점
1~2재고와 주문 저장 공간을 만든다모든 사례가 같은 저장 공간을 사용한다
3빈 줄로 구역을 나눈다실행되는 작업은 없다
4주문 처리 함수를 정의한다실패 이름을 생략하면 빈 문자열이다
5함수 밖의 재고 값을 바꾸겠다고 표시한다주문마다 재고를 새로 만들지 않는다
6~9주문 번호와 수량을 읽고 시작을 출력한다키가 없으면 get은 None을 돌려준다
10~12번호가 문자열인지, 비어 있지 않은지 확인한다실패하면 저장 전에 함수를 끝낸다
13~15수량이 양의 정수인지 확인한다문자열이나 참·거짓 값은 받지 않는다
16같은 번호로 저장된 주문을 찾는다새 주문과 재시도를 구별한다
17~19저장된 수량과 새 수량을 비교한다같은 번호의 내용을 조용히 바꾸지 않는다
20~22이미 완료된 주문을 중단한다결제와 알림을 다시 실행하지 않는다
23~26새 주문의 접수 저장 실패를 흉내 낸다재고 확인과 결제에 도달하지 않는다
27~29수량과 접수 상태를 저장한다이제 번호로 진행 상태를 찾을 수 있다
30~31기존 주문이면 재개 상태를 출력한다재시도의 출발점이 눈에 보인다
32~35접수 상태일 때 재고 부족을 확인한다결제 완료 상태는 이 구역을 건너뛴다
36재고 확인 성공을 출력한다아직 재고를 줄이지 않았다
37~39결제 실패를 흉내 내고 중단한다주문은 접수 상태로 남는다
40~42결제 성공 뒤 재고와 상태를 바꾼다다음 요청에서 결제 반복을 막는 근거다
43~45알림 실패를 흉내 내고 중단한다결제 완료 상태를 유지한다
46~48알림 성공과 전체 완료를 기록한다알림까지 끝나야 완료 상태가 된다
49빈 줄로 사례 목록을 구분한다실행되는 작업은 없다
50~59여덟 가지 요청과 실패 조건을 준비한다D의 재시도에는 같은 번호를 사용한다
60~63각 사례를 순서대로 실행한다호출 뒤 재고와 빈 줄을 출력한다
64~66저장된 주문의 마지막 상태를 출력한다저장되지 않은 A는 목록에 없다

처음 보는 표현 몇 가지를 더 읽어 보자. isinstance는 값이 지정한 종류에 속하는지 확인한다. strip은 문자열 양끝의 공백을 제거하므로 공백만 있는 번호도 거를 수 있다. type(quantity) is int는 수량이 정확히 정수인지 확인한다. Python에서는 참·거짓 값도 정수와 관련된 성질이 있으므로 이 예시에서는 수량으로 받지 않도록 구별한다.

return은 현재 함수의 실행을 끝낸다. 오류 문장을 출력하는 것만으로는 다음 단계가 멈추지 않는다. 중단 조건마다 return이 있는 이유다. 다만 함수를 호출한 바깥 반복은 계속된다. 따라서 실패 사례 하나가 끝나도 다음 사례를 실행한다.

saved와 orders[order_id]는 같은 주문 사전을 가리킨다. 따라서 saved의 status 값을 바꾸면 orders에서 읽는 상태도 바뀐다. 별도의 복사본을 만든 것이 아니다. 마지막 출력에서 D가 완료로 나오는 것은 이 연결 때문이다. 반면 stock은 숫자 값을 새로 대입하므로 함수 밖의 값을 바꾸겠다는 global 표시를 썼다.

대괄호로 감싼 cases는 여러 항목을 순서대로 담는 목록이다. 각 항목은 주문 사전과 실패 이름을 한 쌍으로 묶는다. 반복문은 그 쌍을 order와 failure로 받아 함수에 전달한다. 앞에 f가 붙은 문자열은 중괄호 안의 값을 문장에 넣는다. 출력 문장을 만드는 표현이지 상태를 저장하는 표현은 아니다.

실행 결과

main.py가 있는 폴더에서 다음 명령을 실행한다.

python3 main.py

예상 출력은 다음과 같다. 각 사례 뒤에는 빈 줄이 하나씩 나온다.

[번호 없음] 시작
중단: 입력 누락 또는 오류
남은 재고: 5

[A] 시작
중단: 접수 저장 실패
남은 재고: 5

[B] 시작
접수: 저장 완료
중단: 재고 부족
남은 재고: 5

[C] 시작
접수: 저장 완료
재고: 확인 완료
중단: 결제 실패
남은 재고: 5

[D] 시작
접수: 저장 완료
재고: 확인 완료
결제: 성공
중단: 알림 실패
남은 재고: 3

[D] 시작
재개: 결제 완료
알림: 발송 완료
완료: 주문 처리 끝
남은 재고: 3

[D] 시작
중단: 이미 완료한 주문
남은 재고: 3

[D] 시작
중단: 같은 번호의 수량이 다름
남은 재고: 3

최종 주문 상태
B: 접수
C: 접수
D: 완료

출력을 읽을 때는 세 군데를 연결한다. A는 저장 실패 뒤 재고 확인이 나오지 않는다. C는 결제 실패 뒤에도 재고가 5다. D는 알림 실패 때 재고가 3으로 줄었지만, 재시도에서는 결제 출력 없이 알림만 나오며 재고도 3을 유지한다. 이 세 관찰이 코드의 단계 연결을 확인하는 근거다.

B와 C가 마지막 목록에 남는 것도 살펴야 한다. 실패했다고 접수 기록까지 지우지는 않았다. A는 저장에 실패했으므로 목록에 없다. 실행 결과를 보며 “실패한 주문이 모두 사라진다”거나 “중단되면 아무것도 바뀌지 않는다”고 해석하면 실제 동작과 어긋난다.

실무에서 자주 틀리는 것

오류를 출력하면 실행도 멈춘다고 생각한다

오류 안내와 실행 중단은 다른 일이다. 다음 코드는 실제로 실행되지만, 입력이 잘못되었다고 말한 뒤에도 결제를 진행한다. 이 절의 짧은 코드는 각각 따로 실행해 비교하는 조각이다.

valid = False
if not valid:
    print("입력 오류")
print("결제 진행")

다음처럼 진행 조건을 분명히 나누면 잘못된 입력에서 결제로 가지 않는다. 함수 안이라면 완성 코드처럼 return으로 끝낼 수도 있다.

valid = False
if not valid:
    print("입력 오류")
else:
    print("결제 진행")

AI가 오류 문장을 추가했는지만 확인하면 이 차이를 놓칠 수 있다. 오류 뒤 어떤 줄이 실행되는지 따라 읽어야 한다.

안내 실패를 전체 작업 실패로 되돌린다

결제가 끝났는데 알림이 실패했다고 상태를 접수로 되돌리면, 재시도가 결제를 다시 실행할 수 있다. 다음 코드는 그런 잘못된 판단을 보여 준다.

status = "결제 완료"
notification_ok = False
if not notification_ok:
    status = "접수"
if status == "접수":
    print("결제 다시 실행")

알림 실패 뒤에도 결제 완료 상태를 유지해야 남은 일을 선택할 수 있다. 다음 코드는 결제와 재고 반영이 끝났다는 사실을 유지한 채 알림 재시도를 안내한다.

status = "결제 완료"
notification_ok = False
if not notification_ok:
    print("알림 재시도 필요")
if status == "접수":
    print("결제 다시 실행")

상태는 화면에 보여 주기 좋은 문구보다 실제로 끝난 일을 반영해야 한다. 이 코드에서 결제 재실행 문장이 나오지 않는지 직접 확인한다.

결제 실패 전에 재고부터 줄인다

재고를 먼저 줄인 뒤 결제가 실패하면, 구매가 끝나지 않았는데 수량이 줄어든다. 다음 코드는 실행을 마치지만 남은 재고가 3이 된다.

stock = 5
quantity = 2
payment_ok = False
stock -= quantity
if not payment_ok:
    print("결제 실패")
print(stock)

이번 예시의 기준에서는 결제 성공 때만 재고를 줄인다. 고친 코드는 실패 뒤에도 재고 5를 유지한다.

stock = 5
quantity = 2
payment_ok = False
if payment_ok:
    stock -= quantity
else:
    print("결제 실패")
print(stock)

실제 판매 시스템에서는 결제 전에 재고를 잠시 확보해 두기도 한다. 그 방식이라면 실패 시 확보를 해제하는 흐름도 함께 정해야 한다. 중요한 것은 한 가지 순서를 외우는 일이 아니라, 선택한 순서에서 실패가 남기는 결과를 설명하는 일이다.

주문 번호가 같으면 내용도 같다고 가정한다

번호만 확인하고 기존 주문으로 처리하면 수량이 달라진 요청도 재시도로 받아들인다. 다음 코드는 서로 다른 수량을 확인하지 않고 넘어간다.

orders = {"D": {"quantity": 2}}
order = {"id": "D", "quantity": 1}
if order["id"] in orders:
    print("기존 주문으로 처리")

이미 저장한 내용과 비교하면 요청의 충돌을 드러낼 수 있다. 이 예시는 상품 종류가 하나이므로 수량만 비교한다. 입력 항목이 늘어나면 같은 요청이라고 판단하는 기준도 함께 넓혀야 한다.

orders = {"D": {"quantity": 2}}
order = {"id": "D", "quantity": 1}
saved = orders.get(order["id"])
if saved is not None:
    if saved["quantity"] != order["quantity"]:
        print("중단: 같은 번호의 수량이 다름")
    else:
        print("기존 주문으로 처리")

한눈에 보기

전체 흐름을 읽을 때 던질 질문과 확인할 근거
관점질문이 예시의 근거
입력다음 단계가 사용할 정보가 있는가번호와 양의 정수 수량을 먼저 확인한다
순서앞 단계가 실패해도 뒤로 진행하는가중단 조건에서 return을 실행한다
저장어디까지 끝났는지 다시 읽을 수 있는가주문 번호로 상태를 찾는다
재시도이미 끝난 효과를 반복하는가결제 완료 주문은 알림부터 이어 간다
중복같은 번호에 다른 내용이 들어오는가저장된 수량과 새 수량을 비교한다
검증설명과 실제 실행이 일치하는가출력, 남은 재고, 최종 상태를 함께 본다
범위이번 예시가 다루지 않은 실패는 무엇인가종료 뒤 복구와 동시 요청은 다루지 않는다

전체 그림을 읽을 수 있으면 다른 사람이 작성한 코드도 단계의 목적을 기준으로 검토할 수 있다. 다음 장에서는 이런 판단과 변경 이유를 다른 사람과 공유하는 작업을 살핀다. 이번 장의 흐름 그림과 실패 사례는 그때 설명할 근거가 된다.

연습 문제

  1. 첫 실행에서 D의 알림이 실패한 직후, 주문 상태와 남은 재고를 적어 보라. 같은 주문을 재시도할 때 재고 확인과 결제를 건너뛰는 조건도 찾아 보라.
  2. cases의 마지막에 주문 번호 C, 수량 1, 실패 이름은 빈 문자열인 사례를 추가한다고 가정하라. 추가 사례의 출력과 최종 재고를 실행 전에 예상하고, 직접 실행해 확인하라.
  3. 42번째 줄에서 저장하는 상태를 “결제 완료” 대신 “접수”로 바꾸면 D의 재시도에 어떤 문제가 생기는가. 출력과 재고를 기준으로 설명하라.
  4. 학습 기록장에 같은 기록을 두 번 저장하지 않으려 한다. 기록 번호, 공부한 분 수, 저장 상태가 있다고 가정하고, “같은 번호·같은 분 수”, “같은 번호·다른 분 수”, “번호 누락”을 어떻게 처리할지 적어 보라.

정답과 해설

  1. D의 상태는 “결제 완료”이고 재고는 3이다. 40~42번째 줄에서 결제 성공을 출력하고 재고를 줄인 뒤 상태를 저장했다. 알림 실패는 그 뒤에 발생한다. 재시도에서는 32번째 줄의 “접수 상태인가”라는 조건이 거짓이므로 재고 확인과 결제 구역을 건너뛴다. 이후 알림을 보내고 완료 상태로 바꾼다.

  2. C는 접수 상태로 남아 있으므로 “재개: 접수”부터 이어 간다. 추가 사례가 시작될 때 재고는 3이고 주문 수량은 1이므로 재고 확인과 결제가 성공한다. 재고는 2가 되고 C의 최종 상태도 완료가 된다. B는 접수, D는 완료 상태를 유지한다. 추가 사례의 출력은 다음과 같다.

    [C] 시작
    재개: 접수
    재고: 확인 완료
    결제: 성공
    알림: 발송 완료
    완료: 주문 처리 끝
    남은 재고: 2

    이 출력 뒤에는 반복문이 만드는 빈 줄이 하나 나온다. 프로그램 마지막의 주문 목록에서도 C가 완료로 바뀌었는지 확인한다.

  3. 첫 D 처리에서 재고는 3으로 줄지만 상태가 접수로 남는다. 다음 요청은 “재개: 접수”를 출력하고 재고 확인과 결제를 다시 실행한다. 재고는 1로 줄어든다. 결제 성공 사실을 올바르게 저장하지 않아 같은 주문의 효과가 반복된 것이다. 변경한 코드를 실행하면 결제 성공 문장이 D에 대해 두 번 나타나는지 확인할 수 있다. 확인 뒤 원래 상태 값으로 되돌린다.

  4. 같은 번호와 같은 분 수라면 이미 저장한 기록으로 처리하고 공부 시간을 다시 더하지 않는다. 같은 번호인데 분 수가 다르면 수정 요청인지 입력 실수인지 확인하도록 중단한다. 번호가 없으면 저장 전에 입력을 고치도록 안내한다. 이때도 안내 문장만 추가해서는 충분하지 않다. 저장과 합산 단계가 실제로 실행되지 않는지 확인해야 한다. 같은 기록을 다시 제출해 합계가 유지되는지 실행하고, 코드에서 중복 확인이 합산보다 앞에 있는지 읽는다.

댓글 0

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

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