diff --git a/src/main/java/com/kamco/cd/kamcoback/code/config/CommonCodeCacheManager.java b/src/main/java/com/kamco/cd/kamcoback/code/config/CommonCodeCacheManager.java
index fcd51d9b..71444eea 100644
--- a/src/main/java/com/kamco/cd/kamcoback/code/config/CommonCodeCacheManager.java
+++ b/src/main/java/com/kamco/cd/kamcoback/code/config/CommonCodeCacheManager.java
@@ -13,8 +13,7 @@ import org.springframework.stereotype.Component;
/**
* 공통코드 캐시 관리 및 초기화 클래스
*
- *
애플리케이션 시작 시 공통코드를 Redis 캐시에 미리 로드하고, 캐시 갱신을 관리합니다.
- * 기존 Redis 데이터와의 호환성 문제로 인한 간헐적 오류를 방지합니다.
+ *
애플리케이션 시작 시 공통코드를 Redis 캐시에 미리 로드하고, 캐시 갱신을 관리합니다. 기존 Redis 데이터와의 호환성 문제로 인한 간헐적 오류를 방지합니다.
*/
@Slf4j
@Component
@@ -29,9 +28,8 @@ public class CommonCodeCacheManager {
/**
* 애플리케이션 시작 완료 후 공통코드를 Redis 캐시에 미리 로드
*
- *
이 메서드는 Spring 애플리케이션이 완전히 시작된 후에 자동으로 실행되며, 공통코드 데이터를 Redis
- * 캐시에 미리 로드하여 초기 조회 시 성능을 최적화합니다. 기존 캐시 데이터 호환성 문제를 대비하여 먼저
- * 캐시를 초기화한 후 재로드합니다.
+ *
이 메서드는 Spring 애플리케이션이 완전히 시작된 후에 자동으로 실행되며, 공통코드 데이터를 Redis 캐시에 미리 로드하여 초기 조회 시 성능을 최적화합니다.
+ * 기존 캐시 데이터 호환성 문제를 대비하여 먼저 캐시를 초기화한 후 재로드합니다.
*/
@EventListener(ApplicationReadyEvent.class)
public void initializeCommonCodeCache() {
@@ -48,27 +46,18 @@ public class CommonCodeCacheManager {
// 2. DB에서 새로운 데이터 로드 (캐시 미스 상태)
List allCommonCodes = commonCodeService.getFindAll();
- log.info(
- "✓ 공통코드 {}개를 DB에서 로드하고 Redis 캐시에 저장했습니다.",
- allCommonCodes.size());
+ log.info("✓ 공통코드 {}개를 DB에서 로드하고 Redis 캐시에 저장했습니다.", allCommonCodes.size());
// 3. 로그 출력 (DEBUG 레벨)
if (log.isDebugEnabled()) {
allCommonCodes.forEach(
- code ->
- log.debug(
- " - [{}] {} (ID: {})",
- code.getCode(),
- code.getName(),
- code.getId()));
+ code ->
+ log.debug(" - [{}] {} (ID: {})", code.getCode(), code.getName(), code.getId()));
}
log.info("=== 공통코드 캐시 초기화 완료 ===");
} catch (Exception e) {
- log.warn(
- "공통코드 캐시 초기화 중 오류 발생했습니다. 캐시 없이 계속 진행합니다. "
- + "(첫 번째 조회 시 DB에서 로드되고 캐시됩니다.)",
- e);
+ log.warn("공통코드 캐시 초기화 중 오류 발생했습니다. 캐시 없이 계속 진행합니다. " + "(첫 번째 조회 시 DB에서 로드되고 캐시됩니다.)", e);
}
}
@@ -121,10 +110,31 @@ public class CommonCodeCacheManager {
*/
public int getCachedCommonCodeCount() {
try {
- List cachedCodes = commonCodeService.getFindAll();
- return cachedCodes.size();
+ // 캐시 오류 시 자동으로 재초기화
+ try {
+ List cachedCodes = commonCodeService.getFindAll();
+ return cachedCodes.size();
+ } catch (Exception cacheError) {
+ log.debug("캐시 조회 중 호환성 오류 감지, 캐시 재초기화 중...: {}", cacheError.getMessage());
+
+ // 기존 호환성 문제가 있는 캐시 데이터 강제 제거
+ try {
+ var cache = cacheManager.getCache(COMMON_CODES_CACHE_NAME);
+ if (cache != null) {
+ cache.clear();
+ log.debug("✓ 호환되지 않는 캐시 데이터 제거 완료");
+ }
+ } catch (Exception clearEx) {
+ log.debug("캐시 정리 중 예외: {}", clearEx.getMessage());
+ }
+
+ // 재시도
+ List cachedCodes = commonCodeService.getFindAll();
+ log.info("✓ 캐시 재초기화 완료, 공통코드 {}개 로드됨", cachedCodes.size());
+ return cachedCodes.size();
+ }
} catch (Exception e) {
- log.warn("캐시 상태 확인 중 오류 발생: {}", e.getMessage());
+ log.warn("캐시 상태 확인 중 최종 오류 발생: {}", e.getMessage());
return 0;
}
}
diff --git a/src/main/java/com/kamco/cd/kamcoback/common/utils/FIleChecker.java b/src/main/java/com/kamco/cd/kamcoback/common/utils/FIleChecker.java
index 152b1118..f5527cf5 100644
--- a/src/main/java/com/kamco/cd/kamcoback/common/utils/FIleChecker.java
+++ b/src/main/java/com/kamco/cd/kamcoback/common/utils/FIleChecker.java
@@ -13,8 +13,6 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.gce.geotiff.GeoTiffReader;
@@ -47,9 +45,8 @@ public class FIleChecker {
return true;
}
-
public static boolean verifyFileIntegrity(Path path, String expectedHash)
- throws IOException, NoSuchAlgorithmException {
+ throws IOException, NoSuchAlgorithmException {
// 1. 알고리즘 선택 (SHA-256 권장, MD5는 보안상 비추천)
MessageDigest digest = MessageDigest.getInstance("SHA-256");
@@ -72,7 +69,6 @@ public class FIleChecker {
return actualHash.equalsIgnoreCase(expectedHash);
}
-
public static boolean checkTfw(String filePath) {
File file = new File(filePath);
@@ -90,13 +86,13 @@ public class FIleChecker {
lines.add(Double.parseDouble(line.trim()));
}
}
- }catch (IOException ignored) {
+ } catch (IOException ignored) {
return false;
}
// 2. 6줄이 맞는지 확인
if (lines.size() < 6) {
- //System.out.println("유효하지 않은 TFW 파일입니다. (데이터 부족)");
+ // System.out.println("유효하지 않은 TFW 파일입니다. (데이터 부족)");
return false;
}
@@ -123,9 +119,9 @@ public class FIleChecker {
if (coverage == null) return false;
// 3. GIS 필수 정보(좌표계)가 있는지 확인
- //if (coverage.getCoordinateReferenceSystem() == null) {
- // GeoTIFF가 아니라 일반 TIFF일 수도 있음(이미지는 정상이지만, 좌표계(CRS) 정보가 없습니다.)
- //}
+ // if (coverage.getCoordinateReferenceSystem() == null) {
+ // GeoTIFF가 아니라 일반 TIFF일 수도 있음(이미지는 정상이지만, 좌표계(CRS) 정보가 없습니다.)
+ // }
return true;
@@ -149,59 +145,57 @@ public class FIleChecker {
String resStr = "";
boolean hasDriver = false;
- // 리눅스/맥용
- //ProcessBuilder pb = new ProcessBuilder("sh", "-c", "gdalinfo "+filePath+" | grep -i 'Geo'");
+ // 리눅스/맥용
+ // ProcessBuilder pb = new ProcessBuilder("sh", "-c", "gdalinfo "+filePath+" | grep -i 'Geo'");
- List command = new ArrayList<>();
+ List command = new ArrayList<>();
- //윈도우용
- command.add("cmd.exe"); // 윈도우 명령 프롬프트 실행
- command.add("/c"); // 명령어를 수행하고 종료한다는 옵션
- //command.add("C:\\Program Files\\QGIS 3.44.4\\bin\\gdalinfo");
- command.add("gdalinfo");
- command.add(filePath);
- command.add("|");
- command.add("findstr");
- command.add("/i");
- command.add("Geo");
+ // 윈도우용
+ command.add("cmd.exe"); // 윈도우 명령 프롬프트 실행
+ command.add("/c"); // 명령어를 수행하고 종료한다는 옵션
+ // command.add("C:\\Program Files\\QGIS 3.44.4\\bin\\gdalinfo");
+ command.add("gdalinfo");
+ command.add(filePath);
+ command.add("|");
+ command.add("findstr");
+ command.add("/i");
+ command.add("Geo");
- /*
- command.add("sh"); // 윈도우 명령 프롬프트 실행
- command.add("-c"); // 명령어를 수행하고 종료한다는 옵션
- command.add("gdalinfo");
- command.add(filePath);
- command.add("|");
- command.add("grep");
- command.add("-i");
- command.add("Geo");
- */
+ /*
+ command.add("sh"); // 윈도우 명령 프롬프트 실행
+ command.add("-c"); // 명령어를 수행하고 종료한다는 옵션
+ command.add("gdalinfo");
+ command.add(filePath);
+ command.add("|");
+ command.add("grep");
+ command.add("-i");
+ command.add("Geo");
+ */
- ProcessBuilder processBuilder = new ProcessBuilder(command);
- processBuilder.redirectErrorStream(true);
+ ProcessBuilder processBuilder = new ProcessBuilder(command);
+ processBuilder.redirectErrorStream(true);
- try {
- Process process = processBuilder.start();
+ try {
+ Process process = processBuilder.start();
- // 인코딩은 윈도우 한글 환경에 맞게 MS949로 지정
- BufferedReader reader = new BufferedReader(
- new InputStreamReader(process.getInputStream()));
+ // 인코딩은 윈도우 한글 환경에 맞게 MS949로 지정
+ BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
- String line;
- while ((line = reader.readLine()) != null) {
- //System.out.println(line);
- if( line.contains("Driver: GTiff/GeoTIFF")) {
- hasDriver = true;
- break;
- }
+ String line;
+ while ((line = reader.readLine()) != null) {
+ // System.out.println(line);
+ if (line.contains("Driver: GTiff/GeoTIFF")) {
+ hasDriver = true;
+ break;
}
-
- int exitCode = process.waitFor();
-
- } catch (Exception e) {
- e.printStackTrace();
}
+ int exitCode = process.waitFor();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
return hasDriver;
}
-
}
diff --git a/src/main/java/com/kamco/cd/kamcoback/config/GlobalExceptionHandler.java b/src/main/java/com/kamco/cd/kamcoback/config/GlobalExceptionHandler.java
index 69e49fb5..9133902a 100644
--- a/src/main/java/com/kamco/cd/kamcoback/config/GlobalExceptionHandler.java
+++ b/src/main/java/com/kamco/cd/kamcoback/config/GlobalExceptionHandler.java
@@ -45,198 +45,197 @@ public class GlobalExceptionHandler {
@ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
@ExceptionHandler(EntityNotFoundException.class)
public ApiResponseDto handlerEntityNotFoundException(
- EntityNotFoundException e, HttpServletRequest request) {
+ EntityNotFoundException e, HttpServletRequest request) {
log.warn("[EntityNotFoundException] resource :{} ", e.getMessage());
String codeName = "NOT_FOUND_DATA";
ErrorLogEntity errorLog =
- saveErrorLogData(
- request,
- ApiResponseCode.getCode(codeName),
- HttpStatus.valueOf("UNPROCESSABLE_ENTITY"),
- ErrorLogDto.LogErrorLevel.WARNING,
- e.getStackTrace());
+ saveErrorLogData(
+ request,
+ ApiResponseCode.getCode(codeName),
+ HttpStatus.valueOf("UNPROCESSABLE_ENTITY"),
+ ErrorLogDto.LogErrorLevel.WARNING,
+ e.getStackTrace());
return ApiResponseDto.createException(
- ApiResponseCode.getCode(codeName),
- ApiResponseCode.getMessage(codeName),
- HttpStatus.valueOf("UNPROCESSABLE_ENTITY"),
- errorLog.getId());
+ ApiResponseCode.getCode(codeName),
+ ApiResponseCode.getMessage(codeName),
+ HttpStatus.valueOf("UNPROCESSABLE_ENTITY"),
+ errorLog.getId());
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(HttpMessageNotReadableException.class)
public ApiResponseDto handleUnreadable(
- HttpMessageNotReadableException e, HttpServletRequest request) {
+ HttpMessageNotReadableException e, HttpServletRequest request) {
log.warn("[HttpMessageNotReadableException] resource :{} ", e.getMessage());
String codeName = "BAD_REQUEST";
ErrorLogEntity errorLog =
- saveErrorLogData(
- request,
- ApiResponseCode.getCode(codeName),
- HttpStatus.valueOf(codeName),
- ErrorLogDto.LogErrorLevel.WARNING,
- e.getStackTrace());
+ saveErrorLogData(
+ request,
+ ApiResponseCode.getCode(codeName),
+ HttpStatus.valueOf(codeName),
+ ErrorLogDto.LogErrorLevel.WARNING,
+ e.getStackTrace());
return ApiResponseDto.createException(
- ApiResponseCode.getCode(codeName),
- ApiResponseCode.getMessage(codeName),
- HttpStatus.valueOf(codeName),
- errorLog.getId());
+ ApiResponseCode.getCode(codeName),
+ ApiResponseCode.getMessage(codeName),
+ HttpStatus.valueOf(codeName),
+ errorLog.getId());
}
@ResponseStatus(HttpStatus.NOT_FOUND)
@ExceptionHandler(NoSuchElementException.class)
public ApiResponseDto handlerNoSuchElementException(
- NoSuchElementException e, HttpServletRequest request) {
+ NoSuchElementException e, HttpServletRequest request) {
log.warn("[NoSuchElementException] resource :{} ", e.getMessage());
String codeName = "NOT_FOUND_DATA";
ErrorLogEntity errorLog =
- saveErrorLogData(
- request,
- ApiResponseCode.getCode(codeName),
- HttpStatus.valueOf(codeName),
- ErrorLogDto.LogErrorLevel.WARNING,
- e.getStackTrace());
+ saveErrorLogData(
+ request,
+ ApiResponseCode.getCode(codeName),
+ HttpStatus.valueOf(codeName),
+ ErrorLogDto.LogErrorLevel.WARNING,
+ e.getStackTrace());
return ApiResponseDto.createException(
- ApiResponseCode.getCode(codeName),
- ApiResponseCode.getMessage(codeName),
- HttpStatus.valueOf("NOT_FOUND"),
- errorLog.getId());
+ ApiResponseCode.getCode(codeName),
+ ApiResponseCode.getMessage(codeName),
+ HttpStatus.valueOf("NOT_FOUND"),
+ errorLog.getId());
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(IllegalArgumentException.class)
public ApiResponseDto handlerIllegalArgumentException(
- IllegalArgumentException e, HttpServletRequest request) {
+ IllegalArgumentException e, HttpServletRequest request) {
log.warn("[handlerIllegalArgumentException] resource :{} ", e.getMessage());
String codeName = "BAD_REQUEST";
ErrorLogEntity errorLog =
- saveErrorLogData(
- request,
- ApiResponseCode.getCode(codeName),
- HttpStatus.valueOf(codeName),
- ErrorLogDto.LogErrorLevel.WARNING,
- e.getStackTrace());
+ saveErrorLogData(
+ request,
+ ApiResponseCode.getCode(codeName),
+ HttpStatus.valueOf(codeName),
+ ErrorLogDto.LogErrorLevel.WARNING,
+ e.getStackTrace());
return ApiResponseDto.createException(
- ApiResponseCode.getCode(codeName),
- ApiResponseCode.getMessage(codeName),
- HttpStatus.valueOf(codeName),
- errorLog.getId());
+ ApiResponseCode.getCode(codeName),
+ ApiResponseCode.getMessage(codeName),
+ HttpStatus.valueOf(codeName),
+ errorLog.getId());
}
@ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
@ExceptionHandler(DataIntegrityViolationException.class)
public ApiResponseDto handlerDataIntegrityViolationException(
- DataIntegrityViolationException e, HttpServletRequest request) {
+ DataIntegrityViolationException e, HttpServletRequest request) {
log.warn("[DataIntegrityViolationException] resource :{} ", e.getMessage());
String codeName = "DATA_INTEGRITY_ERROR";
ErrorLogEntity errorLog =
- saveErrorLogData(
- request,
- ApiResponseCode.getCode(codeName),
- HttpStatus.valueOf("UNPROCESSABLE_ENTITY"),
- ErrorLogDto.LogErrorLevel.CRITICAL,
- e.getStackTrace());
+ saveErrorLogData(
+ request,
+ ApiResponseCode.getCode(codeName),
+ HttpStatus.valueOf("UNPROCESSABLE_ENTITY"),
+ ErrorLogDto.LogErrorLevel.CRITICAL,
+ e.getStackTrace());
return ApiResponseDto.createException(
- ApiResponseCode.getCode(codeName),
- ApiResponseCode.getMessage(codeName),
- HttpStatus.valueOf("UNPROCESSABLE_ENTITY"),
- errorLog.getId());
+ ApiResponseCode.getCode(codeName),
+ ApiResponseCode.getMessage(codeName),
+ HttpStatus.valueOf("UNPROCESSABLE_ENTITY"),
+ errorLog.getId());
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public ApiResponseDto handlerMethodArgumentNotValidException(
- MethodArgumentNotValidException e, HttpServletRequest request) {
+ MethodArgumentNotValidException e, HttpServletRequest request) {
log.warn("[MethodArgumentNotValidException] resource :{} ", e.getMessage());
String codeName = "BAD_REQUEST";
ErrorLogEntity errorLog =
- saveErrorLogData(
- request,
- ApiResponseCode.getCode(codeName),
- HttpStatus.valueOf(codeName),
- ErrorLogDto.LogErrorLevel.WARNING,
- e.getStackTrace());
+ saveErrorLogData(
+ request,
+ ApiResponseCode.getCode(codeName),
+ HttpStatus.valueOf(codeName),
+ ErrorLogDto.LogErrorLevel.WARNING,
+ e.getStackTrace());
return ApiResponseDto.createException(
- ApiResponseCode.getCode(codeName),
- ApiResponseCode.getMessage(codeName),
- HttpStatus.valueOf(codeName),
- errorLog.getId());
+ ApiResponseCode.getCode(codeName),
+ ApiResponseCode.getMessage(codeName),
+ HttpStatus.valueOf(codeName),
+ errorLog.getId());
}
@ResponseStatus(HttpStatus.UNAUTHORIZED)
@ExceptionHandler(AccessDeniedException.class)
public ApiResponseDto handlerAccessDeniedException(
- AccessDeniedException e, HttpServletRequest request) {
+ AccessDeniedException e, HttpServletRequest request) {
log.warn("[AccessDeniedException] resource :{} ", e.getMessage());
String codeName = "UNAUTHORIZED";
ErrorLogEntity errorLog =
- saveErrorLogData(
- request,
- ApiResponseCode.getCode(codeName),
- HttpStatus.valueOf(codeName),
- ErrorLogDto.LogErrorLevel.ERROR,
- e.getStackTrace());
+ saveErrorLogData(
+ request,
+ ApiResponseCode.getCode(codeName),
+ HttpStatus.valueOf(codeName),
+ ErrorLogDto.LogErrorLevel.ERROR,
+ e.getStackTrace());
return ApiResponseDto.createException(
- ApiResponseCode.getCode(codeName),
- ApiResponseCode.getMessage(codeName),
- HttpStatus.valueOf(codeName),
- errorLog.getId());
+ ApiResponseCode.getCode(codeName),
+ ApiResponseCode.getMessage(codeName),
+ HttpStatus.valueOf(codeName),
+ errorLog.getId());
}
-
@ResponseStatus(HttpStatus.BAD_GATEWAY)
@ExceptionHandler(HttpServerErrorException.BadGateway.class)
public ApiResponseDto handlerHttpServerErrorException(
- HttpServerErrorException e, HttpServletRequest request) {
+ HttpServerErrorException e, HttpServletRequest request) {
log.warn("[HttpServerErrorException] resource :{} ", e.getMessage());
String codeName = "BAD_GATEWAY";
ErrorLogEntity errorLog =
- saveErrorLogData(
- request,
- ApiResponseCode.getCode(codeName),
- HttpStatus.valueOf(codeName),
- ErrorLogDto.LogErrorLevel.CRITICAL,
- e.getStackTrace());
+ saveErrorLogData(
+ request,
+ ApiResponseCode.getCode(codeName),
+ HttpStatus.valueOf(codeName),
+ ErrorLogDto.LogErrorLevel.CRITICAL,
+ e.getStackTrace());
return ApiResponseDto.createException(
- ApiResponseCode.getCode(codeName),
- ApiResponseCode.getMessage(codeName),
- HttpStatus.valueOf(codeName),
- errorLog.getId());
+ ApiResponseCode.getCode(codeName),
+ ApiResponseCode.getMessage(codeName),
+ HttpStatus.valueOf(codeName),
+ errorLog.getId());
}
@ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
@ExceptionHandler(IllegalStateException.class)
public ApiResponseDto handlerIllegalStateException(
- IllegalStateException e, HttpServletRequest request) {
+ IllegalStateException e, HttpServletRequest request) {
log.warn("[IllegalStateException] resource :{} ", e.getMessage());
String codeName = "UNPROCESSABLE_ENTITY";
ErrorLogEntity errorLog =
- saveErrorLogData(
- request,
- ApiResponseCode.getCode(codeName),
- HttpStatus.valueOf(codeName),
- ErrorLogDto.LogErrorLevel.WARNING,
- e.getStackTrace());
+ saveErrorLogData(
+ request,
+ ApiResponseCode.getCode(codeName),
+ HttpStatus.valueOf(codeName),
+ ErrorLogDto.LogErrorLevel.WARNING,
+ e.getStackTrace());
return ApiResponseDto.createException(
- ApiResponseCode.getCode(codeName),
- ApiResponseCode.getMessage(codeName),
- HttpStatus.valueOf(codeName),
- errorLog.getId());
+ ApiResponseCode.getCode(codeName),
+ ApiResponseCode.getMessage(codeName),
+ HttpStatus.valueOf(codeName),
+ errorLog.getId());
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MemberException.DuplicateMemberException.class)
public ApiResponseDto handlerDuplicateMemberException(
- MemberException.DuplicateMemberException e, HttpServletRequest request) {
+ MemberException.DuplicateMemberException e, HttpServletRequest request) {
log.warn("[DuplicateMemberException] resource :{} ", e.getMessage());
String codeName = "";
@@ -254,115 +253,112 @@ public class GlobalExceptionHandler {
}
ErrorLogEntity errorLog =
- saveErrorLogData(
- request,
- ApiResponseCode.getCode(codeName),
- HttpStatus.valueOf("BAD_REQUEST"),
- ErrorLogDto.LogErrorLevel.WARNING,
- e.getStackTrace());
+ saveErrorLogData(
+ request,
+ ApiResponseCode.getCode(codeName),
+ HttpStatus.valueOf("BAD_REQUEST"),
+ ErrorLogDto.LogErrorLevel.WARNING,
+ e.getStackTrace());
return ApiResponseDto.createException(
- ApiResponseCode.getCode(codeName),
- ApiResponseCode.getMessage(codeName),
- HttpStatus.valueOf("BAD_REQUEST"),
- errorLog.getId());
+ ApiResponseCode.getCode(codeName),
+ ApiResponseCode.getMessage(codeName),
+ HttpStatus.valueOf("BAD_REQUEST"),
+ errorLog.getId());
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MemberException.MemberNotFoundException.class)
public ApiResponseDto handlerMemberNotFoundException(
- MemberException.MemberNotFoundException e, HttpServletRequest request) {
+ MemberException.MemberNotFoundException e, HttpServletRequest request) {
log.warn("[MemberNotFoundException] resource :{} ", e.getMessage());
String codeName = "NOT_FOUND_USER";
ErrorLogEntity errorLog =
- saveErrorLogData(
- request,
- ApiResponseCode.getCode(codeName),
- HttpStatus.valueOf("BAD_REQUEST"),
- ErrorLogDto.LogErrorLevel.WARNING,
- e.getStackTrace());
+ saveErrorLogData(
+ request,
+ ApiResponseCode.getCode(codeName),
+ HttpStatus.valueOf("BAD_REQUEST"),
+ ErrorLogDto.LogErrorLevel.WARNING,
+ e.getStackTrace());
return ApiResponseDto.createException(
- ApiResponseCode.getCode(codeName),
- ApiResponseCode.getMessage(codeName),
- HttpStatus.valueOf("BAD_REQUEST"),
- errorLog.getId());
+ ApiResponseCode.getCode(codeName),
+ ApiResponseCode.getMessage(codeName),
+ HttpStatus.valueOf("BAD_REQUEST"),
+ errorLog.getId());
}
@ResponseStatus(HttpStatus.CONFLICT)
@ExceptionHandler(DuplicateKeyException.class)
public ApiResponseDto handlerDuplicateKeyException(
- DuplicateKeyException e, HttpServletRequest request) {
+ DuplicateKeyException e, HttpServletRequest request) {
log.warn("[DuplicateKeyException] resource :{} ", e.getMessage());
String codeName = "DUPLICATE_DATA";
ErrorLogEntity errorLog =
- saveErrorLogData(
- request,
- ApiResponseCode.getCode(codeName),
- HttpStatus.valueOf("CONFLICT"),
- ErrorLogDto.LogErrorLevel.WARNING,
- e.getStackTrace());
+ saveErrorLogData(
+ request,
+ ApiResponseCode.getCode(codeName),
+ HttpStatus.valueOf("CONFLICT"),
+ ErrorLogDto.LogErrorLevel.WARNING,
+ e.getStackTrace());
return ApiResponseDto.createException(
- ApiResponseCode.getCode(codeName),
- ApiResponseCode.getMessage(codeName),
- HttpStatus.valueOf("CONFLICT"),
- errorLog.getId());
+ ApiResponseCode.getCode(codeName),
+ ApiResponseCode.getMessage(codeName),
+ HttpStatus.valueOf("CONFLICT"),
+ errorLog.getId());
}
-
@ExceptionHandler(BadCredentialsException.class)
public ResponseEntity> handleBadCredentials(
- BadCredentialsException e, HttpServletRequest request
- ) {
+ BadCredentialsException e, HttpServletRequest request) {
log.warn("[BadCredentialsException] resource : {} ", e.getMessage());
String codeName = "UNAUTHORIZED";
ErrorLogEntity errorLog =
- saveErrorLogData(
- request,
- ApiResponseCode.getCode(codeName),
- HttpStatus.valueOf(codeName),
- ErrorLogDto.LogErrorLevel.WARNING,
- e.getStackTrace());
+ saveErrorLogData(
+ request,
+ ApiResponseCode.getCode(codeName),
+ HttpStatus.valueOf(codeName),
+ ErrorLogDto.LogErrorLevel.WARNING,
+ e.getStackTrace());
ApiResponseDto body =
- ApiResponseDto.createException(
- ApiResponseCode.getCode(codeName),
- ApiResponseCode.getMessage(codeName),
- HttpStatus.valueOf(codeName),
- errorLog.getId());
+ ApiResponseDto.createException(
+ ApiResponseCode.getCode(codeName),
+ ApiResponseCode.getMessage(codeName),
+ HttpStatus.valueOf(codeName),
+ errorLog.getId());
- return ResponseEntity
- .status(HttpStatus.UNAUTHORIZED) // 🔥 여기서 401 지정
- .body(body);
+ return ResponseEntity.status(HttpStatus.UNAUTHORIZED) // 🔥 여기서 401 지정
+ .body(body);
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(RuntimeException.class)
public ApiResponseDto handlerRuntimeException(
- RuntimeException e, HttpServletRequest request) {
+ RuntimeException e, HttpServletRequest request) {
log.warn("[RuntimeException] resource :{} ", e.getMessage());
String codeName = "INTERNAL_SERVER_ERROR";
ErrorLogEntity errorLog =
- saveErrorLogData(
- request,
- ApiResponseCode.getCode(codeName),
- HttpStatus.valueOf(codeName),
- ErrorLogDto.LogErrorLevel.CRITICAL,
- e.getStackTrace());
+ saveErrorLogData(
+ request,
+ ApiResponseCode.getCode(codeName),
+ HttpStatus.valueOf(codeName),
+ ErrorLogDto.LogErrorLevel.CRITICAL,
+ e.getStackTrace());
return ApiResponseDto.createException(
- ApiResponseCode.getCode(codeName),
- ApiResponseCode.getMessage(codeName),
- HttpStatus.valueOf(codeName),
- errorLog.getId());
+ ApiResponseCode.getCode(codeName),
+ ApiResponseCode.getMessage(codeName),
+ HttpStatus.valueOf(codeName),
+ errorLog.getId());
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@@ -372,36 +368,36 @@ public class GlobalExceptionHandler {
String codeName = "INTERNAL_SERVER_ERROR";
ErrorLogEntity errorLog =
- saveErrorLogData(
- request,
- ApiResponseCode.getCode(codeName),
- HttpStatus.valueOf(codeName),
- ErrorLogDto.LogErrorLevel.CRITICAL,
- e.getStackTrace());
+ saveErrorLogData(
+ request,
+ ApiResponseCode.getCode(codeName),
+ HttpStatus.valueOf(codeName),
+ ErrorLogDto.LogErrorLevel.CRITICAL,
+ e.getStackTrace());
return ApiResponseDto.createException(
- ApiResponseCode.getCode(codeName),
- ApiResponseCode.getMessage(codeName),
- HttpStatus.valueOf(codeName),
- errorLog.getId());
+ ApiResponseCode.getCode(codeName),
+ ApiResponseCode.getMessage(codeName),
+ HttpStatus.valueOf(codeName),
+ errorLog.getId());
}
/**
* 에러 로그 테이블 저장 로직
*
- * @param request : request
- * @param errorCode : 정의된 enum errorCode
- * @param httpStatus : HttpStatus 값
+ * @param request : request
+ * @param errorCode : 정의된 enum errorCode
+ * @param httpStatus : HttpStatus 값
* @param logErrorLevel : WARNING, ERROR, CRITICAL
- * @param stackTrace : 에러 내용
+ * @param stackTrace : 에러 내용
* @return : insert하고 결과로 받은 Entity
*/
private ErrorLogEntity saveErrorLogData(
- HttpServletRequest request,
- ApiResponseCode errorCode,
- HttpStatus httpStatus,
- ErrorLogDto.LogErrorLevel logErrorLevel,
- StackTraceElement[] stackTrace) {
+ HttpServletRequest request,
+ ApiResponseCode errorCode,
+ HttpStatus httpStatus,
+ ErrorLogDto.LogErrorLevel logErrorLevel,
+ StackTraceElement[] stackTrace) {
Long userid = null;
@@ -415,35 +411,35 @@ public class GlobalExceptionHandler {
* 만든 CustomUserDetails 타입인가? 체크
*/
if (request.getUserPrincipal() instanceof UsernamePasswordAuthenticationToken auth
- && auth.getPrincipal() instanceof CustomUserDetails customUserDetails) {
+ && auth.getPrincipal() instanceof CustomUserDetails customUserDetails) {
// audit 에는 long 타입 user_id가 들어가지만 토큰 sub은 uuid여서 user_id 가져오기
userid = customUserDetails.getMember().getId();
}
String stackTraceStr =
- Arrays.stream(stackTrace)
- .map(StackTraceElement::toString)
- .collect(Collectors.joining("\n"))
- .substring(0, Math.min(stackTrace.length, 255));
+ Arrays.stream(stackTrace)
+ .map(StackTraceElement::toString)
+ .collect(Collectors.joining("\n"))
+ .substring(0, Math.min(stackTrace.length, 255));
ErrorLogEntity errorLogEntity =
- new ErrorLogEntity(
- request.getRequestURI(),
- ApiLogFunction.getEventType(request),
- logErrorLevel,
- String.valueOf(httpStatus.value()),
- errorCode.getText(),
- stackTraceStr,
- userid,
- ZonedDateTime.now());
+ new ErrorLogEntity(
+ request.getRequestURI(),
+ ApiLogFunction.getEventType(request),
+ logErrorLevel,
+ String.valueOf(httpStatus.value()),
+ errorCode.getText(),
+ stackTraceStr,
+ userid,
+ ZonedDateTime.now());
return errorLogRepository.save(errorLogEntity);
}
@ExceptionHandler(CustomApiException.class)
public ResponseEntity> handleCustomApiException(
- CustomApiException e, HttpServletRequest request) {
+ CustomApiException e, HttpServletRequest request) {
log.warn("[CustomApiException] resource : {}", e.getMessage());
String codeName = e.getCodeName();
@@ -453,11 +449,11 @@ public class GlobalExceptionHandler {
ApiResponseCode apiCode = ApiResponseCode.getCode(codeName);
ErrorLogEntity errorLog =
- saveErrorLogData(
- request, apiCode, status, ErrorLogDto.LogErrorLevel.WARNING, e.getStackTrace());
+ saveErrorLogData(
+ request, apiCode, status, ErrorLogDto.LogErrorLevel.WARNING, e.getStackTrace());
ApiResponseDto body =
- ApiResponseDto.createException(apiCode, message, status, errorLog.getId());
+ ApiResponseDto.createException(apiCode, message, status, errorLog.getId());
return new ResponseEntity<>(body, status);
}
diff --git a/src/main/java/com/kamco/cd/kamcoback/config/RedisConfig.java b/src/main/java/com/kamco/cd/kamcoback/config/RedisConfig.java
index 4f03f569..154f1983 100644
--- a/src/main/java/com/kamco/cd/kamcoback/config/RedisConfig.java
+++ b/src/main/java/com/kamco/cd/kamcoback/config/RedisConfig.java
@@ -7,6 +7,7 @@ import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.time.Duration;
+import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
@@ -81,15 +82,21 @@ public class RedisConfig {
cacheObjectMapper.registerModule(new JavaTimeModule());
cacheObjectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
cacheObjectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+ // 알 수 없는 타입에 대해 더 유연하게 처리
+ cacheObjectMapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
cacheObjectMapper.findAndRegisterModules();
// 타입 정보 포함 - JAVA_LANG_OBJECT로 제한적으로 적용
+ // 호환성 문제 해결을 위해 더 많은 타입 허용
PolymorphicTypeValidator ptv =
BasicPolymorphicTypeValidator.builder()
.allowIfSubType("com.kamco.cd.kamcoback")
.allowIfSubType("org.springframework.data.domain")
.allowIfSubType("java.util")
.allowIfSubType("java.time")
+ .allowIfSubType("java.lang")
+ .allowIfBaseType(List.class)
+ .allowIfBaseType("com.kamco.cd.kamcoback.code.dto.CommonCodeDto$Basic")
.build();
cacheObjectMapper.activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT);
diff --git a/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java b/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java
index f0b5acf9..e6566b46 100644
--- a/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java
+++ b/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java
@@ -29,30 +29,29 @@ public class SecurityConfig {
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.disable()) // CSRF 보안 기능 비활성화
- .sessionManagement(
- sm ->
- sm.sessionCreationPolicy(
- SessionCreationPolicy.STATELESS)) // 서버 세션 만들지 않음, 요청은 JWT 인증
- .formLogin(form -> form.disable()) // react에서 로그인 요청 관리
- .httpBasic(basic -> basic.disable()) // 기본 basic 인증 비활성화 JWT 인증사용
- .logout(logout -> logout.disable()) // 기본 로그아웃 비활성화 JWT는 서버 상태가 없으므로 로그아웃 처리 필요 없음
- .authenticationProvider(
- customAuthenticationProvider) // 로그인 패스워드 비교방식 스프링 기본 Provider 사용안함 커스텀 사용
- .authorizeHttpRequests(
- auth ->
- auth.requestMatchers(
- "/api/auth/signin",
- "/api/auth/refresh",
- "/swagger-ui/**",
- "/v3/api-docs/**")
- .permitAll()
- .anyRequest()
- .authenticated())
- .addFilterBefore(
- jwtAuthenticationFilter,
- UsernamePasswordAuthenticationFilter
- .class) // 요청 들어오면 먼저 JWT 토큰 검사 후 security context 에 사용자 정보 저장.
-
+ .sessionManagement(
+ sm ->
+ sm.sessionCreationPolicy(
+ SessionCreationPolicy.STATELESS)) // 서버 세션 만들지 않음, 요청은 JWT 인증
+ .formLogin(form -> form.disable()) // react에서 로그인 요청 관리
+ .httpBasic(basic -> basic.disable()) // 기본 basic 인증 비활성화 JWT 인증사용
+ .logout(logout -> logout.disable()) // 기본 로그아웃 비활성화 JWT는 서버 상태가 없으므로 로그아웃 처리 필요 없음
+ .authenticationProvider(
+ customAuthenticationProvider) // 로그인 패스워드 비교방식 스프링 기본 Provider 사용안함 커스텀 사용
+ .authorizeHttpRequests(
+ auth ->
+ auth.requestMatchers(
+ "/api/auth/signin",
+ "/api/auth/refresh",
+ "/swagger-ui/**",
+ "/v3/api-docs/**")
+ .permitAll()
+ .anyRequest()
+ .authenticated())
+ .addFilterBefore(
+ jwtAuthenticationFilter,
+ UsernamePasswordAuthenticationFilter
+ .class) // 요청 들어오면 먼저 JWT 토큰 검사 후 security context 에 사용자 정보 저장.
;
return http.build();
@@ -60,7 +59,7 @@ public class SecurityConfig {
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration)
- throws Exception {
+ throws Exception {
return configuration.getAuthenticationManager();
}
diff --git a/src/main/java/com/kamco/cd/kamcoback/config/SwaggerConfig.java b/src/main/java/com/kamco/cd/kamcoback/config/SwaggerConfig.java
index b540c026..8aa6f9bc 100644
--- a/src/main/java/com/kamco/cd/kamcoback/config/SwaggerConfig.java
+++ b/src/main/java/com/kamco/cd/kamcoback/config/SwaggerConfig.java
@@ -6,11 +6,8 @@ import org.springframework.context.annotation.Configuration;
@Configuration
@SecurityScheme(
- name = "BearerAuth",
- type = SecuritySchemeType.HTTP,
- scheme = "bearer",
- bearerFormat = "JWT"
-)
-public class SwaggerConfig {
-
-}
+ name = "BearerAuth",
+ type = SecuritySchemeType.HTTP,
+ scheme = "bearer",
+ bearerFormat = "JWT")
+public class SwaggerConfig {}
diff --git a/src/main/java/com/kamco/cd/kamcoback/config/api/ApiLogFunction.java b/src/main/java/com/kamco/cd/kamcoback/config/api/ApiLogFunction.java
index 67536bdb..e4d6ae41 100644
--- a/src/main/java/com/kamco/cd/kamcoback/config/api/ApiLogFunction.java
+++ b/src/main/java/com/kamco/cd/kamcoback/config/api/ApiLogFunction.java
@@ -64,22 +64,22 @@ public class ApiLogFunction {
}
public static String getRequestBody(
- HttpServletRequest servletRequest, ContentCachingRequestWrapper contentWrapper) {
+ HttpServletRequest servletRequest, ContentCachingRequestWrapper contentWrapper) {
StringBuilder resultBody = new StringBuilder();
// GET, form-urlencoded POST 파라미터
Map paramMap = servletRequest.getParameterMap();
String queryParams =
- paramMap.entrySet().stream()
- .map(e -> e.getKey() + "=" + String.join(",", e.getValue()))
- .collect(Collectors.joining("&"));
+ paramMap.entrySet().stream()
+ .map(e -> e.getKey() + "=" + String.join(",", e.getValue()))
+ .collect(Collectors.joining("&"));
resultBody.append(queryParams.isEmpty() ? "" : queryParams);
// JSON Body
if ("POST".equalsIgnoreCase(servletRequest.getMethod())
- && servletRequest.getContentType() != null
- && servletRequest.getContentType().contains("application/json")) {
+ && servletRequest.getContentType() != null
+ && servletRequest.getContentType().contains("application/json")) {
try {
// json인 경우는 Wrapper를 통해 가져오기
resultBody.append(getBodyData(contentWrapper));
@@ -91,8 +91,8 @@ public class ApiLogFunction {
// Multipart form-data
if ("POST".equalsIgnoreCase(servletRequest.getMethod())
- && servletRequest.getContentType() != null
- && servletRequest.getContentType().startsWith("multipart/form-data")) {
+ && servletRequest.getContentType() != null
+ && servletRequest.getContentType().startsWith("multipart/form-data")) {
resultBody.append("multipart/form-data request");
}
diff --git a/src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseAdvice.java b/src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseAdvice.java
index 8fb6ab3b..70d48e3d 100644
--- a/src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseAdvice.java
+++ b/src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseAdvice.java
@@ -31,19 +31,19 @@ public class ApiResponseAdvice implements ResponseBodyAdvice