[선택] 결제 연결 — Toss Payments
이 레슨이 끝나면 (필요한 분만)
- Toss Payments 가입 + 테스트 키 발급이 끝나 있다
/v4-payment로 결제 흐름이 본인 서비스에 추가된다- localhost에서 테스트 카드로 가짜 결제 한 번 통과시킨다
- webhook(결제 완료 시 본인 서버에 자동 알림) + 멱등성(같은 결제 두 번 처리 안 함) 개념을 안다
- 라이브 키 전환 + 출시 직전 점검 체크리스트를 안다
이 레슨은 선택입니다
결제 모델이 없는 서비스(무료 / 포트폴리오 / 광고 모델 / 메일링 가입)는 4-12 건너뛰고 4-13으로 가세요. 결제는 한 번 붙이면 책임이 따라옵니다(환불, CS, 부정결제 대응 등). 출시 후 사용자 검증 끝난 다음에 추가해도 늦지 않아요.
왜 Toss Payments?
한국 결제 PG(Payment Gateway) 중 비개발자에게 가장 친절한 곳이 Toss Payments예요. 이유:
- 가입·심사가 빠름 (개인사업자 OK, 보통 2~3일)
- 문서가 한국어 + 깔끔
- 테스트 환경이 잘 마련됨 (테스트 카드 번호 제공)
- 수수료가 합리적 (카드 결제 약 2.5%)
- webhook + 멱등성 등 기술 측면이 잘 설계됨
대안: 해외 타겟이면 Stripe, 빠른 시작 가성비면 Paypal. 본 코스는 한국 Toss 기준으로 설명.
결제 흐름 — 큰 그림
결제 흐름을 한 그림으로 알아두면 디버깅이 쉬워져요:
- 사용자가 본인 서비스에서 "결제하기" 클릭
- 본인 서버 → Toss에 "결제 요청 만들어줘" API 호출 → 결제 ID 받음
- 사용자 브라우저가 Toss 결제 화면으로 이동 (카드 입력 등)
- 결제 성공 시 Toss → 사용자를 본인 서비스로 다시 redirect (성공 URL)
- 본인 서버 → Toss에 "이 결제 진짜 됐어?" 확인 API 호출 → "진짜 됐다" 응답
- 본인 DB에 결제 정보 저장 + 사용자에게 영수증 표시
- (보너스) Toss → 본인 서버의 webhook URL에 "결제 완료" 자동 알림 (이중 보장)
단계 1 — Toss Payments 가입
- tosspayments.com 접속 → "지금 시작하기".
- 이메일 가입 → 사업자 정보 입력 (개인사업자 OK).
- 심사 신청 (보통 2~3일 소요). 그동안 테스트 키로 개발 가능.
- 승인되면 라이브 키 발급. 그 전까진 테스트 키만.
오늘 진행: 테스트 키로 충분. 라이브 키는 출시 직전(Ch.5)에 교체.
단계 2 — 테스트 키 발급
Toss 대시보드 → "개발자센터" → "API 키" 메뉴. 다음 두 개 키를 복사:
- 클라이언트 키 (test_ck_로 시작): 브라우저에서 사용해도 OK
- 시크릿 키 (test_sk_로 시작): 본인 서버만 사용. 절대 노출 X
.env에 추가:
TOSS_CLIENT_KEY=test_ck_xxxxx TOSS_SECRET_KEY=test_sk_xxxxx TOSS_WEBHOOK_SECRET=웹훅용_본인이_정한_긴_문자열
단계 3 — /v4-payment로 결제 연동
/v4-payment
스킬이 본인에게 묻는 것 + 추천 답:
- "PG 어떤 거 쓸까요?" → Toss
- "결제 모델은?" → 일회성 / 구독 (본인 서비스에 맞게)
- "가격 플랜 몇 개?" → 1~3개 권장 (예: Free / Pro 9,900원 / Team 29,900원)
- "webhook 사용?" → 네 (이중 보장)
- "테스트 모드부터?" → 네 (라이브는 출시 직전)
스킬이 자동으로 해 주는 일:
Payment모델 + DB 마이그레이션 (결제 이력 저장)PaymentsController생성 (결제 요청 / 성공 콜백 / 실패 콜백 / webhook)- 결제 페이지 view (가격 카드 + "결제하기" 버튼)
- Toss SDK 연동 (Ruby gem 또는 직접 HTTP 호출)
- 멱등성 처리 (idempotency key)
- 테스트 코드 (성공·실패·중복·환불 시나리오)
단계 4 — 테스트 카드로 가짜 결제
Toss 테스트 모드는 진짜 카드를 안 써도 결제를 시뮬레이션할 수 있어요. Toss 테스트 카드 문서에서 카드 번호 확인.
흐름:
bin/dev로 서버 띄우기 + localhost:3000.- 회원가입·로그인 후 결제 페이지로 이동.
- "결제하기" 버튼 클릭 → Toss 테스트 화면으로 이동.
- 테스트 카드 번호 입력 (Toss 문서의 "성공 카드").
- 결제 성공 → 본인 서비스로 redirect → "결제 완료" 화면.
- Rails 콘솔로 DB 확인:
Payment.last로 결제 레코드 확인.
webhook + 멱등성 — 한 번에 정리
webhook은 Toss가 본인 서버에 "결제 완료됐어!"를 자동으로 알려주는 콜백이에요. 사용자 브라우저 redirect와 별도로 작동. 왜 필요? 사용자가 결제 화면에서 인터넷 끊거나 브라우저 닫아도 결제는 됐을 수 있어요. webhook이 있으면 본인 서버는 그 사실을 놓치지 않아요.
멱등성(Idempotency)은 "같은 요청 두 번 와도 결제는 한 번만"이라는 원칙. 사용자가 새로고침을 두 번 누르면 안 됩니다. 구현: 각 결제 요청마다 고유 ID(idempotency key)를 보내고, 서버에서 같은 ID 두 번 오면 첫 번째만 처리.
/v4-payment이 둘 다 자동 구현해 줘요. 본인은 개념만 알면 OK.
localhost에서 webhook 테스트 — ngrok
webhook은 본인 서버가 인터넷에 올라 있어야 받을 수 있어요. localhost는 외부에서 접근 X. 해결: ngrok이라는 도구가 localhost를 임시로 공개 URL로 노출해 줘요.
- ngrok.com 가입 + 다운로드.
- 터미널에
ngrok http 3000. - 출력에
https://abc-1234.ngrok-free.app같은 임시 URL이 떠요. - Toss 대시보드 → webhook URL에 그 URL +
/payments/webhook등록. - 다시 테스트 결제 → webhook이 본인 서버에 도착하는 걸 터미널에서 확인.
webhook 테스트는 한 번 잘 되면 출시 후 거의 안 만져요. 처음만 신경 써서 풀어 두세요.
자주 발생하는 문제 + 해결
"401 Unauthorized 에러"
시크릿 키가 잘못 설정됨. .env의 TOSS_SECRET_KEY가 올바른 테스트 키(test_sk_로 시작)인지 확인. 서버 재시작 필수.
"redirect URL이 등록 안 됨"
Toss는 redirect URL을 화이트리스트로 관리. 개발자센터 → 보안 → 허용 URL에 http://localhost:3000/payments/success 추가.
"webhook이 안 와요"
1) ngrok URL이 만료됐을 수 있음 (무료 플랜은 세션 끝나면 새 URL). 2) Toss webhook URL 재등록. 3) webhook signature 검증 실패 → 시크릿 일치 확인.
"라이브 모드로 언제 전환?"
출시 직전 (Ch.5)에 라이브 키로 .env 교체. 이때 진짜 돈이 오가니 환불 / CS / 부정결제 대응 정책도 함께 결정. 첫 라이브 결제는 본인 카드로 1,000원짜리부터 시도.
자가 진단 — 통과 기준 (선택 진행한 분)
- ☐ Toss Payments 가입 + 테스트 키 발급
- ☐ .env에 TOSS_CLIENT_KEY / TOSS_SECRET_KEY 저장
- ☐
/v4-payment진행 → 결제 페이지 + 모델 생성 - ☐ 테스트 카드로 localhost에서 가짜 결제 1회 성공
- ☐ Payment 모델에 결제 레코드 저장 확인
- ☐ webhook + 멱등성 개념을 한 줄로 설명 가능
- ☐ git commit ("Toss Payments 결제 연동 (테스트 모드)")
다음 단계 → 4-13 환경변수 + LLM 변수 + AI 사례 + GitHub (Reflection)
Ch.4 마지막 레슨이에요. 환경변수 (.env / Rails credentials) 정리 + LLM API 키 (Anthropic / OpenAI) 설정 + 본인 서비스에 AI 기능 붙이는 사례 3가지 + GitHub 백업 + Ch.4 전체 Reflection. 이 한 레슨이면 본인 PC에서 돌아가는 진짜 서비스가 GitHub에 백업되고, AI 기능까지 연결돼요.
실습하기
로그인하면 스킬을 실습할 수 있습니다