본문으로 건너뛰기
페이지 목차
이 페이지에서 검색

AI 드리븐

이 페이지에 묻기

AI 드리븐 · 현재 차시와 목차 본문에서만 찾아 답합니다. 답을 지어내지 않고 해당하는 대목을 그대로 보여 주며, 여기에 없으면 없다고 알려 드립니다.

생성형 AI가 아니라 이 페이지 본문을 찾아 그대로 보여 주는 방식입니다. 외부로 나가는 요청이 없습니다.

AI · DEVELOPMENT

AI 드리븐

생성 수정

요구사항과 역할 정의부터 구현·검증·배포·운영까지, AI와 함께 개발하며 사람이 판단할 기준을 정리합니다.

26개 문서 · 2일차 · 17 / 26

16차시 · 결제 연동

지도 위치 : 2일차 · 구현과 검증 · 구현 마무리 | 이전: 15차시 인프라 역할: 설정의 원칙 | 다음: 17차시 자동화된 테스트 키워드 : 결제 대행 구조, 사람이 확인할 안전 항목, 테스트 모드 연동

이 차시를 다 읽으면

  1. 결제 대행사(PG) 를 정의하고, 결제 흐름 여덟 단계에서 "화면의 결제 성공"과 "서버의 승인"이 다른 이유 를 설명할 수 있다.
  2. 금액 위조 공격 이 어떻게 일어나고 서버가 어떻게 막는지 말할 수 있다.
  3. 상태 전이 를 정의하고, 클래스온 예약의 상태 그림과 허용되지 않는 전이 를 댈 수 있다.
  4. 멱등성 키 를 정의하고, 중복 승인을 화면 · 서버 · DB 세 층에서 어떻게 막는지 말할 수 있다.
  5. 웹훅 을 정의하고, 결제 승인(기다림) ↔ 웹훅(나중에 통지)을 동기 ↔ 비동기 축에 놓을 수 있다.
  6. 코드를 읽지 않고 결제 안전 항목을 행동 시험 으로 확인하고, 실키 전환을 왜 사람이 하는지 말할 수 있다.

0. 이 차시의 판별 축

#축왼쪽 (0)오른쪽 (1)이 축으로 갈리는 것큰 축 (README 5장)
1지난 일을 기억하는가무상태 — 요청 하나로 끝상태 — 예약이 PENDING → CONFIRMED → ... 로 이어짐어떤 변화가 허용되는가⑦ 무상태 ↔ 상태
2여러 번 해도 같은가멱등 — 같은 승인 요청 열 번 = 한 번비멱등 — 할 때마다 결제가 하나씩 생김중복 결제멱등 ↔ 비멱등 (⑦의 파생)
3누가 판정하는가화면 — "결제 성공" 표시서버 — 금액 검증 후 승인확정의 기준화면이 판정 ↔ 서버가 판정 (②의 파생)
4결과를 기다리는가동기 — 서버가 승인 응답을 기다림비동기 — 결제사가 나중에 웹훅으로 알림승인 ↔ 취소 · 환불 통지⑥ 동기 ↔ 비동기
5누가 실행하는가사람이 확인한 뒤자동테스트 키 → 실 키 전환사람이 손을 대는가

이 차시가 답하는 질문은 "되돌리기 어려운 돈의 흐름을 어떻게 안전하게 잇는가" 입니다. 결제는 2일차에 배운 원칙이 한꺼번에 시험받는 곳입니다. 서버 판정(10차시), 공개 키와 비밀 키(11차시), UNIQUE와 트랜잭션(12차시), 중복과 동시성(13차시), 비밀값(14차시), 환경 분리(15차시). 여기에 새로 상태 (축 1)와 멱등성 (축 2)이 핵심 축으로 더해집니다.


1. 결제 대행 구조

1.1 정의

결제 대행사 (PG, Payment Gateway) — [결제 처리 업체]인데, [ 가게 대신 카드사 · 은행과 연결해 결제 인증과 승인을 처리한다 ]는 점에서 가게가 카드사와 직접 맺는 계약과 구별된다. 토스페이먼츠, 포트원, Stripe 등이 있습니다. 세부 API는 회사마다 다르지만 큰 흐름은 비슷합니다.

1.2 ⭐ 흐름 여덟 단계

① 사용자: "결제하기" 클릭
② 화면 → 서버: 예약 생성 요청
   서버: 예약을 PENDING_PAYMENT 상태로 만들고, 서버가 계산한 금액과 주문번호를 돌려줌
③ 화면: PG 결제창 띄움 (공개 키 사용, 주문번호 · 금액 전달)
④ 사용자 ↔ PG ↔ 카드사: 카드 인증
⑤ PG → 화면: 결제 인증 성공, 결제 키(paymentKey) 등 전달
⑥ 화면 → 서버: "이 결제를 승인해 줘" (결제 키, 주문번호, 금액)
⑦ 서버: 금액 검증 → PG에 비밀 키로 승인 요청 → 성공 시 예약 CONFIRMED
⑧ (나중에) PG → 서버: 웹훅으로 결제 상태 변경 통지 (취소, 환불 등)

🔍 읽는 포인트 : ⑦ 만 서버가 비밀 키를 씁니다. ③은 공개 키(11차시)입니다. ⑤의 "인증 성공"은 아직 확정이 아닙니다.

⭐ 핵심은 ⑦입니다. 화면에 "결제 성공"이 떠도 서버가 승인하기 전까지는 확정이 아닙니다. 그리고 그 승인은 비밀 키를 가진 서버만 할 수 있습니다. 0절 축 3의 오른쪽입니다.

1.3 반례 — 이건 결제 확정이 아닙니다

대상왜 아닌가
⑤에서 화면이 성공 신호를 받자마자 예약을 "확정"으로 바꿈서버 승인(⑦)을 건너뜀. 승인이 실패해도 확정으로 남음
결제창에 "결제 완료" 화면이 뜸PG의 화면. 우리 서버의 판정이 아님
화면이 서버에 status: "CONFIRMED"를 보냄상태는 요청으로 바뀌지 않습니다 (10차시)

2. 서버가 반드시 지킬 것

항목왜구현
금액 검증화면에서 금액을 바꿔 결제할 수 있음⑥에서 받은 금액과 DB에 저장된 예약 금액 이 다르면 승인 거부
비밀 키는 서버에만비밀 키가 있으면 누구나 승인 · 취소 가능환경변수, 화면 코드에 절대 없음 (11 · 14차시)
중복 승인 방지네트워크 재시도, 버튼 두 번 클릭4절
상태 전이 관리취소된 예약이 다시 확정되는 등의 꼬임3절
웹훅 진위 확인가짜 웹훅으로 "결제 완료"를 위조5절
실패 시 정리결제는 실패했는데 자리만 줄어든 상태일정 시간 지난 PENDING 예약은 만료시키고 자리 복구

금액 위조 공격의 모양 — 사용자가 개발자 도구로 ③의 금액을 55,000원에서 100원으로 바꿉니다. PG는 받은 대로 100원짜리 결제를 인증합니다(④ · ⑤). ⑥에서 화면이 "100원 결제 승인해 줘"를 보냅니다. 서버가 DB의 55,000원과 비교하지 않으면 100원에 확정 예약이 생깁니다. 막는 곳은 ⑦의 첫 동작, 금액 검증 하나입니다.


3. ⭐ 상태 전이

3.1 정의

상태 전이 (State Transition) — [데이터 변경]인데, [ 정해진 상태 사이를 허용된 방향으로만 옮겨 간다 ]는 점에서 아무 값이나 덮어쓰는 일반 수정과 구별된다.

PENDING_PAYMENT ──승인 성공──▶ CONFIRMED ──취소──▶ CANCELLED ──환불 완료──▶ REFUNDED
       │
       └──시간 초과 / 결제 실패──▶ EXPIRED (자리 복구)

🔍 읽는 포인트 : 화살표가 있는 방향만 허용됩니다. 화살표가 없는 이동은 전부 거부입니다.

3.2 경계 — 허용되는 전이와 안 되는 전이

지금다음허용?누가 일으키나
PENDING_PAYMENTCONFIRMED⭕서버 — PG 승인 성공 시
PENDING_PAYMENTEXPIRED⭕서버 — 시간 초과 · 결제 실패
CONFIRMEDCANCELLED⭕서버 — 본인 취소 요청 + 취소 기한 확인
CANCELLEDREFUNDED⭕서버 — PG의 환불 완료 통지
CANCELLEDCONFIRMED❌— (늦게 도착한 승인 응답 등으로 생기는 꼬임)
EXPIREDCONFIRMED❌— 자리가 이미 복구되어 다른 사람이 예약했을 수 있음

0절 축 1의 오른쪽입니다. 예약은 지난 일을 기억하는 데이터라서, 지금 상태에 따라 할 수 있는 일이 다릅니다. 앞에서 배운 "상태 값은 정해진 것만" 제약(12차시 3.1)이 이 그림의 바닥입니다.

💡 비유는 마지막에 — 택배 조회 화면입니다. "배송 완료"가 "집하 중"으로 돌아가지 않고, "반송"된 상자가 갑자기 "배송 완료"가 되지 않습니다.


4. ⭐ 멱등성과 멱등성 키

4.1 정의

앞에서 배운 멱등 (4차시) — 같은 요청을 여러 번 보내도 결과 상태가 한 번 보낸 것과 같은 성질 — 을 결제에 적용합니다.

멱등성 키 (Idempotency Key) — [요청 식별값]인데, [ 같은 의도의 요청에 같은 값을 붙여, 서버가 두 번째부터는 처리하지 않고 첫 결과를 돌려주게 한다 ]는 점에서 요청마다 새로 만들어지는 일반 요청 번호와 구별된다.

클래스온에서는 결제 키(paymentKey) 나 주문번호 가 그 역할을 합니다. PG사 다수가 승인 요청에 멱등성 키를 붙이는 방법도 제공합니다(방식은 공식 문서 확인).

4.2 중복은 어디서 오는가, 어디서 막는가

중복의 원인예
사용자결제 버튼 두 번 클릭, 새로고침, 뒤로 가기 후 다시 진행
네트워크응답이 늦어 화면이나 서버가 자동으로 다시 보냄
PG같은 웹훅을 여러 번 보냄 (5절)
층장치혼자서 충분한가
화면요청 중 버튼 비활성화 (11차시)❌ 새로고침 · 네트워크 재시도는 못 막음
서버같은 결제 키 요청은 첫 번째 결과를 그대로 돌려줌주 방어
DBpayments.pg_payment_key에 UNIQUE (12차시)마지막 방어선 — 서버 검사가 뚫려도 두 번째 기록을 거부

⚠️ 중복 요청은 경쟁 상태(13차시)와 다른 문제입니다. 경쟁 상태는 다른 사람들 이 같은 자원을 노리는 것이고, 중복 요청은 같은 의도 가 두 번 들어오는 것입니다. 앞은 조건부 갱신 · 잠금으로, 뒤는 멱등성 키로 풉니다.

💡 비유는 마지막에 — 엘리베이터 호출 버튼입니다. 열 번 눌러도 엘리베이터는 한 번 옵니다. 결제 승인 요청도 그래야 합니다.


5. 웹훅 — 나중에 오는 통지

5.1 정의와 경계

웹훅 (Webhook) — [서버 간 알림 방식]인데, [ 외부 서비스가 이벤트가 생겼을 때 우리 서버의 정해진 주소로 먼저 요청을 보낸다 ]는 점에서 우리가 묻고 답을 기다리는 일반 API 호출과 구별된다.

승인 요청 (1.2의 ⑦)웹훅 (1.2의 ⑧)
0절 축 4동기 — 서버가 묻고 응답을 기다림비동기 — PG가 나중에 알려 옴
누가 시작하나우리 서버PG
주로 쓰는 일결제 확정취소 · 환불 · 입금 완료처럼 나중에 생기는 변화

5.2 웹훅에서 지킬 것

지킬 것이유
진위 확인웹훅 주소는 공개되어 있어 누구나 "결제 완료" 요청을 보낼 수 있음. PG 문서의 방법(서명 검증, 또는 받은 뒤 PG에 상태를 다시 조회)을 사용
멱등 처리PG는 전달을 확실히 하려고 같은 통지를 여러 번 보낼 수 있음. 이미 처리한 통지는 무시
상태 전이 규칙 적용웹훅도 3.2의 허용 표를 따름. 늦게 온 통지가 상태를 거꾸로 돌리지 않게

앞으로 다시 만납니다 — 웹훅은 PG가 인터넷에서 닿는 주소 로 보내야 하므로, 로컬만으로는 시험하기 어렵습니다. 15차시의 스테이징이 필요한 이유이고, 21 · 22차시 배포 뒤에 끝까지 시험합니다.


6. 테스트 모드와 사람의 몫

6.1 테스트 모드

PG사들은 테스트 키 와 테스트 카드 번호 를 제공합니다. 실제 돈이 오가지 않고 전체 흐름을 시험할 수 있습니다.

원칙이유
로컬 · 스테이징은 항상 테스트 키15차시 3.2
성공뿐 아니라 실패 (잔액 부족, 사용자 취소, 결제창 닫기)도 시험AI 코드의 버그는 실패 경로에 숨음 (13차시)
운영 키 파일 · 설정은 에이전트 권한에서 차단14차시 4.2
실 키 전환은 사람이 직접 , 6.2의 시험을 통과한 뒤0절 축 5. 되돌릴 수 없는 돈의 흐름

⚠️ 결제 API는 반드시 공식 최신 문서 를 맥락으로 줍니다. AI가 기억하는 옛 API 방식으로 구현하는 일이 흔합니다.

6.2 ⭐ 안전 항목을 행동 시험으로

결제의 안전 항목은 원래 "사람이 코드를 읽고 확인"하는 자리입니다. 코드를 읽지 않는다면 각 항목을 행동 시험 으로 바꿉니다.

안전 항목코드 없이 확인하는 법
승인 금액이 DB 값에서 나오는가개발자 도구(11차시)로 결제 요청의 금액을 바꿔 보냄 → 승인 거부 . 또는 AI에게 금액 위조 시험을 실행시키고 출력 원문을 받음
비밀 키가 화면에 없는가배포된 화면에서 F12 → Sources 또는 Network에서 secret, 비밀 키 접두사로 검색 (접두사는 PG 공식 문서 확인)
중복 승인이 무시되는가결제 완료 직후 새로고침, 뒤로 가기 후 다시 진행 → PG 테스트 대시보드에 결제 1건
승인 실패 시 확정되지 않는가테스트 카드 중 "실패용" 번호로 결제 → 내 예약에 "확정" 없음
결제 이탈 시 자리 복구결제창을 닫고 정해진 시간 뒤 남은 자리가 원래대로
테스트 키인가PG 대시보드가 결제를 "테스트 모드" 로 기록하는가
환불 · 취소 정책이 기획과 같은가취소 기한 직전 · 직후에 취소해 봄 (3차시의 인수 기준과 대조)

⭐ PG 대시보드가 진실의 원천입니다. 우리 화면이 무엇을 보여 주든, 실제로 몇 건이 얼마에 결제됐는지는 PG 대시보드에 남습니다. 행동 시험 뒤에는 항상 PG 대시보드와 우리 DB(12차시의 조회 도구)를 대조 합니다.

6.3 이 방식의 한계

행동 시험은 내가 생각해 낸 경우만 확인합니다. 실제 돈을 받기 전에는 코드를 읽을 수 있는 개발자에게 결제와 인증 부분만이라도 한 번 검토를 요청하세요(README 9.6). 맡기는 방식으로 할 수 있는 일과 없는 일의 경계가 가장 뚜렷한 곳이 결제입니다. 운영 전환 시에는 이용약관, 환불 규정, 사업자 정보 표시 같은 법적 요건도 별도로 확인합니다.

앞으로 다시 만납니다 — 20차시에서 "자동 리뷰가 아무리 좋아도 사람이 남겨 둘 몫"을 정할 때, 결제는 그 목록의 맨 위에 다시 나옵니다.


7. 클래스온에 적용하면

docs/api.md의 POST /payments/confirm을 구현해줘. PG사 공식 문서의 결제 승인 API를 따른다.
(공식 문서 주소: ...)
- 금액은 reservations 테이블의 amount와 비교하고, 다르면 400 AMOUNT_MISMATCH
- 같은 paymentKey 중복 요청은 첫 번째 결과를 그대로 돌려준다
- 상태는 3.2의 허용 표에 있는 전이만 가능하게
- 비밀 키는 PG_SECRET_KEY 환경변수에서만 읽는다
- 운영 키 관련 설정은 건드리지 마

🔍 읽는 포인트 : 다섯 줄이 각각 2절 표의 금액 검증 · 중복 방지 · 상태 전이 · 비밀 키, 그리고 0절 축 5입니다.


8. 실습 — 맡기고 검수하기

지시

7절의 지시대로 구현한 뒤, 테스트 키로 아래를 시험해줘.
[시험 | 기대 | 실제 응답 | 예약 상태 | PG 대시보드 건수 | 통과?] 표로 보고하고, 각 시험의 실행 출력 원문을 붙여줘.
1. 정상 결제  2. 금액을 100원으로 바꾼 승인 요청  3. 같은 paymentKey로 승인 요청 두 번
4. 실패용 테스트 카드  5. CANCELLED 예약에 승인 요청
그리고 승인 금액이 어디서 오는지 [파일 | 줄 | 하는 일 한 문장]으로 답하고,
화면에서 보낸 금액이 승인 요청에 들어가는 경로가 하나라도 있으면 알려줘.
키 값은 출력하지 마. 실 키로 바꾸는 작업은 하지 마.

받을 증거

  • 시험 다섯 개의 결과 표와 실행 출력 원문
  • 승인 금액의 출처 위치(파일 · 줄)

내가 직접 확인할 것

볼 것이걸로 아는 것 / 왜 내가 보는가
6.2 표의 행동 시험을 내가 직접 한다 (특히 금액 바꾸기, 새로고침, 실패용 카드)AI의 표가 아니라 내 눈으로 본 결과가 근거 (README 9.1)
시험 뒤 PG 대시보드 건수 · 금액 과 우리 DB의 결제 행 이 일치하는가진실의 원천과 우리 기록의 대조 (6.2)
결과 표의 5번(CANCELLED에 승인)이 거부 인가상태 전이 규칙 (3.2)
금액 출처 답이 DB의 예약 금액 한 곳 인가모호하면 리뷰 역할에게 같은 질문을 따로 (교차 검증)
대시보드가 테스트 모드 로 기록했는가실 키가 섞이지 않았는가
운영 전환 전 사람 검토 를 받았는가6.3의 한계

부록 A. 스스로 확인하기

#질문답이 있는 곳
1PG를 유와 종차로 정의하면?1.1
2결제 흐름에서 "화면의 결제 성공"과 "서버의 승인"이 다른 이유는?1.2, 1.3
3금액 위조 공격은 어떻게 일어나고 어디서 막는가?2
4상태 전이를 정의하고, 허용되지 않는 전이 두 가지를 대면?3.1, 3.2
5멱등성 키를 정의하고, 클래스온에서 그 역할을 하는 값은?4.1
6중복 승인을 화면 · 서버 · DB에서 각각 어떻게 막는가?4.2
7중복 요청과 경쟁 상태는 어떻게 다른가?4.2
8웹훅을 정의하고, 승인 요청과 동기 ↔ 비동기 축에서 비교하면?5.1
9웹훅에서 지킬 세 가지는?5.2
10실 키 전환을 에이전트에게 맡기지 않는 이유와, 행동 시험의 한계는?6.1, 6.3

부록 B. 자주 하는 실수

실수바로잡기
화면에서 결제 성공 신호를 받자마자 예약 확정❌ 서버 승인(⑦) 뒤에만 확정 (1.3)
승인 요청 금액을 화면이 보낸 값으로 쓴다❌ DB의 예약 금액과 비교 (2)
결제 실패 · 이탈 시 줄어든 자리를 복구하지 않는다⚠️ 시간 초과 시 EXPIRED + 자리 복구 (3.1)
버튼 비활성화로 중복 결제를 막았다고 끝낸다❌ 서버 멱등 처리 + UNIQUE까지 (4.2)
웹훅을 받으면 그대로 믿고 상태를 바꾼다❌ 진위 확인 · 멱등 · 전이 규칙 (5.2)
AI가 기억하는 옛 PG API로 구현⚠️ 공식 최신 문서를 맥락으로 (6.1)
우리 화면만 보고 결제가 맞다고 판단⭕ PG 대시보드와 DB를 대조 (6.2)

부록 C. NotebookLM 복습 프롬프트

이 16차시 노트만 근거로 6문제를 내줘. 비전공자 기준으로.
"화면의 성공과 서버의 승인", "상태 전이에서 허용되지 않는 전이", "멱등성 키와 중복 방지 세 층", "웹훅과 동기↔비동기"는 반드시 포함해줘.
답은 내가 답한 다음에 채점하고, 틀린 이유를 노트의 절 번호를 근거로 설명해줘.