From e72c5347a1e6637afcb3f5bc8eacf90b609b52a3 Mon Sep 17 00:00:00 2001 From: hykim02 Date: Mon, 24 Mar 2025 17:46:42 +0900 Subject: [PATCH 1/8] =?UTF-8?q?[Fix]Test=20=EC=BD=94=EB=93=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cafeteria/CafeteriaServiceV2Test.java | 47 +----- .../cafeteria/CampusServiceV2Test.java | 15 +- .../service/notice/CategoryServiceV2Test.java | 51 +++++++ .../notice/NoticeCategoryServiceV2Test.java | 40 ----- .../service/notice/NoticeServiceV2Test.java | 139 ++++++++++++++++++ .../userInfo/DepartmentServiceV2Test.java | 10 +- .../service/userInfo/UserServiceV2Test.java | 33 +---- 7 files changed, 203 insertions(+), 132 deletions(-) create mode 100644 src/test/java/com/example/Jinus/service/notice/CategoryServiceV2Test.java delete mode 100644 src/test/java/com/example/Jinus/service/notice/NoticeCategoryServiceV2Test.java create mode 100644 src/test/java/com/example/Jinus/service/notice/NoticeServiceV2Test.java diff --git a/src/test/java/com/example/Jinus/service/cafeteria/CafeteriaServiceV2Test.java b/src/test/java/com/example/Jinus/service/cafeteria/CafeteriaServiceV2Test.java index be6ba52..2a57bbd 100644 --- a/src/test/java/com/example/Jinus/service/cafeteria/CafeteriaServiceV2Test.java +++ b/src/test/java/com/example/Jinus/service/cafeteria/CafeteriaServiceV2Test.java @@ -8,6 +8,8 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.beans.factory.annotation.Autowired; @@ -25,16 +27,11 @@ import static org.springframework.test.web.client.ExpectedCount.times; @ExtendWith(MockitoExtension.class) -@SpringBootTest public class CafeteriaServiceV2Test { - @Autowired - private CafeteriaServiceV2 cafeteriaServiceV2; - @Autowired - private RedisTemplate redisTemplate; - @Autowired + @InjectMocks private CacheServiceV2 cacheServiceV2; - @MockBean + @Mock private CafeteriaRepositoryV2 cafeteriaRepositoryV2; @Test @@ -54,40 +51,4 @@ public void checkUserCafeteriaList() { // then assertThat(result).usingRecursiveComparison().isEqualTo(resultList); } - -// @Test -// @DisplayName("campusId, cafeteriaName을 키값으로 캐싱하여 cafeteriaId 값을 찾는다.") -// public void checkCacheData() { -// // given -// int campusId = 1; -// String cafeteriaName = "교직원식당"; -// int expectedCafeteriaId = 4; -// String expectedCacheKey = "cafeteridId::" + campusId + "::" + cafeteriaName; // 캐싱 키 예상값 -// -// // Mock 설정: DB 조회 시 특정 값 반환하도록 설정 -// Mockito.when(cafeteriaRepositoryV2.findCafeteriaId(cafeteriaName, campusId)).thenReturn(Optional.of(expectedCafeteriaId)); -// -// // when: 첫 번째 호출 (DB 조회 발생 후 Redis에 캐싱됨) -// int cafeteriaId = cafeteriaServiceV2.getCafeteriaId(cafeteriaName, campusId); -// -// // then: DB에서 가져온 값이 기대한 값과 같은지 확인 -// assertThat(cafeteriaId).isEqualTo(expectedCafeteriaId); -// -// // Redis에서 직접 키 조회하여 확인 -// ValueOperations valueOps = redisTemplate.opsForValue(); -// String cachedValue = valueOps.get(expectedCacheKey); -// -// assertThat(cachedValue).isNotNull(); // 캐시가 존재해야 함 -// assertThat(Integer.parseInt(cachedValue)).isEqualTo(expectedCafeteriaId); // 저장된 값이 예상한 값과 같은지 확인 -// -// // 캐시가 적용되었는지 검증: 두 번째 호출에서는 DB 조회가 발생하면 안 됨 -// int cachedCafeteriaId = cafeteriaServiceV2.getCafeteriaId(cafeteriaName, campusId); -// -// // 두 번째 호출은 캐시에서 가져와야 하므로 DB 호출이 한 번만 발생해야 함 -// verify(cafeteriaRepositoryV2, Mockito.times(1)).findCafeteriaId(cafeteriaName, campusId); -// -// // 캐시된 값과 두 번째 조회한 값이 같은지 확인 -// assertThat(cachedCafeteriaId).isEqualTo(expectedCafeteriaId); -// -// } } diff --git a/src/test/java/com/example/Jinus/service/cafeteria/CampusServiceV2Test.java b/src/test/java/com/example/Jinus/service/cafeteria/CampusServiceV2Test.java index 698e134..1ca2b10 100644 --- a/src/test/java/com/example/Jinus/service/cafeteria/CampusServiceV2Test.java +++ b/src/test/java/com/example/Jinus/service/cafeteria/CampusServiceV2Test.java @@ -2,33 +2,26 @@ import com.example.Jinus.entity.cafeteria.CampusEntity; import com.example.Jinus.repository.v2.cafeteria.CampusRepositoryV2; -import com.example.Jinus.repository.v2.userInfo.UserRepositoryV2; import com.example.Jinus.service.v2.cafeteria.CampusServiceV2; -import com.example.Jinus.service.v2.userInfo.UserServiceV2; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.context.ActiveProfiles; import java.util.ArrayList; import java.util.List; -import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; @ExtendWith(MockitoExtension.class) -@SpringBootTest public class CampusServiceV2Test { - @Autowired + @InjectMocks private CampusServiceV2 campusServiceV2; - @MockBean + @Mock private CampusRepositoryV2 campusRepositoryV2; @Test diff --git a/src/test/java/com/example/Jinus/service/notice/CategoryServiceV2Test.java b/src/test/java/com/example/Jinus/service/notice/CategoryServiceV2Test.java new file mode 100644 index 0000000..67117b5 --- /dev/null +++ b/src/test/java/com/example/Jinus/service/notice/CategoryServiceV2Test.java @@ -0,0 +1,51 @@ +package com.example.Jinus.service.notice; + +import com.example.Jinus.entity.notice.NoticeCategoryEntity; +import com.example.Jinus.repository.v2.notice.CategoryRepositoryV2; +import com.example.Jinus.service.v2.notice.CategoryServiceV2; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + + +@ExtendWith(MockitoExtension.class) +public class CategoryServiceV2Test { + + @Mock + private CategoryRepositoryV2 noticeCategoryRepository; + @InjectMocks + private CategoryServiceV2 categoryService; + + @Test + @DisplayName("사용자 학과id와 일치하는 카테고리 찾기") + void checkGetCategoryEntityTest() { + // Given - 테스트 데이터 생성 + int departmentId = 1; + List expectedCategories = List.of( + new NoticeCategoryEntity(1, 1, "공지사항", 0, 0, 0, null), + new NoticeCategoryEntity(2, 1, "학사일정", 0, 0, 0, null) + ); + + // Mocking - 목 객체의 동작 정의 + when(noticeCategoryRepository.findCategoryListByDepartmentId(departmentId)) + .thenReturn(expectedCategories); + + // When - 서비스 호출 + List result = categoryService.getCategoryEntity(departmentId); + + // Then - 결과 검증 + assertEquals(expectedCategories.size(), result.size()); // 2개의 카테고리 반환해야 함 + assertEquals(expectedCategories, result); + // 서비스 메소드 중복 호출 방지를 위한 호출 횟수 확인 + verify(noticeCategoryRepository, times(1)) + .findCategoryListByDepartmentId(departmentId); + } +} diff --git a/src/test/java/com/example/Jinus/service/notice/NoticeCategoryServiceV2Test.java b/src/test/java/com/example/Jinus/service/notice/NoticeCategoryServiceV2Test.java deleted file mode 100644 index e6b1163..0000000 --- a/src/test/java/com/example/Jinus/service/notice/NoticeCategoryServiceV2Test.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.example.Jinus.service.notice; - -import com.example.Jinus.repository.v2.notice.CategoryRepositoryV2; -import com.example.Jinus.service.v2.notice.CategoryServiceV2; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; - -import static org.assertj.core.api.Assertions.assertThat; - - -@SpringBootTest -@ExtendWith(MockitoExtension.class) - -public class NoticeCategoryServiceV2Test { - - @Autowired - CategoryServiceV2 categoryService; - @MockBean - CategoryRepositoryV2 noticeCategoryRepository; - -// @Test -// @DisplayName("사용자 학과id와 일치하는 카테고리 찾기") -// public void checkCategoryByDepartmentId() { -// // given -// int departmentId = 1; -// List categoryList = new ArrayList<>(); -// categoryList.add(new NoticeCategoryEntity(1, 1, "취업", 12, 12, 12, "3/4")); -// categoryList.add(new NoticeCategoryEntity(2, 1, "공지", 12, 12, 12, "3/4")); -// -// // when -// Mockito.when(noticeCategoryRepository.findCategoryListByDepartmentId(departmentId)).thenReturn(categoryList); -// List> result = categoryService.getCategoryEntity(departmentId); -// -// // then -// assertThat(result).usingRecursiveComparison().isEqualTo(categoryList); -// } -} diff --git a/src/test/java/com/example/Jinus/service/notice/NoticeServiceV2Test.java b/src/test/java/com/example/Jinus/service/notice/NoticeServiceV2Test.java new file mode 100644 index 0000000..4bbdf53 --- /dev/null +++ b/src/test/java/com/example/Jinus/service/notice/NoticeServiceV2Test.java @@ -0,0 +1,139 @@ +package com.example.Jinus.service.notice; + +import com.example.Jinus.dto.response.ListItemDto; +import com.example.Jinus.entity.notice.NoticeCategoryEntity; +import com.example.Jinus.entity.notice.NoticeEntity; +import com.example.Jinus.repository.v2.notice.NoticeRepositoryV2; +import com.example.Jinus.service.v2.notice.CategoryServiceV2; +import com.example.Jinus.service.v2.notice.NoticeServiceV2; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class NoticeServiceV2Test { + + @InjectMocks + private NoticeServiceV2 noticeServiceV2; + @Mock + private CategoryServiceV2 categoryServiceV2; + @Mock + private NoticeRepositoryV2 noticeRepositoryV2; + + private List mockCategoryEntities; + private List mockNoticeEntities; + + @BeforeEach + void setUp() { + // 공지 카테고리 엔티티 Mock 데이터 생성 + mockCategoryEntities = new ArrayList<>(); + NoticeCategoryEntity category = new NoticeCategoryEntity(); + category.setId(1); + category.setMi(123); + category.setBbsId(456); + category.setCategory("학과공지"); + mockCategoryEntities.add(category); + + // 공지 엔티티 Mock 데이터 생성 + mockNoticeEntities = new ArrayList<>(); + NoticeEntity notice = new NoticeEntity(); + notice.setTitle("시험 일정 공지"); + notice.setCreatedAt("2025-03-24"); + notice.setNttSn(1001); + mockNoticeEntities.add(notice); + } + + @Test + @DisplayName("학과정보 존재하는 경우 공지리스트 반환") + void checkExistUserReturnNotice() { + // given + String departmentEng = "computer"; + int departmentId = 1; + + when(categoryServiceV2.getCategoryEntity(departmentId)).thenReturn(mockCategoryEntities); + when(noticeRepositoryV2.findNoticeListByCategoryId(1)).thenReturn(mockNoticeEntities); + + // when + String result = noticeServiceV2.existUserReturnNotice(departmentEng, departmentId); + + // then + assertNotNull(result); + assertTrue(result.contains("학과공지")); // JSON 결과에 "학과공지" 포함 확인 + verify(categoryServiceV2, times(1)).getCategoryEntity(departmentId); + } + + @Test + @DisplayName("공지가 존재하지 않는 경우") + void checkThereIsNoNoticeData() { + // given + String departmentEng = "computer"; + int departmentId = 1; + + when(categoryServiceV2.getCategoryEntity(departmentId)).thenReturn(new ArrayList<>()); + + // when + String result = noticeServiceV2.existUserReturnNotice(departmentEng, departmentId); + + // then + assertNotNull(result); + assertTrue(result.contains("최근에 등록된 공지사항이 없어!")); + } + + @Test + @DisplayName("학과 정보가 없어서 학과 등록 블록 반환") + void checkDoesNotExistUserReturnBlock() { + // when + String result = noticeServiceV2.doesNotExistUserReturnBlock(); + + // then + assertNotNull(result); + assertTrue(result.contains("학과 등록")); + assertTrue(result.contains("66cf0c8ae5715f75b254dfea")); // 블록 ID 포함 여부 확인 + } + + @Test + @DisplayName("공지 가져오기") + void checkGetNoticeList() { + // given + int categoryId = 1; + String departmentEng = "computer"; + String mi = "123"; + String bbsId = "456"; + + when(noticeRepositoryV2.findNoticeListByCategoryId(categoryId)).thenReturn(mockNoticeEntities); + + // when + List result = noticeServiceV2.getNoticeList(categoryId, mi, bbsId, departmentEng); + + // then + assertNotNull(result); + assertEquals(1, result.size()); + assertEquals("시험 일정 공지", result.getFirst().getTitle()); + } + + @Test + @DisplayName("url 생성 테스트") + void checkNoticeDetailUrl() { + // given + String departmentEng = "computer"; + String mi = "123"; + String bbsId = "456"; + int nttSn = 1001; + + // when + String url = noticeServiceV2.noticeDetailUrl(departmentEng, mi, bbsId, nttSn); + + // then + assertEquals("https://www.gnu.ac.kr/computer/na/ntt/selectNttInfo.do?mi=123&bbsId=456&nttSn=1001", url); + } +} diff --git a/src/test/java/com/example/Jinus/service/userInfo/DepartmentServiceV2Test.java b/src/test/java/com/example/Jinus/service/userInfo/DepartmentServiceV2Test.java index 0c12791..feaa043 100644 --- a/src/test/java/com/example/Jinus/service/userInfo/DepartmentServiceV2Test.java +++ b/src/test/java/com/example/Jinus/service/userInfo/DepartmentServiceV2Test.java @@ -5,20 +5,18 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; import static org.assertj.core.api.Assertions.assertThat; @ExtendWith(MockitoExtension.class) -@SpringBootTest public class DepartmentServiceV2Test { - @Autowired + @InjectMocks private DepartmentServiceV2 departmentServiceV2; - @MockBean + @Mock private DepartmentRepositoryV2 departmentRepositoryV2; @Test diff --git a/src/test/java/com/example/Jinus/service/userInfo/UserServiceV2Test.java b/src/test/java/com/example/Jinus/service/userInfo/UserServiceV2Test.java index a2bf5b4..7d323d1 100644 --- a/src/test/java/com/example/Jinus/service/userInfo/UserServiceV2Test.java +++ b/src/test/java/com/example/Jinus/service/userInfo/UserServiceV2Test.java @@ -9,25 +9,17 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.context.ActiveProfiles; import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.times; @ExtendWith(MockitoExtension.class) -@SpringBootTest public class UserServiceV2Test { - @Autowired @InjectMocks private UserServiceV2 userServiceV2; - @MockBean + @Mock private UserRepositoryV2 userRepositoryV2; @Test @@ -87,27 +79,4 @@ public void checkDoesNotExistUserDepartmentId() { // then assertThat(result).isEqualTo(-1); } - - - @Test - @DisplayName("사용자 학과 ID 캐싱 테스트") - public void testUserCampusIdCaching() { - // Given: 특정 userId에 대해 학과 ID 반환 - String userId = "user123"; - int campusId = 12; - - Mockito.when(userRepositoryV2.findCampusIdById(userId)) - .thenReturn(Optional.of(campusId)); - - // When: 첫 번째 조회 (DB에서 가져옴) - int firstCall = userServiceV2.getUserCampusId(userId); - int secondCall = userServiceV2.getUserCampusId(userId); // 캐시에서 가져와야 함 - - // Then: 두 번째 호출 시 DB 호출 없이 동일한 값이 반환되어야 함 - assertThat(firstCall).isEqualTo(12); // - assertThat(secondCall).isEqualTo(firstCall); - - // Verify: 한 번만 호출되어야 함 - Mockito.verify(userRepositoryV2, times(1)).findCampusIdById(userId); - } } From b91f4a74b3a4594281af97fe89bee86973928c13 Mon Sep 17 00:00:00 2001 From: hykim02 Date: Thu, 27 Mar 2025 16:31:01 +0900 Subject: [PATCH 2/8] =?UTF-8?q?[Refactor]CafeteriaServiceV2=20=EB=8B=A8?= =?UTF-8?q?=EC=9D=BC=20=EC=B1=85=EC=9E=84=20=EC=9B=90=EC=B9=99=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EC=97=AC=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/v2/CafeteriaControllerV2.java | 4 +- .../v2/cafeteria/CafeteriaQueryServiceV2.java | 23 +++ .../cafeteria/CafeteriaResponseServiceV2.java | 52 ++++++ .../v2/cafeteria/CafeteriaServiceV2.java | 163 +++++++++--------- .../service/v2/cafeteria/DietServiceV2.java | 6 +- 5 files changed, 166 insertions(+), 82 deletions(-) create mode 100644 src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaQueryServiceV2.java create mode 100644 src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaResponseServiceV2.java diff --git a/src/main/java/com/example/Jinus/controller/v2/CafeteriaControllerV2.java b/src/main/java/com/example/Jinus/controller/v2/CafeteriaControllerV2.java index cdd7280..822dad3 100644 --- a/src/main/java/com/example/Jinus/controller/v2/CafeteriaControllerV2.java +++ b/src/main/java/com/example/Jinus/controller/v2/CafeteriaControllerV2.java @@ -22,10 +22,10 @@ public class CafeteriaControllerV2 { public String responseCafeteriaOrCampusListCard(@RequestBody RequestDto requestDto) { // userId로 campusId 찾기 String userId = requestDto.getUserRequest().getUser().getId(); - int campusId = userServiceV2.getUserCampusId(userId); + int userCampusId = userServiceV2.getUserCampusId(userId); int sysCampusId = requestDto.getAction().getClientExtra().getSys_campus_id(); - return cafeteriaServiceV2.campusOrCafeteria(campusId, sysCampusId); + return cafeteriaServiceV2.campusOrCafeteria(userCampusId, sysCampusId); } } diff --git a/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaQueryServiceV2.java b/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaQueryServiceV2.java new file mode 100644 index 0000000..bed0a39 --- /dev/null +++ b/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaQueryServiceV2.java @@ -0,0 +1,23 @@ +package com.example.Jinus.service.v2.cafeteria; + +import com.example.Jinus.repository.v2.cafeteria.CafeteriaRepositoryV2; +import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class CafeteriaQueryServiceV2 { + private final CafeteriaRepositoryV2 cafeteriaRepositoryV2; + + @Cacheable(value = "cafeteriaId", key = "#campusId + '::' + #cafeteriaName", + unless = "#result == -1", + cacheManager = "contentCacheManager") + public int getCafeteriaId(String cafeteriaName, int campusId) { + return cafeteriaRepositoryV2.findCafeteriaId(cafeteriaName, campusId).orElse(-1); + } + + public String getImgUrl(int cafeteriaId) { + return cafeteriaRepositoryV2.findImgUrlByCafeteriaId(cafeteriaId); + } +} diff --git a/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaResponseServiceV2.java b/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaResponseServiceV2.java new file mode 100644 index 0000000..22bdb5c --- /dev/null +++ b/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaResponseServiceV2.java @@ -0,0 +1,52 @@ +package com.example.Jinus.service.v2.cafeteria; + +import com.example.Jinus.dto.data.CafeteriaDto; +import com.example.Jinus.dto.response.ButtonDto; +import com.example.Jinus.dto.response.ListItemDto; +import com.example.Jinus.dto.response.ResponseDto; +import com.example.Jinus.utility.JsonUtils; +import com.example.Jinus.utility.ListCardResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +@RequiredArgsConstructor +public class CafeteriaResponseServiceV2 { + + // 식당 리스트 카드 생성 + public String createCafeteriaListCard(String campusName, List cafeteriaList) { + List listItems = mappingCafeteriaList(campusName, cafeteriaList); + ResponseDto responseDto = ListCardResponse.mappingResponseDto( + "어떤 교내 식당 정보가 알고 싶어?", listItems, mappingButtonDto() + ); + return JsonUtils.toJsonResponse(responseDto); + } + + // 식당 아이템 객체 생성 + private List mappingCafeteriaList(String campusName, List cafeteriaList) { + List listItems = new ArrayList<>(); + for (CafeteriaDto cafeteria : cafeteriaList) { + String userMessage = campusName + " " + cafeteria.getCafeteriaNameKo(); + ListItemDto listItem = new ListItemDto( + cafeteria.getCafeteriaNameKo(), campusName, + cafeteria.getThumbnailUrl(), "message", userMessage + ); + listItems.add(listItem); + } + return listItems; + } + + // 더보기 버튼 생성 + private List mappingButtonDto() { + List buttonDto = new ArrayList<>(); + Map extra = new HashMap<>(); + extra.put("sys_campus_id", -1); + buttonDto.add(new ButtonDto("더보기", "block", "66067167cdd882158c759fc2", extra)); + return buttonDto; + } +} diff --git a/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaServiceV2.java b/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaServiceV2.java index 1a88646..7776dda 100644 --- a/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaServiceV2.java +++ b/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaServiceV2.java @@ -1,102 +1,111 @@ package com.example.Jinus.service.v2.cafeteria; import com.example.Jinus.dto.data.CafeteriaDto; -import com.example.Jinus.dto.response.ButtonDto; -import com.example.Jinus.dto.response.ListItemDto; -import com.example.Jinus.dto.response.ResponseDto; -import com.example.Jinus.repository.v2.cafeteria.CafeteriaRepositoryV2; -import com.example.Jinus.utility.JsonUtils; -import com.example.Jinus.utility.ListCardResponse; import lombok.RequiredArgsConstructor; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; @Service @RequiredArgsConstructor public class CafeteriaServiceV2 { - private final CafeteriaRepositoryV2 cafeteriaRepositoryV2; private final CampusServiceV2 campusServiceV2; private final CacheServiceV2 cacheServiceV2; + private final CafeteriaResponseServiceV2 cafeteriaResponseServiceV2; - - // 반환 조건 설정 - public String campusOrCafeteria(int campusId, int sysCampusId) { - // 더보기 버튼 누른 경우 - if (sysCampusId == -1) { + // 사용자가 선택한 블록 ID값에 따라 반환 조건 설정 + // campusId가 -1이면 사용자 정보가 존재하지 않는 경우임 + public String campusOrCafeteria(int userCampusId, int sysCampusId) { + if (sysCampusId == -1) { // 더보기 버튼 누른 경우 -> 캠퍼스 리스트 반환 return campusServiceV2.makeCampusListCard(); } - - // 사용자가 원하는 캠퍼스가 있을 때 - if (sysCampusId > 0) { - return makeCafeteriaListCard(sysCampusId); - } - - // 사용자가 원하는 캠퍼스가 없을 때 - return (campusId != -1) // 사용자 존재 여부 - ? makeCafeteriaListCard(campusId) - : campusServiceV2.makeCampusListCard(); + // 사용자가 캠퍼스를 선택한 경우 + int targetCampusId = (sysCampusId > 0) ? sysCampusId : userCampusId; + return (targetCampusId != -1) // 사용자 정보 DB 존재 여부 + ? returnCafeteriaListCard(targetCampusId) // 존재 O -> 식당 정보 반환 + : campusServiceV2.makeCampusListCard(); // 존재 X -> 캠퍼스 정보 반환 } - // 식당 리스트 반환 메소드 - private String makeCafeteriaListCard(int campusId) { + // 식당 리스트 반환 + private String returnCafeteriaListCard(int campusId) { String campusName = campusServiceV2.getUserCampusName(campusId); List cafeteriaList = cacheServiceV2.getCafeteriaList(campusId); - - // 식당 리스트 객체 생성 - List listItems = mappingCafeteriaList(campusName, cafeteriaList); - // response 객체 생성 - ResponseDto responseDto = ListCardResponse.mappingResponseDto("어떤 교내 식당 정보가 알고싶어 ?", listItems, mappingButtonDto()); - - return JsonUtils.toJsonResponse(responseDto); + return cafeteriaResponseServiceV2.createCafeteriaListCard(campusName, cafeteriaList); } - // 식당 리스트 객체 생성 - private List mappingCafeteriaList(String campusName, List cafeteriaList) { - List listItems = new ArrayList<>(); - for (CafeteriaDto cafeteria : cafeteriaList) { - String userMessage = campusName + " " + cafeteria.getCafeteriaNameKo(); - - // 리스트 아이템 객체 생성 - ListItemDto listItem = new ListItemDto(cafeteria.getCafeteriaNameKo(), campusName, - cafeteria.getThumbnailUrl(), "message", userMessage); - listItems.add(listItem); - } - return listItems; - } - - - // 더보기 버튼 리스트 생성 - private List mappingButtonDto() { - List buttonDto = new ArrayList<>(); - Map extra = new HashMap<>(); - extra.put("sys_campus_id", -1); - // 버튼 객체 생성 - ButtonDto button = new ButtonDto("더보기", "block", "66067167cdd882158c759fc2", extra); - buttonDto.add(button); - return buttonDto; - } - - - - @Cacheable(value = "cafeteriaId", key = "#campusId + '::' + #cafeteriaName", - unless = "#result == -1", - cacheManager = "contentCacheManager") - // 캠퍼스에 식당이 존재한다면 cafeteriaId 찾기 - public int getCafeteriaId(String cafeteriaName, int campusId) { - return cafeteriaRepositoryV2.findCafeteriaId(cafeteriaName, campusId).orElse(-1); - } - - - // 식당 imgUrl 찾기 - public String getImgUrl(int cafeteriaId) { - return cafeteriaRepositoryV2.findImgUrlByCafeteriaId(cafeteriaId); - } +// // 반환 조건 설정 +// public String campusOrCafeteria(int campusId, int sysCampusId) { +// // 더보기 버튼 누른 경우 +// if (sysCampusId == -1) { +// return campusServiceV2.makeCampusListCard(); +// } +// +// // 사용자가 원하는 캠퍼스가 있을 때 +// if (sysCampusId > 0) { +// return makeCafeteriaListCard(sysCampusId); +// } +// +// // 사용자가 원하는 캠퍼스가 없을 때 +// return (campusId != -1) // 사용자 존재 여부 +// ? makeCafeteriaListCard(campusId) +// : campusServiceV2.makeCampusListCard(); +// } +// +// // 식당 리스트 반환 메소드 +// private String makeCafeteriaListCard(int campusId) { +// String campusName = campusServiceV2.getUserCampusName(campusId); +// List cafeteriaList = cacheServiceV2.getCafeteriaList(campusId); +// +// // 식당 리스트 객체 생성 +// List listItems = mappingCafeteriaList(campusName, cafeteriaList); +// // response 객체 생성 +// ResponseDto responseDto = ListCardResponse.mappingResponseDto("어떤 교내 식당 정보가 알고싶어 ?", listItems, mappingButtonDto()); +// +// return JsonUtils.toJsonResponse(responseDto); +// } +// +// +// // 식당 리스트 객체 생성 +// private List mappingCafeteriaList(String campusName, List cafeteriaList) { +// List listItems = new ArrayList<>(); +// for (CafeteriaDto cafeteria : cafeteriaList) { +// String userMessage = campusName + " " + cafeteria.getCafeteriaNameKo(); +// +// // 리스트 아이템 객체 생성 +// ListItemDto listItem = new ListItemDto(cafeteria.getCafeteriaNameKo(), campusName, +// cafeteria.getThumbnailUrl(), "message", userMessage); +// listItems.add(listItem); +// } +// return listItems; +// } +// +// +// // 더보기 버튼 리스트 생성 +// private List mappingButtonDto() { +// List buttonDto = new ArrayList<>(); +// Map extra = new HashMap<>(); +// extra.put("sys_campus_id", -1); +// // 버튼 객체 생성 +// ButtonDto button = new ButtonDto("더보기", "block", "66067167cdd882158c759fc2", extra); +// buttonDto.add(button); +// return buttonDto; +// } +// +// +// +// @Cacheable(value = "cafeteriaId", key = "#campusId + '::' + #cafeteriaName", +// unless = "#result == -1", +// cacheManager = "contentCacheManager") +// // 캠퍼스에 식당이 존재한다면 cafeteriaId 찾기 +// public int getCafeteriaId(String cafeteriaName, int campusId) { +// return cafeteriaRepositoryV2.findCafeteriaId(cafeteriaName, campusId).orElse(-1); +// } +// +// +// // 식당 imgUrl 찾기 +// public String getImgUrl(int cafeteriaId) { +// return cafeteriaRepositoryV2.findImgUrlByCafeteriaId(cafeteriaId); +// } } diff --git a/src/main/java/com/example/Jinus/service/v2/cafeteria/DietServiceV2.java b/src/main/java/com/example/Jinus/service/v2/cafeteria/DietServiceV2.java index 641ce81..23f3b22 100644 --- a/src/main/java/com/example/Jinus/service/v2/cafeteria/DietServiceV2.java +++ b/src/main/java/com/example/Jinus/service/v2/cafeteria/DietServiceV2.java @@ -31,9 +31,9 @@ public class DietServiceV2 { private final DietRepositoryV2 dietRepositoryV2; private final CampusServiceV2 campusServiceV2; - private final CafeteriaServiceV2 cafeteriaServiceV2; private final UserServiceV2 userServiceV2; private final CacheServiceV2 dietCacheServiceV2; + private final CafeteriaQueryServiceV2 queryServiceV2; // 식단 데이터 찾기 위해 필요한 파라미터 추출 및 초기화 public String requestHandler(RequestDto requestDto) { @@ -70,7 +70,7 @@ private Optional extractValue(DetailParamsItemFieldDto fieldDto) { // response 생성 로직 private String makeResponse(HandleRequestDto parameters) { int campusId = campusServiceV2.getCampusId(parameters.getCampusName()); - int cafeteriaId = cafeteriaServiceV2.getCafeteriaId(parameters.getCafeteriaName(), campusId); + int cafeteriaId = queryServiceV2.getCafeteriaId(parameters.getCafeteriaName(), campusId); // 캠퍼스에 식당이 존재하지 않는 경우 if (cafeteriaId == -1) { @@ -144,7 +144,7 @@ private StringBuilder processDietList(MultiValueMap dietList) { // 응답 내용 초기화 private String makeContents(HandleRequestDto parameters, int cafeteriaId, String diets) { // 식당 img 찾기 - String imgUrl = cafeteriaServiceV2.getImgUrl(cafeteriaId); + String imgUrl = queryServiceV2.getImgUrl(cafeteriaId); // title 데이터 연결 String title = "\uD83C\uDF71 " + From f19aa3dc49b91a1115600dd9538f21f0506cf58b Mon Sep 17 00:00:00 2001 From: hykim02 Date: Thu, 27 Mar 2025 17:02:48 +0900 Subject: [PATCH 3/8] Update Java CI-CD.yml dependency submission code removed --- .github/workflows/Java CI-CD.yml | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/.github/workflows/Java CI-CD.yml b/.github/workflows/Java CI-CD.yml index 02ceed8..8dcc546 100644 --- a/.github/workflows/Java CI-CD.yml +++ b/.github/workflows/Java CI-CD.yml @@ -1,10 +1,3 @@ -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. -# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle - name: Java CI with Gradle on: @@ -83,23 +76,3 @@ jobs: run: |- echo '${{ steps.compute-ssh.outputs.stdout }}' echo '${{ steps.compute-ssh.outputs.stderr }}' - - - dependency-submission: - - runs-on: ubuntu-latest - permissions: - contents: write - - steps: - - uses: actions/checkout@v4 - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - java-version: '21' - distribution: 'temurin' - - # Generates and submits a dependency graph, enabling Dependabot Alerts for all project dependencies. - # See: https://github.com/gradle/actions/blob/main/dependency-submission/README.md - - name: Generate and submit dependency graph - uses: gradle/actions/dependency-submission@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 From dd851d2deadeea00fcc1bebb99c3748c68edbb1c Mon Sep 17 00:00:00 2001 From: hykim02 Date: Thu, 27 Mar 2025 17:23:47 +0900 Subject: [PATCH 4/8] =?UTF-8?q?[Refactor]CampusServiceV2=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../v2/cafeteria/CafeteriaServiceV2.java | 80 +------------------ .../v2/cafeteria/CampusResponseServiceV2.java | 47 +++++++++++ .../service/v2/cafeteria/CampusServiceV2.java | 35 -------- 3 files changed, 50 insertions(+), 112 deletions(-) create mode 100644 src/main/java/com/example/Jinus/service/v2/cafeteria/CampusResponseServiceV2.java diff --git a/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaServiceV2.java b/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaServiceV2.java index 69ec74a..b251997 100644 --- a/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaServiceV2.java +++ b/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaServiceV2.java @@ -11,6 +11,7 @@ public class CafeteriaServiceV2 { private final CampusServiceV2 campusServiceV2; + private final CampusResponseServiceV2 campusResponseServiceV2; private final CacheServiceV2 cacheServiceV2; private final CafeteriaResponseServiceV2 cafeteriaResponseServiceV2; @@ -18,13 +19,13 @@ public class CafeteriaServiceV2 { // campusId가 -1이면 사용자 정보가 존재하지 않는 경우임 public String campusOrCafeteria(int userCampusId, int sysCampusId) { if (sysCampusId == -1) { // 더보기 버튼 누른 경우 -> 캠퍼스 리스트 반환 - return campusServiceV2.makeCampusListCard(); + return campusResponseServiceV2.makeCampusListCard(); } // 사용자가 캠퍼스를 선택한 경우 int targetCampusId = (sysCampusId > 0) ? sysCampusId : userCampusId; return (targetCampusId != -1) // 사용자 정보 DB 존재 여부 ? returnCafeteriaListCard(targetCampusId) // 존재 O -> 식당 정보 반환 - : campusServiceV2.makeCampusListCard(); // 존재 X -> 캠퍼스 정보 반환 + : campusResponseServiceV2.makeCampusListCard(); // 존재 X -> 캠퍼스 정보 반환 } // 식당 리스트 반환 @@ -33,79 +34,4 @@ private String returnCafeteriaListCard(int campusId) { List cafeteriaList = cacheServiceV2.getCafeteriaList(campusId); return cafeteriaResponseServiceV2.createCafeteriaListCard(campusName, cafeteriaList); } - -// // 반환 조건 설정 -// public String campusOrCafeteria(int campusId, int sysCampusId) { -// // 더보기 버튼 누른 경우 -// if (sysCampusId == -1) { -// return campusServiceV2.makeCampusListCard(); -// } -// -// // 사용자가 원하는 캠퍼스가 있을 때 -// if (sysCampusId > 0) { -// return makeCafeteriaListCard(sysCampusId); -// } -// -// // 사용자가 원하는 캠퍼스가 없을 때 -// return (campusId != -1) // 사용자 존재 여부 -// ? makeCafeteriaListCard(campusId) -// : campusServiceV2.makeCampusListCard(); -// } -// -// // 식당 리스트 반환 메소드 -// private String makeCafeteriaListCard(int campusId) { -// String campusName = campusServiceV2.getUserCampusName(campusId); -// List cafeteriaList = cacheServiceV2.getCafeteriaList(campusId); -// -// // 식당 리스트 객체 생성 -// List listItems = mappingCafeteriaList(campusName, cafeteriaList); -// // response 객체 생성 -// ResponseDto responseDto = ListCardResponse.mappingResponseDto("어떤 교내 식당 정보가 알고싶어 ?", listItems, mappingButtonDto()); -// -// return JsonUtils.toJsonResponse(responseDto); -// } -// -// -// // 식당 리스트 객체 생성 -// private List mappingCafeteriaList(String campusName, List cafeteriaList) { -// List listItems = new ArrayList<>(); -// for (CafeteriaDto cafeteria : cafeteriaList) { -// String userMessage = campusName + " " + cafeteria.getCafeteriaNameKo(); -// -// // 리스트 아이템 객체 생성 -// ListItemDto listItem = new ListItemDto(cafeteria.getCafeteriaNameKo(), campusName, -// cafeteria.getThumbnailUrl(), "message", userMessage); -// listItems.add(listItem); -// } -// return listItems; -// } -// -// -// // 더보기 버튼 리스트 생성 -// private List mappingButtonDto() { -// List buttonDto = new ArrayList<>(); -// Map extra = new HashMap<>(); -// extra.put("sys_campus_id", -1); -// // 버튼 객체 생성 -// ButtonDto button = new ButtonDto("더보기", "block", "66067167cdd882158c759fc2", extra); -// buttonDto.add(button); -// return buttonDto; -// } -// -// -// -// @Cacheable(value = "cafeteriaId", key = "#campusId + '::' + #cafeteriaName", -// unless = "#result == -1", -// cacheManager = "contentCacheManager") -// // 캠퍼스에 식당이 존재한다면 cafeteriaId 찾기 -// public int getCafeteriaId(String cafeteriaName, int campusId) { -// return cafeteriaRepositoryV2.findCafeteriaId(cafeteriaName, campusId).orElse(-1); -// } -// -// -// // 식당 imgUrl 찾기 -// public String getImgUrl(int cafeteriaId) { -// return cafeteriaRepositoryV2.findImgUrlByCafeteriaId(cafeteriaId); -// } - } diff --git a/src/main/java/com/example/Jinus/service/v2/cafeteria/CampusResponseServiceV2.java b/src/main/java/com/example/Jinus/service/v2/cafeteria/CampusResponseServiceV2.java new file mode 100644 index 0000000..efb3b0f --- /dev/null +++ b/src/main/java/com/example/Jinus/service/v2/cafeteria/CampusResponseServiceV2.java @@ -0,0 +1,47 @@ +package com.example.Jinus.service.v2.cafeteria; + +import com.example.Jinus.dto.response.ListItemDto; +import com.example.Jinus.dto.response.ResponseDto; +import com.example.Jinus.entity.cafeteria.CampusEntity; +import com.example.Jinus.utility.JsonUtils; +import com.example.Jinus.utility.ListCardResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +@RequiredArgsConstructor +public class CampusResponseServiceV2 { + + private final CampusServiceV2 campusServiceV2; + + // 캠퍼스 리스트 반환 메소드 + public String makeCampusListCard() { + List campusList = campusServiceV2.getCampusList(); + // 캠퍼스 리스트 객체 생성 + List listItems = mappingCampusList(campusList); + // response 객체 생성 + ResponseDto responseDto = ListCardResponse.mappingResponseDto("어떤 캠퍼스 식당 정보가 궁금해 ?", listItems, null); + return JsonUtils.toJsonResponse(responseDto); + } + + // 캠퍼스 리스트 객체 생성 + private List mappingCampusList(List campusList) { + List listItems = new ArrayList<>(); + for (CampusEntity campus : campusList) { + String campusName = campus.getCampusNameKo(); + String imageUrl = campus.getThumbnailUrl(); + Map extra = new HashMap<>(); + extra.put("sys_campus_id", campus.getId()); + + // 캠퍼스 아이템 객체 생성 + ListItemDto listItem = new ListItemDto(campusName, imageUrl, "block", "66067167cdd882158c759fc2", extra); + listItems.add(listItem); + } + return listItems; + } +} diff --git a/src/main/java/com/example/Jinus/service/v2/cafeteria/CampusServiceV2.java b/src/main/java/com/example/Jinus/service/v2/cafeteria/CampusServiceV2.java index eb61f20..4f4e938 100644 --- a/src/main/java/com/example/Jinus/service/v2/cafeteria/CampusServiceV2.java +++ b/src/main/java/com/example/Jinus/service/v2/cafeteria/CampusServiceV2.java @@ -1,18 +1,11 @@ package com.example.Jinus.service.v2.cafeteria; -import com.example.Jinus.dto.response.ListItemDto; -import com.example.Jinus.dto.response.ResponseDto; import com.example.Jinus.entity.cafeteria.CampusEntity; import com.example.Jinus.repository.v2.cafeteria.CampusRepositoryV2; -import com.example.Jinus.utility.JsonUtils; -import com.example.Jinus.utility.ListCardResponse; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; @Service @RequiredArgsConstructor @@ -34,32 +27,4 @@ public List getCampusList() { public int getCampusId(String campusName) { return campusRepositoryV2.findCampusIdByName(campusName); } - - // 캠퍼스 리스트 반환 메소드 - public String makeCampusListCard() { - List campusList = getCampusList(); - - // 캠퍼스 리스트 객체 생성 - List listItems = mappingCampusList(campusList); - // response 객체 생성 - ResponseDto responseDto = ListCardResponse.mappingResponseDto("어떤 캠퍼스 식당 정보가 궁금해 ?", listItems, null); - - return JsonUtils.toJsonResponse(responseDto); - } - - // 캠퍼스 리스트 객체 생성 - private List mappingCampusList(List campusList) { - List listItems = new ArrayList<>(); - for (CampusEntity campus : campusList) { - String campusName = campus.getCampusNameKo(); - String imageUrl = campus.getThumbnailUrl(); - Map extra = new HashMap<>(); - extra.put("sys_campus_id", campus.getId()); - - // 캠퍼스 아이템 객체 생성 - ListItemDto listItem = new ListItemDto(campusName, imageUrl, "block", "66067167cdd882158c759fc2", extra); - listItems.add(listItem); - } - return listItems; - } } From fbca9f391baa188db5a1c21584e7a82536b57da6 Mon Sep 17 00:00:00 2001 From: hykim02 Date: Thu, 27 Mar 2025 18:06:58 +0900 Subject: [PATCH 5/8] =?UTF-8?q?[Refactor]DietServiceV2=20=EC=84=9C?= =?UTF-8?q?=EB=B9=84=EC=8A=A4=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../v2/cafeteria/DietParameterServiceV2.java | 91 ++++++++ .../v2/cafeteria/DietQueryServiceV2.java | 72 ++++++ .../v2/cafeteria/DietResponseServiceV2.java | 68 ++++++ .../service/v2/cafeteria/DietServiceV2.java | 212 ++---------------- 4 files changed, 244 insertions(+), 199 deletions(-) create mode 100644 src/main/java/com/example/Jinus/service/v2/cafeteria/DietParameterServiceV2.java create mode 100644 src/main/java/com/example/Jinus/service/v2/cafeteria/DietQueryServiceV2.java create mode 100644 src/main/java/com/example/Jinus/service/v2/cafeteria/DietResponseServiceV2.java diff --git a/src/main/java/com/example/Jinus/service/v2/cafeteria/DietParameterServiceV2.java b/src/main/java/com/example/Jinus/service/v2/cafeteria/DietParameterServiceV2.java new file mode 100644 index 0000000..60d5139 --- /dev/null +++ b/src/main/java/com/example/Jinus/service/v2/cafeteria/DietParameterServiceV2.java @@ -0,0 +1,91 @@ +package com.example.Jinus.service.v2.cafeteria; + +import com.example.Jinus.dto.data.HandleRequestDto; +import com.example.Jinus.dto.request.DetailParamsItemFieldDto; +import com.example.Jinus.dto.request.RequestDto; +import com.example.Jinus.service.v2.userInfo.UserServiceV2; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.sql.Date; +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.Optional; + +@Service +@RequiredArgsConstructor +public class DietParameterServiceV2 { + + private final UserServiceV2 userServiceV2; + private final CampusServiceV2 campusServiceV2; + + // 요청 파라미터 객체 생성 + public HandleRequestDto setParameters(String kakaoId, LocalTime time, RequestDto requestDto) { + // 요청 필수 파라미터 추출 + String cafeteriaName = requestDto.getAction().getParams().getSys_cafeteria_name(); + + // DetailParams에서 일반 파라미터 추출 및 초기화(null 체크 포함) + String campusNameValue = extractValue(requestDto.getAction().getDetailParams().getSys_campus_name()) + .orElseGet(() -> getCampusName(kakaoId)); + String dayValue = extractValue(requestDto.getAction().getDetailParams().getSys_date()) + .orElseGet(() -> getDay(time)); + String periodValue = extractValue(requestDto.getAction().getDetailParams().getSys_time_period()) + .orElseGet(() -> getPeriodOfDay(time)); + + // 오늘, 내일 문자열로 날짜 생성 + Date dietDate = getCurrentDate(dayValue); + // 요청 파라미터 객체 생성 + return new HandleRequestDto(kakaoId, campusNameValue, dayValue, periodValue, cafeteriaName, dietDate); + } + + // 일반 파라미터가 null인 경우 기본값 설정 + private Optional extractValue(DetailParamsItemFieldDto fieldDto) { + return Optional.ofNullable(fieldDto).map(DetailParamsItemFieldDto::getValue); + } + + // 일반 파라미터 값 채우기 + // sys_campus_name 파라미터 초기화 + private String getCampusName(String kakaoId) { + // 학과 등록 여부 확인 + int campusId = userServiceV2.getUserCampusId(kakaoId); + // 학과 등록한 경우 campusId가 존재함 + if (campusId != -1) { + return campusServiceV2.getUserCampusName(campusId); + } else { // 학과 등록 안한 경우 + return "가좌캠퍼스"; + } + } + + // sys_date 파라미터 초기화 - 시간 범위에 따라 오늘, 내일 판별 + private String getDay(LocalTime time) { + if (time.isAfter(LocalTime.parse("00:00:00")) && time.isBefore(LocalTime.parse("19:00:00"))) { + return "오늘"; + } else { + return "내일"; + } + } + + // sys_period 파라미터 초기화 - 시간 범위에 따라 아침, 점심, 저녁을 판별 + private String getPeriodOfDay(LocalTime time) { + if (time.isAfter(LocalTime.parse("19:00:00")) || time.isBefore(LocalTime.parse("09:30:00"))) { + return "아침"; + } else if (!time.isBefore(LocalTime.parse("09:30:00")) && time.isBefore(LocalTime.parse("13:30:00"))) { + return "점심"; + } else { + return "저녁"; + } + } + + // sysDay 파라미터 값으로 조회할 날짜 찾는 함수 + private Date getCurrentDate(String sysDate) { + // 현재 날짜 + LocalDate today = LocalDate.now(); + LocalDate tomorrow = today.plusDays(1); // 하루 뒤 날짜 계산 + + if (sysDate.equals("오늘")) { + return Date.valueOf(today); + } else { // 내일 + return Date.valueOf(tomorrow); + } + } +} diff --git a/src/main/java/com/example/Jinus/service/v2/cafeteria/DietQueryServiceV2.java b/src/main/java/com/example/Jinus/service/v2/cafeteria/DietQueryServiceV2.java new file mode 100644 index 0000000..8ec2634 --- /dev/null +++ b/src/main/java/com/example/Jinus/service/v2/cafeteria/DietQueryServiceV2.java @@ -0,0 +1,72 @@ +package com.example.Jinus.service.v2.cafeteria; + +import com.example.Jinus.dto.data.DietDto; +import com.example.Jinus.dto.data.HandleRequestDto; +import com.example.Jinus.repository.v2.cafeteria.DietRepositoryV2; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +import java.sql.Date; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +@Service +@RequiredArgsConstructor +public class DietQueryServiceV2 { + + private final CacheServiceV2 cacheServiceV2; + private final DietRepositoryV2 dietRepositoryV2; + + // 메뉴 존재 여부에 따른 반환값 처리 로직 + public String getDietResponse(HandleRequestDto parameters, int cafeteriaId) { + // 메뉴 존재하는 경우 + if (checkThereIsDiet(parameters, cafeteriaId) != -1) { + // 메뉴 찾기 + MultiValueMap dietList = getDiets(parameters, cafeteriaId); + return processDietList(dietList).toString(); + } + return "\n메뉴가 존재하지 않습니다."; // 메뉴가 없는 경우 + } + + + // 식당 메뉴 존재여부 확인 + private int checkThereIsDiet(HandleRequestDto parameters, int cafeteriaId) { + // 오늘, 내일 문자열로 날짜 설정하기 + Date dietDate = parameters.getDietDate(); + List dietDtos = + dietRepositoryV2.findDietList(dietDate, parameters.getPeriod(), cafeteriaId); + return (!dietDtos.isEmpty()) ? 1 : -1; + } + + + // 카테고리별 메뉴 리스트 생성하기 + private MultiValueMap getDiets(HandleRequestDto parameters, int cafeteriaId) { + List dietDtos = cacheServiceV2.getDietList(parameters, cafeteriaId); + MultiValueMap dietList = new LinkedMultiValueMap<>(); // 중복 키 허용(값을 리스트로 반환) + + for (DietDto o : dietDtos) { + String key = (o.getDishCategory() != null) ? o.getDishCategory() + : (o.getDishType() != null) ? o.getDishType() + : "메뉴"; + + dietList.add(key, o.getDishName()); + } + return dietList; + } + + // 카테고리별 메뉴 문자열로 나열하기 + private StringBuilder processDietList(MultiValueMap dietList) { + // 키 추출 + Set keys = new TreeSet<>(dietList.keySet()); // 순서 보장 - 오름차순 + StringBuilder description = new StringBuilder(); + + for (String key : keys) { + description.append("\n[").append(key).append("]").append("\n"); + dietList.get(key).forEach(diet -> description.append(diet).append("\n")); + } + return description; + } +} diff --git a/src/main/java/com/example/Jinus/service/v2/cafeteria/DietResponseServiceV2.java b/src/main/java/com/example/Jinus/service/v2/cafeteria/DietResponseServiceV2.java new file mode 100644 index 0000000..a033a1f --- /dev/null +++ b/src/main/java/com/example/Jinus/service/v2/cafeteria/DietResponseServiceV2.java @@ -0,0 +1,68 @@ +package com.example.Jinus.service.v2.cafeteria; + +import com.example.Jinus.dto.data.HandleRequestDto; +import com.example.Jinus.dto.response.*; +import com.example.Jinus.utility.JsonUtils; +import com.example.Jinus.utility.SimpleTextResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class DietResponseServiceV2 { + + // 응답 객체 매핑 + public String mappingResponse(HandleRequestDto parameters, String imgUrl, String title, String description) { + // imgUrl 객체 생성 + ThumbnailDto thumbnail = new ThumbnailDto(imgUrl); + + // 버튼 리스트 객체 생성 + List buttonList = List.of(new ButtonDto("공유하기", "share")); + + // 아이템 객체 생성 + BasicCardDto basicCardDto = new BasicCardDto(title, description, thumbnail, buttonList); + List outputs = List.of(new ComponentDto(basicCardDto)); + + List quickReplies = mappingQuickReply(parameters); + + TemplateDto templateDto = new TemplateDto(outputs, quickReplies); + ResponseDto responseDto = new ResponseDto("2.0", templateDto); + + return JsonUtils.toJsonResponse(responseDto); + } + + private List mappingQuickReply(HandleRequestDto parameters) { + List periods = getNextMealPeriods(parameters.getPeriod()); + return periods.stream() + .map(period -> createQuickReply(period, parameters)) + .collect(Collectors.toList()); + } + + // 현재 시간대(period)에 따라 다음 선택할 식사 시간대를 반환 + private List getNextMealPeriods(String currentPeriod) { + return switch (currentPeriod) { + case "아침" -> List.of("점심", "저녁"); + case "점심" -> List.of("아침", "저녁"); + default -> List.of("아침", "점심"); + }; + } + + // QuickReplyDto 객체를 생성하는 메서드 + private QuickReplyDto createQuickReply(String period, HandleRequestDto parameters) { + String message = String.format("%s %s %s %s 메뉴", + parameters.getCampusName(), + parameters.getCafeteriaName(), + parameters.getDay(), + period); + return new QuickReplyDto(period, "message", message); + } + + // 캠퍼스에 식당이 존재하지 않는 경우 메시지 출력 + public String errorMsgThereIsNoCafeteria() { + return SimpleTextResponse + .simpleTextResponse("식당을 찾지 못했어!\n어떤 캠퍼스에 있는 식당인지 정확히 알려줘!"); + } +} diff --git a/src/main/java/com/example/Jinus/service/v2/cafeteria/DietServiceV2.java b/src/main/java/com/example/Jinus/service/v2/cafeteria/DietServiceV2.java index 23f3b22..57f22ba 100644 --- a/src/main/java/com/example/Jinus/service/v2/cafeteria/DietServiceV2.java +++ b/src/main/java/com/example/Jinus/service/v2/cafeteria/DietServiceV2.java @@ -1,147 +1,57 @@ package com.example.Jinus.service.v2.cafeteria; -import com.example.Jinus.dto.data.DietDto; -import com.example.Jinus.dto.request.DetailParamsItemFieldDto; import com.example.Jinus.dto.data.HandleRequestDto; import com.example.Jinus.dto.request.RequestDto; -import com.example.Jinus.dto.response.*; import com.example.Jinus.repository.v2.cafeteria.DietRepositoryV2; -import com.example.Jinus.service.v2.userInfo.UserServiceV2; import com.example.Jinus.utility.DateUtils; -import com.example.Jinus.utility.JsonUtils; -import com.example.Jinus.utility.SimpleTextResponse; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import java.sql.Date; -import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.ZoneId; -import java.util.List; -import java.util.Optional; import java.util.Set; import java.util.TreeSet; -import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class DietServiceV2 { - private final DietRepositoryV2 dietRepositoryV2; + private final CampusServiceV2 campusServiceV2; - private final UserServiceV2 userServiceV2; - private final CacheServiceV2 dietCacheServiceV2; private final CafeteriaQueryServiceV2 queryServiceV2; + private final DietParameterServiceV2 parameterServiceV2; + private final DietResponseServiceV2 dietResponseServiceV2; + private final DietQueryServiceV2 dietQueryServiceV2; // 식단 데이터 찾기 위해 필요한 파라미터 추출 및 초기화 public String requestHandler(RequestDto requestDto) { String kakaoId = requestDto.getUserRequest().getUser().getId(); - // 현재 시간 파악 LocalTime time = getCurrentTime(); + // 사용자 발화에서 파라미터 추출 및 객체 생성 + HandleRequestDto parameters = parameterServiceV2.setParameters(kakaoId, time, requestDto); - // DetailParams에서 값 추출 (null 체크 포함) - String campusNameValue = extractValue(requestDto.getAction().getDetailParams().getSys_campus_name()) - .orElseGet(() -> getCampusName(kakaoId)); - String dayValue = extractValue(requestDto.getAction().getDetailParams().getSys_date()) - .orElseGet(() -> getDay(time)); - String periodValue = extractValue(requestDto.getAction().getDetailParams().getSys_time_period()) - .orElseGet(() -> getPeriodOfDay(time)); - - // 요청 필수 파라미터 추출 - String cafeteriaName = requestDto.getAction().getParams().getSys_cafeteria_name(); - // 오늘, 내일 문자열로 날짜 생성 - Date dietDate = getCurrentDate(dayValue); - // 요청 파라미터 객체 생성 - HandleRequestDto parameters = new HandleRequestDto(kakaoId, campusNameValue, dayValue, periodValue, cafeteriaName, dietDate); - - return makeResponse(parameters); + return checkIsCafeteriaInCampus(parameters); } - - // 기본값 설정 유틸 - private Optional extractValue(DetailParamsItemFieldDto fieldDto) { - return Optional.ofNullable(fieldDto).map(DetailParamsItemFieldDto::getValue); - } - - - // response 생성 로직 - private String makeResponse(HandleRequestDto parameters) { + // 식당 존재 여부에 따른 메뉴 조회 로직 + private String checkIsCafeteriaInCampus(HandleRequestDto parameters) { int campusId = campusServiceV2.getCampusId(parameters.getCampusName()); int cafeteriaId = queryServiceV2.getCafeteriaId(parameters.getCafeteriaName(), campusId); // 캠퍼스에 식당이 존재하지 않는 경우 if (cafeteriaId == -1) { - return errorMsgThereIsNoCafeteria(); + return dietResponseServiceV2.errorMsgThereIsNoCafeteria(); } - // 캠퍼스에 식당이 존재하는 경우 - String diets = getDietResponse(parameters, cafeteriaId); + String diets = dietQueryServiceV2.getDietResponse(parameters, cafeteriaId); return makeContents(parameters, cafeteriaId, diets); } - // 메뉴 존재 여부 확인 - private String getDietResponse(HandleRequestDto parameters, int cafeteriaId) { - // 메뉴 존재하는 경우 - if (checkThereIsDiet(parameters, cafeteriaId) != -1) { - // 메뉴 찾기 - MultiValueMap dietList = getDiets(parameters, cafeteriaId); - return processDietList(dietList).toString(); - } - return "\n메뉴가 존재하지 않습니다."; // 메뉴가 없는 경우 - } - - - // 캠퍼스에 식당이 존재하지 않는 경우 메시지 출력 - private String errorMsgThereIsNoCafeteria() { - return SimpleTextResponse - .simpleTextResponse("식당을 찾지 못했어!\n어떤 캠퍼스에 있는 식당인지 정확히 알려줘!"); - } - - - // 식당 메뉴 존재여부 확인 - private int checkThereIsDiet(HandleRequestDto parameters, int cafeteriaId) { - // 오늘, 내일 문자열로 날짜 설정하기 - Date dietDate = parameters.getDietDate(); - List dietDtos = - dietRepositoryV2.findDietList(dietDate, parameters.getPeriod(), cafeteriaId); - return (!dietDtos.isEmpty()) ? 1 : -1; - } - - - // 카테고리별 메뉴 리스트 생성하기 - private MultiValueMap getDiets(HandleRequestDto parameters, int cafeteriaId) { - List dietDtos = dietCacheServiceV2.getDietList(parameters, cafeteriaId); - MultiValueMap dietList = new LinkedMultiValueMap<>(); // 중복 키 허용(값을 리스트로 반환) - - for (DietDto o : dietDtos) { - String key = (o.getDishCategory() != null) ? o.getDishCategory() - : (o.getDishType() != null) ? o.getDishType() - : "메뉴"; - - dietList.add(key, o.getDishName()); - } - return dietList; - } - - - // 카테고리별 메뉴 문자열로 나열하기 - private StringBuilder processDietList(MultiValueMap dietList) { - // 키 추출 - Set keys = new TreeSet<>(dietList.keySet()); // 순서 보장 - 오름차순 - StringBuilder description = new StringBuilder(); - - for (String key : keys) { - description.append("\n[").append(key).append("]").append("\n"); - dietList.get(key).forEach(diet -> description.append(diet).append("\n")); - } - return description; - } - - // 응답 내용 초기화 + // 응답 내용 생성 private String makeContents(HandleRequestDto parameters, int cafeteriaId, String diets) { // 식당 img 찾기 String imgUrl = queryServiceV2.getImgUrl(cafeteriaId); @@ -159,91 +69,9 @@ private String makeContents(HandleRequestDto parameters, int cafeteriaId, String String description = dietDate + "(" + day + ") " + parameters.getPeriod() + "\n" + diets; - return mappingResponse(parameters, imgUrl, title, description); + return dietResponseServiceV2.mappingResponse(parameters, imgUrl, title, description); } - // 응답 객체 매핑 - private String mappingResponse(HandleRequestDto parameters, String imgUrl, String title, String description) { - // imgUrl 객체 생성 - ThumbnailDto thumbnail = new ThumbnailDto(imgUrl); - - // 버튼 리스트 객체 생성 - List buttonList = List.of(new ButtonDto("공유하기", "share")); - - // 아이템 객체 생성 - BasicCardDto basicCardDto = new BasicCardDto(title, description, thumbnail, buttonList); - List outputs = List.of(new ComponentDto(basicCardDto)); - - List quickReplies = mappingQuickReply(parameters); - - TemplateDto templateDto = new TemplateDto(outputs, quickReplies); - ResponseDto responseDto = new ResponseDto("2.0", templateDto); - - return JsonUtils.toJsonResponse(responseDto); - } - - - private List mappingQuickReply(HandleRequestDto parameters) { - List periods = getNextMealPeriods(parameters.getPeriod()); - return periods.stream() - .map(period -> createQuickReply(period, parameters)) - .collect(Collectors.toList()); - } - - - // 현재 시간대(period)에 따라 다음 선택할 식사 시간대를 반환 - private List getNextMealPeriods(String currentPeriod) { - return switch (currentPeriod) { - case "아침" -> List.of("점심", "저녁"); - case "점심" -> List.of("아침", "저녁"); - default -> List.of("아침", "점심"); - }; - } - - - // QuickReplyDto 객체를 생성하는 메서드 - private QuickReplyDto createQuickReply(String period, HandleRequestDto parameters) { - String message = String.format("%s %s %s %s 메뉴", - parameters.getCampusName(), - parameters.getCafeteriaName(), - parameters.getDay(), - period); - return new QuickReplyDto(period, "message", message); - } - - - // 일반 파라미터 값 채우기 - // sys_campus_name 파라미터 초기화 - private String getCampusName(String kakaoId) { - // 학과 등록 여부 확인 - int campusId = userServiceV2.getUserCampusId(kakaoId); - // 학과 등록한 경우 campusId가 존재함 - if (campusId != -1) { - return campusServiceV2.getUserCampusName(campusId); - } else { // 학과 등록 안한 경우 - return "가좌캠퍼스"; - } - } - - // sys_date 파라미터 초기화 - 시간 범위에 따라 오늘, 내일 판별 - private String getDay(LocalTime time) { - if (time.isAfter(LocalTime.parse("00:00:00")) && time.isBefore(LocalTime.parse("19:00:00"))) { - return "오늘"; - } else { - return "내일"; - } - } - - // sys_period 파라미터 초기화 - 시간 범위에 따라 아침, 점심, 저녁을 판별 - private String getPeriodOfDay(LocalTime time) { - if (time.isAfter(LocalTime.parse("19:00:00")) || time.isBefore(LocalTime.parse("09:30:00"))) { - return "아침"; - } else if (!time.isBefore(LocalTime.parse("09:30:00")) && time.isBefore(LocalTime.parse("13:30:00"))) { - return "점심"; - } else { - return "저녁"; - } - } // 현재 시간 출력 함수 private LocalTime getCurrentTime() { @@ -253,18 +81,4 @@ private LocalTime getCurrentTime() { return LocalTime.parse(timeSplit[0]); } - - - // sysDay 파라미터 값으로 조회할 날짜 찾는 함수 - private Date getCurrentDate(String sysDate) { - // 현재 날짜 - LocalDate today = LocalDate.now(); - LocalDate tomorrow = today.plusDays(1); // 하루 뒤 날짜 계산 - - if (sysDate.equals("오늘")) { - return Date.valueOf(today); - } else { // 내일 - return Date.valueOf(tomorrow); - } - } } From e70e82bb144ae86654ec3a01cb8216564b6cf116 Mon Sep 17 00:00:00 2001 From: hykim02 Date: Thu, 17 Apr 2025 14:37:42 +0900 Subject: [PATCH 6/8] =?UTF-8?q?[fix]Cafeteria=20Cacheable=20=EC=A3=BC?= =?UTF-8?q?=EC=84=9D=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/Jinus/controller/v2/NoticeControllerV2.java | 4 ---- .../Jinus/service/v2/cafeteria/CafeteriaQueryServiceV2.java | 6 +++--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/example/Jinus/controller/v2/NoticeControllerV2.java b/src/main/java/com/example/Jinus/controller/v2/NoticeControllerV2.java index 1f653f1..dd47949 100644 --- a/src/main/java/com/example/Jinus/controller/v2/NoticeControllerV2.java +++ b/src/main/java/com/example/Jinus/controller/v2/NoticeControllerV2.java @@ -4,9 +4,7 @@ import com.example.Jinus.service.v2.notice.NoticeServiceV2; import com.example.Jinus.service.v2.userInfo.DepartmentServiceV2; import com.example.Jinus.service.v2.userInfo.UserServiceV2; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -20,8 +18,6 @@ public class NoticeControllerV2 { private final NoticeServiceV2 noticeServiceV2; private final DepartmentServiceV2 departmentServiceV2; private final UserServiceV2 userServiceV2; - @Autowired - private ObjectMapper objectMapper; // 학교 공지사항 조회 @PostMapping("/v2/main-notice") diff --git a/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaQueryServiceV2.java b/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaQueryServiceV2.java index bed0a39..305f4fa 100644 --- a/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaQueryServiceV2.java +++ b/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaQueryServiceV2.java @@ -10,9 +10,9 @@ public class CafeteriaQueryServiceV2 { private final CafeteriaRepositoryV2 cafeteriaRepositoryV2; - @Cacheable(value = "cafeteriaId", key = "#campusId + '::' + #cafeteriaName", - unless = "#result == -1", - cacheManager = "contentCacheManager") +// @Cacheable(value = "cafeteriaId", key = "#campusId + '::' + #cafeteriaName", +// unless = "#result == -1", +// cacheManager = "contentCacheManager") public int getCafeteriaId(String cafeteriaName, int campusId) { return cafeteriaRepositoryV2.findCafeteriaId(cafeteriaName, campusId).orElse(-1); } From 00f353217bf4a05fa8cb78a4ec01ef0a2a6ed1b5 Mon Sep 17 00:00:00 2001 From: hykim02 Date: Fri, 18 Apr 2025 01:31:21 +0900 Subject: [PATCH 7/8] =?UTF-8?q?[Refactor]=EC=BA=90=EC=8B=9C=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=20=EB=B0=8F=20=EC=A4=91=EB=B3=B5=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B5=9C=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Jinus/config/RedisCacheManager.java | 39 ++++++++++----- .../Jinus/config/RestTemplateConfig.java | 28 ----------- .../Jinus/controller/v2/DietControllerV2.java | 2 + .../service/v2/cafeteria/CacheServiceV2.java | 49 ++++++++++++++----- .../v2/cafeteria/CafeteriaQueryServiceV2.java | 14 ++++-- .../service/v2/cafeteria/CampusServiceV2.java | 12 ++++- .../v2/cafeteria/DietParameterServiceV2.java | 2 + .../v2/cafeteria/DietQueryServiceV2.java | 21 +++----- .../service/v2/cafeteria/DietServiceV2.java | 6 +-- .../service/v2/userInfo/UserServiceV2.java | 2 + 10 files changed, 102 insertions(+), 73 deletions(-) delete mode 100644 src/main/java/com/example/Jinus/config/RestTemplateConfig.java diff --git a/src/main/java/com/example/Jinus/config/RedisCacheManager.java b/src/main/java/com/example/Jinus/config/RedisCacheManager.java index c01fc88..7fa82d9 100644 --- a/src/main/java/com/example/Jinus/config/RedisCacheManager.java +++ b/src/main/java/com/example/Jinus/config/RedisCacheManager.java @@ -21,37 +21,53 @@ public class RedisCacheManager { public CacheManager contentCacheManager(RedisConnectionFactory cf) { Map cacheConfigurations = new HashMap<>(); - // 1. 식당 리스트 캐시 (불변 데이터, 7일 유지) + // 1. 식당 리스트 캐시 (불변 데이터, 30일 유지) cacheConfigurations.put("cafeteriaList", RedisCacheConfiguration.defaultCacheConfig() .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) // Key Serializer .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())) // Value Serializer - .entryTtl(Duration.ofDays(7)) // 7일 유지 + .entryTtl(Duration.ofDays(30)) .disableCachingNullValues()); // null 캐싱 방지 // 2. 식단 데이터 캐시 (하루 단위로 갱신) - cacheConfigurations.put("dietList", +// cacheConfigurations.put("dietList", +// RedisCacheConfiguration.defaultCacheConfig() +// .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) // Key Serializer +// .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())) // Value Serializer +// .entryTtl(Duration.ofHours(12)) +// .disableCachingNullValues()); + + // 3. 캠퍼스 이름 캐시 (불변 데이터, 30일 유지) + cacheConfigurations.put("campusName", RedisCacheConfiguration.defaultCacheConfig() .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) // Key Serializer .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())) // Value Serializer - .entryTtl(Duration.ofHours(12)) // 12시간 유지 - .disableCachingNullValues()); + .entryTtl(Duration.ofDays(30)) + .disableCachingNullValues()); // null 캐싱 방지 - // 3. 캠퍼스 이름별 캠퍼스 id 캐시 (불변 데이터, 7일 유지) - cacheConfigurations.put("campusName", + // 3. 식당 id 캐시 (불변 데이터, 30일 유지) + cacheConfigurations.put("cafeteriaId", RedisCacheConfiguration.defaultCacheConfig() .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) // Key Serializer .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())) // Value Serializer - .entryTtl(Duration.ofDays(7)) // 7일 유지 + .entryTtl(Duration.ofDays(30)) .disableCachingNullValues()); // null 캐싱 방지 - // 3. 식당별 식당 id 캐시 (불변 데이터, 7일 유지) - cacheConfigurations.put("cafeteriaId", + // 4. 캠퍼스 id 캐시 (불변 데이터, 30일 유지) + cacheConfigurations.put("campusId", RedisCacheConfiguration.defaultCacheConfig() .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) // Key Serializer .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())) // Value Serializer - .entryTtl(Duration.ofDays(7)) // 7일 유지 + .entryTtl(Duration.ofDays(30)) + .disableCachingNullValues()); // null 캐싱 방지 + + // 5. 식당 url 캐시 (불변 데이터, 30일 유지) + cacheConfigurations.put("cafeteriaUrl", + RedisCacheConfiguration.defaultCacheConfig() + .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) // Key Serializer + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())) // Value Serializer + .entryTtl(Duration.ofDays(30)) .disableCachingNullValues()); // null 캐싱 방지 @@ -60,4 +76,5 @@ public CacheManager contentCacheManager(RedisConnectionFactory cf) { .withInitialCacheConfigurations(cacheConfigurations) // 캐시별 설정 적용 .build(); } + } diff --git a/src/main/java/com/example/Jinus/config/RestTemplateConfig.java b/src/main/java/com/example/Jinus/config/RestTemplateConfig.java deleted file mode 100644 index b7046fc..0000000 --- a/src/main/java/com/example/Jinus/config/RestTemplateConfig.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.example.Jinus.config; - -import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.client.BufferingClientHttpRequestFactory; -import org.springframework.http.client.SimpleClientHttpRequestFactory; -import org.springframework.http.converter.StringHttpMessageConverter; -import org.springframework.web.client.RestTemplate; - -import java.nio.charset.StandardCharsets; - -@Configuration -public class RestTemplateConfig { - @Bean - public RestTemplate restTemplate(RestTemplateBuilder builder) { - return builder - .requestFactory( - () -> new BufferingClientHttpRequestFactory( - new SimpleClientHttpRequestFactory() - ) - ).additionalMessageConverters( - new StringHttpMessageConverter( - StandardCharsets.UTF_8 - ) - ).build(); - } -} diff --git a/src/main/java/com/example/Jinus/controller/v2/DietControllerV2.java b/src/main/java/com/example/Jinus/controller/v2/DietControllerV2.java index 4fcdd3f..fb949c6 100644 --- a/src/main/java/com/example/Jinus/controller/v2/DietControllerV2.java +++ b/src/main/java/com/example/Jinus/controller/v2/DietControllerV2.java @@ -4,6 +4,7 @@ import com.example.Jinus.service.v2.cafeteria.DietServiceV2; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -11,6 +12,7 @@ import org.springframework.web.bind.annotation.RestController; @RestController +@Slf4j @RequestMapping("/api/spring") @RequiredArgsConstructor public class DietControllerV2 { diff --git a/src/main/java/com/example/Jinus/service/v2/cafeteria/CacheServiceV2.java b/src/main/java/com/example/Jinus/service/v2/cafeteria/CacheServiceV2.java index 2353549..6eb741b 100644 --- a/src/main/java/com/example/Jinus/service/v2/cafeteria/CacheServiceV2.java +++ b/src/main/java/com/example/Jinus/service/v2/cafeteria/CacheServiceV2.java @@ -1,40 +1,65 @@ package com.example.Jinus.service.v2.cafeteria; +import com.example.Jinus.config.RedisConfig; import com.example.Jinus.dto.data.CafeteriaDto; import com.example.Jinus.dto.data.DietDto; import com.example.Jinus.dto.data.HandleRequestDto; import com.example.Jinus.repository.v2.cafeteria.CafeteriaRepositoryV2; import com.example.Jinus.repository.v2.cafeteria.DietRepositoryV2; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import java.sql.Date; +import java.time.Duration; +import java.time.LocalDateTime; import java.util.List; @Service +@Slf4j @RequiredArgsConstructor public class CacheServiceV2 { private final DietRepositoryV2 dietRepositoryV2; private final CafeteriaRepositoryV2 cafeteriaRepositoryV2; + private final RedisConfig redisConfig; -// @Cacheable( -// value = "dietList", -// key = "#parameters?.dietDate?.toString() + '::' + #parameters?.period + '::' + #cafeteriaId", -// unless = "#result == null || #result.isEmpty()", -// cacheManager = "contentCacheManager" -// ) - // 식단 데이터 가져오기 public List getDietList(HandleRequestDto parameters, int cafeteriaId) { - // 오늘, 내일 문자열로 날짜 설정하기 - Date dietDate = parameters.getDietDate(); - // 식단 데이터 반환 - return dietRepositoryV2.findDietList(dietDate, parameters.getPeriod(), cafeteriaId); + String key = parameters.getDietDate() + "::" + parameters.getPeriod() + "::" + cafeteriaId; + + List cached = (List) redisConfig.redisTemplate().opsForValue().get(key); + if (cached != null) return cached; + + List result = dietRepositoryV2.findDietList(parameters.getDietDate(), parameters.getPeriod(), cafeteriaId); + + if (result != null && !result.isEmpty()) { + long ttlSeconds = calculateTtlUntilNextMidnight(parameters.getDietDate()); + redisConfig.redisTemplate().opsForValue().set(key, result, Duration.ofSeconds(ttlSeconds)); + } + + return result; + } + + // 식단 데이터 TTL 동적 생성 -> 조회 시간과 하루 뒤의 자정시간까지의 시간차이가 TTL 시간 + // 즉, 날짜가 바뀌면 만료되어야 함 + private long calculateTtlUntilNextMidnight(Date dietDate) { + LocalDateTime expireAt = dietDate.toLocalDate().plusDays(1).atStartOfDay(); // dietDate + 1일 자정 + LocalDateTime now = LocalDateTime.now(); + + Duration duration = Duration.between(now, expireAt); + long seconds = duration.getSeconds(); + + // 만약 이미 만료되었거나, 현재 시간이 더 크면 0 리턴 (저장 안 함) + return seconds > 0 ? seconds : 0; } // Redis에서 조회 (없으면 DB에서 가져옴) -// @Cacheable(value = "cafeteriaList", key = "#campusId", cacheManager = "contentCacheManager") + @Cacheable( + value = "cafeteriaList", + key = "#p0", + cacheManager = "contentCacheManager") public List getCafeteriaList(int campusId) { return cafeteriaRepositoryV2.findCafeteriaListByCampusId(campusId); } diff --git a/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaQueryServiceV2.java b/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaQueryServiceV2.java index 305f4fa..b974ae5 100644 --- a/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaQueryServiceV2.java +++ b/src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaQueryServiceV2.java @@ -2,21 +2,29 @@ import com.example.Jinus.repository.v2.cafeteria.CafeteriaRepositoryV2; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor +@Slf4j public class CafeteriaQueryServiceV2 { private final CafeteriaRepositoryV2 cafeteriaRepositoryV2; -// @Cacheable(value = "cafeteriaId", key = "#campusId + '::' + #cafeteriaName", -// unless = "#result == -1", -// cacheManager = "contentCacheManager") + @Cacheable( + value = "cafeteriaId", + key = "#p0 + '::' + #p1", + unless = "#result == -1", + cacheManager = "contentCacheManager") public int getCafeteriaId(String cafeteriaName, int campusId) { return cafeteriaRepositoryV2.findCafeteriaId(cafeteriaName, campusId).orElse(-1); } + @Cacheable( + value = "cafeteriaUrl", + key = "#p0", + cacheManager = "contentCacheManager") public String getImgUrl(int cafeteriaId) { return cafeteriaRepositoryV2.findImgUrlByCafeteriaId(cafeteriaId); } diff --git a/src/main/java/com/example/Jinus/service/v2/cafeteria/CampusServiceV2.java b/src/main/java/com/example/Jinus/service/v2/cafeteria/CampusServiceV2.java index 4f4e938..8e4c1bc 100644 --- a/src/main/java/com/example/Jinus/service/v2/cafeteria/CampusServiceV2.java +++ b/src/main/java/com/example/Jinus/service/v2/cafeteria/CampusServiceV2.java @@ -3,15 +3,22 @@ import com.example.Jinus.entity.cafeteria.CampusEntity; import com.example.Jinus.repository.v2.cafeteria.CampusRepositoryV2; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import java.util.List; @Service @RequiredArgsConstructor +@Slf4j public class CampusServiceV2 { private final CampusRepositoryV2 campusRepositoryV2; + @Cacheable( + value = "campusId", + key = "#p0", + cacheManager = "contentCacheManager") // 사용자의 campusId 받아 캠퍼스 이름 찾기 public String getUserCampusName(int campusId) { return campusRepositoryV2.findCampusNameByCampusId(campusId); @@ -22,7 +29,10 @@ public List getCampusList() { return campusRepositoryV2.findCampusList(); } -// @Cacheable(value = "campusName", key = "#campusName", cacheManager = "contentCacheManager") + @Cacheable( + value = "campusName", + key = "#p0", + cacheManager = "contentCacheManager") // 캠퍼스 이름으로 id 찾기 public int getCampusId(String campusName) { return campusRepositoryV2.findCampusIdByName(campusName); diff --git a/src/main/java/com/example/Jinus/service/v2/cafeteria/DietParameterServiceV2.java b/src/main/java/com/example/Jinus/service/v2/cafeteria/DietParameterServiceV2.java index 60d5139..c13a527 100644 --- a/src/main/java/com/example/Jinus/service/v2/cafeteria/DietParameterServiceV2.java +++ b/src/main/java/com/example/Jinus/service/v2/cafeteria/DietParameterServiceV2.java @@ -5,6 +5,7 @@ import com.example.Jinus.dto.request.RequestDto; import com.example.Jinus.service.v2.userInfo.UserServiceV2; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.sql.Date; @@ -14,6 +15,7 @@ @Service @RequiredArgsConstructor +@Slf4j public class DietParameterServiceV2 { private final UserServiceV2 userServiceV2; diff --git a/src/main/java/com/example/Jinus/service/v2/cafeteria/DietQueryServiceV2.java b/src/main/java/com/example/Jinus/service/v2/cafeteria/DietQueryServiceV2.java index 8ec2634..5cd0c6f 100644 --- a/src/main/java/com/example/Jinus/service/v2/cafeteria/DietQueryServiceV2.java +++ b/src/main/java/com/example/Jinus/service/v2/cafeteria/DietQueryServiceV2.java @@ -4,6 +4,7 @@ import com.example.Jinus.dto.data.HandleRequestDto; import com.example.Jinus.repository.v2.cafeteria.DietRepositoryV2; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -15,6 +16,7 @@ @Service @RequiredArgsConstructor +@Slf4j public class DietQueryServiceV2 { private final CacheServiceV2 cacheServiceV2; @@ -22,29 +24,20 @@ public class DietQueryServiceV2 { // 메뉴 존재 여부에 따른 반환값 처리 로직 public String getDietResponse(HandleRequestDto parameters, int cafeteriaId) { + // 메뉴 가져오기 + List dietDtos = cacheServiceV2.getDietList(parameters, cafeteriaId); // 메뉴 존재하는 경우 - if (checkThereIsDiet(parameters, cafeteriaId) != -1) { + if (!dietDtos.isEmpty()) { // 메뉴 찾기 - MultiValueMap dietList = getDiets(parameters, cafeteriaId); + MultiValueMap dietList = getDiets(dietDtos); return processDietList(dietList).toString(); } return "\n메뉴가 존재하지 않습니다."; // 메뉴가 없는 경우 } - // 식당 메뉴 존재여부 확인 - private int checkThereIsDiet(HandleRequestDto parameters, int cafeteriaId) { - // 오늘, 내일 문자열로 날짜 설정하기 - Date dietDate = parameters.getDietDate(); - List dietDtos = - dietRepositoryV2.findDietList(dietDate, parameters.getPeriod(), cafeteriaId); - return (!dietDtos.isEmpty()) ? 1 : -1; - } - - // 카테고리별 메뉴 리스트 생성하기 - private MultiValueMap getDiets(HandleRequestDto parameters, int cafeteriaId) { - List dietDtos = cacheServiceV2.getDietList(parameters, cafeteriaId); + private MultiValueMap getDiets(List dietDtos) { MultiValueMap dietList = new LinkedMultiValueMap<>(); // 중복 키 허용(값을 리스트로 반환) for (DietDto o : dietDtos) { diff --git a/src/main/java/com/example/Jinus/service/v2/cafeteria/DietServiceV2.java b/src/main/java/com/example/Jinus/service/v2/cafeteria/DietServiceV2.java index e6a4598..9439e14 100644 --- a/src/main/java/com/example/Jinus/service/v2/cafeteria/DietServiceV2.java +++ b/src/main/java/com/example/Jinus/service/v2/cafeteria/DietServiceV2.java @@ -2,20 +2,18 @@ import com.example.Jinus.dto.data.HandleRequestDto; import com.example.Jinus.dto.request.RequestDto; -import com.example.Jinus.repository.v2.cafeteria.DietRepositoryV2; import com.example.Jinus.utility.DateUtils; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import org.springframework.util.MultiValueMap; import java.sql.Date; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.ZoneId; -import java.util.Set; -import java.util.TreeSet; @Service +@Slf4j @RequiredArgsConstructor public class DietServiceV2 { diff --git a/src/main/java/com/example/Jinus/service/v2/userInfo/UserServiceV2.java b/src/main/java/com/example/Jinus/service/v2/userInfo/UserServiceV2.java index ae0a802..387e0b4 100644 --- a/src/main/java/com/example/Jinus/service/v2/userInfo/UserServiceV2.java +++ b/src/main/java/com/example/Jinus/service/v2/userInfo/UserServiceV2.java @@ -2,6 +2,7 @@ import com.example.Jinus.repository.v2.userInfo.UserRepositoryV2; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; @@ -11,6 +12,7 @@ @Service @RequiredArgsConstructor +@Slf4j public class UserServiceV2 { private final UserRepositoryV2 userRepositoryV2; From cbd71efc1c2ef8652edd15cf3a567a68452afe02 Mon Sep 17 00:00:00 2001 From: hykim02 Date: Mon, 21 Apr 2025 23:14:15 +0900 Subject: [PATCH 8/8] =?UTF-8?q?[fix]userService=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D=ED=95=9C=20hikariCP=20connection=20error=20?= =?UTF-8?q?=EC=B0=BE=EB=8A=94=20=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/v2/userInfo/UserServiceV2.java | 51 ------------------- 1 file changed, 51 deletions(-) diff --git a/src/main/java/com/example/Jinus/service/v2/userInfo/UserServiceV2.java b/src/main/java/com/example/Jinus/service/v2/userInfo/UserServiceV2.java index 387e0b4..faa85bf 100644 --- a/src/main/java/com/example/Jinus/service/v2/userInfo/UserServiceV2.java +++ b/src/main/java/com/example/Jinus/service/v2/userInfo/UserServiceV2.java @@ -16,57 +16,6 @@ public class UserServiceV2 { private final UserRepositoryV2 userRepositoryV2; - private final RedisTemplate redisTemplate; - -// // 사용자 등록 여부 확인 -// public int getUserCampusId(String userId) { -// // redis에서 데이터 찾음 -// String key = "campusId:" + userId; -// // null값 처리 위해 Integer 사용 -// Integer campusId = (Integer) redisTemplate.opsForValue().get(key); -// System.out.println("campusId:" + campusId); -// -// // redis에 데이터 없는 경우 db 조회 -// if (campusId == null) { -// campusId = userRepositoryV2.findCampusIdById(userId).orElse(-1); -// // campusId가 -1이 아니면 캐시 저장 -// if (campusId != -1) { -// redisTemplate.opsForValue().set(key, campusId, Duration.ofDays(1)); // 1일 TTL 설정 -// } -// } -// return campusId; -// } -// -// // 사용자 학과 id 찾기 -// public int getUserDepartmentId(String userId) { -// String key = "departmentId:" + userId; -// Integer departmentId = (Integer) redisTemplate.opsForValue().get(key); -// System.out.println("departmentId:" + departmentId); -// -// if (departmentId == null) { -// departmentId = userRepositoryV2.findDepartmentIdById(userId).orElse(-1); -// // campusId가 -1이 아니면 캐시 저장 -// if (departmentId != -1) { -// redisTemplate.opsForValue().set(key, departmentId, Duration.ofDays(1)); // 1일 TTL 설정 -// } -// } -// return getParentDepartmentId(departmentId); -// } -// -// // 부모 게시판 매핑 (해당 학과 ID가 없으면 기본값 그대로 유지) -// public int getParentDepartmentId(int childDepartmentId) { -// Map parentDepartmentMap = Map.of( -// 52, 51, -// 53, 51, -// 103, 102, -// 104, 102, -// 106, 105, -// 107, 105 -// ); -// return parentDepartmentMap.getOrDefault(childDepartmentId, childDepartmentId); -// } - - public int getUserCampusId(String userId) { Optional campusId = userRepositoryV2.findCampusIdById(userId);