nestpay 선불결제 시스템 · 발주사 인프라 기준
발주사(페이네스트)의 금융결제원 신고 전산설비 구성을 그대로 준수합니다. WEB(DMZ) → WAS(내부망) → DB의 3-tier 이중화 구조입니다.
flowchart TB
U["사용자 앱 / 브라우저"] --> WEB
subgraph DMZ["DMZ 존"]
WEB["WEB 서버 × 2 (이중화)
www 소개 · 정적 · 리버스프록시"]
end
subgraph INT["내부망"]
WAS["WAS 서버 × 2 (이중화)
Spring Boot: api · admin · agent"]
DB[("MariaDB 10.3
maxscale + keepalived
마스터 / 슬레이브")]
end
WEB --> WAS
WAS --> DB
| 구성 | 내용 |
|---|---|
| 서버 | 4대 — WEB 2대(DMZ) + WAS 2대(내부망), 각 이중화 |
| 사양 | CPU 40코어 · 메모리 32G · CentOS 7.9.2009 |
| DB | MariaDB 10.3.35 · maxscale+keepalived 이중화 · 마스터/슬레이브(현재 마스터 활용) |
| 망 구조 | WEB=DMZ 공개 인입 · WAS=내부망(WEB 경유만) · DB=내부망 |
서비스 배치: 공개 소개(www)는 WEB/DMZ, 회원·매장·관리 API(api·admin·agent)는 내부망 WAS에 위치해 외부 직접 노출을 차단합니다.
요청하신 역할 분담(SQL / logic / endpoint)을 Spring Boot 표준 3계층으로 구현합니다.
flowchart LR IN["요청 (in)"] --> C["Controller
endpoint · 타입/데이터 검증
OpenAPI 문서"] C --> S["Service
모든 비즈니스 로직"] S --> M["Mapper (MyBatis)
SQL 파일 실행"] M --> D[("MariaDB")] D --> M --> S --> C --> OUT["응답 (out)"]
| 요청하신 역할 | 계층 | 도구 |
|---|---|---|
| SQL 파일 관리 등록·수정·삭제·조회 | Mapper | MyBatis — SQL을 XML 파일에 직접 관리(JPA처럼 SQL을 숨기지 않음) |
| logic 구분 SQL로 DB 처리·모든 로직 | Service | Spring @Service |
| endpoint 관리 in/out·type·data 체크 | Controller + DTO | Spring Web · Validation · Springdoc |
paynest-v1/apps/api/
├─ src/main/java/kr/nestpay/api/
│ ├─ controller/ endpoint (API 정의 · 문서)
│ ├─ dto/ in/out 데이터 (type·data)
│ ├─ service/ 로직
│ ├─ mapper/ MyBatis 인터페이스
│ └─ config/ 설정 (OpenAPI · DataSource)
└─ src/main/resources/
├─ mapper/*.xml SQL 파일
├─ db/migration/*.sql Flyway 마이그레이션
└─ application.yml DB 접속 설정
새 API는 항상 이 순서로 파일 5개만 작성합니다. 프로젝트 전체가 이 패턴의 반복입니다. (예: 지갑 잔액 조회)
// ① dto/BalanceDto.java — 응답 데이터(type)
public record BalanceDto(Long balance) {}
// ② resources/mapper/WalletMapper.xml — SQL (여기만 고치면 쿼리 변경)
<select id="selectBalance" resultType="...BalanceDto">
SELECT balance FROM wallets WHERE card_id=#{cardId} AND owner_type='USER_CARD'
</select>
// ③ mapper/WalletMapper.java — SQL 연결점
@Mapper public interface WalletMapper { BalanceDto selectBalance(Long cardId); }
// ④ service/WalletService.java — 로직
@Service public class WalletService {
private final WalletMapper mapper;
public BalanceDto getBalance(Long cardId){ return mapper.selectBalance(cardId); }
}
// ⑤ controller/WalletController.java — endpoint + 문서
@RestController @RequestMapping("/api/wallets")
public class WalletController {
private final WalletService service;
@Operation(summary="지갑 잔액 조회") // Swagger 문서 자동 생성
@GetMapping("/{cardId}/balance")
public BalanceDto balance(@PathVariable Long cardId){ return service.getBalance(cardId); }
}
| 레이어 | 기술 | 비고 |
|---|---|---|
| API 서버 | Java 17/21 · Spring Boot 3.x | 발주사 Java 확정에 맞춤 |
| SQL 관리 | MyBatis (mapper XML) | SQL 파일 직접 관리 |
| DB | MariaDB 10.3 · mariadb-java-client | 발주사 버전 호환 검증 완료 |
| API 문서 | Springdoc OpenAPI | Swagger UI 자동 생성 |
| 마이그레이션 | Flyway | 스키마 버전관리·자동 적용 |
| 관리자·매장·소개 웹 | HTML + Vanilla JS | admin · agent · www |
| 앱 | Flutter (Material 3) | 회원 · 매장 앱 |
| 본인인증·계좌 | 쿠콘 / 드림시큐리티 | 본인인증 · 1원인증 · 계좌실명조회 |
| 결제·충전 | 발주사 PG | 가상계좌 입금(웹훅) · 펌뱅킹 출금이체 |
Springdoc OpenAPI가 Controller의 어노테이션을 읽어 문서를 자동 생성합니다. endpoint를 추가·수정하면 문서가 자동 갱신되어 별도 문서 작업이 필요 없습니다.
| 환경 | 구성 |
|---|---|
| local | 개발자 로컬 (docker-compose: MariaDB 10.3 + 마이그레이션 자동 적용) |
| sandbox(외부) | 프로토타입·개발 검증 (외부망 허용, docker 동일 재현) |
| production(내부망) | 발주사 신고 구성 준수 · 본사 온사이트 배포(SSH+내부망 물리연결) |
./gradlew build → 실행 가능한 jar(내장 Tomcat) 생성java -jar api.jar 기동 → 시작 시 Flyway가 마이그레이션 자동 적용