API 개발 가이드
x2bee-api 프로젝트는 마이크로 서비스별 API를 제공하는 프로젝트입니다.
각 마이크로 서비스별로 구분되어 x2bee-api-display(전시), x2bee-api-order(주문) 등등의 프로젝트로 나뉘어져 있습니다.
x2bee-api의 모든 API는 REST API로 제공되며, JSON 형식으로 입력 값과 출력 값을 처리합니다.
x2bee-api에는 세션 정보와 같은 상태정보가 없습니다. API 처리에 필요한 정보는 그때그때 입력값으로 받거나 DB 조회해서 얻어야 하며, 불가피한 경우 캐시를 사용할 수도 있습니다.
x2bee-api는 클라이언트에서 호출되거나, 다른 x2bee-api에서 호출될 수 있습니다.
패키지명
업무 대분류를 기준으로 패키지를 분류하고 명명합니다.
예) 샘플 패키지/폴더
컨트롤러
com.x2bee.api.display.app.controller.sample
서비스
com.x2bee.api.display.app.service.sample
리포지토리
com.x2bee.api.display.app.repository.sample
DTO
com.x2bee.api.display.app.dto.request.sample com.x2bee.api.display.app.dto.response.sample
mapper XML
mapper/rwdb/sample mapper/rodb/display
message(다국어처리)
message/display
entity/enum은 업무별 패키지 구분하지 않고 모두 entity/enum 패키지 아래에 작성합니다.
컨트롤러 작성
컨트롤러는 입력 파라미터를 받아서 DTO에 설정하고, 업무로직 처리를 위한 서비스 메소드를 호출한 후 서비스 메소드의 결과값을 적절한 응답 식으로 변환하여 return합니다.
클래스 어노테이션
클래스 레벨에 다음의 어노테이션을 사용합니다.
Spring
@RestController
Rest 컨트롤러임을 표시하는 Spring bean 어노테이션. @ResponseBody + @Controller 역할을 합니다.
@RequestMapping
컨트롤러 클래스 수준의 Request Mapping URI 공통부분을 지정합니다.
@RequiredArgsConstructor
생성자 주입 편의를 위한 lombok 어노테이션입니다.
@Slf4j
로그 작성을 위해 사용하는 lombok 어노테이션입니다.
Swagger3 UI
@Tag
Swagger API 그룹 설정 시 사용합니다. 태그 이름과 description을 추가할 수 있습니다.
예시:
메소드 어노테이션
메소드 레벨에 다음의 어노테이션을 사용합니다.
HTTP 요청
@GetMapping
get 메소드(조회/검색) 시 사용
@PostMapping
post 메소드(등록) 시 사용
@PutMapping
put 메소드(전체수정) 시 사용
@PatchMapping
patch 메소드(일부수정) 시 사용
@DeleteMapping
delete 메소드(삭제) 시 사용
Swagger3 UI
@Operation
Swagger API 설명 설정 시 사용
@ApiResponse
Swagger API response 설정 시 사용
@Parameters / @Parameter
Swagger API parameter 설정 시 사용
예시:
매핑 URI 형식
@RequestMapping의 path 파라미터로 작성될 매핑 URI의 형식은 다음과 같습니다.
/api/<업무대분류명(패키지명)>: context-path로 지정. 프로그램에서 지정하지 않음
/resource명 복수형: 클래스레벨 @RequestMapping에서 지정
/하위resource명 복수형: 메소드레벨 Mapping에서 지정. 없는 경우 생략
예) 카테고리 처리:
클래스레벨 RequestMapping: @RequestMapping("/api/display/categories")
주요 매핑 예시:
카테고리 트리 조회
@GetMapping("/trees")
카테고리 상세 조회
@GetMapping("/{id}")
카테고리 등록
@PostMapping("")
카테고리 수정
@PutMapping("/{id}")
카테고리 삭제
@DeleteMapping("/{id}")
카테고리 비전시 처리
@PatchMapping("/{id}?displayYn=false")
메소드 파라미터 어노테이션
메소드 파라미터에 다음의 어노테이션을 사용할 수 있습니다.
@RequestBody
모든 API 파라미터 전달은 Request body에 JSON 유형의 데이터를 사용합니다. 해당 파라미터를 입력받기 위해 @RequestBody를 사용합니다.
@Valid, @Validated
파라미터 모델클래스 멤버변수의 유효성을 체크합니다. 멤버변수에 @NotNull, @Size, @Min, @Max, @Digits, @Pattern 등의 제약을 주고 검증 실패 시 MethodArgumentNotValidException이 발생합니다.
예시:
메소드 리턴값
API 응답은 응답 데이터를 Response 객체로 감싸서 return합니다. 클래스 레벨에 @RestController가 사용되었으므로 실제 응답값은 Java 객체를 JSON으로 변환한 값이 됩니다.
예시:
Response 클래스는 응답값이 작성된 Timestamp와 처리 오류코드/메시지를 지정할 수 있으며, payload에는 실제 응답 데이터가 들어갑니다.
서비스 클래스 작성
서비스 클래스는 특정 업무의 핵심 로직을 처리합니다.
인터페이스/구현클래스 구분
소메뉴별로 1개의 서비스 클래스를 작성하며, 인터페이스와 구현 클래스를 구분합니다.
예) CategoryService / CategoryServiceImpl
서비스 어노테이션
클래스 레벨에 아래 어노테이션을 사용합니다.
@Service
서비스 클래스임을 표시하는 Spring bean 어노테이션
@Slf4j
로그 작성을 위한 lombok 어노테이션
@RequiredArgsConstructor
생성자 주입 편의를 위한 lombok 어노테이션
예시:
메소드 구성
서비스 메소드는 리포지토리 메소드 호출, 타 서비스 API 호출 및 기타 업무로직 처리 등의 작업을 실행한 후 결과를 반환합니다. 핵심 업무로직이 구현되도록 구성합니다.
트랜잭션 처리
등록/수정/삭제 서비스 메소드에 @Transactional 어노테이션을 통해 명시적으로 관리합니다.
@Transactional이 선언된 클래스 및 메소드는 ReadWrite 데이터베이스로 연결됩니다.
선언되지 않은 Service 메소드는 ReadOnly 데이터베이스로 연결됩니다.
CRUD가 혼재된 경우 명시적으로 트랜잭션을 선언합니다.
예:
value에는 displayRwdbTxManager, orderRwdbTxManager, eventRwdbTxManager 등 트랜잭션 매니저를 명시해야 합니다.
트랜잭션이 정상 동작하려면 오타가 없도록 유의하세요.
Mapper 작성
Mapper interface 작성
DB 테이블별로 1개의 ***Mapper와 1개의 ***TrxMapper를 작성합니다.
***Mapper: select 문 (read-only)
***TrxMapper: insert/update/delete 문 (read-write)
readonly 맵퍼에 insert/update/delete문을 작성하면 오류가 발생하므로 반드시 구분하여 작성합니다.
Mapper는 interface 자바 파일과 SQL mapper XML 파일 두 개로 작성합니다. Interface에는 호출될 메소드 시그니처를 기록하고 SQL은 mapper XML에 기술합니다.
예: CategoryMapper.java
Mapper XML 작성
Mapper 메소드 호출시 실행될 SQL을 작성합니다.
예: CategoryMapper.xml
DTO / Entity 작성
Request DTO 작성
Request DTO는 조회/검색 컨트롤러 메소드의 파라미터를 담는 Bean 객체입니다.
조회/검색 조건 파라미터가 존재하는 메소드 작성 시 Request DTO를 작성하여 요청 파라미터 값을 받아야 합니다.
DTO 클래스는 BaseCommonEntity 클래스를 상속받아 생성합니다. (생성자/수정자/생성일시/수정일시/페이징/엑셀다운로드 관련 정보 포함)
DTO 클래스에는 @Alias 어노테이션을 사용하여 Mapper의 타입 축약어로 사용할 수 있도록 합니다.
컨트롤러에서 받은 정보를 별도의 수정 없이 서비스/Mapper 메소드에서 사용할 수 있습니다.
serialVersionUID는 반드시 UUID를 생성하여 사용합니다.
예: PrDispGrpBaseRequest.java
Response DTO 작성
Response DTO는 조회/검색 컨트롤러 메소드의 결과값을 담는 Bean 객체입니다.
조회/검색 결과가 존재하는 메소드 작성 시 Response DTO를 작성합니다.
DTO 클래스는 BaseCommonEntity를 상속하지 않습니다.
@Alias 어노테이션을 사용하여 Mapper 메소드의 리턴타입으로 사용할 수 있도록 합니다.
serialVersionUID는 반드시 UUID를 생성하여 사용합니다.
예: PrDispGrpBaseResponse.java
Entity 작성
Entity 클래스는 등록/수정/삭제 컨트롤러 메소드의 파라미터를 담는 Bean 객체입니다.
등록/수정/삭제 메소드 작성 시 Entity 클래스를 통해 요청 파라미터 값을 받습니다.
Entity 클래스는 필드와 DB 테이블 필드와 동일하게 구성합니다.
Entity 클래스는 BaseCommonEntity 클래스를 상속받아 생성합니다.
@Alias 어노테이션을 사용하여 Mapper XML에서 사용할 수 있도록 합니다.
serialVersionUID는 반드시 UUID를 생성하여 사용합니다.
예: PrDispCtgBase.java
오류처리
오류 발생 시 ApiException()을 throw합니다. 생성자 파라미터로 ApiError를 지정합니다.
ApiError는 enumeration으로 오류유형과 메시지 key를 포함한 오류 상수들로 구성되어 있습니다.
예:
해당 예시 호출 시 반환되는 응답 예: HTTP status: 400 BAD REQUEST
ApiError 예시:
메시지용 common.properties (예시)
common.error.emptyParameter = 파라미터 값이 없습니다: {0}
common.error.invalidParameter = 파라미터가 올바르지 않습니다.
common.error.dataNotFound = 데이터가 존재하지 않습니다.
common.error.bindingError = 파라미터 바인딩 오류입니다.
common.error.bindingErrorNotNull = 파라미터 바인딩 오류입니다: not null
common.error.unknown = 알 수 없는 오류입니다.
common.message.success = 성공
프로퍼티
application.yml: 스프링 설정값이나 base 클래스 설정값을 관리합니다.
config/application-<profile명>.properties: 업무 개발 시 필요한 프로퍼티 항목들을 관리합니다. 각 업무 개발자가 필요 시 항목을 추가할 수 있습니다.
java에서 프로퍼티 사용 예:
environment 빈을 통한 조회 예:
메시지 사용
메시지는 src/main/resources/message 폴더에 관리합니다. 업무 대분류별로 개별 폴더를 생성하고 컨트롤러별로 메시지 파일을 관리합니다.
java에서 메시지 사용
MessageResolver 클래스를 사용하여 메세지를 조회합니다. 메세지 key로 조회하거나 AppError enum을 사용할 수 있습니다. 메세지는 다국어를 지원하며, LocalContext에 저장된 locale에 따라 언어를 구분하거나 메소드 호출 시 Locale을 직접 지정할 수 있습니다.
MessageResolver 메소드 형식 예:
로그
로깅 라이브러리: logback 사용 (설정: logback-spring.xml). slf4j 인터페이스 사용.
로그 작성: @Slf4j lombok 어노테이션 사용 후 log 객체로 작성.
예:
로그 레벨 사용: error(오류 상황), debug(디버그 용)
로그 조회: 로컬 개발 환경에서는 콘솔 또는 파일로 조회. 기본 로그 파일 경로: c:/X2BEE-DEV/log/x2bee-***.log 개발/운영 환경에서는 설정된 Kibana를 통해 로그 조회 가능 (접속정보 별도 확인).
마스킹(Masking)
동작원리
Request DTO에 @Masking 필드 어노테이션을 적용하고 type을 지정하면, SQL 조회 시 해당 @Masking 적용된 DTO 필드에 대해 지정된 type 유형의 masking이 자동 적용됩니다.
예: MaskingCUD.java
마스킹 유형
이름
NAME_KR
이름 두번째 마스킹
홍동 / 을문덕
영문이름
NAME_EN
이름 중 첫번째와 마지막 알파벳 제외하고 마스킹
John Smith → J**h Smith
전화번호
MOBILE_NUM
중간번호 전체 마스킹
010****2134
주소 (동이하)
ADDRESS
동이하 주소 전체 마스킹
서울 강남구 압구정동 ****
도로명(길이하)
ADDRESS
길이하 주소 전체 마스킹
서울 강남구 압구정로 ****
상세주소
ADDRESS_DTL
상세주소 전체 마스킹
-
이메일
아이디 4번째부터 끝까지 마스킹
abc***@**********
주민번호
RRN
주민번호 뒤 7자리 이상 마스킹
801212-*******
생년월일
BIRTH
일 자리 마스킹
1980-12-**
운전면허번호
LICENSE
5번째부터 6자리 이상 마스킹
서울 95-******-61
여권번호
PASSPORT
뒤 4자리 이상 마스킹
M9999****
현금영수증카드
CARD
9번째부터 4자리 이상 마스킹
1544-2020-****-123456
신용카드(14자리)
CARD
8번째부터 4자리 이상 마스킹
9500-0012-****-0000
기타카드(11자리)
CARD
7번째부터 4자리 이상 마스킹
9500-00**-**0
기타카드(13~19자리)
CARD
8번째부터 4자리 이상 마스킹
9500-0012-****-0000
사업자등록번호
BNO
3번째부터 4자리 이상 마스킹
12*-**-*1234
계좌번호
ACTN
6번째부터 끝까지 마스킹
12345**********
QR코드
QRCODE
5번째부터 4자리 이상 마스킹
126-0-****-1234
IP
IP
7번째부터 3자리 이상 마스킹
123.123.***.123
ID
ID
4자리부터 끝까지 마스킹
kim******
MaskingUtils 사용
개별 데이터 마스킹이 필요한 경우 MaskingUtils를 사용할 수 있습니다.
masking(String src, int startIdx)
문자의 startIdx에서 끝까지 마스킹
masking(String src, int startIdx, int length)
문자의 startIdx에서 length 길이만큼 마스킹
DB 데이터 필드 암복화
동작원리
Request DTO 및 Entity의 암호화 대상 필드에 @Encrypt 필드 어노테이션을 적용합니다. Mapper에서 SQL insert/update 시 해당 @Encrypt 적용된 필드가 암호화되어 DB에 저장되고, select 시 복호화 되어 조회됩니다.
예:
적용 알고리즘
암복화에 AES-256-GCM을 사용합니다. 적용 알고리즘 요약:
암호화 알고리즘
AES-256-GCM
데이터 암호화 키 길이(비트)
256
키 추출 알고리즘
HKDF (SHA-384 포함)
서명 알고리즘
P-384 및 SHA-384 포함된 ECDSA
기간 약정
HKDF (SHA-512 포함)
암호문 데이터 길이
암호화된 데이터 길이는 평문보다 길어지며, DB 필드 설계 시 고려해야 합니다.
암호화 필드 길이 계산식
EncryptUtils 사용
개별 암호화/복호화가 필요한 경우 EncryptUtils의 static 메소드를 사용합니다.
암호화: public static String getEncryptValue(String value) throws Exception;
복호화: public static String getDecryptValue(String value) throws Exception;
암호화 key 환경변수
암호화/복호화 시 사용될 key는 application.yml에 관리됩니다. 암호화 키는 32자리 입력.
예:
메소드 권한 및 로그인 사용자 정보
예시:
@Secured("ROLE_MEMBER")을 사용하면 회원 로그인된 경우만 진입 가능.
로그인 상태가 아니면 호출 시 HTTP 403 FORBIDDEN 발생.
컨트롤러 메소드에서 로그인 사용자 정보는 @AuthenticationPrincipal로 주입받아 사용합니다.
userDetail.getMbrNo()로 회원번호 조회 가능.
Swagger3 @Schema
@Schema
description
한글명
defaultValue
기본값
allowableValues
허용 가능한 값(열거형)
example
예시값
Request/Response DTO 작성 시 위 어노테이션과 속성을 설정하여 Swagger UI에서 확인할 수 있습니다.
마지막 업데이트