https://github.com/MinWoo1995/spring-payment-prac
GitHub - MinWoo1995/spring-payment-prac
Contribute to MinWoo1995/spring-payment-prac development by creating an account on GitHub.
github.com
### 과제 1: "1000원 해커를 막아라!" (상품 가격 위변조 방어)
**가장 추천하는 과제입니다.** 이론에서 강조했던 SSOT(진실의 원천) 개념을 직접 코드로 구현해보는 미션입니다.
- **[상황 부여]**
현재 우리 코드의 `PaymentFacade`를 보면 금액을 이렇게 하드코딩해서 계산하고 있습니다.
```java
Long calculatedAmount = 1000L * request.getQuantity(); // 임시 로직
```
악의적인 해커가 프론트엔드 코드를 조작해서, 원래 10,000원짜리 상품을 1000원으로 결제창에 띄워 정상 승인을 받아버렸습니다!
- **[과제 목표]**
1. `Product` 엔티티와 `ProductRepository`를 간단하게 만드세요. (DB에 '스프링 부트 강의', 가격 '10,000원' 데이터가 있다고 가정)
2. `PaymentFacade`의 `preparePayment` 메서드를 수정하여, 하드코딩된 100원이 아니라 **실제 DB에 있는 상품 가격을 조회해서 총 결제 금액(`calculatedAmount`)을 산출**하도록 변경하세요.
3. 프론트엔드(`index.html`)에서 임의로 결제 요청 금액을 1000원으로 조작해서 결제를 시도해 보고, 백엔드의 **교차 검증 로직(`verifyAndApprove`)에서 에러가 터지며 결제가 방어되는 것**을 캡처해서 제출하세요.
과제 1: 결제 금액 위변조 방어 트러블슈팅
1. 현상 (Problem)
프론트엔드(index.html)에서 결제창을 호출할 때 사용자가 스크립트를 조작하여 결제 금액(totalAmount)을 임의로 낮출 수 있는 보안 취약점 발견. 실제로 2,000원인 상품을 1000원으로 결제 시도했을 때 PG사 결제창이 1000원으로 뜨는 것을 확인.
2. 원인 분석 (Cause)
- 클라이언트 신뢰 불가: 브라우저 환경은 사용자가 소스 코드를 언제든 수정할 수 있으므로, 결제창에 표시되는 금액을 전적으로 신뢰해서는 안 됨.
- 검증 로직 부재: 서버에서 결제 완료 요청을 받을 때, DB에 저장된 실제 단가와 PG사로부터 전달받은 승인 금액을 대조하는 프로세스가 없었음.
3. 해결책 (Solution)
- 교차 검증(Cross-Validation) 도입: 포트원 Confirm API 호출 시, 서버 측에서 다음 두 데이터를 비교하도록 구현.
- savedAmount: 주문 생성 시 DB에 기록한 정가(SSOT).
- pgData.amount: 포트원 API를 통해 가져온 실제 카드 승인 금액.
- 방어적 예외 처리: 두 금액이 일치하지 않을 경우 IllegalArgumentException을 발생시키고 결제 확정 처리를 중단함.
결과


과제 2: "버려진 유령 결제건 청소기" (스케줄러/배치)
주니어 개발자 포트폴리오에 들어가면 면접관들이 아주 좋아하는 '데이터 라이프사이클 관리' 경험입니다.
- [상황 부여] 사용자가 '결제하기' 버튼을 눌러서 우리 DB에 PENDING 상태의 결제 데이터가 생겼습니다. 그런데 사용자가 변심해서 결제창을 그냥 닫아버렸습니다! 이 사용자는 영영 돌아오지 않기 때문에 Confirm도, Webhook도 오지 않습니다. 이런 데이터가 1년 동안 쌓이면 우리 DB에는 의미 없는 PENDING 쓰레기 데이터가 수백만 건 쌓이게 됩니다.
- [과제 목표]
- 스프링 부트의 @EnableScheduling과 @Scheduled를 활용하여 결제 청소 스케줄러 클래스를 하나 만드세요.
- 매 5분마다 실행되면서, "생성된 지 30분이 지났는데도 여전히 상태가 PENDING인 결제건"을 모두 DB에서 조회하세요. (엔티티에 createdAt 필드 추가 필요)
조회된 녀석들의 상태를 PENDING에서 FAILED (또는 EXPIRED)로 일괄 업데이트하는 로직을 작성하세요.
과제 2: 유령 결제 데이터 정리 스케줄러 트러블슈팅
1. 현상 (Problem)
사용자가 결제창을 띄운 후 결제를 진행하지 않고 이탈할 경우, DB에는 PENDING 상태의 불완전한 데이터가 영구적으로 남게 됨. 데이터가 누적될 경우 DB 성능 저하 및 통계 데이터 오염의 원인이 됨.
2. 원인 분석 (Cause)
- 결제 라이프사이클 미관리: 결제 시작(Ready)과 완료(Confirm) 사이의 타임아웃 처리가 서버 측에 구현되어 있지 않음.
- 상태 추적 기준 부재: 어떤 데이터가 얼마나 오래되었는지 판단할 수 있는 시간 기록(CreatedAt) 필드가 엔티티에 없었음.
3. 해결책 (Solution)
- JPA Auditing 활용: Payment 엔티티에 @CreatedDate를 추가하여 모든 결제 데이터의 생성 시간을 자동 기록함.
- 배치 처리(Scheduler) 구현: 스프링의 @Scheduled 기능을 활용하여 5분마다 백그라운드에서 동작하는 청소기 클래스 생성.
- 데이터 정리 로직: 생성 시점으로부터 1분이 지난 PENDING 건들을 자동으로 조회하여 FAILED 상태로 일괄 변경 처리.
결과

'spring_2기[본캠프] > 과제' 카테고리의 다른 글
| [과제] Spring 플러스 프로젝트 Day 4 (0) | 2026.03.13 |
|---|---|
| [과제] Spring 플러스 프로젝트 Day 3 (0) | 2026.03.11 |
| [과제] Spring 플러스 프로젝트 Day 2 (1) | 2026.03.06 |
| [과제] Spring 플러스 프로젝트 Day 1 (0) | 2026.03.05 |
| [과제]CH 5 플러스 Spring 과제 (0) | 2026.03.03 |