From b215af90daa7225c325b023db727553e68fb2228 Mon Sep 17 00:00:00 2001 From: chounjae Date: Mon, 23 Feb 2026 21:31:01 +0900 Subject: [PATCH 1/4] =?UTF-8?q?[#18];=20refactor:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=ED=95=84=EB=93=9C=20=EC=A0=9C=EA=B1=B0=20?= =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/UniversitySearchRequest.kt | 11 +++++++++-- .../university/business/UniversityServiceImpl.kt | 1 - .../university/business/query/UniversityQuery.kt | 1 - .../domain/university/implement/UniversityReader.kt | 3 +-- .../university/implement/UniversityRepository.kt | 1 - .../university/storage/UniversityRepositoryImpl.kt | 3 --- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/kotlin/org/example/beyondubackend/domain/university/application/dto/UniversitySearchRequest.kt b/src/main/kotlin/org/example/beyondubackend/domain/university/application/dto/UniversitySearchRequest.kt index 69073b8..fdb46c6 100644 --- a/src/main/kotlin/org/example/beyondubackend/domain/university/application/dto/UniversitySearchRequest.kt +++ b/src/main/kotlin/org/example/beyondubackend/domain/university/application/dto/UniversitySearchRequest.kt @@ -1,15 +1,23 @@ package org.example.beyondubackend.domain.university.application.dto +import io.swagger.v3.oas.annotations.media.Schema import org.example.beyondubackend.domain.university.business.query.UniversityQuery data class UniversitySearchRequest( + @Schema(description = "국가 필터 (예: 미국, 일본)") val nation: String? = null, + @Schema(description = "교환학생 가능 여부") val isExchange: Boolean? = null, + @Schema(description = "방문학생 가능 여부") val isVisit: Boolean? = null, + //TO DO: 대학 이름 검색 사용시 추가 + @Schema(hidden = true) val search: String? = null, + @Schema(description = "최소 GPA (입력한 GPA 이상 지원 가능한 학교 조회)", example = "3.5") val gpa: Double? = null, - val nations: String? = null, + @Schema(description = "전공 필터") val major: String? = null, + @Schema(description = "후기 보유 여부") val hasReview: Boolean? = null ) { fun toQuery(examScores: Map): UniversityQuery { @@ -19,7 +27,6 @@ data class UniversitySearchRequest( isVisit = isVisit, search = search, gpa = gpa, - nations = nations, major = major, hasReview = hasReview, examScores = examScores diff --git a/src/main/kotlin/org/example/beyondubackend/domain/university/business/UniversityServiceImpl.kt b/src/main/kotlin/org/example/beyondubackend/domain/university/business/UniversityServiceImpl.kt index 0d9cc52..6ac40f4 100644 --- a/src/main/kotlin/org/example/beyondubackend/domain/university/business/UniversityServiceImpl.kt +++ b/src/main/kotlin/org/example/beyondubackend/domain/university/business/UniversityServiceImpl.kt @@ -25,7 +25,6 @@ class UniversityServiceImpl( isVisit = query.isVisit, search = query.search, gpa = query.gpa, - nations = query.nations, major = query.major, hasReview = query.hasReview, examScores = query.examScores, diff --git a/src/main/kotlin/org/example/beyondubackend/domain/university/business/query/UniversityQuery.kt b/src/main/kotlin/org/example/beyondubackend/domain/university/business/query/UniversityQuery.kt index 7fd2a52..8e1914b 100644 --- a/src/main/kotlin/org/example/beyondubackend/domain/university/business/query/UniversityQuery.kt +++ b/src/main/kotlin/org/example/beyondubackend/domain/university/business/query/UniversityQuery.kt @@ -6,7 +6,6 @@ data class UniversityQuery( val isVisit: Boolean? = null, val search: String? = null, val gpa: Double? = null, - val nations: String? = null, val major: String? = null, val hasReview: Boolean? = null, val examScores: Map = emptyMap() diff --git a/src/main/kotlin/org/example/beyondubackend/domain/university/implement/UniversityReader.kt b/src/main/kotlin/org/example/beyondubackend/domain/university/implement/UniversityReader.kt index 8c75792..66ff868 100644 --- a/src/main/kotlin/org/example/beyondubackend/domain/university/implement/UniversityReader.kt +++ b/src/main/kotlin/org/example/beyondubackend/domain/university/implement/UniversityReader.kt @@ -20,14 +20,13 @@ class UniversityReader( isVisit: Boolean?, search: String?, gpa: Double?, - nations: String?, major: String?, hasReview: Boolean?, examScores: Map, pageable: Pageable ): Page { return universityRepository.findAllWithFilters( - nation, isExchange, isVisit, search, gpa, nations, major, hasReview, examScores, pageable + nation, isExchange, isVisit, search, gpa, major, hasReview, examScores, pageable ) } diff --git a/src/main/kotlin/org/example/beyondubackend/domain/university/implement/UniversityRepository.kt b/src/main/kotlin/org/example/beyondubackend/domain/university/implement/UniversityRepository.kt index 9db37da..2680c3b 100644 --- a/src/main/kotlin/org/example/beyondubackend/domain/university/implement/UniversityRepository.kt +++ b/src/main/kotlin/org/example/beyondubackend/domain/university/implement/UniversityRepository.kt @@ -10,7 +10,6 @@ interface UniversityRepository { isVisit: Boolean?, search: String?, gpa: Double?, - nations: String?, major: String?, hasReview: Boolean?, examScores: Map, diff --git a/src/main/kotlin/org/example/beyondubackend/domain/university/storage/UniversityRepositoryImpl.kt b/src/main/kotlin/org/example/beyondubackend/domain/university/storage/UniversityRepositoryImpl.kt index fbdc8eb..9f23bdd 100644 --- a/src/main/kotlin/org/example/beyondubackend/domain/university/storage/UniversityRepositoryImpl.kt +++ b/src/main/kotlin/org/example/beyondubackend/domain/university/storage/UniversityRepositoryImpl.kt @@ -24,7 +24,6 @@ class UniversityRepositoryImpl( isVisit: Boolean?, search: String?, gpa: Double?, - nations: String?, major: String?, hasReview: Boolean?, examScores: Map, @@ -39,7 +38,6 @@ class UniversityRepositoryImpl( isVisitEq(isVisit), searchKeyword(search), gpaLoe(gpa), - nationsIn(nations), majorContains(major), hasReviewEq(hasReview), examScoresMatch(examScores) @@ -66,7 +64,6 @@ class UniversityRepositoryImpl( isVisitEq(isVisit), searchKeyword(search), gpaLoe(gpa), - nationsIn(nations), majorContains(major), hasReviewEq(hasReview), examScoresMatch(examScores) From 001780e8c1a4fc1129c5cb1cfc6e7e3e8bbc05f9 Mon Sep 17 00:00:00 2001 From: chounjae Date: Mon, 23 Feb 2026 21:48:02 +0900 Subject: [PATCH 2/4] =?UTF-8?q?[#18];=20fix:=20=EB=B0=A9=EB=AC=B8=EC=9C=A0?= =?UTF-8?q?=ED=98=95=20=EC=9D=91=EB=8B=B5=EC=97=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../university/business/dto/UniversityDetailResponse.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/kotlin/org/example/beyondubackend/domain/university/business/dto/UniversityDetailResponse.kt b/src/main/kotlin/org/example/beyondubackend/domain/university/business/dto/UniversityDetailResponse.kt index cee5332..21775eb 100644 --- a/src/main/kotlin/org/example/beyondubackend/domain/university/business/dto/UniversityDetailResponse.kt +++ b/src/main/kotlin/org/example/beyondubackend/domain/university/business/dto/UniversityDetailResponse.kt @@ -10,6 +10,7 @@ data class UniversityDetailResponse( val region: String, val isExchange: Boolean, val isVisit: Boolean, + val programType: String, val badge: String, val hasReview: Boolean, val minGpa: Double, @@ -26,6 +27,12 @@ data class UniversityDetailResponse( university: University, languageRequirements: List ): UniversityDetailResponse { + val programType = when { + university.isExchange -> "일반교환" + university.isVisit -> "방문교환" + else -> "" + } + return UniversityDetailResponse( id = university.id!!, nameKor = university.nameKor, @@ -34,6 +41,7 @@ data class UniversityDetailResponse( region = university.region, isExchange = university.isExchange, isVisit = university.isVisit, + programType = programType, badge = university.badge, hasReview = university.hasReview, minGpa = university.minGpa, From 94524019048956fc9029124aff613cc7005397ab Mon Sep 17 00:00:00 2001 From: chounjae Date: Mon, 23 Feb 2026 21:57:21 +0900 Subject: [PATCH 3/4] =?UTF-8?q?[#18];=20refactor:=20Swagger=20=ED=8C=8C?= =?UTF-8?q?=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EB=AA=85=EC=84=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/UniversityController.kt | 59 +++++++++++++++++-- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/org/example/beyondubackend/domain/university/application/UniversityController.kt b/src/main/kotlin/org/example/beyondubackend/domain/university/application/UniversityController.kt index 889d615..7066fdf 100644 --- a/src/main/kotlin/org/example/beyondubackend/domain/university/application/UniversityController.kt +++ b/src/main/kotlin/org/example/beyondubackend/domain/university/application/UniversityController.kt @@ -2,6 +2,9 @@ package org.example.beyondubackend.domain.university.application import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.Parameter +import io.swagger.v3.oas.annotations.Parameters +import io.swagger.v3.oas.annotations.enums.ParameterIn +import io.swagger.v3.oas.annotations.media.Schema import io.swagger.v3.oas.annotations.tags.Tag import org.example.beyondubackend.common.annotation.ExamScoreParams import org.example.beyondubackend.common.dto.ApiResponse @@ -9,6 +12,7 @@ import org.example.beyondubackend.domain.university.application.dto.UniversitySe import org.example.beyondubackend.domain.university.business.UniversityService import org.example.beyondubackend.domain.university.business.dto.UniversityDetailResponse import org.example.beyondubackend.domain.university.business.dto.UniversityListResponse +import org.springdoc.core.annotations.ParameterObject import org.springframework.data.domain.PageRequest import org.springframework.data.domain.Sort import org.springframework.http.ResponseEntity @@ -25,18 +29,61 @@ class UniversityController( summary = "대학교 목록 조회", description = """ 대학교 목록을 조회합니다. - - 필터링: nation, isExchange, isVisit, gpa, nations, major, hasReview - - 언어 점수: TOEFL, IELTS, TOEIC, JLPT 등 - - 페이지네이션: page + - 필터링: nation, isExchange, isVisit, gpa, major, hasReview + - 어학 점수 필터: TOEFL_IBT, TOEFL_ITP, IELTS, TOEIC, TOEIC_Speaking, HSK, JLPT, JPT, DELF, ZD + - 페이지네이션: page (기본값 0), size (기본값 12) + - 모든 파라미터는 optional이며, null이면 전체 조회 """ ) + @Parameters(value = [ + Parameter( + name = "TOEFL_IBT", description = "TOEFL iBT 점수", + required = false, `in` = ParameterIn.QUERY, schema = Schema(type = "number", example = "80") + ), + Parameter( + name = "TOEFL_ITP", description = "TOEFL ITP 점수", + required = false, `in` = ParameterIn.QUERY, schema = Schema(type = "number", example = "550") + ), + Parameter( + name = "IELTS", description = "IELTS 점수", + required = false, `in` = ParameterIn.QUERY, schema = Schema(type = "number", example = "6.5") + ), + Parameter( + name = "TOEIC", description = "TOEIC 점수", + required = false, `in` = ParameterIn.QUERY, schema = Schema(type = "number", example = "800") + ), + Parameter( + name = "TOEIC_Speaking", description = "TOEIC Speaking 점수", + required = false, `in` = ParameterIn.QUERY, schema = Schema(type = "number", example = "160") + ), + Parameter( + name = "HSK", description = "HSK 급수", + required = false, `in` = ParameterIn.QUERY, schema = Schema(type = "number", example = "4") + ), + Parameter( + name = "JLPT", description = "JLPT 레벨 (1=N1 ~ 5=N5, 숫자가 낮을수록 높은 레벨)", + required = false, `in` = ParameterIn.QUERY, schema = Schema(type = "number", example = "2") + ), + Parameter( + name = "JPT", description = "JPT 점수", + required = false, `in` = ParameterIn.QUERY, schema = Schema(type = "number", example = "700") + ), + Parameter( + name = "DELF", description = "DELF 급수", + required = false, `in` = ParameterIn.QUERY, schema = Schema(type = "number", example = "4") + ), + Parameter( + name = "ZD", description = "ZD 급수 (독어 자격증)", + required = false, `in` = ParameterIn.QUERY, schema = Schema(type = "number", example = "4") + ) + ]) @GetMapping fun getUniversities( - @ModelAttribute request: UniversitySearchRequest, - @Parameter(description = "언어 시험 점수 (예: TOEFL=80, IELTS=6.5)", required = false) - @ExamScoreParams examScores: Map, + @ParameterObject @ModelAttribute request: UniversitySearchRequest, + @Parameter(hidden = true) @ExamScoreParams examScores: Map, @Parameter(description = "페이지 번호", example = "0") @RequestParam(defaultValue = "0") page: Int, + @Parameter(description = "페이지 크기", example = "12") @RequestParam(defaultValue = "12") size: Int ): ResponseEntity> { val pageable = PageRequest.of(page, size, Sort.by(Sort.Order.asc("nameEng"), Sort.Order.asc("nameKor"))) From 5797db807efc1741d3690856a586521657964e99 Mon Sep 17 00:00:00 2001 From: chounjae Date: Mon, 23 Feb 2026 21:57:38 +0900 Subject: [PATCH 4/4] =?UTF-8?q?[#18];=20fix:=20Location=20=ED=8C=8C?= =?UTF-8?q?=EC=8B=B1=20=EC=9D=91=EB=8B=B5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business/dto/UniversityDetailResponse.kt | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/org/example/beyondubackend/domain/university/business/dto/UniversityDetailResponse.kt b/src/main/kotlin/org/example/beyondubackend/domain/university/business/dto/UniversityDetailResponse.kt index 21775eb..e63e589 100644 --- a/src/main/kotlin/org/example/beyondubackend/domain/university/business/dto/UniversityDetailResponse.kt +++ b/src/main/kotlin/org/example/beyondubackend/domain/university/business/dto/UniversityDetailResponse.kt @@ -21,6 +21,7 @@ data class UniversityDetailResponse( val availableMajors: List?, val courseListUrl: String?, val studentCount: String?, + val location: String?, ) { companion object { fun from( @@ -52,6 +53,7 @@ data class UniversityDetailResponse( availableMajors = parseAvailableMajors(university.availableMajors), courseListUrl = parseCourseListUrl(university.availableMajors), studentCount = parseStudentCount(university.remark), + location = parseLocation(university.remark), ) } @@ -82,6 +84,18 @@ data class UniversityDetailResponse( return regex.find(availableMajors)?.groupValues?.get(1)?.trim() } + /** + * remark에서 위치 파싱 + * 예: "* 위치: Vechta\n* 특징: ..." -> "Vechta" + * 예: "* 위치: Brühl (쾰른에서 기차로 10분) * 특징: ..." -> "Brühl (쾰른에서 기차로 10분)" + * 없으면 null 반환 + */ + private fun parseLocation(remark: String?): String? { + if (remark == null) return null + val regex = """\*\s*위치\s*:\s*([^*\n]+)""".toRegex() + return regex.find(remark)?.groupValues?.get(1)?.trim()?.takeIf { it.isNotBlank() } + } + /** * remark에서 학생 수 파싱 * 예: "... 학생 수 약 28,600명 ..." -> "약 28,600명" @@ -91,7 +105,7 @@ data class UniversityDetailResponse( if (remark == null) return "학생 수 정보 없음" val regex = """학생\s*수\s*약?\s*([\d,]+)\s*명""".toRegex() val count = regex.find(remark)?.groupValues?.get(1)?.trim() - return if (count != null) "약 ${count} 명" else "학생 수 정보 없음" + return if (count != null) "약 $count 명" else "학생 수 정보 없음" } } }