Skip to content

Commit 3c88189

Browse files
authored
feat: 학과 조회 API (#228)
1 parent 9393685 commit 3c88189

File tree

21 files changed

+507
-182
lines changed

21 files changed

+507
-182
lines changed

build.gradle

Lines changed: 111 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
// 1. Import 추가
2+
import org.hidetake.gradle.swagger.generator.GenerateSwaggerUI
3+
14
buildscript {
25
ext {
3-
restdocsApiSpecVersion = '0.17.1' // restdocsApiSpecVersion 버전 변수 설정
6+
restdocsApiSpecVersion = '0.18.3' // restdocsApiSpecVersion 버전 변수 설정
47
}
58
}
69

@@ -9,17 +12,76 @@ plugins {
912
id 'org.springframework.boot' version '3.3.4'
1013
id 'io.spring.dependency-management' version '1.1.6'
1114
id 'org.asciidoctor.jvm.convert' version '3.3.2'
12-
id "com.gorylenko.gradle-git-properties" version "2.4.1"
1315
// epages-restdocs 플러그인 추가
1416
id 'com.epages.restdocs-api-spec' version "${restdocsApiSpecVersion}"
15-
// swagger generator 플러그인 추가
17+
//swagger generator 플러그인 추가
1618
id 'org.hidetake.swagger.generator' version '2.18.2'
1719
id 'jacoco'
1820
}
1921

2022
group = 'ku-rum'
2123
version = '0.0.1-SNAPSHOT'
2224

25+
jacoco {
26+
toolVersion = "0.8.8"
27+
reportsDirectory = layout.buildDirectory.dir('customJacocoReportDir')
28+
}
29+
30+
test {
31+
finalizedBy jacocoTestReport // test 작업이 끝나고 jacocoTestReport를 실행
32+
}
33+
34+
jacocoTestReport {
35+
dependsOn test // test 종속성 추가
36+
37+
reports {
38+
xml.required = true
39+
csv.required = false
40+
html.required = true
41+
}
42+
43+
def QDomainList = []
44+
for (qPattern in '**/QA'..'**/QZ') { // QClass 대응
45+
QDomainList.add(qPattern + '*')
46+
}
47+
48+
afterEvaluate {
49+
classDirectories.setFrom(files(classDirectories.files.collect {
50+
fileTree(dir: it, exclude: [
51+
'**/dto/**',
52+
'**/event/**',
53+
'**/*InitData*',
54+
'**/*Application*',
55+
'**/exception/**',
56+
'**/service/alarm/**',
57+
'**/aop/**',
58+
'**/config/**',
59+
'**/MemberRole*',
60+
'**/oauth/**'
61+
] + QDomainList)
62+
}))
63+
}
64+
65+
finalizedBy 'jacocoTestCoverageVerification' // jacocoTestReport 태스크가 끝난 후 실행
66+
}
67+
68+
jacocoTestCoverageVerification {
69+
violationRules {
70+
71+
rule {
72+
enabled = true
73+
//코드 버커리지 체크 기준
74+
element = 'CLASS'
75+
76+
limit {
77+
counter = 'CLASS'
78+
value = 'COVEREDRATIO'
79+
minimum = 0.0
80+
}
81+
}
82+
}
83+
}
84+
2385
java {
2486
toolchain {
2587
languageVersion = JavaLanguageVersion.of(17)
@@ -30,15 +92,29 @@ configurations {
3092
compileOnly {
3193
extendsFrom annotationProcessor
3294
}
33-
asciidoctorExt
3495
}
3596

3697
repositories {
3798
mavenCentral()
3899
}
39100

40-
ext{
41-
set("snippetsDir", file("build/generated-snippets"))
101+
// 5. 생성된 API 스펙이 어느 위치에 있는지 지정
102+
swaggerSources {
103+
sample {
104+
setInputFile(file("${project.buildDir}/api-spec/openapi3.yaml"))
105+
}
106+
}
107+
108+
// 6. openapi3 스펙 생성시 설정 정보
109+
openapi3 {
110+
servers = [
111+
{ url = "https://kuroom.shop" },
112+
{ url = "http://localhost:8080" }
113+
]
114+
title = "쿠룸 백엔드 API 문서"
115+
description = "RestDocs를 이용한 Swagger API 문서입니다."
116+
version = "1.0"
117+
format = "yaml"
42118
}
43119

44120
dependencies {
@@ -122,129 +198,49 @@ dependencies {
122198

123199
}
124200

125-
jacoco {
126-
toolVersion = "0.8.8"
127-
reportsDirectory = layout.buildDirectory.dir('customJacocoReportDir')
128-
}
129-
130-
test {
131-
finalizedBy jacocoTestReport // test 작업이 끝나고 jacocoTestReport를 실행
132-
}
133-
134-
jacocoTestReport {
135-
dependsOn test // test 종속성 추가
136-
137-
reports {
138-
xml.required = true
139-
csv.required = false
140-
html.required = true
141-
}
142-
143-
def QDomainList = []
144-
for (qPattern in '**/QA'..'**/QZ') { // QClass 대응
145-
QDomainList.add(qPattern + '*')
146-
}
147-
148-
afterEvaluate {
149-
classDirectories.setFrom(files(classDirectories.files.collect {
150-
fileTree(dir: it, exclude: [
151-
'**/dto/**',
152-
'**/event/**',
153-
'**/*InitData*',
154-
'**/*Application*',
155-
'**/exception/**',
156-
'**/service/alarm/**',
157-
'**/aop/**',
158-
'**/config/**',
159-
'**/MemberRole*',
160-
'**/oauth/**'
161-
] + QDomainList)
162-
}))
163-
}
164-
165-
finalizedBy 'jacocoTestCoverageVerification' // jacocoTestReport 태스크가 끝난 후 실행
166-
}
167-
168-
jacocoTestCoverageVerification {
169-
violationRules {
170-
171-
rule {
172-
enabled = true
173-
//코드 버커리지 체크 기준
174-
element = 'CLASS'
175-
176-
limit {
177-
counter = 'CLASS'
178-
value = 'COVEREDRATIO'
179-
minimum = 0.0
180-
}
181-
}
182-
}
183-
}
184201

185202
tasks.named('test') {
186-
outputs.dir snippetsDir
187203
useJUnitPlatform()
188204
}
189205

190-
tasks.register("restDocsTest", Test) {
191-
outputs.dir snippetsDir
192-
useJUnitPlatform {
193-
includeTags("restDocs")
194-
}
195-
196-
finalizedBy "openapi3"
197-
}
198-
199-
tasks.named("asciidoctor") {
200-
dependsOn restDocsTest
201-
202-
inputs.dir snippetsDir
203-
configurations "asciidoctorExt"
204-
baseDirFollowsSourceDir() // 원본파일작업은 .adoc 디렉터리 기준
205-
}
206-
207-
openapi3 {
208-
servers = [
209-
{ url = "https://kuroom.shop" },
210-
{ url = "http://localhost:8080" }
211-
]
212-
title = "API 문서"
213-
description = "RestDocsWithSwagger Docs"
214-
version = "0.0.1"
215-
format = "yaml"
206+
tasks.named('jar') {
207+
enabled = false
216208
}
217209

218-
tasks.register("apiBuild", GradleBuild) {
219-
tasks = ["clean", "restDocsTest", "build"]
220-
}
210+
// 10. openapi3가 먼저 실행
211+
tasks.withType(GenerateSwaggerUI) {
212+
dependsOn 'openapi3'
213+
doFirst {
214+
def swaggerUIFile = file("${openapi3.outputDirectory}/openapi3.yaml")
221215

222-
springBoot {
223-
buildInfo()
224-
}
216+
/* def securitySchemesContent = " securitySchemes:\n" + \
217+
" APIKey:\n" + \
218+
" type: apiKey\n" + \
219+
" name: Authorization\n" + \
220+
" in: header\n" + \
221+
"security:\n" +
222+
" - APIKey: [] # Apply the security scheme here"
225223
226-
gitProperties {
227-
dateFormat = "yyyy-MM-dd'T'HH:mm:ss.Zz"
228-
dateFormatTimeZone = "Asia/Seoul"
229-
failOnNoGitDirectory = false
230-
}
231-
232-
bootJar {
233-
from("swagger-ui") {
234-
into "BOOT-INF/classes/static/swagger"
235-
}
236-
from("${asciidoctor.outputDir}") {
237-
into "BOOT-INF/classes/static/docs"
224+
swaggerUIFile.append securitySchemesContent*/
238225
}
239-
from("build/api-spec") {
240-
into "BOOT-INF/classes/static/swagger"
241-
}
242-
243-
archiveFileName.set "application.jar"
244226
}
245227

246228
def querydslSrcDir = 'src/main/generated'
247229

248230
clean {
249231
delete file(querydslSrcDir)
250232
}
233+
234+
//tasks.register("copySwaggerDocs", Copy) {
235+
// dependsOn generateSwaggerUISample
236+
// from("${generateSwaggerUISample.outputDir}")
237+
// into("${project.projectDir}/src/main/resources/static/docs")
238+
//}
239+
240+
// 11. 생성된 openapi3 스펙을 기반으로 SwaggerUISample 생성 및 static/docs 패키지에 복사
241+
bootJar {
242+
dependsOn generateSwaggerUISample
243+
from("${generateSwaggerUISample.outputDir}") {
244+
into 'static/docs'
245+
}
246+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package ku_rum.backend.domain.college.application;
2+
3+
import ku_rum.backend.domain.college.domain.College;
4+
import ku_rum.backend.domain.college.domain.repository.CollegeRepository;
5+
import ku_rum.backend.domain.college.dto.response.CollegeResponse;
6+
import lombok.RequiredArgsConstructor;
7+
import org.springframework.stereotype.Service;
8+
import org.springframework.transaction.annotation.Transactional;
9+
10+
import java.util.List;
11+
12+
@Service
13+
@RequiredArgsConstructor
14+
@Transactional(readOnly = true)
15+
public class CollegeQueryService {
16+
private final CollegeRepository collegeRepository;
17+
18+
public CollegeResponse findAll() {
19+
List<College> all = collegeRepository.findAll();
20+
21+
List<String> names = all.stream()
22+
.map(College::getName)
23+
.toList();
24+
25+
return new CollegeResponse(names);
26+
}
27+
}

src/main/java/ku_rum/backend/domain/college/domain/repository/CollegeRepository.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@
44
import org.springframework.data.jpa.repository.JpaRepository;
55

66
public interface CollegeRepository extends JpaRepository<College, Long> {
7+
78
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package ku_rum.backend.domain.college.dto.response;
2+
3+
import java.util.List;
4+
5+
public record CollegeResponse(List<String> name) {
6+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package ku_rum.backend.domain.college.presentation;
2+
3+
import ku_rum.backend.domain.college.application.CollegeQueryService;
4+
import ku_rum.backend.domain.college.dto.response.CollegeResponse;
5+
import ku_rum.backend.global.support.response.BaseResponse;
6+
import lombok.RequiredArgsConstructor;
7+
import org.springframework.web.bind.annotation.GetMapping;
8+
import org.springframework.web.bind.annotation.RequestMapping;
9+
import org.springframework.web.bind.annotation.RestController;
10+
11+
@RestController
12+
@RequestMapping("/api/v1/colleges")
13+
@RequiredArgsConstructor
14+
public class CollegeQueryController {
15+
16+
private final CollegeQueryService collegeQueryService;
17+
18+
@GetMapping
19+
public BaseResponse<CollegeResponse> getCollege() {
20+
return BaseResponse.ok(collegeQueryService.findAll());
21+
}
22+
}

src/main/java/ku_rum/backend/domain/department/application/DepartmentQueryService.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22

33
import ku_rum.backend.domain.department.domain.Department;
44
import ku_rum.backend.domain.department.domain.repository.DepartmentRepository;
5+
import ku_rum.backend.domain.department.dto.CollegeDepartmentResponse;
56
import ku_rum.backend.domain.user.dto.request.UserSaveRequest;
67
import ku_rum.backend.global.exception.department.NoSuchDepartmentException;
78
import lombok.RequiredArgsConstructor;
89
import lombok.extern.slf4j.Slf4j;
910
import org.springframework.stereotype.Service;
1011
import org.springframework.transaction.annotation.Transactional;
1112

13+
import java.util.List;
14+
1215
import static ku_rum.backend.global.support.status.BaseExceptionResponseStatus.NO_SUCH_DEPARTMENT;
1316

1417
@Service
@@ -24,4 +27,10 @@ public Department getDepartment(final UserSaveRequest userSaveRequest) {
2427
return departmentRepository.findFirstByName(userSaveRequest.department())
2528
.orElseThrow(() -> new NoSuchDepartmentException(NO_SUCH_DEPARTMENT));
2629
}
30+
31+
public CollegeDepartmentResponse getDepartmentsByCollege(final String college) {
32+
List<Department> departments = departmentRepository.findAllByCollege_Name(college);
33+
List<String> list = departments.stream().map(Department::getName).toList();
34+
return new CollegeDepartmentResponse(list);
35+
}
2736
}

src/main/java/ku_rum/backend/domain/department/domain/repository/DepartmentRepository.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
import org.springframework.data.jpa.repository.JpaRepository;
55
import org.springframework.stereotype.Repository;
66

7+
import java.util.List;
78
import java.util.Optional;
89

910
@Repository
1011
public interface DepartmentRepository extends JpaRepository<Department, Long> {
1112
boolean existsByName(String name);
1213
Optional<Department> findFirstByName(String name);
14+
List<Department> findAllByCollege_Name(String college);
1315
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package ku_rum.backend.domain.department.dto;
2+
3+
import java.util.List;
4+
5+
public record CollegeDepartmentResponse(List<String> name) {
6+
}

0 commit comments

Comments
 (0)