Skip to content

Commit 6bb9227

Browse files
authored
Merge pull request #173 from SystemConsultantGroup/develop
feat: 갤러리 필터·캐시 및 기능 개선, 프로젝트 카테고리 중 일부에 AI 추가
2 parents 9a95911 + 50f4251 commit 6bb9227

37 files changed

Lines changed: 875 additions & 766 deletions

src/main/java/com/scg/stop/file/controller/FileController.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,20 @@
99
import lombok.RequiredArgsConstructor;
1010
import org.springframework.core.io.InputStreamResource;
1111
import org.springframework.core.io.Resource;
12+
import org.springframework.http.CacheControl;
1213
import org.springframework.http.HttpHeaders;
1314
import org.springframework.http.HttpStatus;
1415
import org.springframework.http.MediaType;
1516
import org.springframework.http.ResponseEntity;
17+
import org.springframework.web.context.request.WebRequest;
1618
import org.springframework.web.bind.annotation.*;
1719
import org.springframework.web.multipart.MultipartFile;
1820
import org.springframework.web.util.UriUtils;
1921

2022
import java.io.InputStream;
2123
import java.nio.charset.StandardCharsets;
2224
import java.util.List;
25+
import java.util.concurrent.TimeUnit;
2326

2427
@RestController
2528
@RequiredArgsConstructor
@@ -35,10 +38,20 @@ public ResponseEntity<List<FileResponse>> uploadFiles(@RequestPart("files") List
3538
}
3639

3740
@GetMapping("/{fileId}")
38-
public ResponseEntity<InputStreamResource> getFile(@PathVariable("fileId") Long fileId) {
39-
InputStream stream = fileService.getFile(fileId);
41+
public ResponseEntity<InputStreamResource> getFile(
42+
@PathVariable("fileId") Long fileId,
43+
WebRequest request) {
4044
File file = fileService.getFileMetadata(fileId);
45+
String etag = file.getUuid();
46+
47+
if (request.checkNotModified(etag)) {
48+
return null;
49+
}
50+
51+
InputStream stream = fileService.getFile(fileId);
4152
return ResponseEntity.ok()
53+
.cacheControl(CacheControl.maxAge(365, TimeUnit.DAYS).cachePublic())
54+
.eTag(etag)
4255
.contentType(MediaType.parseMediaType(file.getMimeType()))
4356
.body(new InputStreamResource(stream));
4457
}

src/main/java/com/scg/stop/gallery/controller/GalleryController.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
import com.scg.stop.user.domain.AccessType;
88
import com.scg.stop.user.domain.User;
99
import jakarta.validation.Valid;
10+
import jakarta.validation.constraints.Size;
1011
import lombok.RequiredArgsConstructor;
1112
import org.springframework.data.domain.Page;
1213
import org.springframework.data.domain.Pageable;
1314
import org.springframework.data.web.PageableDefault;
1415
import org.springframework.http.HttpStatus;
1516
import org.springframework.http.ResponseEntity;
17+
import org.springframework.validation.annotation.Validated;
1618
import org.springframework.web.bind.annotation.*;
1719

1820
@RestController
@@ -35,8 +37,9 @@ public ResponseEntity<GalleryResponse> createGallery(
3537
public ResponseEntity<Page<GalleryResponse>> getGalleries(
3638
@RequestParam(value = "year", required = false) Integer year,
3739
@RequestParam(value = "month", required = false) Integer month,
40+
@Validated @RequestParam(value = "title", required = false) @Size(max = 100) String title,
3841
@PageableDefault(page = 0, size = 10) Pageable pageable) {
39-
Page<GalleryResponse> galleries = galleryService.getGalleries(year, month, pageable);
42+
Page<GalleryResponse> galleries = galleryService.getGalleries(year, month, title, pageable);
4043
return ResponseEntity.ok(galleries);
4144
}
4245

src/main/java/com/scg/stop/gallery/repository/GalleryRepository.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ public interface GalleryRepository extends JpaRepository<Gallery, Long> {
1313

1414
@Query("SELECT g FROM Gallery g " +
1515
"WHERE (:year IS NULL OR g.year = :year) " +
16-
"AND (:month IS NULL OR g.month = :month)" +
16+
"AND (:month IS NULL OR g.month = :month) " +
17+
"AND (:title IS NULL OR g.title LIKE %:title%) " +
1718
"ORDER BY g.year DESC, g.month DESC")
1819
Page<Gallery> findGalleries(
1920
@Param("year") Integer year,
2021
@Param("month") Integer month,
22+
@Param("title") String title,
2123
Pageable pageable
2224
);
2325
}

src/main/java/com/scg/stop/gallery/service/GalleryService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ public GalleryResponse createGallery(GalleryRequest request) {
3939
}
4040

4141
@Transactional(readOnly = true)
42-
public Page<GalleryResponse> getGalleries(Integer year, Integer month, Pageable pageable) {
43-
Page<Gallery> galleries = galleryRepository.findGalleries(year, month, pageable);
42+
public Page<GalleryResponse> getGalleries(Integer year, Integer month, String title, Pageable pageable) {
43+
Page<Gallery> galleries = galleryRepository.findGalleries(year, month, title, pageable);
4444
return galleries.map(GalleryResponse::from);
4545
}
4646

src/main/java/com/scg/stop/project/domain/ProjectCategory.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
package com.scg.stop.project.domain;
22

3-
import com.scg.stop.global.exception.BadRequestException;
3+
import static com.scg.stop.global.exception.ExceptionCode.INVALID_PROJECT_CATEGORY_KOREAN_NAME;
44

55
import java.util.HashMap;
66
import java.util.Map;
77

8-
import static com.scg.stop.global.exception.ExceptionCode.INVALID_PROJECT_CATEGORY_KOREAN_NAME;
8+
import com.scg.stop.global.exception.BadRequestException;
99

1010
public enum ProjectCategory {
1111

12-
COMPUTER_VISION("컴퓨터비전"),
12+
COMPUTER_VISION("AI/컴퓨터비전"),
1313
SYSTEM_NETWORK("시스템/네트워크"),
1414
WEB_APPLICATION("웹/어플리케이션"),
1515
SECURITY_SOFTWARE_ENGINEERING("보안/SW공학"),
16-
NATURAL_LANGUAGE_PROCESSING("자연어처리"),
17-
BIG_DATA_ANALYSIS("빅데이터분석"),
16+
NATURAL_LANGUAGE_PROCESSING("AI/자연어처리"),
17+
BIG_DATA_ANALYSIS("AI/빅데이터분석"),
1818
AI_MACHINE_LEARNING("AI/머신러닝"),
1919
INTERACTION_AUGMENTED_REALITY("인터렉션/증강현실");
2020

@@ -33,7 +33,8 @@ public enum ProjectCategory {
3333

3434
public static ProjectCategory fromKoreanName(String koreanName) {
3535
if (!KOREAN_NAME_MAP.containsKey(koreanName)) {
36-
throw new BadRequestException(INVALID_PROJECT_CATEGORY_KOREAN_NAME, String.format("프로젝트 분야의 한글 이름이 올바르지 않습니다 : %s", koreanName));
36+
throw new BadRequestException(INVALID_PROJECT_CATEGORY_KOREAN_NAME,
37+
String.format("프로젝트 분야의 한글 이름이 올바르지 않습니다 : %s", koreanName));
3738
}
3839
return KOREAN_NAME_MAP.get(koreanName);
3940
}

src/main/resources/static/docs/aihub-controller-test.html

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -566,8 +566,8 @@ <h4 id="_http_response">HTTP response</h4>
566566
Content-Length: 1221
567567

568568
{
569-
"totalElements" : 2,
570569
"totalPages" : 1,
570+
"totalElements" : 2,
571571
"size" : 10,
572572
"content" : [ {
573573
"title" : "title",
@@ -598,8 +598,6 @@ <h4 id="_http_response">HTTP response</h4>
598598
"sorted" : false,
599599
"unsorted" : true
600600
},
601-
"first" : true,
602-
"last" : true,
603601
"numberOfElements" : 2,
604602
"pageable" : {
605603
"pageNumber" : 0,
@@ -613,6 +611,8 @@ <h4 id="_http_response">HTTP response</h4>
613611
"paged" : true,
614612
"unpaged" : false
615613
},
614+
"first" : true,
615+
"last" : true,
616616
"empty" : false
617617
}</code></pre>
618618
</div>
@@ -944,8 +944,8 @@ <h4 id="_http_response">HTTP response</h4>
944944
Content-Length: 1217
945945

946946
{
947-
"totalElements" : 2,
948947
"totalPages" : 1,
948+
"totalElements" : 2,
949949
"size" : 10,
950950
"content" : [ {
951951
"title" : "title",
@@ -976,8 +976,6 @@ <h4 id="_http_response">HTTP response</h4>
976976
"sorted" : false,
977977
"unsorted" : true
978978
},
979-
"first" : true,
980-
"last" : true,
981979
"numberOfElements" : 2,
982980
"pageable" : {
983981
"pageNumber" : 0,
@@ -991,6 +989,8 @@ <h4 id="_http_response">HTTP response</h4>
991989
"paged" : true,
992990
"unpaged" : false
993991
},
992+
"first" : true,
993+
"last" : true,
994994
"empty" : false
995995
}</code></pre>
996996
</div>
@@ -1206,7 +1206,7 @@ <h4 id="_response_fields">Response fields</h4>
12061206
<div id="footer">
12071207
<div id="footer-text">
12081208
Version 0.0.1-SNAPSHOT<br>
1209-
Last updated 2026-03-09 14:08:49 +0900
1209+
Last updated 2026-03-09 22:08:40 +0900
12101210
</div>
12111211
</div>
12121212
</body>

src/main/resources/static/docs/application.html

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -497,45 +497,43 @@ <h4 id="_http_response">HTTP response</h4>
497497
Vary: Access-Control-Request-Method
498498
Vary: Access-Control-Request-Headers
499499
Content-Type: application/json
500-
Content-Length: 1196
500+
Content-Length: 1136
501501

502502
{
503-
"totalElements" : 3,
504503
"totalPages" : 1,
504+
"totalElements" : 3,
505505
"size" : 10,
506506
"content" : [ {
507507
"id" : 1,
508508
"name" : "김영한",
509509
"division" : "배민",
510510
"position" : null,
511511
"userType" : "INACTIVE_COMPANY",
512-
"createdAt" : "2026-03-09T14:45:51.578888573",
513-
"updatedAt" : "2026-03-09T14:45:51.578896971"
512+
"createdAt" : "2024-01-01T00:00:00",
513+
"updatedAt" : "2024-01-01T00:00:00"
514514
}, {
515515
"id" : 2,
516516
"name" : "김교수",
517517
"division" : "솦융대",
518518
"position" : "교수",
519519
"userType" : "INACTIVE_PROFESSOR",
520-
"createdAt" : "2026-03-09T14:45:51.578937524",
521-
"updatedAt" : "2026-03-09T14:45:51.578939097"
520+
"createdAt" : "2024-01-01T00:00:00",
521+
"updatedAt" : "2024-01-01T00:00:00"
522522
}, {
523523
"id" : 3,
524524
"name" : "박교수",
525525
"division" : "정통대",
526526
"position" : "교수",
527527
"userType" : "INACTIVE_PROFESSOR",
528-
"createdAt" : "2026-03-09T14:45:51.578945944",
529-
"updatedAt" : "2026-03-09T14:45:51.578947442"
528+
"createdAt" : "2024-01-01T00:00:00",
529+
"updatedAt" : "2024-01-01T00:00:00"
530530
} ],
531531
"number" : 0,
532532
"sort" : {
533533
"empty" : true,
534534
"sorted" : false,
535535
"unsorted" : true
536536
},
537-
"first" : true,
538-
"last" : true,
539537
"numberOfElements" : 3,
540538
"pageable" : {
541539
"pageNumber" : 0,
@@ -549,6 +547,8 @@ <h4 id="_http_response">HTTP response</h4>
549547
"paged" : true,
550548
"unpaged" : false
551549
},
550+
"first" : true,
551+
"last" : true,
552552
"empty" : false
553553
}</code></pre>
554554
</div>
@@ -786,7 +786,7 @@ <h4 id="_http_response">HTTP response</h4>
786786
Vary: Access-Control-Request-Method
787787
Vary: Access-Control-Request-Headers
788788
Content-Type: application/json
789-
Content-Length: 278
789+
Content-Length: 258
790790

791791
{
792792
"id" : 1,
@@ -796,8 +796,8 @@ <h4 id="_http_response">HTTP response</h4>
796796
"division" : "배민",
797797
"position" : "CEO",
798798
"userType" : "INACTIVE_COMPANY",
799-
"createdAt" : "2026-03-09T14:45:51.664182733",
800-
"updatedAt" : "2026-03-09T14:45:51.664222751"
799+
"createdAt" : "2024-01-01T00:00:00",
800+
"updatedAt" : "2024-01-01T00:00:00"
801801
}</code></pre>
802802
</div>
803803
</div>
@@ -926,7 +926,7 @@ <h4 id="_http_response">HTTP response</h4>
926926
Vary: Access-Control-Request-Method
927927
Vary: Access-Control-Request-Headers
928928
Content-Type: application/json
929-
Content-Length: 269
929+
Content-Length: 249
930930

931931
{
932932
"id" : 1,
@@ -936,8 +936,8 @@ <h4 id="_http_response">HTTP response</h4>
936936
"division" : "배민",
937937
"position" : "CEO",
938938
"userType" : "COMPANY",
939-
"createdAt" : "2026-03-09T14:45:51.637606699",
940-
"updatedAt" : "2026-03-09T14:45:51.637612649"
939+
"createdAt" : "2024-01-01T00:00:00",
940+
"updatedAt" : "2024-01-01T00:00:00"
941941
}</code></pre>
942942
</div>
943943
</div>
@@ -1077,7 +1077,7 @@ <h4 id="_http_response">HTTP response</h4>
10771077
<div id="footer">
10781078
<div id="footer-text">
10791079
Version 0.0.1-SNAPSHOT<br>
1080-
Last updated 2026-03-09 14:08:49 +0900
1080+
Last updated 2026-03-09 22:08:40 +0900
10811081
</div>
10821082
</div>
10831083
</body>

src/main/resources/static/docs/auth-controller-test.html

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -489,17 +489,35 @@ <h4 id="_http_response">HTTP response</h4>
489489
Vary: Origin
490490
Vary: Access-Control-Request-Method
491491
Vary: Access-Control-Request-Headers
492-
Set-Cookie: refresh-token=refresh_token; Path=/; Max-Age=604800; Expires=Mon, 16 Mar 2026 05:45:42 GMT; Secure; HttpOnly; SameSite=None
493-
Set-Cookie: access-token=access_token; Path=/; Max-Age=604800; Expires=Mon, 16 Mar 2026 05:45:42 GMT; Secure; SameSite=None
494-
Location: http://localhost:3000/login/kakao</code></pre>
492+
Set-Cookie: refresh-token=refresh_token; Path=/; Max-Age=604800; Expires=Mon, 16 Mar 2026 14:06:00 GMT; Secure; HttpOnly; SameSite=None
493+
Set-Cookie: access-token=access_token; Path=/; Max-Age=604800; Expires=Mon, 16 Mar 2026 14:06:00 GMT; Secure; SameSite=None
494+
Location: 1234</code></pre>
495495
</div>
496496
</div>
497497
</div>
498498
<div class="sect3">
499499
<h4 id="_response_fields">Response fields</h4>
500-
<div class="paragraph">
501-
<p>Snippet response-fields not found for operation::auth-controller-test/kakao-social-login</p>
502-
</div>
500+
<table class="tableblock frame-all grid-all stretch">
501+
<colgroup>
502+
<col style="width: 33.3333%;">
503+
<col style="width: 33.3333%;">
504+
<col style="width: 33.3334%;">
505+
</colgroup>
506+
<thead>
507+
<tr>
508+
<th class="tableblock halign-left valign-top">Path</th>
509+
<th class="tableblock halign-left valign-top">Type</th>
510+
<th class="tableblock halign-left valign-top">Description</th>
511+
</tr>
512+
</thead>
513+
<tbody>
514+
<tr>
515+
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>accessToken</code></p></td>
516+
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>String</code></p></td>
517+
<td class="tableblock halign-left valign-top"><p class="tableblock">access token</p></td>
518+
</tr>
519+
</tbody>
520+
</table>
503521
</div>
504522
</div>
505523
</div>
@@ -785,7 +803,7 @@ <h4 id="_http_response">HTTP response</h4>
785803
<div id="footer">
786804
<div id="footer-text">
787805
Version 0.0.1-SNAPSHOT<br>
788-
Last updated 2026-03-09 14:08:49 +0900
806+
Last updated 2026-03-09 22:08:40 +0900
789807
</div>
790808
</div>
791809
</body>

src/main/resources/static/docs/department.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -521,8 +521,8 @@ <h4 id="_response_fields">Response fields</h4>
521521
<div id="footer">
522522
<div id="footer-text">
523523
Version 0.0.1-SNAPSHOT<br>
524-
Last updated 2026-03-09 14:08:49 +0900
524+
Last updated 2026-03-09 22:08:40 +0900
525525
</div>
526526
</div>
527527
</body>
528-
</html>
528+
</html>

0 commit comments

Comments
 (0)