diff --git a/proj-acquirex/README.md b/proj-acquirex/README.md
new file mode 100644
index 0000000..9b1fc6d
--- /dev/null
+++ b/proj-acquirex/README.md
@@ -0,0 +1,29 @@
+# proj-acquirex
+
+## 카드 매입 승인 경로 Spring Boot 3 전환
+
+### 전환 범위
+- Spring Boot 3.2.5 (Jakarta EE 9+)
+- Java 17+
+- Spring Framework 6.x
+- Hibernate 6.x
+
+### 검증 절차
+1. `./mvnw clean compile` - 컴파일 검증
+2. `./mvnw test` - 단위 테스트 실행
+3. `./mvnw verify` - 통합 검증
+
+### API 엔드포인트
+- `POST /api/v1/approvals/card-acquisition` - 카드 매입 승인 요청
+- `GET /api/v1/approvals/card-acquisition/{approvalId}` - 승인 상태 조회
+
+### 프로젝트 구조
+```
+src/main/java/com/acquirex/
+├── AcquirexApplication.java # 메인 애플리케이션
+├── CardAcquisitionApprovalStatus.java # 승인 상태 enum
+├── CardAcquisitionApprovalRequest.java # 요청 DTO
+├── CardAcquisitionApprovalResponse.java # 응답 DTO
+├── CardAcquisitionApprovalService.java # 비즈니스 로직
+└── CardAcquisitionApprovalController.java # REST 컨트롤러
+```
diff --git a/proj-acquirex/pom.xml b/proj-acquirex/pom.xml
new file mode 100644
index 0000000..7f8bbd4
--- /dev/null
+++ b/proj-acquirex/pom.xml
@@ -0,0 +1,66 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.5
+
+
+
+ com.acquirex
+ proj-acquirex
+ 1.0.0-SNAPSHOT
+ proj-acquirex
+ 카드 매입 승인 경로 - Spring Boot 3 전환
+
+
+ 17
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ com.h2database
+ h2
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+
diff --git a/proj-acquirex/src/main/java/com/acquirex/AcquirexApplication.java b/proj-acquirex/src/main/java/com/acquirex/AcquirexApplication.java
new file mode 100644
index 0000000..cbf43e9
--- /dev/null
+++ b/proj-acquirex/src/main/java/com/acquirex/AcquirexApplication.java
@@ -0,0 +1,11 @@
+package com.acquirex;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class AcquirexApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(AcquirexApplication.class, args);
+ }
+}
diff --git a/proj-acquirex/src/main/java/com/acquirex/approval/CardAcquisitionApprovalRequest.java b/proj-acquirex/src/main/java/com/acquirex/approval/CardAcquisitionApprovalRequest.java
new file mode 100644
index 0000000..5ae51d9
--- /dev/null
+++ b/proj-acquirex/src/main/java/com/acquirex/approval/CardAcquisitionApprovalRequest.java
@@ -0,0 +1,34 @@
+package com.acquirex.approval;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class CardAcquisitionApprovalRequest {
+ @NotBlank(message = "가맹점 ID는 필수입니다")
+ private String merchantId;
+
+ @NotBlank(message = "카드사 코드는 필수입니다")
+ private String cardCompanyCode;
+
+ @NotNull(message = "거래 금액은 필수입니다")
+ @Positive(message = "거래 금액은 양수여야 합니다")
+ private BigDecimal transactionAmount;
+
+ @NotBlank(message = "거래 유형은 필수입니다")
+ private String transactionType;
+
+ private String merchantName;
+ private LocalDateTime requestDateTime;
+}
diff --git a/proj-acquirex/src/main/java/com/acquirex/approval/CardAcquisitionApprovalResponse.java b/proj-acquirex/src/main/java/com/acquirex/approval/CardAcquisitionApprovalResponse.java
new file mode 100644
index 0000000..255c289
--- /dev/null
+++ b/proj-acquirex/src/main/java/com/acquirex/approval/CardAcquisitionApprovalResponse.java
@@ -0,0 +1,25 @@
+package com.acquirex.approval;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class CardAcquisitionApprovalResponse {
+ private String approvalId;
+ private String merchantId;
+ private String cardCompanyCode;
+ private BigDecimal transactionAmount;
+ private CardAcquisitionApprovalStatus status;
+ private String statusMessage;
+ private LocalDateTime approvalDateTime;
+ private String responseCode;
+ private String responseMessage;
+}
diff --git a/proj-acquirex/src/main/java/com/acquirex/approval/CardAcquisitionApprovalService.java b/proj-acquirex/src/main/java/com/acquirex/approval/CardAcquisitionApprovalService.java
new file mode 100644
index 0000000..9bb2985
--- /dev/null
+++ b/proj-acquirex/src/main/java/com/acquirex/approval/CardAcquisitionApprovalService.java
@@ -0,0 +1,59 @@
+package com.acquirex.approval;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Slf4j
+@Service
+public class CardAcquisitionApprovalService {
+ private final Map approvalStore = new ConcurrentHashMap<>();
+
+ public CardAcquisitionApprovalResponse processApproval(CardAcquisitionApprovalRequest request) {
+ log.info("카드 매입 승인 요청 처리: merchantId={}, amount={}",
+ request.getMerchantId(), request.getTransactionAmount());
+
+ String approvalId = generateApprovalId();
+ CardAcquisitionApprovalStatus status = determineApprovalStatus(request);
+
+ CardAcquisitionApprovalResponse response = CardAcquisitionApprovalResponse.builder()
+ .approvalId(approvalId)
+ .merchantId(request.getMerchantId())
+ .cardCompanyCode(request.getCardCompanyCode())
+ .transactionAmount(request.getTransactionAmount())
+ .status(status)
+ .statusMessage(status.getDescription())
+ .approvalDateTime(LocalDateTime.now())
+ .responseCode(status == CardAcquisitionApprovalStatus.APPROVED ? "0000" : "9999")
+ .responseMessage(status == CardAcquisitionApprovalStatus.APPROVED ? "승인 완료" : "승인 실패")
+ .build();
+
+ approvalStore.put(approvalId, response);
+ log.info("카드 매입 승인 완료: approvalId={}, status={}", approvalId, status);
+ return response;
+ }
+
+ public CardAcquisitionApprovalResponse getApprovalStatus(String approvalId) {
+ log.info("승인 상태 조회: approvalId={}", approvalId);
+ return approvalStore.get(approvalId);
+ }
+
+ private CardAcquisitionApprovalStatus determineApprovalStatus(CardAcquisitionApprovalRequest request) {
+ if (request.getTransactionAmount() == null) {
+ return CardAcquisitionApprovalStatus.REJECTED;
+ }
+ if (request.getTransactionAmount().compareTo(new BigDecimal("100000")) >= 0) {
+ return CardAcquisitionApprovalStatus.PROCESSING;
+ }
+ return CardAcquisitionApprovalStatus.APPROVED;
+ }
+
+ private String generateApprovalId() {
+ return "APR-" + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
+ }
+}
diff --git a/proj-acquirex/src/main/java/com/acquirex/approval/CardAcquisitionApprovalStatus.java b/proj-acquirex/src/main/java/com/acquirex/approval/CardAcquisitionApprovalStatus.java
new file mode 100644
index 0000000..56a9d35
--- /dev/null
+++ b/proj-acquirex/src/main/java/com/acquirex/approval/CardAcquisitionApprovalStatus.java
@@ -0,0 +1,19 @@
+package com.acquirex.approval;
+
+public enum CardAcquisitionApprovalStatus {
+ PENDING("승인 대기"),
+ APPROVED("승인 완료"),
+ REJECTED("승인 거절"),
+ CANCELLED("승인 취소"),
+ PROCESSING("처리 중");
+
+ private final String description;
+
+ CardAcquisitionApprovalStatus(String description) {
+ this.description = description;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+}
diff --git a/proj-acquirex/src/test/java/com/acquirex/approval/CardAcquisitionApprovalServiceTest.java b/proj-acquirex/src/test/java/com/acquirex/approval/CardAcquisitionApprovalServiceTest.java
new file mode 100644
index 0000000..db245b2
--- /dev/null
+++ b/proj-acquirex/src/test/java/com/acquirex/approval/CardAcquisitionApprovalServiceTest.java
@@ -0,0 +1,80 @@
+package com.acquirex.approval;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.math.BigDecimal;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@DisplayName("카드 매입 승인 서비스 테스트")
+class CardAcquisitionApprovalServiceTest {
+
+ private CardAcquisitionApprovalService approvalService;
+
+ @BeforeEach
+ void setUp() {
+ approvalService = new CardAcquisitionApprovalService();
+ }
+
+ @Test
+ @DisplayName("소액 거래 승인 처리 성공")
+ void testSmallAmountApproval() {
+ CardAcquisitionApprovalRequest request = CardAcquisitionApprovalRequest.builder()
+ .merchantId("MERCHANT001")
+ .cardCompanyCode("CARD001")
+ .transactionAmount(new BigDecimal("50000"))
+ .transactionType("PURCHASE")
+ .build();
+
+ CardAcquisitionApprovalResponse response = approvalService.processApproval(request);
+
+ assertNotNull(response);
+ assertNotNull(response.getApprovalId());
+ assertTrue(response.getApprovalId().startsWith("APR-"));
+ assertEquals("MERCHANT001", response.getMerchantId());
+ assertEquals(CardAcquisitionApprovalStatus.APPROVED, response.getStatus());
+ assertEquals("0000", response.getResponseCode());
+ }
+
+ @Test
+ @DisplayName("대액 거래 처리 중 상태")
+ void testLargeAmountProcessing() {
+ CardAcquisitionApprovalRequest request = CardAcquisitionApprovalRequest.builder()
+ .merchantId("MERCHANT002")
+ .cardCompanyCode("CARD002")
+ .transactionAmount(new BigDecimal("150000"))
+ .transactionType("PURCHASE")
+ .build();
+
+ CardAcquisitionApprovalResponse response = approvalService.processApproval(request);
+
+ assertNotNull(response);
+ assertEquals(CardAcquisitionApprovalStatus.PROCESSING, response.getStatus());
+ }
+
+ @Test
+ @DisplayName("승인 상태 조회 성공")
+ void testGetApprovalStatus() {
+ CardAcquisitionApprovalRequest request = CardAcquisitionApprovalRequest.builder()
+ .merchantId("MERCHANT003")
+ .cardCompanyCode("CARD003")
+ .transactionAmount(new BigDecimal("30000"))
+ .transactionType("PURCHASE")
+ .build();
+
+ CardAcquisitionApprovalResponse created = approvalService.processApproval(request);
+ CardAcquisitionApprovalResponse found = approvalService.getApprovalStatus(created.getApprovalId());
+
+ assertNotNull(found);
+ assertEquals(created.getApprovalId(), found.getApprovalId());
+ }
+
+ @Test
+ @DisplayName("존재하지 않는 승인 ID 조회 시 null 반환")
+ void testGetNonExistentApproval() {
+ CardAcquisitionApprovalResponse response = approvalService.getApprovalStatus("APR-NONEXIST");
+ assertNull(response);
+ }
+}