Skip to content

Commit 6fed733

Browse files
authored
docs : Swagger 어노테이션 추가 - 커뮤니티 및 알림 controller/dto (#52)
* docs : dto swagger 어노테이션 적용 * docs : controller swagger 어노테이션 적용 * docs : Pageable 관련 Swagger 어노테이션 및 설명 추가
1 parent 7b640de commit 6fed733

File tree

12 files changed

+258
-56
lines changed

12 files changed

+258
-56
lines changed

src/main/java/org/ezcode/codetest/application/community/dto/request/DiscussionCreateRequest.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,30 @@
11
package org.ezcode.codetest.application.community.dto.request;
22

3+
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.*;
4+
35
import org.ezcode.codetest.domain.community.model.Discussion;
46
import org.ezcode.codetest.domain.language.model.entity.Language;
57
import org.ezcode.codetest.domain.problem.model.entity.Problem;
68
import org.ezcode.codetest.domain.user.model.entity.User;
79

10+
import io.swagger.v3.oas.annotations.media.Schema;
811
import jakarta.validation.constraints.NotBlank;
912
import jakarta.validation.constraints.NotNull;
1013
import jakarta.validation.constraints.Size;
1114

15+
@Schema(name = "DiscussionCreateRequest", description = "새로운 Discussion 생성 요청 DTO")
1216
public record DiscussionCreateRequest(
1317

18+
@Schema(description = "문제에 사용할 언어 ID", example = "1", requiredMode = REQUIRED)
1419
@NotNull(message = "languageId는 필수값입니다.")
1520
Long languageId,
1621

22+
@Schema(description = "토론 내용", example = "이 문제에 대해 이렇게 생각했습니다...", maxLength = 2000, requiredMode = REQUIRED)
1723
@NotBlank(message = "내용을 입력해야 합니다.")
1824
@Size(max = 2000, message = "내용은 최대 2000자까지 허용됩니다.")
1925
String content
2026

2127
) {
22-
2328
public static Discussion toEntity(
2429
User user,
2530
Problem problem,
@@ -33,5 +38,4 @@ public static Discussion toEntity(
3338
.content(request.content())
3439
.build();
3540
}
36-
3741
}

src/main/java/org/ezcode/codetest/application/community/dto/request/DiscussionModifyRequest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
package org.ezcode.codetest.application.community.dto.request;
22

3+
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.*;
4+
5+
import io.swagger.v3.oas.annotations.media.Schema;
36
import jakarta.validation.constraints.NotBlank;
47
import jakarta.validation.constraints.NotNull;
58
import jakarta.validation.constraints.Size;
69

10+
@Schema(name = "DiscussionModifyRequest", description = "기존 Discussion 수정 요청 DTO")
711
public record DiscussionModifyRequest(
812

13+
@Schema(description = "문제에 사용할 언어 ID", example = "1", requiredMode = REQUIRED)
914
@NotNull(message = "languageId는 필수값입니다.")
1015
Long languageId,
1116

17+
@Schema(description = "수정할 토론 내용", example = "내용을 이렇게 바꿨습니다...", maxLength = 2000, requiredMode = REQUIRED)
1218
@NotBlank(message = "내용을 입력해야 합니다.")
1319
@Size(max = 2000, message = "내용은 최대 2000자까지 허용됩니다.")
1420
String content

src/main/java/org/ezcode/codetest/application/community/dto/request/ReplyCreateRequest.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
package org.ezcode.codetest.application.community.dto.request;
22

3+
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.*;
4+
35
import org.ezcode.codetest.domain.community.model.Discussion;
46
import org.ezcode.codetest.domain.community.model.Reply;
57
import org.ezcode.codetest.domain.user.model.entity.User;
68

9+
import io.swagger.v3.oas.annotations.media.Schema;
710
import jakarta.validation.constraints.NotBlank;
811
import jakarta.validation.constraints.Size;
912

13+
@Schema(name = "ReplyCreateRequest", description = "새로운 Reply 생성 요청 DTO")
1014
public record ReplyCreateRequest(
1115

12-
// nullable
16+
@Schema(description = "부모 Reply ID (대댓글인 경우)", example = "5", nullable = true)
1317
Long parentReplyId,
1418

19+
@Schema(description = "댓글 내용", example = "좋은 의견입니다!", maxLength = 2000, requiredMode = REQUIRED)
1520
@NotBlank(message = "내용을 입력해야 합니다.")
1621
@Size(max = 2000, message = "내용은 최대 2000자까지 허용됩니다.")
1722
String content
@@ -28,7 +33,7 @@ public static Reply toEntity(
2833
.discussion(discussion)
2934
.user(user)
3035
.parent(parent)
31-
.content(request.content)
36+
.content(request.content())
3237
.build();
3338
}
3439
}

src/main/java/org/ezcode/codetest/application/community/dto/request/ReplyModifyRequest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
package org.ezcode.codetest.application.community.dto.request;
22

3+
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.*;
4+
5+
import io.swagger.v3.oas.annotations.media.Schema;
36
import jakarta.validation.constraints.NotBlank;
47
import jakarta.validation.constraints.Size;
58

9+
@Schema(name = "ReplyModifyRequest", description = "기존 Reply 수정 요청 DTO")
610
public record ReplyModifyRequest(
711

12+
@Schema(description = "수정할 댓글 내용", example = "내용을 이렇게 변경합니다.", maxLength = 2000, requiredMode = REQUIRED)
813
@NotBlank(message = "내용을 입력해야 합니다.")
914
@Size(max = 2000, message = "내용은 최대 2000자까지 허용됩니다.")
1015
String content

src/main/java/org/ezcode/codetest/application/community/dto/response/DiscussionResponse.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
package org.ezcode.codetest.application.community.dto.response;
22

3+
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.*;
4+
35
import org.ezcode.codetest.application.usermanagement.user.dto.response.SimpleUserInfoResponse;
46
import org.ezcode.codetest.domain.community.model.Discussion;
57

6-
public record DiscussionResponse(
8+
import io.swagger.v3.oas.annotations.media.Schema;
79

10+
@Schema(name = "DiscussionResponse", description = "Discussion 조회 응답 DTO")
11+
public record DiscussionResponse(
12+
@Schema(description = "Discussion 고유 ID", example = "123", requiredMode = REQUIRED)
813
Long discussionId,
914

15+
@Schema(description = "작성자 정보", requiredMode = REQUIRED)
1016
SimpleUserInfoResponse userInfo,
1117

18+
@Schema(description = "관련 문제 ID", example = "45", requiredMode = REQUIRED)
1219
Long problemId,
1320

21+
@Schema(description = "사용 언어명", example = "Java 17", requiredMode = REQUIRED)
1422
String languages,
1523

24+
@Schema(description = "토론 내용", example = "이 문제는 이렇게 풀 수 있습니다...", requiredMode = REQUIRED)
1625
String content
17-
1826
) {
1927

2028
public static DiscussionResponse fromEntity(Discussion discussion) {
@@ -26,5 +34,4 @@ public static DiscussionResponse fromEntity(Discussion discussion) {
2634
discussion.getContent()
2735
);
2836
}
29-
3037
}

src/main/java/org/ezcode/codetest/application/community/dto/response/ReplyResponse.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,34 @@
11
package org.ezcode.codetest.application.community.dto.response;
22

3+
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.*;
4+
35
import org.ezcode.codetest.application.usermanagement.user.dto.response.SimpleUserInfoResponse;
46
import org.ezcode.codetest.domain.community.model.Reply;
57

6-
public record ReplyResponse(
8+
import io.swagger.v3.oas.annotations.media.Schema;
79

10+
@Schema(name = "ReplyResponse", description = "Reply 조회 응답 DTO")
11+
public record ReplyResponse(
12+
@Schema(description = "Reply 고유 ID", example = "456", requiredMode = REQUIRED)
813
Long replyId,
914

15+
@Schema(description = "부모 Reply ID (없으면 null)", example = "123", nullable = true, requiredMode = NOT_REQUIRED)
1016
Long parentId,
1117

18+
@Schema(description = "소속 Discussion ID", example = "123", requiredMode = REQUIRED)
1219
Long discussionId,
1320

21+
@Schema(description = "작성자 정보", requiredMode = REQUIRED)
1422
SimpleUserInfoResponse userInfo,
1523

24+
@Schema(description = "댓글 내용", example = "동의합니다!", requiredMode = REQUIRED)
1625
String content
17-
1826
) {
1927

2028
public static ReplyResponse fromEntity(Reply reply) {
2129
Long parentId = (reply.getParent() != null)
2230
? reply.getParent().getId()
2331
: null;
24-
2532
return new ReplyResponse(
2633
reply.getId(),
2734
parentId,
Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
package org.ezcode.codetest.application.community.dto.response;
22

3-
public record VoteResponse(
3+
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.*;
44

5-
// 추천 등록되면 true, 취소되면 false
6-
boolean voteStatus
5+
import io.swagger.v3.oas.annotations.media.Schema;
76

7+
@Schema(name = "VoteResponse", description = "추천 상태 응답 DTO")
8+
public record VoteResponse(
9+
@Schema(
10+
description = "추천 상태 (추천되어 있으면 true, 취소되면 false)",
11+
example = "true",
12+
requiredMode = REQUIRED
13+
)
14+
boolean voteStatus
815
) {
916
}

src/main/java/org/ezcode/codetest/presentation/community/DiscussionController.java

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import org.ezcode.codetest.application.community.dto.response.DiscussionResponse;
66
import org.ezcode.codetest.application.community.service.DiscussionService;
77
import org.ezcode.codetest.domain.user.model.entity.AuthUser;
8+
import org.springdoc.core.annotations.ParameterObject;
89
import org.springframework.data.domain.Page;
910
import org.springframework.data.domain.Pageable;
1011
import org.springframework.data.web.PageableDefault;
@@ -20,55 +21,95 @@
2021
import org.springframework.web.bind.annotation.RequestMapping;
2122
import org.springframework.web.bind.annotation.RestController;
2223

24+
import io.swagger.v3.oas.annotations.Operation;
25+
import io.swagger.v3.oas.annotations.Parameter;
26+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
27+
import io.swagger.v3.oas.annotations.tags.Tag;
2328
import jakarta.validation.Valid;
2429
import lombok.RequiredArgsConstructor;
2530

2631
@RestController
2732
@RequestMapping("/problems/{problemId}/discussions")
33+
@Tag(name = "Discussions", description = "문제별 토론 관리 API")
2834
@RequiredArgsConstructor
2935
public class DiscussionController {
3036

3137
private final DiscussionService discussionService;
3238

39+
@Operation(
40+
summary = "토론 생성",
41+
description = "주어진 문제(problemId)에 새로운 토론을 생성합니다.",
42+
parameters = {
43+
@Parameter(name = "problemId", description = "문제 ID", required = true)
44+
}
45+
)
46+
@ApiResponse(responseCode = "201", description = "생성된 Discussion 반환")
3347
@PostMapping
3448
public ResponseEntity<DiscussionResponse> createDiscussion(
3549
@PathVariable Long problemId,
3650
@RequestBody @Valid DiscussionCreateRequest request,
3751
@AuthenticationPrincipal AuthUser authUser
3852
) {
39-
return ResponseEntity
40-
.status(HttpStatus.CREATED)
41-
.body(discussionService.createDiscussion(problemId, request, authUser.getId()));
53+
54+
DiscussionResponse dto = discussionService.createDiscussion(problemId, request, authUser.getId());
55+
return ResponseEntity.status(HttpStatus.CREATED).body(dto);
4256
}
4357

58+
@Operation(
59+
summary = "토론 목록 조회",
60+
description = "해당 문제의 토론 목록을 페이징하여 조회합니다.",
61+
parameters = {
62+
@Parameter(name = "problemId", description = "문제 ID", required = true)
63+
}
64+
)
65+
@ApiResponse(responseCode = "200", description = "토론 목록 조회 성공")
4466
@GetMapping
4567
public ResponseEntity<Page<DiscussionResponse>> getDiscussions(
4668
@PathVariable Long problemId,
47-
@PageableDefault Pageable pageable
69+
@ParameterObject @PageableDefault Pageable pageable
4870
) {
49-
return ResponseEntity
50-
.ok()
51-
.body(discussionService.getDiscussions(problemId, pageable));
71+
72+
Page<DiscussionResponse> page = discussionService.getDiscussions(problemId, pageable);
73+
return ResponseEntity.ok(page);
5274
}
5375

76+
@Operation(
77+
summary = "토론 수정",
78+
description = "특정 토론(discussionId)을 수정합니다.",
79+
parameters = {
80+
@Parameter(name = "problemId", description = "문제 ID", required = true),
81+
@Parameter(name = "discussionId", description = "토론 ID", required = true)
82+
}
83+
)
84+
@ApiResponse(responseCode = "200", description = "수정된 Discussion 반환")
5485
@PutMapping("/{discussionId}")
5586
public ResponseEntity<DiscussionResponse> modifyDiscussion(
5687
@PathVariable Long problemId,
5788
@PathVariable Long discussionId,
5889
@RequestBody @Valid DiscussionModifyRequest request,
5990
@AuthenticationPrincipal AuthUser authUser
6091
) {
61-
return ResponseEntity
62-
.ok()
63-
.body(discussionService.modifyDiscussion(problemId, discussionId, request, authUser.getId()));
92+
93+
DiscussionResponse dto = discussionService.modifyDiscussion(problemId, discussionId, request, authUser.getId());
94+
return ResponseEntity.ok(dto);
6495
}
6596

97+
@Operation(
98+
summary = "토론 삭제",
99+
description = "특정 토론(discussionId)을 삭제합니다.",
100+
parameters = {
101+
@Parameter(name = "problemId", description = "문제 ID", required = true),
102+
@Parameter(name = "discussionId", description = "토론 ID", required = true)
103+
}
104+
)
105+
@ApiResponse(responseCode = "200", description = "삭제 성공")
66106
@DeleteMapping("/{discussionId}")
67107
public ResponseEntity<Void> removeDiscussion(
68108
@PathVariable Long problemId,
69109
@PathVariable Long discussionId,
70110
@AuthenticationPrincipal AuthUser authUser
71111
) {
112+
72113
discussionService.removeDiscussion(problemId, discussionId, authUser.getId());
73114
return ResponseEntity.ok().build();
74115
}

src/main/java/org/ezcode/codetest/presentation/community/DiscussionVoteController.java

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,38 +12,59 @@
1212
import org.springframework.web.bind.annotation.RequestMapping;
1313
import org.springframework.web.bind.annotation.RestController;
1414

15+
import io.swagger.v3.oas.annotations.Operation;
16+
import io.swagger.v3.oas.annotations.Parameter;
17+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
18+
import io.swagger.v3.oas.annotations.tags.Tag;
1519
import lombok.RequiredArgsConstructor;
1620

1721
@RestController
1822
@RequestMapping("/problems/{problemId}/discussions/{discussionId}/votes")
23+
@Tag(name = "DiscussionVotes", description = "토론 추천(Vote) 관리 API")
1924
@RequiredArgsConstructor
2025
public class DiscussionVoteController {
2126

2227
private final DiscussionVoteService discussionVoteService;
2328

29+
@Operation(
30+
summary = "토론 추천 토글",
31+
description = "토론에 대한 추천을 생성하거나 취소합니다. 이 부분은 추후 추천/비추천 기능으로 변경될 수 있습니다.",
32+
parameters = {
33+
@Parameter(name = "problemId", description = "문제 ID", required = true),
34+
@Parameter(name = "discussionId", description = "토론 ID", required = true)
35+
}
36+
)
37+
@ApiResponse(responseCode = "201", description = "추천 생성됨 (voteStatus=true)")
38+
@ApiResponse(responseCode = "200", description = "추천 취소됨 (voteStatus=false)")
2439
@PostMapping
2540
public ResponseEntity<VoteResponse> toggleVote(
2641
@PathVariable Long problemId,
2742
@PathVariable Long discussionId,
2843
@AuthenticationPrincipal AuthUser authUser
2944
) {
45+
3046
VoteResponse response = discussionVoteService.validateAndToggleVote(problemId, discussionId, authUser.getId());
3147
HttpStatus status = response.voteStatus() ? HttpStatus.CREATED : HttpStatus.OK;
32-
33-
return ResponseEntity
34-
.status(status)
35-
.body(response);
48+
return ResponseEntity.status(status).body(response);
3649
}
3750

51+
@Operation(
52+
summary = "토론 추천 상태 조회",
53+
description = "현재 사용자가 해당 토론에 추천했는지 여부를 반환합니다.",
54+
parameters = {
55+
@Parameter(name = "problemId", description = "문제 ID", required = true),
56+
@Parameter(name = "discussionId", description = "토론 ID", required = true)
57+
}
58+
)
59+
@ApiResponse(responseCode = "200", description = "VoteResponse 반환")
3860
@GetMapping
3961
public ResponseEntity<VoteResponse> getVoteStatus(
4062
@PathVariable Long problemId,
4163
@PathVariable Long discussionId,
4264
@AuthenticationPrincipal AuthUser authUser
4365
) {
66+
4467
VoteResponse response = discussionVoteService.getVoteStatus(authUser.getId(), discussionId);
45-
return ResponseEntity
46-
.ok()
47-
.body(response);
68+
return ResponseEntity.ok(response);
4869
}
4970
}

0 commit comments

Comments
 (0)