diff --git a/src/main/java/com/example/solidconnection/university/repository/UniversityInfoForApplyRepository.java b/src/main/java/com/example/solidconnection/university/repository/UniversityInfoForApplyRepository.java index 4adc0d718..60474c13d 100644 --- a/src/main/java/com/example/solidconnection/university/repository/UniversityInfoForApplyRepository.java +++ b/src/main/java/com/example/solidconnection/university/repository/UniversityInfoForApplyRepository.java @@ -45,6 +45,14 @@ OR u.region.code IN ( """) List findUniversityInfoForAppliesBySiteUsersInterestedCountryOrRegionAndTerm(@Param("siteUser") SiteUser siteUser, @Param("term") String term); + @Query(value = """ + SELECT * + FROM university_info_for_apply + WHERE term = :term + ORDER BY RAND() LIMIT :limitNum + """, nativeQuery = true) + List findRandomByTerm(@Param("term") String term, @Param("limitNum") int limitNum); + default UniversityInfoForApply getUniversityInfoForApplyById(Long id) { return findById(id) .orElseThrow(() -> new CustomException(UNIVERSITY_INFO_FOR_APPLY_NOT_FOUND)); diff --git a/src/main/java/com/example/solidconnection/university/service/GeneralRecommendUniversities.java b/src/main/java/com/example/solidconnection/university/service/GeneralRecommendUniversities.java deleted file mode 100644 index 92054eee6..000000000 --- a/src/main/java/com/example/solidconnection/university/service/GeneralRecommendUniversities.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.example.solidconnection.university.service; - -import com.example.solidconnection.repositories.CountryRepository; -import com.example.solidconnection.university.domain.UniversityInfoForApply; -import com.example.solidconnection.university.repository.UniversityInfoForApplyRepository; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.context.event.EventListener; -import org.springframework.stereotype.Component; - -import java.util.List; - -import static com.example.solidconnection.university.service.UniversityRecommendService.RECOMMEND_UNIVERSITY_NUM; - -@RequiredArgsConstructor -@Component -public class GeneralRecommendUniversities { - - /* - * 매 선발 시기(term) 마다 지원할 수 있는 대학교가 달라지므르, 추천 대학교도 달라져야 한다. - * 하지만 매번 추천 대학교를 바꾸기에는 번거롭다. - * 따라서 '추천 대학교 후보'들을 설정하고, DB 에서 현재 term 에 대해 찾아지는 대학교만 추천 대학교로 지정한다. - * */ - @Getter - private final List recommendUniversities; - private final UniversityInfoForApplyRepository universityInfoForApplyRepository; - private final CountryRepository countryRepository; - private final List candidates = List.of( - "오스트라바 대학", "RMIT멜버른공과대학(A형)", "알브슈타트 지그마링엔 대학", - "뉴저지시티대학(A형)", "도요대학", "템플대학(A형)", "빈 공과대학교", - "리스본대학 공과대학", "바덴뷔르템베르크 산학협력대학", "긴다이대학", "네바다주립대학 라스베이거스(B형)", "릴 가톨릭 대학", - "그라츠공과대학", "그라츠 대학", "코펜하겐 IT대학", "메이지대학", "분쿄가쿠인대학", "린츠 카톨릭 대학교", - "밀라노공과대학", "장물랭리옹3세대학교", "시드니대학", "아우크스부르크대학", "쳄니츠 공과대학", "북경외국어대학교 IBS" - ); - - @Value("${university.term}") - public String term; - - @EventListener(ApplicationReadyEvent.class) - public void init() { - int i = 0; - while (recommendUniversities.size() < RECOMMEND_UNIVERSITY_NUM && i < candidates.size()) { - universityInfoForApplyRepository.findFirstByKoreanNameAndTerm(candidates.get(i), term) - .ifPresent(recommendUniversities::add); - i++; - } - } -} diff --git a/src/main/java/com/example/solidconnection/university/service/GeneralUniversityRecommendService.java b/src/main/java/com/example/solidconnection/university/service/GeneralUniversityRecommendService.java new file mode 100644 index 000000000..d39fee1ec --- /dev/null +++ b/src/main/java/com/example/solidconnection/university/service/GeneralUniversityRecommendService.java @@ -0,0 +1,35 @@ +package com.example.solidconnection.university.service; + +import com.example.solidconnection.university.domain.UniversityInfoForApply; +import com.example.solidconnection.university.repository.UniversityInfoForApplyRepository; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Service; + +import java.util.List; + +import static com.example.solidconnection.university.service.UniversityRecommendService.RECOMMEND_UNIVERSITY_NUM; + +@Service +@RequiredArgsConstructor +public class GeneralUniversityRecommendService { + + /* + * 해당 시기에 열리는 대학교들 중 랜덤으로 선택해서 목록을 구성한다. + * */ + private final UniversityInfoForApplyRepository universityInfoForApplyRepository; + + @Getter + private List recommendUniversities; + + @Value("${university.term}") + public String term; + + @EventListener(ApplicationReadyEvent.class) + public void init() { + recommendUniversities = universityInfoForApplyRepository.findRandomByTerm(term, RECOMMEND_UNIVERSITY_NUM); + } +} diff --git a/src/main/java/com/example/solidconnection/university/service/UniversityRecommendService.java b/src/main/java/com/example/solidconnection/university/service/UniversityRecommendService.java index 6a6a43fbf..654b08390 100644 --- a/src/main/java/com/example/solidconnection/university/service/UniversityRecommendService.java +++ b/src/main/java/com/example/solidconnection/university/service/UniversityRecommendService.java @@ -23,7 +23,7 @@ public class UniversityRecommendService { public static final int RECOMMEND_UNIVERSITY_NUM = 6; private final UniversityInfoForApplyRepository universityInfoForApplyRepository; - private final GeneralRecommendUniversities generalRecommendUniversities; + private final GeneralUniversityRecommendService generalUniversityRecommendService; private final SiteUserRepository siteUserRepository; @Value("${university.term}") @@ -56,7 +56,7 @@ public UniversityRecommendsResponse getPersonalRecommends(String email) { } private List getGeneralRecommendsExcludingSelected(List alreadyPicked) { - List generalRecommend = new ArrayList<>(generalRecommendUniversities.getRecommendUniversities()); + List generalRecommend = new ArrayList<>(generalUniversityRecommendService.getRecommendUniversities()); generalRecommend.removeAll(alreadyPicked); Collections.shuffle(generalRecommend); return generalRecommend.subList(0, RECOMMEND_UNIVERSITY_NUM - alreadyPicked.size()); @@ -68,8 +68,7 @@ private List getGeneralRecommendsExcludingSelected(List< @Transactional(readOnly = true) @ThunderingHerdCaching(key = "university:recommend:general", cacheManager = "customCacheManager", ttlSec = 86400) public UniversityRecommendsResponse getGeneralRecommends() { - List generalRecommends = new ArrayList<>(generalRecommendUniversities.getRecommendUniversities()); - Collections.shuffle(generalRecommends); + List generalRecommends = new ArrayList<>(generalUniversityRecommendService.getRecommendUniversities()); return new UniversityRecommendsResponse(generalRecommends.stream() .map(UniversityInfoForApplyPreviewResponse::from) .toList()); diff --git a/src/test/java/com/example/solidconnection/e2e/UniversityRecommendTest.java b/src/test/java/com/example/solidconnection/e2e/UniversityRecommendTest.java index 00afbc8e3..4f3bd3042 100644 --- a/src/test/java/com/example/solidconnection/e2e/UniversityRecommendTest.java +++ b/src/test/java/com/example/solidconnection/e2e/UniversityRecommendTest.java @@ -10,7 +10,7 @@ import com.example.solidconnection.siteuser.repository.SiteUserRepository; import com.example.solidconnection.university.dto.UniversityInfoForApplyPreviewResponse; import com.example.solidconnection.university.dto.UniversityRecommendsResponse; -import com.example.solidconnection.university.service.GeneralRecommendUniversities; +import com.example.solidconnection.university.service.GeneralUniversityRecommendService; import io.restassured.RestAssured; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -41,7 +41,7 @@ class UniversityRecommendTest extends UniversityDataSetUpEndToEndTest { private TokenProvider tokenProvider; @Autowired - private GeneralRecommendUniversities generalRecommendUniversities; + private GeneralUniversityRecommendService generalUniversityRecommendService; private SiteUser siteUser; private String accessToken; @@ -51,7 +51,7 @@ void setUp() { // setUp - 회원 정보 저장 String email = "email@email.com"; siteUser = siteUserRepository.save(createSiteUserByEmail(email)); - generalRecommendUniversities.init(); + generalUniversityRecommendService.init(); // setUp - 엑세스 토큰 생성과 리프레시 토큰 생성 및 저장 accessToken = tokenProvider.generateToken(email, TokenType.ACCESS); @@ -156,7 +156,7 @@ void setUp() { .extract().as(UniversityRecommendsResponse.class); List generalRecommendUniversities - = this.generalRecommendUniversities.getRecommendUniversities().stream() + = this.generalUniversityRecommendService.getRecommendUniversities().stream() .map(UniversityInfoForApplyPreviewResponse::from) .toList(); assertAll( @@ -179,7 +179,7 @@ void setUp() { .extract().as(UniversityRecommendsResponse.class); List generalRecommendUniversities - = this.generalRecommendUniversities.getRecommendUniversities().stream() + = this.generalUniversityRecommendService.getRecommendUniversities().stream() .map(UniversityInfoForApplyPreviewResponse::from) .toList(); assertAll( diff --git a/src/test/java/com/example/solidconnection/university/service/GeneralUniversityRecommendServiceTest.java b/src/test/java/com/example/solidconnection/university/service/GeneralUniversityRecommendServiceTest.java new file mode 100644 index 000000000..d93765a44 --- /dev/null +++ b/src/test/java/com/example/solidconnection/university/service/GeneralUniversityRecommendServiceTest.java @@ -0,0 +1,41 @@ +package com.example.solidconnection.university.service; + +import com.example.solidconnection.support.TestContainerSpringBootTest; +import com.example.solidconnection.support.integration.BaseIntegrationTest; +import com.example.solidconnection.university.domain.UniversityInfoForApply; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; + +import java.util.List; + +import static com.example.solidconnection.university.service.UniversityRecommendService.RECOMMEND_UNIVERSITY_NUM; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +@DisplayName("공통 추천 대학 서비스 테스트") +@TestContainerSpringBootTest +class GeneralUniversityRecommendServiceTest extends BaseIntegrationTest { + + @Autowired + private GeneralUniversityRecommendService generalUniversityRecommendService; + + @Value("${university.term}") + private String term; + + @Test + void 모집_시기의_대학들_중에서_랜덤하게_N개를_추천_목록으로_구성한다() { + // given + generalUniversityRecommendService.init(); + List universities = generalUniversityRecommendService.getRecommendUniversities(); + + // when & then + assertAll( + () -> assertThat(universities) + .extracting("term") + .allMatch(term::equals), + () -> assertThat(universities).hasSize(RECOMMEND_UNIVERSITY_NUM) + ); + } +} diff --git a/src/test/java/com/example/solidconnection/university/service/UniversityRecommendServiceTest.java b/src/test/java/com/example/solidconnection/university/service/UniversityRecommendServiceTest.java index cadd45aaf..17d951614 100644 --- a/src/test/java/com/example/solidconnection/university/service/UniversityRecommendServiceTest.java +++ b/src/test/java/com/example/solidconnection/university/service/UniversityRecommendServiceTest.java @@ -38,11 +38,11 @@ class UniversityRecommendServiceTest extends BaseIntegrationTest { private InterestedCountyRepository interestedCountyRepository; @Autowired - private GeneralRecommendUniversities generalRecommendUniversities; + private GeneralUniversityRecommendService generalUniversityRecommendService; @BeforeEach void setUp() { - generalRecommendUniversities.init(); + generalUniversityRecommendService.init(); } @Test @@ -118,7 +118,7 @@ void setUp() { assertThat(response.recommendedUniversities()) .hasSize(RECOMMEND_UNIVERSITY_NUM) .containsExactlyInAnyOrderElementsOf( - generalRecommendUniversities.getRecommendUniversities().stream() + generalUniversityRecommendService.getRecommendUniversities().stream() .map(UniversityInfoForApplyPreviewResponse::from) .toList() ); @@ -133,7 +133,7 @@ void setUp() { assertThat(response.recommendedUniversities()) .hasSize(RECOMMEND_UNIVERSITY_NUM) .containsExactlyInAnyOrderElementsOf( - generalRecommendUniversities.getRecommendUniversities().stream() + generalUniversityRecommendService.getRecommendUniversities().stream() .map(UniversityInfoForApplyPreviewResponse::from) .toList() );