feat: Refactor monolith to microservices architecture

This commit is contained in:
jade
2026-07-05 17:27:44 +09:00
parent 367a47516d
commit 10f3f0513d
200 changed files with 541 additions and 1789 deletions

View File

@@ -0,0 +1,29 @@
package io.shinhanlife.glow;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
//@Schema(description = "응답 에러 객체. 성공 케이스일 경우 null. 실제 에러가 발생할 경우에만 예외명, 예외 메시지 필드 세팅 예정.")
public class BaseException {
// @Schema(description = "Error 코드 Meta 참조 운영. (예) 20001, 50001 등", shinhanlife = "20001")
String code;
// @Schema(description = "메시지")
String message;
// @Schema(description = "예외명.", shinhanlife = "NullPointerException")
@Builder.Default
String exceptionName = "";
// @Schema(description = "예외상세", shinhanlife = "StackTrace")
@Builder.Default
String exceptionDetail = "";
}

View File

@@ -0,0 +1,25 @@
package io.shinhanlife.glow;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.ToString;
@ToString
@Getter
@Builder
@AllArgsConstructor
public class BaseResponse<T> {
// @Schema(description = "응답 코드 HTTP STATUS 오류 - 실제 Header 는 200 으로 내려감", shinhanlife = "200")
private int code;
// @Schema(description = "응답 메시지. 응답 코드와 매핑된 메시지.", shinhanlife = "데이터 생성 성공")
private String message;
// @Schema(description = "응답 본문 데이터. 실제 비즈니스 데이터.")
private T data;
private BaseException error;
}

View File

@@ -0,0 +1,6 @@
package io.shinhanlife.glow;
public class BizException extends RuntimeException {
public BizException(String s) {
}
}

View File

@@ -0,0 +1,13 @@
package io.shinhanlife.glow;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GlowAppServiceId {
String value();
String description() default "";
}

View File

@@ -0,0 +1,5 @@
package io.shinhanlife.glow;
public @interface GlowControllerId {
String value();
}

View File

@@ -0,0 +1,9 @@
package io.shinhanlife.glow;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GlowIndexPaging {
}

View File

@@ -0,0 +1,15 @@
package io.shinhanlife.glow;
import java.lang.annotation.*;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GlowLogTarget {
Target[] value() default {};
enum Target {
FILE, CONSOLE
}
}

View File

@@ -0,0 +1,19 @@
package io.shinhanlife.glow;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("prototype")
public class GlowLogger {
private Logger log = LoggerFactory.getLogger(GlowLogger.class);
public void debug(String message, Object... args) { log.debug(message, args); }
public void info(String message, Object... args) { log.info(message, args); }
public void warn(String message, Object... args) { log.warn(message, args); }
public void error(String message, Object... args) { log.error(message, args); }
public void error(String message, Throwable t) { log.error(message, t); }
}

View File

@@ -0,0 +1,18 @@
package io.shinhanlife.glow;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
/**
* MyBatis Mapper 인터페이스를 나타내는 어노테이션
* MyBatis Mapper와 동일한 기능을 제공합니다.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapper
@Component
public @interface GlowMybatisMapper {
}

View File

@@ -0,0 +1,7 @@
package io.shinhanlife.glow;
public @interface GlowServiceGroupId {
String value();
String description();
}

View File

@@ -0,0 +1,25 @@
package io.shinhanlife.glow;
import java.lang.annotation.*;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GlowTrgmField {
/**
* 필드 순서
*/
int order();
/**
* 필드 길이
*/
int length();
/**
* 필드 설명
*/
String description() default "";
}

View File

@@ -0,0 +1,68 @@
package io.shinhanlife.glow;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import org.apache.ibatis.session.RowBounds;
import java.io.Serial;
import java.io.Serializable;
@Getter
@Setter
@JsonIgnoreProperties(ignoreUnknown = true)
@EqualsAndHashCode(callSuper = true)
public class PageInfo extends RowBounds implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 페이지번호 ( 입력값 )
*/
@GlowTrgmField(order = 1, length = 5, description = "페이지번호")
private int pageNo;
/**
* 페이지 데이터 건수 ( 열 건수, 입력값 )
*/
@GlowTrgmField(order = 2, length = 5, description = "페이지데이터건수")
private int pageDataCc;
/**
* 총페이지 수 ( 리턴값 )
*/
@GlowTrgmField(order = 3, length = 10, description = "총페이지수")
private int totaPageCn;
/**
* 총 페이지 데이터 건수 ( 리턴값 )
*/
@GlowTrgmField(order = 4, length = 10, description = "총페이지데이터건수")
private int totaPageDataCc;
public PageInfo(int pageNo, int pageDataCc) {
super(((pageNo <= 0 ? 1 : pageNo) - 1) * pageDataCc, pageDataCc);
this.pageNo = pageNo;
this.pageDataCc = pageDataCc;
}
public PageInfo() {
}
@JsonIgnore
@Override
public int getOffset() {
return super.getOffset();
}
@JsonIgnore
@Override
public int getLimit() {
return super.getLimit();
}
}

View File

@@ -0,0 +1,31 @@
package io.shinhanlife.glow;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
@Getter
@RequiredArgsConstructor
public enum ResponseCode {
/* ===================== 성공 ===================== */
SUCCESS(HttpStatus.OK, "정상 처리되었습니다."),
CREATED(HttpStatus.CREATED, "데이터 생성 성공"),
/* ===================== 클라이언트 오류 (4xx) ===================== */
BAD_REQUEST(HttpStatus.BAD_REQUEST, "잘못된 요청입니다."),
INVALID_PARAMETER(HttpStatus.BAD_REQUEST, "유효하지 않은 파라미터입니다."),
UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "인증이 필요합니다."),
FORBIDDEN(HttpStatus.FORBIDDEN, "접근 권한이 없습니다."),
NOT_FOUND(HttpStatus.NOT_FOUND, "요청한 리소스를 찾을 수 없습니다."),
METHOD_NOT_ALLOWED(HttpStatus.METHOD_NOT_ALLOWED, "허용되지 않은 HTTP 메서드입니다."),
CONFLICT(HttpStatus.CONFLICT, "이미 존재하는 데이터입니다."),
/* ===================== 서버 오류 (5xx) ===================== */
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "서버 내부 오류가 발생했습니다."),
SERVICE_UNAVAILABLE(HttpStatus.SERVICE_UNAVAILABLE, "서비스를 사용할 수 없습니다.");
private final HttpStatus status;
private final String message;
}

View File

@@ -0,0 +1,111 @@
package io.shinhanlife.glow;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
public final class ResponseUtil {
private ResponseUtil() {
}
public static <T> ResponseEntity<BaseResponse<T>> ok() {
return ResponseEntity.ok(
BaseResponse.<T>builder()
.code(ResponseCode.SUCCESS.getStatus().value())
.message(ResponseCode.SUCCESS.getMessage())
.build()
);
}
public static <T> ResponseEntity<BaseResponse<T>> ok(T data) {
return ResponseEntity.ok(
BaseResponse.<T>builder()
.code(ResponseCode.SUCCESS.getStatus().value())
.message(ResponseCode.SUCCESS.getMessage())
.data(data)
.build()
);
}
public static <T> ResponseEntity<BaseResponse<T>> ok(T data, ResponseCode responseCode) {
return ResponseEntity.ok(
BaseResponse.<T>builder()
.code(responseCode.getStatus().value())
.message(responseCode.getMessage())
.data(data)
.build()
);
}
public static <T> ResponseEntity<BaseResponse<T>> error(
HttpStatus status, String code, String message
) {
return ResponseEntity.status(status)
.body(
BaseResponse.<T>builder()
.code(status.value())
.error(
BaseException.builder()
.code(code)
.message(message)
.build()
)
.build()
);
}
public static <T> ResponseEntity<BaseResponse<T>> error(
HttpStatus status, String code, String message, String exceptionName, String stackTrace
) {
return ResponseEntity.status(status)
.body(
BaseResponse.<T>builder()
.code(status.value())
.error(
BaseException.builder()
.code(code)
.message(message)
.exceptionName(exceptionName)
.exceptionDetail(stackTrace)
.build()
)
.build()
);
}
public static <T> ResponseEntity<BaseResponse<T>> okError(
HttpStatus status, String code, String message
) {
return ResponseEntity.ok(
BaseResponse.<T>builder()
.code(status.value())
.error(
BaseException.builder()
.code(code)
.message(message)
.build()
)
.build()
);
}
public static <T> ResponseEntity<BaseResponse<T>> okError(
HttpStatus status, String code, String message, String exceptionName, String stackTrace
) {
return ResponseEntity.ok(
BaseResponse.<T>builder()
.code(status.value())
.error(
BaseException.builder()
.code(code)
.message(message)
.exceptionName(exceptionName)
.exceptionDetail(stackTrace)
.build()
)
.build()
);
}
}

View File

@@ -0,0 +1,16 @@
package io.shinhanlife.glow.db.dto;
import java.util.Date;
public class AuditInfo {
private Date systRgiDt; // 시스템등록일시
private String systRgiPrafNo; // 시스템등록인사번호
private String systRgiOgnzNo; // 시스템등록조직번호
private String systRgiSystCd; // 시스템등록시스템코드
private String systRgiPrgrId; // 시스템등록프로그램ID
private Date systChgDt; // 시스템변경일시
private String systChgPrafNo; // 시스템변경인사번호
private String systChgOgnzNo; // 시스템변경조직번호
private String systChgSystCd; // 시스템변경시스템코드
private String systChgPrgrId; // 시스템변경프로그램ID
}