diff --git a/.editorconfig b/.editorconfig
index a6d93a81..da27dc81 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,7 +1,7 @@
root = true
[*]
-indent_style = tab
+indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
@@ -9,4 +9,4 @@ trim_trailing_whitespace = true
insert_final_newline = true
[*.java]
-max_line_length = 100
+max_line_length = 180
diff --git a/CODE_STYLE_SETUP.md b/CODE_STYLE_SETUP.md
index 3bfdd0e4..2c07ff5b 100644
--- a/CODE_STYLE_SETUP.md
+++ b/CODE_STYLE_SETUP.md
@@ -4,26 +4,22 @@
## 자동 포맷팅 구성
-### 1. 커밋 시점 자동 체크 (Git Pre-commit Hook)
+### 1. 커밋 시점 자동 포맷팅 (Git Pre-commit Hook)
-커밋 전에 자동으로 코드 스타일을 체크하고, 문제가 있으면 커밋을 막습니다.
+커밋 전에 자동으로 코드를 포맷팅하고 스테이징합니다.
**설정 완료:** `.git/hooks/pre-commit` 파일이 자동으로 실행됩니다.
**동작 방식:**
-- 커밋 시도 시 `./gradlew spotlessCheck` 자동 실행
-- 포맷팅 오류가 있으면 커밋 차단 및 안내 메시지 출력
-- 포맷팅이 올바르면 커밋 허용
+- 커밋 시도 시 `./gradlew spotlessApply` 자동 실행
+- 스테이징된 Java 파일을 자동으로 포맷팅
+- 포맷팅된 파일을 자동으로 다시 스테이징
+- 포맷팅이 완료되면 커밋 진행
-**포맷팅 오류 발생 시:**
-```bash
-# 자동 포맷팅 적용
-./gradlew spotlessApply
-
-# 변경사항 추가 후 다시 커밋
-git add .
-git commit
-```
+**장점:**
+- 수동으로 `spotlessApply`를 실행할 필요 없음
+- 항상 일관된 코드 스타일 유지
+- 포맷팅 누락 방지
### 2. IntelliJ IDEA 저장 시점 자동 포맷팅
@@ -38,6 +34,7 @@ git commit
#### 방법 2: 저장 시 자동 포맷팅 활성화
+
**Option A: Actions on Save 설정**
1. **Settings/Preferences** > **Tools > Actions on Save**
@@ -84,7 +81,7 @@ git commit
프로젝트는 **Google Java Style Guide** 기반으로 다음 규칙을 따릅니다:
- **Indentation**: 2 spaces (탭 아님)
-- **Line Length**: 100 characters
+- **Line Length**: 180 characters
- **Line Endings**: LF (Unix-style)
- **Charset**: UTF-8
- **Import Order**: Static imports → 빈 줄 → Regular imports
@@ -112,4 +109,4 @@ chmod +x .git/hooks/pre-commit
- **Google Java Style Guide**: https://google.github.io/styleguide/javaguide.html
- **Spotless Plugin**: https://github.com/diffplug/spotless
-- **IntelliJ Code Style**: https://www.jetbrains.com/help/idea/code-style.html
\ No newline at end of file
+- **IntelliJ Code Style**: https://www.jetbrains.com/help/idea/code-style.html
diff --git a/README.md b/README.md
index 9b560246..5878b610 100644
--- a/README.md
+++ b/README.md
@@ -193,10 +193,6 @@ kamco-back/
│ │ │ │ └── StartupLogger.java # 시작 로그
│ │ │ ├── common/ # 공통 유틸리티
│ │ │ │ └── utils/geometry/ # GeoJSON 직렬화
-│ │ │ ├── domain/ # 도메인 엔티티 (예정)
-│ │ │ ├── repository/ # 리포지토리 (예정)
-│ │ │ ├── service/ # 비즈니스 로직 (예정)
-│ │ │ └── controller/ # REST 컨트롤러 (예정)
│ │ └── resources/
│ │ ├── application.yml # 기본 설정 + local/prod
│ │ └── application-dev.yml # 개발 환경 설정
diff --git a/intellij-java-google-style.xml b/intellij-java-google-style.xml
index f3a6743e..d63d7310 100644
--- a/intellij-java-google-style.xml
+++ b/intellij-java-google-style.xml
@@ -25,7 +25,7 @@
-
+
diff --git a/settings.gradle b/settings.gradle
index 51bf7bfb..d4e5fa60 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1 +1,6 @@
+pluginManagement {
+ plugins {
+ id 'org.jetbrains.kotlin.jvm' version '2.2.20'
+ }
+}
rootProject.name = 'kamco-back'
diff --git a/src/main/java/com/kamco/cd/kamcoback/KamcoBackApplication.java b/src/main/java/com/kamco/cd/kamcoback/KamcoBackApplication.java
index 7a54c513..6ac3c950 100644
--- a/src/main/java/com/kamco/cd/kamcoback/KamcoBackApplication.java
+++ b/src/main/java/com/kamco/cd/kamcoback/KamcoBackApplication.java
@@ -6,8 +6,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class KamcoBackApplication {
- public static void main(String[] args) {
- SpringApplication.run(KamcoBackApplication.class, args);
- }
-
+ public static void main(String[] args) {
+ SpringApplication.run(KamcoBackApplication.class, args);
+ }
}
diff --git a/src/main/java/com/kamco/cd/kamcoback/common/api/HelloApiController.java b/src/main/java/com/kamco/cd/kamcoback/common/api/HelloApiController.java
index bd41dc49..2553dfec 100644
--- a/src/main/java/com/kamco/cd/kamcoback/common/api/HelloApiController.java
+++ b/src/main/java/com/kamco/cd/kamcoback/common/api/HelloApiController.java
@@ -1,4 +1,25 @@
package com.kamco.cd.kamcoback.common.api;
+import com.kamco.cd.kamcoback.common.api.HelloDto.Res;
+import com.kamco.cd.kamcoback.common.service.HelloService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/api/hello")
public class HelloApiController {
+
+ private final HelloService helloService;
+
+ @GetMapping
+ public HelloDto.Res hello(HelloDto.Req req) {
+ req.valid();
+
+ Res res = helloService.sayHello(req);
+
+ return res;
+ }
}
diff --git a/src/main/java/com/kamco/cd/kamcoback/common/api/HelloDto.java b/src/main/java/com/kamco/cd/kamcoback/common/api/HelloDto.java
index 963b385e..58375271 100644
--- a/src/main/java/com/kamco/cd/kamcoback/common/api/HelloDto.java
+++ b/src/main/java/com/kamco/cd/kamcoback/common/api/HelloDto.java
@@ -1,9 +1,36 @@
package com.kamco.cd.kamcoback.common.api;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
public class HelloDto {
- public static class Req{
- private String id;
- }
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class Req {
+ private String id;
+ public void valid() {
+ if (id == null) {
+ throw new IllegalArgumentException(id);
+ }
+ }
+ }
+
+ @Getter
+ public static class Res {
+ private String id;
+ private String name;
+
+ @Builder
+ public Res(String id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+ }
}
diff --git a/src/main/java/com/kamco/cd/kamcoback/common/service/BaseCoreService.java b/src/main/java/com/kamco/cd/kamcoback/common/service/BaseCoreService.java
new file mode 100644
index 00000000..cc583e5a
--- /dev/null
+++ b/src/main/java/com/kamco/cd/kamcoback/common/service/BaseCoreService.java
@@ -0,0 +1,38 @@
+package com.kamco.cd.kamcoback.common.service;
+
+import org.springframework.data.domain.Page;
+
+/**
+ * Base Core Service Interface
+ *
+ *
CRUD operations를 정의하는 기본 서비스 인터페이스
+ *
+ * @param Entity 타입
+ * @param Entity의 ID 타입
+ * @param Search Request 타입
+ */
+public interface BaseCoreService {
+
+ /**
+ * ID로 엔티티를 삭제합니다.
+ *
+ * @param id 삭제할 엔티티의 ID
+ */
+ void remove(ID id);
+
+ /**
+ * ID로 단건 조회합니다.
+ *
+ * @param id 조회할 엔티티의 ID
+ * @return 조회된 엔티티
+ */
+ T getOneById(ID id);
+
+ /**
+ * 검색 조건과 페이징으로 조회합니다.
+ *
+ * @param searchReq 검색 조건
+ * @return 페이징 처리된 검색 결과
+ */
+ Page search(S searchReq);
+}
diff --git a/src/main/java/com/kamco/cd/kamcoback/common/service/HelloService.java b/src/main/java/com/kamco/cd/kamcoback/common/service/HelloService.java
index c0520578..e7b0ce3e 100644
--- a/src/main/java/com/kamco/cd/kamcoback/common/service/HelloService.java
+++ b/src/main/java/com/kamco/cd/kamcoback/common/service/HelloService.java
@@ -1,4 +1,17 @@
package com.kamco.cd.kamcoback.common.service;
+import com.kamco.cd.kamcoback.common.api.HelloDto;
+import java.util.UUID;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
public class HelloService {
+
+ public HelloDto.Res sayHello(HelloDto.Req req) {
+ log.info("hello");
+ String name = UUID.randomUUID().toString();
+ return HelloDto.Res.builder().id(req.getId()).name(name).build();
+ }
}
diff --git a/src/main/java/com/kamco/cd/kamcoback/common/utils/geometry/GeometryDeserializer.java b/src/main/java/com/kamco/cd/kamcoback/common/utils/geometry/GeometryDeserializer.java
index f6eecdb2..aa536dd9 100644
--- a/src/main/java/com/kamco/cd/kamcoback/common/utils/geometry/GeometryDeserializer.java
+++ b/src/main/java/com/kamco/cd/kamcoback/common/utils/geometry/GeometryDeserializer.java
@@ -4,12 +4,11 @@ import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+import java.io.IOException;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.geojson.GeoJsonReader;
import org.springframework.util.StringUtils;
-import java.io.IOException;
-
public class GeometryDeserializer extends StdDeserializer {
public GeometryDeserializer(Class targetType) {
@@ -20,7 +19,7 @@ public class GeometryDeserializer extends StdDeserializer
@SuppressWarnings("unchecked")
@Override
public T deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
- throws IOException, JacksonException {
+ throws IOException, JacksonException {
String json = jsonParser.readValueAsTree().toString();
if (!StringUtils.hasText(json)) {
diff --git a/src/main/java/com/kamco/cd/kamcoback/common/utils/geometry/GeometrySerializer.java b/src/main/java/com/kamco/cd/kamcoback/common/utils/geometry/GeometrySerializer.java
index b5433da6..50b7abb3 100644
--- a/src/main/java/com/kamco/cd/kamcoback/common/utils/geometry/GeometrySerializer.java
+++ b/src/main/java/com/kamco/cd/kamcoback/common/utils/geometry/GeometrySerializer.java
@@ -3,11 +3,10 @@ package com.kamco.cd.kamcoback.common.utils.geometry;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
-import org.locationtech.jts.geom.Geometry;
-import org.locationtech.jts.io.geojson.GeoJsonWriter;
-
import java.io.IOException;
import java.util.Objects;
+import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.io.geojson.GeoJsonWriter;
public class GeometrySerializer extends StdSerializer {
@@ -17,8 +16,9 @@ public class GeometrySerializer extends StdSerializer {
}
@Override
- public void serialize(T geometry, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
- throws IOException {
+ public void serialize(
+ T geometry, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
+ throws IOException {
if (Objects.nonNull(geometry)) {
// default: 8자리 강제로 반올림시킴. 16자리로 늘려줌
GeoJsonWriter writer = new GeoJsonWriter(16);
diff --git a/src/main/java/com/kamco/cd/kamcoback/config/StartupLogger.java b/src/main/java/com/kamco/cd/kamcoback/config/StartupLogger.java
index 1de2b594..178f5201 100644
--- a/src/main/java/com/kamco/cd/kamcoback/config/StartupLogger.java
+++ b/src/main/java/com/kamco/cd/kamcoback/config/StartupLogger.java
@@ -1,6 +1,5 @@
package com.kamco.cd.kamcoback.config;
-
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
import lombok.RequiredArgsConstructor;
@@ -15,85 +14,85 @@ import org.springframework.stereotype.Component;
@RequiredArgsConstructor
public class StartupLogger {
- private final Environment environment;
- private final DataSource dataSource;
+ private final Environment environment;
+ private final DataSource dataSource;
- @EventListener(ApplicationReadyEvent.class)
- public void logStartupInfo() {
- String[] activeProfiles = environment.getActiveProfiles();
- String profileInfo =
- activeProfiles.length > 0 ? String.join(", ", activeProfiles) : "default";
+ @EventListener(ApplicationReadyEvent.class)
+ public void logStartupInfo() {
+ String[] activeProfiles = environment.getActiveProfiles();
+ String profileInfo =
+ activeProfiles.length > 0 ? String.join(", ", activeProfiles) : "default";
- // Database connection information
- String dbUrl = environment.getProperty("spring.datasource.url");
- String dbUsername = environment.getProperty("spring.datasource.username");
- String dbDriver = environment.getProperty("spring.datasource.driver-class-name");
+ // Database connection information
+ String dbUrl = environment.getProperty("spring.datasource.url");
+ String dbUsername = environment.getProperty("spring.datasource.username");
+ String dbDriver = environment.getProperty("spring.datasource.driver-class-name");
- // HikariCP pool settings
- String poolInfo = "";
- if (dataSource instanceof HikariDataSource hikariDs) {
- poolInfo =
- String.format(
- """
- │ Pool Size : min=%d, max=%d
- │ Connection Timeout: %dms
- │ Idle Timeout : %dms
- │ Max Lifetime : %dms""",
- hikariDs.getMinimumIdle(),
- hikariDs.getMaximumPoolSize(),
- hikariDs.getConnectionTimeout(),
- hikariDs.getIdleTimeout(),
- hikariDs.getMaxLifetime());
- }
+ // HikariCP pool settings
+ String poolInfo = "";
+ if (dataSource instanceof HikariDataSource hikariDs) {
+ poolInfo =
+ String.format(
+ """
+ │ Pool Size : min=%d, max=%d
+ │ Connection Timeout: %dms
+ │ Idle Timeout : %dms
+ │ Max Lifetime : %dms""",
+ hikariDs.getMinimumIdle(),
+ hikariDs.getMaximumPoolSize(),
+ hikariDs.getConnectionTimeout(),
+ hikariDs.getIdleTimeout(),
+ hikariDs.getMaxLifetime());
+ }
- // JPA/Hibernate settings
- String showSql = environment.getProperty("spring.jpa.show-sql", "false");
- String ddlAuto = environment.getProperty("spring.jpa.hibernate.ddl-auto", "none");
- String batchSize =
- environment.getProperty("spring.jpa.properties.hibernate.jdbc.batch_size", "N/A");
- String batchFetchSize =
- environment.getProperty(
- "spring.jpa.properties.hibernate.default_batch_fetch_size", "N/A");
+ // JPA/Hibernate settings
+ String showSql = environment.getProperty("spring.jpa.show-sql", "false");
+ String ddlAuto = environment.getProperty("spring.jpa.hibernate.ddl-auto", "none");
+ String batchSize =
+ environment.getProperty("spring.jpa.properties.hibernate.jdbc.batch_size", "N/A");
+ String batchFetchSize =
+ environment.getProperty(
+ "spring.jpa.properties.hibernate.default_batch_fetch_size", "N/A");
- String startupMessage =
- String.format(
- """
+ String startupMessage =
+ String.format(
+ """
- ╔════════════════════════════════════════════════════════════════════════════════╗
- ║ 🚀 APPLICATION STARTUP INFORMATION ║
- ╠════════════════════════════════════════════════════════════════════════════════╣
- ║ PROFILE CONFIGURATION ║
- ╠────────────────────────────────────────────────────────────────────────────────╣
- │ Active Profile(s): %s
- ╠════════════════════════════════════════════════════════════════════════════════╣
- ║ DATABASE CONFIGURATION ║
- ╠────────────────────────────────────────────────────────────────────────────────╣
- │ Database URL : %s
- │ Username : %s
- │ Driver : %s
- ╠════════════════════════════════════════════════════════════════════════════════╣
- ║ HIKARICP CONNECTION POOL ║
- ╠────────────────────────────────────────────────────────────────────────────────╣
- %s
- ╠════════════════════════════════════════════════════════════════════════════════╣
- ║ JPA/HIBERNATE CONFIGURATION ║
- ╠────────────────────────────────────────────────────────────────────────────────╣
- │ Show SQL : %s
- │ DDL Auto : %s
- │ JDBC Batch Size : %s
- │ Fetch Batch Size : %s
- ╚════════════════════════════════════════════════════════════════════════════════╝
- """,
- profileInfo,
- dbUrl != null ? dbUrl : "N/A",
- dbUsername != null ? dbUsername : "N/A",
- dbDriver != null ? dbDriver : "PostgreSQL JDBC Driver (auto-detected)",
- poolInfo,
- showSql,
- ddlAuto,
- batchSize,
- batchFetchSize);
+ ╔════════════════════════════════════════════════════════════════════════════════╗
+ ║ 🚀 APPLICATION STARTUP INFORMATION ║
+ ╠════════════════════════════════════════════════════════════════════════════════╣
+ ║ PROFILE CONFIGURATION ║
+ ╠────────────────────────────────────────────────────────────────────────────────╣
+ │ Active Profile(s): %s
+ ╠════════════════════════════════════════════════════════════════════════════════╣
+ ║ DATABASE CONFIGURATION ║
+ ╠────────────────────────────────────────────────────────────────────────────────╣
+ │ Database URL : %s
+ │ Username : %s
+ │ Driver : %s
+ ╠════════════════════════════════════════════════════════════════════════════════╣
+ ║ HIKARICP CONNECTION POOL ║
+ ╠────────────────────────────────────────────────────────────────────────────────╣
+ %s
+ ╠════════════════════════════════════════════════════════════════════════════════╣
+ ║ JPA/HIBERNATE CONFIGURATION ║
+ ╠────────────────────────────────────────────────────────────────────────────────╣
+ │ Show SQL : %s
+ │ DDL Auto : %s
+ │ JDBC Batch Size : %s
+ │ Fetch Batch Size : %s
+ ╚════════════════════════════════════════════════════════════════════════════════╝
+ """,
+ profileInfo,
+ dbUrl != null ? dbUrl : "N/A",
+ dbUsername != null ? dbUsername : "N/A",
+ dbDriver != null ? dbDriver : "PostgreSQL JDBC Driver (auto-detected)",
+ poolInfo,
+ showSql,
+ ddlAuto,
+ batchSize,
+ batchFetchSize);
- log.info(startupMessage);
- }
+ log.info(startupMessage);
+ }
}
diff --git a/src/main/java/com/kamco/cd/kamcoback/config/WebConfig.java b/src/main/java/com/kamco/cd/kamcoback/config/WebConfig.java
index 6671faba..f20fd274 100644
--- a/src/main/java/com/kamco/cd/kamcoback/config/WebConfig.java
+++ b/src/main/java/com/kamco/cd/kamcoback/config/WebConfig.java
@@ -26,8 +26,6 @@ public class WebConfig {
module.addSerializer(Point.class, new GeometrySerializer<>(Point.class));
module.addDeserializer(Point.class, new GeometryDeserializer<>(Point.class));
- return Jackson2ObjectMapperBuilder.json()
- .modulesToInstall(module)
- .build();
+ return Jackson2ObjectMapperBuilder.json().modulesToInstall(module).build();
}
}
diff --git a/src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseDto.java b/src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseDto.java
index 4e586ac4..49f7e413 100644
--- a/src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseDto.java
+++ b/src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseDto.java
@@ -1,4 +1,120 @@
package com.kamco.cd.kamcoback.config.api;
-public class ApiResponseDto {
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.kamco.cd.kamcoback.config.enums.EnumType;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;
+
+@Getter
+@ToString
+public class ApiResponseDto {
+
+ private T data;
+
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ private Error error;
+
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ private T errorData;
+
+ public ApiResponseDto(T data) {
+ this.data = data;
+ }
+
+ public ApiResponseDto(ApiResponseCode code) {
+ this.error = new Error(code.getId(), code.getMessage());
+ }
+
+ public ApiResponseDto(ApiResponseCode code, String message) {
+ this.error = new Error(code.getId(), message);
+ }
+
+ public ApiResponseDto(ApiResponseCode code, String message, T errorData) {
+ this.error = new Error(code.getId(), message);
+ this.errorData = errorData;
+ }
+
+ public static ApiResponseDto createOK(T data) {
+ return new ApiResponseDto<>(data);
+ }
+
+ public static ApiResponseDto createException(ApiResponseCode code) {
+ return new ApiResponseDto<>(code);
+ }
+
+ public static ApiResponseDto createException(ApiResponseCode code, String message) {
+ return new ApiResponseDto<>(code, message);
+ }
+
+ public static ApiResponseDto createException(
+ ApiResponseCode code, String message, T data) {
+ return new ApiResponseDto<>(code, message, data);
+ }
+
+ @Getter
+ public static class Error {
+
+ private final String code;
+ private final String message;
+
+ public Error(String code, String message) {
+ this.code = code;
+ this.message = message;
+ }
+ }
+
+ @Getter
+ @RequiredArgsConstructor
+ public enum ApiResponseCode implements EnumType {
+
+ // @formatter:off
+ OK("요청이 성공하였습니다."),
+ BAD_REQUEST("요청 파라미터가 잘못되었습니다."),
+ ALREADY_EXIST_MALL("이미 등록된 쇼핑센터입니다."),
+ NOT_FOUND_MAP("지도를 찾을 수 없습니다."),
+ UNAUTHORIZED("권한이 없습니다."),
+ CONFLICT("이미 등록된 컨텐츠입니다."),
+ NOT_FOUND("Resource를 찾을 수 없습니다."),
+ NOT_FOUND_DATA("데이터를 찾을 수 없습니다."),
+ NOT_FOUND_WEATHER_DATA("날씨 데이터를 찾을 수 없습니다."),
+ FAIL_SEND_MESSAGE("메시지를 전송하지 못했습니다."),
+ TOO_MANY_CONNECTED_MACHINES("연결된 기기가 너무 많습니다."),
+ UNAUTHENTICATED("인증에 실패하였습니다."),
+ INVALID_TOKEN("잘못된 토큰입니다."),
+ EXPIRED_TOKEN("만료된 토큰입니다."),
+ INTERNAL_SERVER_ERROR("서버에 문제가 발생 하였습니다."),
+ FORBIDDEN("권한을 확인해주세요."),
+ INVALID_PASSWORD("잘못된 비밀번호 입니다."),
+ NOT_FOUND_CAR_IN("입차정보가 없습니다."),
+ WRONG_STATUS("잘못된 상태입니다."),
+ FAIL_VERIFICATION("인증에 실패하였습니다."),
+ INVALID_EMAIL("잘못된 형식의 이메일입니다."),
+ REQUIRED_EMAIL("이메일은 필수 항목입니다."),
+ WRONG_PASSWORD("잘못된 패스워드입니다.."),
+ DUPLICATE_EMAIL("이미 가입된 이메일입니다."),
+ DUPLICATE_DATA("이미 등록되여 있습니다."),
+ DATA_INTEGRITY_ERROR("요청을 처리할수 없습니다."),
+ FOREIGN_KEY_ERROR("참조 중인 데이터가 있어 삭제할 수 없습니다."),
+ DUPLICATE_EMPLOYEEID("이미 가입된 사번입니다."),
+ NOT_FOUND_USER_FOR_EMAIL("이메일로 유저를 찾을 수 없습니다."),
+ NOT_FOUND_USER("사용자를 찾을 수 없습니다."),
+ INVALID_EMAIL_TOKEN(
+ "You can only reset your password within 24 hours from when the email was sent.\n"
+ + "To reset your password again, please submit a new request through \"Forgot"
+ + " Password.\""),
+ ;
+ // @formatter:on
+ private final String message;
+
+ @Override
+ public String getId() {
+ return name();
+ }
+
+ @Override
+ public String getText() {
+ return message;
+ }
+ }
}
diff --git a/src/main/java/com/kamco/cd/kamcoback/config/enums/EnumType.java b/src/main/java/com/kamco/cd/kamcoback/config/enums/EnumType.java
index c8c94836..7531f0ff 100644
--- a/src/main/java/com/kamco/cd/kamcoback/config/enums/EnumType.java
+++ b/src/main/java/com/kamco/cd/kamcoback/config/enums/EnumType.java
@@ -1,4 +1,8 @@
-package com.kamco.cd.kamcoback.config.api;
+package com.kamco.cd.kamcoback.config.enums;
public interface EnumType {
+
+ String getId();
+
+ String getText();
}
diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/CommonDateEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/CommonDateEntity.java
new file mode 100644
index 00000000..b2914860
--- /dev/null
+++ b/src/main/java/com/kamco/cd/kamcoback/postgres/CommonDateEntity.java
@@ -0,0 +1,34 @@
+package com.kamco.cd.kamcoback.postgres;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.MappedSuperclass;
+import jakarta.persistence.PrePersist;
+import jakarta.persistence.PreUpdate;
+import java.time.ZonedDateTime;
+import lombok.Getter;
+import org.springframework.data.annotation.CreatedDate;
+import org.springframework.data.annotation.LastModifiedDate;
+
+@Getter
+@MappedSuperclass
+public class CommonDateEntity {
+
+ @CreatedDate
+ @Column(name = "created_date", updatable = false, nullable = false)
+ private ZonedDateTime createdDate;
+
+ @LastModifiedDate
+ @Column(name = "modified_date", nullable = false)
+ private ZonedDateTime modifiedDate;
+
+ @PrePersist
+ protected void onPersist() {
+ this.createdDate = ZonedDateTime.now();
+ this.modifiedDate = ZonedDateTime.now();
+ }
+
+ @PreUpdate
+ protected void onUpdate() {
+ this.modifiedDate = ZonedDateTime.now();
+ }
+}
diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/QueryDslConfig.java b/src/main/java/com/kamco/cd/kamcoback/postgres/QueryDslConfig.java
new file mode 100644
index 00000000..6212f6e3
--- /dev/null
+++ b/src/main/java/com/kamco/cd/kamcoback/postgres/QueryDslConfig.java
@@ -0,0 +1,19 @@
+package com.kamco.cd.kamcoback.postgres;
+
+import com.querydsl.jpa.impl.JPAQueryFactory;
+import jakarta.persistence.EntityManager;
+import lombok.RequiredArgsConstructor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@RequiredArgsConstructor
+@Configuration
+public class QueryDslConfig {
+
+ private final EntityManager entityManager;
+
+ @Bean
+ public JPAQueryFactory jpaQueryFactory() {
+ return new JPAQueryFactory(entityManager);
+ }
+}
diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/AnimalCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/AnimalCoreService.java
new file mode 100644
index 00000000..b6f74997
--- /dev/null
+++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/AnimalCoreService.java
@@ -0,0 +1,68 @@
+package com.kamco.cd.kamcoback.postgres.core;
+
+import com.kamco.cd.kamcoback.common.service.BaseCoreService;
+import com.kamco.cd.kamcoback.postgres.entity.AnimalEntity;
+import com.kamco.cd.kamcoback.postgres.repository.AnimalRepository;
+import com.kamco.cd.kamcoback.zoo.dto.AnimalDto;
+import jakarta.persistence.EntityNotFoundException;
+import lombok.RequiredArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+@RequiredArgsConstructor
+@Transactional(readOnly = true)
+public class AnimalCoreService
+ implements BaseCoreService {
+
+ private final AnimalRepository animalRepository;
+
+ @Transactional(readOnly = true)
+ public AnimalDto.Basic getDataByUuid(String uuid) {
+ AnimalEntity getZoo =
+ animalRepository
+ .getAnimalByUuid(uuid)
+ .orElseThrow(
+ () ->
+ new EntityNotFoundException(
+ "Zoo not found with uuid: " + uuid));
+ return getZoo.toDto();
+ }
+
+ // AddReq를 받는 추가 메서드
+ @Transactional
+ public AnimalDto.Basic create(AnimalDto.AddReq req) {
+ AnimalEntity entity = new AnimalEntity(req.getCategory(), req.getSpecies(), req.getName());
+ AnimalEntity saved = animalRepository.save(entity);
+ return saved.toDto();
+ }
+
+ @Override
+ @Transactional
+ public void remove(Long id) {
+ AnimalEntity getZoo =
+ animalRepository
+ .getAnimalByUid(id)
+ .orElseThrow(
+ () -> new EntityNotFoundException("Zoo not found with id: " + id));
+ getZoo.deleted();
+ }
+
+ @Override
+ public AnimalDto.Basic getOneById(Long id) {
+ AnimalEntity getZoo =
+ animalRepository
+ .getAnimalByUid(id)
+ .orElseThrow(
+ () -> new EntityNotFoundException("Zoo not found with id: " + id));
+ return getZoo.toDto();
+ }
+
+ @Override
+ public Page search(AnimalDto.SearchReq searchReq) {
+
+ Page zooEntities = animalRepository.listAnimal(searchReq);
+ return zooEntities.map(AnimalEntity::toDto);
+ }
+}
diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/AnimalEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/AnimalEntity.java
new file mode 100644
index 00000000..71c58fda
--- /dev/null
+++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/AnimalEntity.java
@@ -0,0 +1,67 @@
+package com.kamco.cd.kamcoback.postgres.entity;
+
+import com.kamco.cd.kamcoback.postgres.CommonDateEntity;
+import com.kamco.cd.kamcoback.zoo.dto.AnimalDto;
+import com.kamco.cd.kamcoback.zoo.dto.AnimalDto.Category;
+import com.kamco.cd.kamcoback.zoo.dto.AnimalDto.Species;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import java.util.UUID;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+// 기본구조 관련
+
+@Entity
+@Getter
+@NoArgsConstructor(access = AccessLevel.PROTECTED)
+@Table(name = "tb_animal")
+public class AnimalEntity extends CommonDateEntity {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long uid;
+
+ @Column(unique = true)
+ private UUID uuid;
+
+ @Enumerated(EnumType.STRING)
+ private Category category;
+
+ @Enumerated(EnumType.STRING)
+ private Species species;
+
+ private String name;
+ private Boolean isDeleted;
+
+ // Construct
+ public AnimalEntity(Category category, Species species, String name) {
+ this.uuid = UUID.randomUUID();
+ this.category = category;
+ this.species = species;
+ this.name = name;
+ this.isDeleted = false;
+ }
+
+ public AnimalDto.Basic toDto() {
+ return new AnimalDto.Basic(
+ this.uid,
+ this.uuid.toString(),
+ this.name,
+ this.category,
+ this.species,
+ super.getCreatedDate(),
+ super.getModifiedDate());
+ }
+
+ public void deleted() {
+ this.isDeleted = true;
+ }
+}
diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/AnimalRepository.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/AnimalRepository.java
new file mode 100644
index 00000000..cf78ffdb
--- /dev/null
+++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/AnimalRepository.java
@@ -0,0 +1,7 @@
+package com.kamco.cd.kamcoback.postgres.repository;
+
+import com.kamco.cd.kamcoback.postgres.entity.AnimalEntity;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface AnimalRepository
+ extends JpaRepository, AnimalRepositoryCustom {}
diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/AnimalRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/AnimalRepositoryCustom.java
new file mode 100644
index 00000000..79a39a27
--- /dev/null
+++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/AnimalRepositoryCustom.java
@@ -0,0 +1,15 @@
+package com.kamco.cd.kamcoback.postgres.repository;
+
+import com.kamco.cd.kamcoback.postgres.entity.AnimalEntity;
+import com.kamco.cd.kamcoback.zoo.dto.AnimalDto;
+import java.util.Optional;
+import org.springframework.data.domain.Page;
+
+public interface AnimalRepositoryCustom {
+
+ Optional getAnimalByUid(Long uid);
+
+ Optional getAnimalByUuid(String uuid);
+
+ Page listAnimal(AnimalDto.SearchReq req);
+}
diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/AnimalRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/AnimalRepositoryImpl.java
new file mode 100644
index 00000000..d54e26fd
--- /dev/null
+++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/AnimalRepositoryImpl.java
@@ -0,0 +1,99 @@
+package com.kamco.cd.kamcoback.postgres.repository;
+
+import com.kamco.cd.kamcoback.postgres.entity.AnimalEntity;
+import com.kamco.cd.kamcoback.postgres.entity.QAnimalEntity;
+import com.kamco.cd.kamcoback.zoo.dto.AnimalDto;
+import com.kamco.cd.kamcoback.zoo.dto.AnimalDto.Category;
+import com.kamco.cd.kamcoback.zoo.dto.AnimalDto.Species;
+import com.querydsl.core.types.dsl.BooleanExpression;
+import com.querydsl.jpa.impl.JPAQueryFactory;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport;
+
+public class AnimalRepositoryImpl extends QuerydslRepositorySupport
+ implements AnimalRepositoryCustom {
+
+ private final JPAQueryFactory queryFactory;
+
+ public AnimalRepositoryImpl(JPAQueryFactory queryFactory) {
+ super(AnimalEntity.class);
+ this.queryFactory = queryFactory;
+ }
+
+ public Optional getAnimalByUid(Long uid) {
+ QAnimalEntity animal = QAnimalEntity.animalEntity;
+
+ return Optional.ofNullable(
+ queryFactory.selectFrom(animal).where(animal.uid.eq(uid)).fetchFirst());
+ }
+
+ public Optional getAnimalByUuid(String uuid) {
+ QAnimalEntity animal = QAnimalEntity.animalEntity;
+
+ return Optional.ofNullable(
+ queryFactory
+ .selectFrom(animal)
+ .where(animal.uuid.eq(UUID.fromString(uuid)))
+ .fetchFirst());
+ }
+
+ @Override
+ public Page listAnimal(AnimalDto.SearchReq req) {
+ QAnimalEntity animal = QAnimalEntity.animalEntity;
+
+ Pageable pageable = req.toPageable();
+
+ List content =
+ queryFactory
+ .selectFrom(animal)
+ .where(
+ animal.isDeleted.eq(false),
+ eqCategory(animal, req.getCategory()),
+ eqSpecies(animal, req.getSpecies()),
+ likeName(animal, req.getName()))
+ .offset(pageable.getOffset())
+ .limit(pageable.getPageSize())
+ .orderBy(animal.createdDate.desc())
+ .fetch();
+
+ // count 쿼리
+ Long total =
+ queryFactory
+ .select(animal.count())
+ .from(animal)
+ .where(
+ animal.isDeleted.eq(false),
+ eqCategory(animal, req.getCategory()),
+ eqSpecies(animal, req.getSpecies()),
+ likeName(animal, req.getName()))
+ .fetchOne();
+
+ return new PageImpl<>(content, pageable, total);
+ }
+
+ private BooleanExpression likeName(QAnimalEntity animal, String nameStr) {
+ if (nameStr == null || nameStr.isEmpty()) {
+ return null;
+ }
+ return animal.name.containsIgnoreCase(nameStr.trim());
+ }
+
+ private BooleanExpression eqCategory(QAnimalEntity animal, Category category) {
+ if (category == null) {
+ return null;
+ }
+ return animal.category.eq(category);
+ }
+
+ private BooleanExpression eqSpecies(QAnimalEntity animal, Species species) {
+ if (species == null) {
+ return null;
+ }
+ return animal.species.eq(species);
+ }
+}
diff --git a/src/main/java/com/kamco/cd/kamcoback/zoo/AnimalApiController.java b/src/main/java/com/kamco/cd/kamcoback/zoo/AnimalApiController.java
new file mode 100644
index 00000000..87a0c2bc
--- /dev/null
+++ b/src/main/java/com/kamco/cd/kamcoback/zoo/AnimalApiController.java
@@ -0,0 +1,82 @@
+package com.kamco.cd.kamcoback.zoo;
+
+import com.kamco.cd.kamcoback.zoo.dto.AnimalDto;
+import com.kamco.cd.kamcoback.zoo.dto.AnimalDto.Category;
+import com.kamco.cd.kamcoback.zoo.dto.AnimalDto.Species;
+import com.kamco.cd.kamcoback.zoo.service.AnimalService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+@RequiredArgsConstructor
+@RestController
+@RequestMapping({"/api/animals", "/v1/api/animals"})
+public class AnimalApiController {
+
+ private final AnimalService animalService;
+
+ /**
+ * 동물 생성
+ *
+ * @param req 동물 생성 요청
+ * @return 생성된 동물 정보
+ */
+ @PostMapping
+ public ResponseEntity createAnimal(@RequestBody AnimalDto.AddReq req) {
+ AnimalDto.Basic created = animalService.createAnimal(req);
+ return ResponseEntity.status(HttpStatus.CREATED).body(created);
+ }
+
+ /**
+ * UUID로 동물 조회
+ *
+ * @param uuid 동물 UUID
+ * @return 동물 정보
+ */
+ @GetMapping("/{uuid}")
+ public ResponseEntity getAnimal(@PathVariable String uuid) {
+ Long id = animalService.getAnimalByUuid(uuid);
+ AnimalDto.Basic animal = animalService.getAnimal(id);
+ return ResponseEntity.ok(animal);
+ }
+
+ /**
+ * UUID로 동물 삭제 (논리 삭제)
+ *
+ * @param uuid 동물 UUID
+ * @return 삭제 성공 메시지
+ */
+ @DeleteMapping("/{uuid}")
+ public ResponseEntity deleteAnimal(@PathVariable String uuid) {
+ Long id = animalService.getAnimalByUuid(uuid);
+ animalService.deleteZoo(id);
+ return ResponseEntity.noContent().build();
+ }
+
+ /**
+ * 동물 검색 (페이징)
+ *
+ * @param name 동물 이름 (선택)
+ * @param category 서식지 타입 (선택)
+ * @param species 동물종 (선택) 개, 고양이등.
+ * @param page 페이지 번호 (기본값: 0)
+ * @param size 페이지 크기 (기본값: 20)
+ * @param sort 정렬 조건 (예: "name,asc")
+ * @return 페이징 처리된 동물 목록
+ */
+ @GetMapping
+ public ResponseEntity> searchAnimals(
+ @RequestParam(required = false) String name,
+ @RequestParam(required = false) Category category,
+ @RequestParam(required = false) Species species,
+ @RequestParam(defaultValue = "0") int page,
+ @RequestParam(defaultValue = "20") int size,
+ @RequestParam(required = false) String sort) {
+ AnimalDto.SearchReq searchReq =
+ new AnimalDto.SearchReq(name, category, species, page, size, sort);
+ Page animals = animalService.search(searchReq);
+ return ResponseEntity.ok(animals);
+ }
+}
diff --git a/src/main/java/com/kamco/cd/kamcoback/zoo/dto/AnimalDto.java b/src/main/java/com/kamco/cd/kamcoback/zoo/dto/AnimalDto.java
new file mode 100644
index 00000000..79dcf7bb
--- /dev/null
+++ b/src/main/java/com/kamco/cd/kamcoback/zoo/dto/AnimalDto.java
@@ -0,0 +1,129 @@
+package com.kamco.cd.kamcoback.zoo.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.kamco.cd.kamcoback.config.enums.EnumType;
+import java.time.ZonedDateTime;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+
+public class AnimalDto {
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class AddReq {
+
+ private Category category;
+ private Species species;
+ private String name;
+ }
+
+ @Getter
+ public static class Basic {
+
+ @JsonIgnore private Long id;
+ private String uuid;
+ private Category category;
+ private Species species;
+ private String name;
+
+ @JsonFormat(
+ shape = JsonFormat.Shape.STRING,
+ pattern = "yyyy-MM-dd'T'HH:mm:ssXXX",
+ timezone = "Asia/Seoul")
+ private ZonedDateTime createdDate;
+
+ @JsonFormat(
+ shape = JsonFormat.Shape.STRING,
+ pattern = "yyyy-MM-dd'T'HH:mm:ssXXX",
+ timezone = "Asia/Seoul")
+ private ZonedDateTime modifiedDate;
+
+ public Basic(
+ Long id,
+ String uuid,
+ String name,
+ Category category,
+ Species species,
+ ZonedDateTime createdDate,
+ ZonedDateTime modifiedDate) {
+ this.id = id;
+ this.uuid = uuid;
+ this.name = name;
+ this.category = category;
+ this.species = species;
+ this.createdDate = createdDate;
+ this.modifiedDate = modifiedDate;
+ }
+ }
+
+ @Getter
+ @AllArgsConstructor
+ public enum Category implements EnumType {
+ // @formatter:off
+ MAMMALS("100", "포유류"), // 땅에 사는 동물
+ BIRDS("200", "조류"), // 하늘을 나는 동물
+ FISH("300", "어류"),
+ AMPHIBIANS("400", "양서류"),
+ REPTILES("500", "파충류"),
+ INSECTS("500", "곤충"),
+ INVERTEBRATES("500", "무척추동물"),
+ ;
+ // @formatter:on
+ private final String id;
+ private final String text;
+ }
+
+ @Getter
+ @AllArgsConstructor
+ public enum Species implements EnumType {
+ // @formatter:off
+ DOG("101", "개"),
+ CAT("102", "강아지"),
+ DOVE("201", "비둘기"),
+ EAGLE("202", "독수리"),
+ SALMON("301", "연어"),
+ TUNA("302", "참치"),
+ ;
+ // @formatter:on
+ private final String id;
+ private final String text;
+ }
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class SearchReq {
+
+ // 검색 조건
+ private String name;
+ private Category category;
+ private Species species;
+
+ // 페이징 파라미터
+ private int page = 0;
+ private int size = 20;
+ private String sort;
+
+ public Pageable toPageable() {
+ if (sort != null && !sort.isEmpty()) {
+ String[] sortParams = sort.split(",");
+ String property = sortParams[0];
+ Sort.Direction direction =
+ sortParams.length > 1
+ ? Sort.Direction.fromString(sortParams[1])
+ : Sort.Direction.ASC;
+ return PageRequest.of(page, size, Sort.by(direction, property));
+ }
+ return PageRequest.of(page, size);
+ }
+ }
+}
diff --git a/src/main/java/com/kamco/cd/kamcoback/zoo/service/AnimalService.java b/src/main/java/com/kamco/cd/kamcoback/zoo/service/AnimalService.java
new file mode 100644
index 00000000..a4fdaaff
--- /dev/null
+++ b/src/main/java/com/kamco/cd/kamcoback/zoo/service/AnimalService.java
@@ -0,0 +1,61 @@
+package com.kamco.cd.kamcoback.zoo.service;
+
+import com.kamco.cd.kamcoback.postgres.core.AnimalCoreService;
+import com.kamco.cd.kamcoback.zoo.dto.AnimalDto;
+import lombok.RequiredArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@RequiredArgsConstructor
+@Service
+@Transactional(readOnly = true)
+public class AnimalService {
+ private final AnimalCoreService zooCoreService;
+
+ // 동물의 UUID로 id조회
+ public Long getAnimalByUuid(String uuid) {
+ return zooCoreService.getDataByUuid(uuid).getId();
+ }
+
+ /**
+ * 동물 생성
+ *
+ * @param req 동물 생성 요청
+ * @return 생성된 동물 정보
+ */
+ @Transactional
+ public AnimalDto.Basic createAnimal(AnimalDto.AddReq req) {
+ return zooCoreService.create(req);
+ }
+
+ /**
+ * 동물 삭제 (논리 삭제)
+ *
+ * @param id 동물 ID
+ */
+ @Transactional
+ public void deleteZoo(Long id) {
+ zooCoreService.remove(id);
+ }
+
+ /**
+ * 동물 단건 조회
+ *
+ * @param id 동물 ID
+ * @return 동물 정보
+ */
+ public AnimalDto.Basic getAnimal(Long id) {
+ return zooCoreService.getOneById(id);
+ }
+
+ /**
+ * 동물 검색 (페이징)
+ *
+ * @param searchReq 검색 조건
+ * @return 페이징 처리된 동물 목록
+ */
+ public Page search(AnimalDto.SearchReq searchReq) {
+ return zooCoreService.search(searchReq);
+ }
+}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 5546dc61..8d388d31 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -23,3 +23,5 @@ spring:
maximum-pool-size: 20
+
+
diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml
index 8979d647..09108754 100644
--- a/src/main/resources/application-local.yml
+++ b/src/main/resources/application-local.yml
@@ -15,11 +15,10 @@ spring:
format_sql: true # ⚠️ 선택 - SQL 포맷팅 (가독성)
datasource:
- url: jdbc:postgresql://10.100.0.10:25432/temp
- username: temp
- password: temp123!
+ url: jdbc:postgresql://192.168.2.127:15432/kamco_cds
+ username: kamco_cds
+ password: kamco_cds_Q!W@E#R$
hikari:
minimum-idle: 1
maximum-pool-size: 5
-
diff --git a/src/test/java/com/kamco/cd/kamcoback/KamcoBackApplicationTests.java b/src/test/java/com/kamco/cd/kamcoback/KamcoBackApplicationTests.java
index 54c6c482..c3272fb3 100644
--- a/src/test/java/com/kamco/cd/kamcoback/KamcoBackApplicationTests.java
+++ b/src/test/java/com/kamco/cd/kamcoback/KamcoBackApplicationTests.java
@@ -6,8 +6,6 @@ import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class KamcoBackApplicationTests {
- @Test
- void contextLoads() {
- }
-
+ @Test
+ void contextLoads() {}
}