diff --git a/src/main/java/com/dduru/gildongmu/S3/controller/S3ApiDocs.java b/src/main/java/com/dduru/gildongmu/S3/controller/S3ApiDocs.java index 03e8f408..62fea44e 100644 --- a/src/main/java/com/dduru/gildongmu/S3/controller/S3ApiDocs.java +++ b/src/main/java/com/dduru/gildongmu/S3/controller/S3ApiDocs.java @@ -2,10 +2,10 @@ import com.dduru.gildongmu.S3.dto.ImageUploadRequest; import com.dduru.gildongmu.S3.dto.ImageUploadResponse; +import com.dduru.gildongmu.common.annotation.ApiErrorResponses; import com.dduru.gildongmu.common.dto.ApiResult; +import com.dduru.gildongmu.common.exception.ErrorCode; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.http.ResponseEntity; @@ -16,8 +16,10 @@ public interface S3ApiDocs { @Operation(summary = "이미지 업로드를 위한 Presigned URL 생성", description = "S3에 이미지를 직접 업로드하기 위한 Presigned URL을 생성합니다.") - @ApiResponse(responseCode = "200", description = "Presigned URL 생성 성공", - content = @Content(mediaType = "application/json", - schema = @Schema(implementation = ImageUploadResponse.class))) + @ApiResponse(responseCode = "200", description = "Presigned URL 생성 성공") + @ApiErrorResponses({ + ErrorCode.INVALID_INPUT_VALUE, + ErrorCode.INVALID_FILE_EXTENSION + }) ResponseEntity> prepareUpload(@RequestBody ImageUploadRequest request); } diff --git a/src/main/java/com/dduru/gildongmu/auth/controller/OauthApiDocs.java b/src/main/java/com/dduru/gildongmu/auth/controller/OauthApiDocs.java index 4d6ba605..4ada136a 100644 --- a/src/main/java/com/dduru/gildongmu/auth/controller/OauthApiDocs.java +++ b/src/main/java/com/dduru/gildongmu/auth/controller/OauthApiDocs.java @@ -3,11 +3,13 @@ import com.dduru.gildongmu.auth.dto.LoginRequest; import com.dduru.gildongmu.auth.dto.LoginResponse; import com.dduru.gildongmu.auth.dto.RefreshTokenRequest; +import com.dduru.gildongmu.common.annotation.ApiErrorResponses; import com.dduru.gildongmu.common.dto.ApiResult; +import com.dduru.gildongmu.common.exception.ErrorCode; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; @@ -18,10 +20,13 @@ public interface OauthApiDocs { @Operation(summary = "ID Token 로그인 (모바일)", description = "ID Token을 사용한 OAuth 로그인을 처리합니다.") - @ApiResponses({ - @ApiResponse(responseCode = "200", description = "로그인 성공"), - @ApiResponse(responseCode = "400", description = "잘못된 요청"), - @ApiResponse(responseCode = "401", description = "유효하지 않은 ID Token") + @ApiResponse(responseCode = "200", description = "로그인 성공") + @ApiErrorResponses({ + ErrorCode.INVALID_INPUT_VALUE, + ErrorCode.UNSUPPORTED_SOCIAL_LOGIN, + ErrorCode.SOCIAL_LOGIN_FAILED, + ErrorCode.INVALID_TOKEN, + ErrorCode.DUPLICATE_EMAIL }) ResponseEntity> loginWithIdToken( @Parameter(description = "OAuth Provider (kakao, google)", example = "kakao") String provider, @@ -29,16 +34,16 @@ ResponseEntity> loginWithIdToken( ); @Operation(summary = "Access Token 갱신", description = "Refresh Token을 사용하여 Access Token을 갱신합니다.") - @ApiResponses({ - @ApiResponse(responseCode = "200", description = "토큰 갱신 성공"), - @ApiResponse(responseCode = "400", description = "잘못된 Refresh Token") + @ApiResponse(responseCode = "200", description = "토큰 갱신 성공") + @ApiErrorResponses({ + ErrorCode.INVALID_INPUT_VALUE, + ErrorCode.INVALID_TOKEN, + ErrorCode.EXPIRED_TOKEN }) ResponseEntity> refreshAccessToken(@Valid RefreshTokenRequest request); @Operation(summary = "로그아웃", description = "사용자 로그아웃을 처리합니다.", security = @SecurityRequirement(name = "JWT")) - @ApiResponses({ - @ApiResponse(responseCode = "204", description = "로그아웃 성공"), - @ApiResponse(responseCode = "401", description = "인증되지 않은 사용자") - }) + @ApiResponse(responseCode = "204", description = "로그아웃 성공", content = @Content()) + @ApiErrorResponses({ErrorCode.UNAUTHORIZED, ErrorCode.INVALID_TOKEN, ErrorCode.EXPIRED_TOKEN}) ResponseEntity> logout(@Parameter(hidden = true) Long userId); } diff --git a/src/main/java/com/dduru/gildongmu/comment/controller/CommentApiDocs.java b/src/main/java/com/dduru/gildongmu/comment/controller/CommentApiDocs.java index 92249a78..7f8ef2c3 100644 --- a/src/main/java/com/dduru/gildongmu/comment/controller/CommentApiDocs.java +++ b/src/main/java/com/dduru/gildongmu/comment/controller/CommentApiDocs.java @@ -3,11 +3,13 @@ import com.dduru.gildongmu.comment.dto.CommentCreateRequest; import com.dduru.gildongmu.comment.dto.CommentResponse; import com.dduru.gildongmu.comment.dto.CommentUpdateRequest; +import com.dduru.gildongmu.common.annotation.ApiErrorResponses; import com.dduru.gildongmu.common.dto.ApiResult; +import com.dduru.gildongmu.common.exception.ErrorCode; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import org.springframework.http.ResponseEntity; @@ -17,10 +19,14 @@ @Tag(name = "Comments", description = "댓글 API") public interface CommentApiDocs { @Operation(summary = "댓글 작성", description = "게시글에 새로운 댓글을 작성합니다.") - @ApiResponses({ - @ApiResponse(responseCode = "201", description = "작성 성공"), - @ApiResponse(responseCode = "400", description = "잘못된 요청"), - @ApiResponse(responseCode = "404", description = "게시글 또는 부모 댓글을 찾을 수 없음") + @ApiResponse(responseCode = "201", description = "작성 성공") + @ApiErrorResponses({ + ErrorCode.INVALID_INPUT_VALUE, + ErrorCode.POST_NOT_FOUND, + ErrorCode.COMMENT_NOT_FOUND, + ErrorCode.INVALID_PARENT_COMMENT, + ErrorCode.USER_NOT_FOUND, + ErrorCode.UNAUTHORIZED }) ResponseEntity> createComment( @Parameter(hidden = true) Long userId, @@ -29,18 +35,20 @@ ResponseEntity> createComment( ); @Operation(summary = "게시글 댓글 조회", description = "특정 게시글의 모든 댓글을 조회합니다. 대댓글 포함 계층 구조로 반환됩니다.") - @ApiResponses({ - @ApiResponse(responseCode = "200", description = "조회 성공"), - @ApiResponse(responseCode = "404", description = "게시글을 찾을 수 없음") - }) + @ApiResponse(responseCode = "200", description = "조회 성공") + @ApiErrorResponses({ErrorCode.POST_NOT_FOUND}) ResponseEntity>> retrieveComments( @Parameter(description = "게시글 ID") Long postId ); @Operation(summary = "댓글 삭제", description = "특정 게시글의 댓글을 삭제합니다.") - @ApiResponses({ - @ApiResponse(responseCode = "204", description = "삭제 성공"), - @ApiResponse(responseCode = "404", description = "게시글 또는 댓글을 찾을 수 없음") + @ApiResponse(responseCode = "204", description = "삭제 성공", content = @Content()) + @ApiErrorResponses({ + ErrorCode.POST_NOT_FOUND, + ErrorCode.COMMENT_NOT_FOUND, + ErrorCode.COMMENT_ACCESS_DENIED, + ErrorCode.INVALID_PARENT_COMMENT, + ErrorCode.UNAUTHORIZED }) ResponseEntity> deleteComment( @Parameter(hidden = true) Long userId, @@ -49,9 +57,14 @@ ResponseEntity> deleteComment( ); @Operation(summary = "댓글 수정", description = "특정 게시글의 댓글을 수정합니다.") - @ApiResponses({ - @ApiResponse(responseCode = "204", description = "수정 성공"), - @ApiResponse(responseCode = "404", description = "게시글 또는 댓글을 찾을 수 없음") + @ApiResponse(responseCode = "204", description = "수정 성공", content = @Content()) + @ApiErrorResponses({ + ErrorCode.INVALID_INPUT_VALUE, + ErrorCode.POST_NOT_FOUND, + ErrorCode.COMMENT_NOT_FOUND, + ErrorCode.COMMENT_ACCESS_DENIED, + ErrorCode.INVALID_PARENT_COMMENT, + ErrorCode.UNAUTHORIZED }) ResponseEntity> updateComment( @Parameter(hidden = true) Long userId, diff --git a/src/main/java/com/dduru/gildongmu/like/controller/CommentLikeApiDocs.java b/src/main/java/com/dduru/gildongmu/like/controller/CommentLikeApiDocs.java index 11cb9934..a83d7caa 100644 --- a/src/main/java/com/dduru/gildongmu/like/controller/CommentLikeApiDocs.java +++ b/src/main/java/com/dduru/gildongmu/like/controller/CommentLikeApiDocs.java @@ -1,9 +1,12 @@ package com.dduru.gildongmu.like.controller; +import com.dduru.gildongmu.common.annotation.ApiErrorResponses; import com.dduru.gildongmu.common.annotation.CurrentUser; import com.dduru.gildongmu.common.dto.ApiResult; +import com.dduru.gildongmu.common.exception.ErrorCode; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.http.ResponseEntity; @@ -12,6 +15,11 @@ @Tag(name = "Comments", description = "댓글 좋아요 관련 API") public interface CommentLikeApiDocs { @Operation(summary = "댓글 좋아요 토글", description = "댓글에 대한 좋아요를 추가하거나 삭제합니다.") - @ApiResponse(responseCode = "204", description = "좋아요 토글 성공") + @ApiResponse(responseCode = "204", description = "좋아요 토글 성공", content = @Content()) + @ApiErrorResponses({ + ErrorCode.COMMENT_NOT_FOUND, + ErrorCode.USER_NOT_FOUND, + ErrorCode.UNAUTHORIZED + }) ResponseEntity> toggleCommentLike(@Parameter(hidden = true) @CurrentUser Long userId, @PathVariable Long commentId); } diff --git a/src/main/java/com/dduru/gildongmu/like/controller/PostLikeApiDocs.java b/src/main/java/com/dduru/gildongmu/like/controller/PostLikeApiDocs.java index 89bcac8c..a39f6ad6 100644 --- a/src/main/java/com/dduru/gildongmu/like/controller/PostLikeApiDocs.java +++ b/src/main/java/com/dduru/gildongmu/like/controller/PostLikeApiDocs.java @@ -1,9 +1,12 @@ package com.dduru.gildongmu.like.controller; +import com.dduru.gildongmu.common.annotation.ApiErrorResponses; import com.dduru.gildongmu.common.annotation.CurrentUser; import com.dduru.gildongmu.common.dto.ApiResult; +import com.dduru.gildongmu.common.exception.ErrorCode; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.http.ResponseEntity; @@ -12,6 +15,11 @@ @Tag(name = "Posts", description = "게시글 좋아요 관련 API") public interface PostLikeApiDocs { @Operation(summary = "게시글 좋아요 토글", description = "게시글에 대한 좋아요를 추가하거나 삭제합니다.") - @ApiResponse(responseCode = "204", description = "좋아요 토글 성공") + @ApiResponse(responseCode = "204", description = "좋아요 토글 성공", content = @Content()) + @ApiErrorResponses({ + ErrorCode.POST_NOT_FOUND, + ErrorCode.USER_NOT_FOUND, + ErrorCode.UNAUTHORIZED + }) ResponseEntity> togglePostLike(@Parameter(hidden = true) @CurrentUser Long userId, @PathVariable Long postId); } diff --git a/src/main/java/com/dduru/gildongmu/participation/controller/ParticipationApiDocs.java b/src/main/java/com/dduru/gildongmu/participation/controller/ParticipationApiDocs.java index a57886fb..2989a9c2 100644 --- a/src/main/java/com/dduru/gildongmu/participation/controller/ParticipationApiDocs.java +++ b/src/main/java/com/dduru/gildongmu/participation/controller/ParticipationApiDocs.java @@ -1,12 +1,14 @@ package com.dduru.gildongmu.participation.controller; +import com.dduru.gildongmu.common.annotation.ApiErrorResponses; import com.dduru.gildongmu.common.dto.ApiResult; +import com.dduru.gildongmu.common.exception.ErrorCode; import com.dduru.gildongmu.participation.dto.ParticipationRequest; import com.dduru.gildongmu.participation.dto.ParticipationResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; @@ -19,8 +21,15 @@ public interface ParticipationApiDocs { @Operation(summary = "참여 신청", description = "게시글에 참여 신청을 합니다.") - @ApiResponses(value = { - @ApiResponse(responseCode = "201", description = "참여 신청 성공"), + @ApiResponse(responseCode = "201", description = "참여 신청 성공") + @ApiErrorResponses({ + ErrorCode.INVALID_INPUT_VALUE, + ErrorCode.POST_NOT_FOUND, + ErrorCode.RECRUITMENT_CLOSED, + ErrorCode.DUPLICATE_PARTICIPATION, + ErrorCode.SELF_PARTICIPATION_NOT_ALLOWED, + ErrorCode.USER_NOT_FOUND, + ErrorCode.UNAUTHORIZED }) ResponseEntity> createParticipation( @Parameter(description = "게시글 ID") Long postId, @@ -29,8 +38,11 @@ ResponseEntity> createParticipation( ); @Operation(summary = "게시글 참여자 목록 조회", description = "게시글에 참여한 사용자 목록을 조회합니다.") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "참여자 목록 조회 성공"), + @ApiResponse(responseCode = "200", description = "참여자 목록 조회 성공") + @ApiErrorResponses({ + ErrorCode.POST_NOT_FOUND, + ErrorCode.POST_ACCESS_DENIED, + ErrorCode.UNAUTHORIZED }) ResponseEntity>> getPostParticipants( @Parameter(description = "게시글 ID") Long postId, @@ -38,8 +50,14 @@ ResponseEntity>> getPostParticipants( ); @Operation(summary = "참여 신청 승인", description = "게시글 참여 신청을 승인합니다.") - @ApiResponses(value = { - @ApiResponse(responseCode = "204", description = "참여 신청 승인 성공"), + @ApiResponse(responseCode = "204", description = "참여 신청 승인 성공", content = @Content()) + @ApiErrorResponses({ + ErrorCode.POST_NOT_FOUND, + ErrorCode.PARTICIPATION_NOT_FOUND, + ErrorCode.POST_ACCESS_DENIED, + ErrorCode.PARTICIPATION_POST_MISMATCH, + ErrorCode.RECRUIT_COUNT_EXCEED_CAPACITY, + ErrorCode.UNAUTHORIZED }) ResponseEntity> approveParticipation( @Parameter(description = "게시글 ID") Long postId, @@ -48,8 +66,13 @@ ResponseEntity> approveParticipation( ); @Operation(summary = "참여 신청 거절", description = "게시글 참여 신청을 거절합니다.") - @ApiResponses(value = { - @ApiResponse(responseCode = "204", description = "참여 신청 거절 성공"), + @ApiResponse(responseCode = "204", description = "참여 신청 거절 성공", content = @Content()) + @ApiErrorResponses({ + ErrorCode.POST_NOT_FOUND, + ErrorCode.PARTICIPATION_NOT_FOUND, + ErrorCode.POST_ACCESS_DENIED, + ErrorCode.PARTICIPATION_POST_MISMATCH, + ErrorCode.UNAUTHORIZED }) ResponseEntity> rejectParticipation( @Parameter(description = "게시글 ID") Long postId, @@ -58,8 +81,14 @@ ResponseEntity> rejectParticipation( ); @Operation(summary = "참여 취소", description = "게시글 참여를 취소합니다.") - @ApiResponses(value = { - @ApiResponse(responseCode = "204", description = "참여 취소 성공"), + @ApiResponse(responseCode = "204", description = "참여 취소 성공", content = @Content()) + @ApiErrorResponses({ + ErrorCode.POST_NOT_FOUND, + ErrorCode.PARTICIPATION_NOT_FOUND, + ErrorCode.POST_ACCESS_DENIED, + ErrorCode.PARTICIPATION_POST_MISMATCH, + ErrorCode.RECRUIT_COUNT_BELOW_ZERO, + ErrorCode.UNAUTHORIZED }) ResponseEntity> cancelParticipation( @Parameter(description = "게시글 ID") Long postId, diff --git a/src/main/java/com/dduru/gildongmu/post/controller/PostApiDocs.java b/src/main/java/com/dduru/gildongmu/post/controller/PostApiDocs.java index eb81df32..0c8f9f97 100644 --- a/src/main/java/com/dduru/gildongmu/post/controller/PostApiDocs.java +++ b/src/main/java/com/dduru/gildongmu/post/controller/PostApiDocs.java @@ -1,11 +1,18 @@ package com.dduru.gildongmu.post.controller; +import com.dduru.gildongmu.common.annotation.ApiErrorResponses; import com.dduru.gildongmu.common.dto.ApiResult; -import com.dduru.gildongmu.post.dto.*; +import com.dduru.gildongmu.common.exception.ErrorCode; +import com.dduru.gildongmu.post.dto.PostCreateRequest; +import com.dduru.gildongmu.post.dto.PostCreateResponse; +import com.dduru.gildongmu.post.dto.PostDetailResponse; +import com.dduru.gildongmu.post.dto.PostListResponse; +import com.dduru.gildongmu.post.dto.PostStatusUpdateRequest; +import com.dduru.gildongmu.post.dto.PostUpdateRequest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import org.springframework.format.annotation.DateTimeFormat; @@ -31,18 +38,22 @@ ResponseEntity> retrievePostsWithFilter( ); @Operation(summary = "게시글 상세 조회", description = "게시글 상세 정보를 조회합니다.") - @ApiResponses({ - @ApiResponse(responseCode = "200", description = "조회 성공"), - @ApiResponse(responseCode = "404", description = "게시글을 찾을 수 없음") - }) + @ApiResponse(responseCode = "200", description = "조회 성공") + @ApiErrorResponses({ErrorCode.POST_NOT_FOUND}) ResponseEntity> getPostDetail( @Parameter(description = "게시글 ID") Long postId ); @Operation(summary = "게시글 작성", description = "새로운 게시글을 작성합니다.") - @ApiResponses({ - @ApiResponse(responseCode = "201", description = "작성 성공"), - @ApiResponse(responseCode = "400", description = "잘못된 요청") + @ApiResponse(responseCode = "201", description = "작성 성공") + @ApiErrorResponses({ + ErrorCode.INVALID_INPUT_VALUE, + ErrorCode.INVALID_POST_DATE, + ErrorCode.INVALID_BUDGET_RANGE, + ErrorCode.INVALID_AGE_RANGE, + ErrorCode.DESTINATION_NOT_FOUND, + ErrorCode.USER_NOT_FOUND, + ErrorCode.UNAUTHORIZED }) ResponseEntity> createPost( @Parameter(hidden = true) Long userId, @@ -50,10 +61,20 @@ ResponseEntity> createPost( ); @Operation(summary = "게시글 수정", description = "게시글을 수정합니다.") - @ApiResponses({ - @ApiResponse(responseCode = "204", description = "수정 성공"), - @ApiResponse(responseCode = "403", description = "권한 없음"), - @ApiResponse(responseCode = "404", description = "게시글을 찾을 수 없음") + @ApiResponse(responseCode = "204", description = "수정 성공", content = @Content()) + @ApiErrorResponses({ + ErrorCode.INVALID_INPUT_VALUE, + ErrorCode.POST_NOT_FOUND, + ErrorCode.POST_ACCESS_DENIED, + ErrorCode.INVALID_POST_DATE, + ErrorCode.INVALID_BUDGET_RANGE, + ErrorCode.INVALID_AGE_RANGE, + ErrorCode.DESTINATION_NOT_FOUND, + ErrorCode.TRAVEL_ALREADY_STARTED, + ErrorCode.TRAVEL_ALREADY_ENDED, + ErrorCode.INVALID_RECRUIT_CAPACITY, + ErrorCode.USER_NOT_FOUND, + ErrorCode.UNAUTHORIZED }) ResponseEntity> updatePost( @Parameter(description = "게시글 ID") Long postId, @@ -62,10 +83,11 @@ ResponseEntity> updatePost( ); @Operation(summary = "게시글 삭제", description = "게시글을 삭제합니다.") - @ApiResponses({ - @ApiResponse(responseCode = "204", description = "삭제 성공"), - @ApiResponse(responseCode = "403", description = "권한 없음"), - @ApiResponse(responseCode = "404", description = "게시글을 찾을 수 없음") + @ApiResponse(responseCode = "204", description = "삭제 성공", content = @Content()) + @ApiErrorResponses({ + ErrorCode.POST_NOT_FOUND, + ErrorCode.POST_ACCESS_DENIED, + ErrorCode.UNAUTHORIZED }) ResponseEntity> deletePost( @Parameter(description = "게시글 ID") Long postId, @@ -73,11 +95,13 @@ ResponseEntity> deletePost( ); @Operation(summary = "게시글 모집 상태 변경", description = "게시글 모집 상태를 변경합니다. (true: 모집중, false: 모집마감)") - @ApiResponses({ - @ApiResponse(responseCode = "204", description = "상태 변경 성공"), - @ApiResponse(responseCode = "400", description = "잘못된 요청"), - @ApiResponse(responseCode = "403", description = "권한 없음"), - @ApiResponse(responseCode = "404", description = "게시글을 찾을 수 없음") + @ApiResponse(responseCode = "204", description = "상태 변경 성공", content = @Content()) + @ApiErrorResponses({ + ErrorCode.INVALID_INPUT_VALUE, + ErrorCode.POST_NOT_FOUND, + ErrorCode.POST_ACCESS_DENIED, + ErrorCode.INVALID_POST_STATUS, + ErrorCode.UNAUTHORIZED }) ResponseEntity> updatePostStatus( @Parameter(description = "게시글 ID") Long postId, diff --git a/src/main/java/com/dduru/gildongmu/profile/controller/ProfileApiDocs.java b/src/main/java/com/dduru/gildongmu/profile/controller/ProfileApiDocs.java index 95efa4cc..2f979145 100644 --- a/src/main/java/com/dduru/gildongmu/profile/controller/ProfileApiDocs.java +++ b/src/main/java/com/dduru/gildongmu/profile/controller/ProfileApiDocs.java @@ -11,9 +11,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import org.springframework.http.ResponseEntity; @@ -22,14 +20,7 @@ public interface ProfileApiDocs { @Operation(summary = "닉네임 수정", description = "사용자의 닉네임을 수정합니다.") - @ApiResponses({ - @ApiResponse( - responseCode = "204", - description = "닉네임 수정 성공", - content = @Content(mediaType = "application/json", - schema = @Schema(implementation = ApiResult.class)) - ) - }) + @ApiResponse(responseCode = "204", description = "닉네임 수정 성공", content = @Content()) @ApiErrorResponses({ ErrorCode.NICKNAME_INVALID_LENGTH, ErrorCode.NICKNAME_INVALID_CHARACTERS, @@ -44,14 +35,7 @@ ResponseEntity> updateNickname( ); @Operation(summary = "닉네임 유효성 확인", description = "닉네임의 사용 가능 여부를 확인합니다. 닉네임 형식 검증 및 중복 여부를 체크합니다.") - @ApiResponses({ - @ApiResponse( - responseCode = "200", - description = "닉네임 유효성 확인 성공 - 사용 가능한 닉네임임", - content = @Content(mediaType = "application/json", - schema = @Schema(implementation = NicknameValidateResponse.class)) - ) - }) + @ApiResponse(responseCode = "200", description = "닉네임 유효성 확인 성공(사용가능)") @ApiErrorResponses({ ErrorCode.NICKNAME_INVALID_LENGTH, ErrorCode.NICKNAME_INVALID_CHARACTERS, @@ -67,14 +51,7 @@ ResponseEntity> checkNickname( ); @Operation(summary = "랜덤 닉네임 생성", description = "랜덤으로 사용 가능한 닉네임을 생성합니다. 형용사와 명사 조합에 랜덤 숫자를 추가하여 고유성을 보장합니다.") - @ApiResponses({ - @ApiResponse( - responseCode = "200", - description = "랜덤 닉네임 생성 성공", - content = @Content(mediaType = "application/json", - schema = @Schema(implementation = NicknameRandomResponse.class)) - ) - }) + @ApiResponse(responseCode = "200", description = "랜덤 닉네임 생성 성공") @ApiErrorResponses({ErrorCode.UNAUTHORIZED}) ResponseEntity> generateRandomNickname(); @@ -82,14 +59,7 @@ ResponseEntity> checkNickname( summary = "프로필 초기 설정", description = "온보딩 과정에서 사용자의 프로필 정보를 초기 설정합니다. 닉네임, 성별, 전화번호, 생년월일을 저장하며, 비관적 잠금을 사용하여 닉네임 중복을 방지합니다." ) - @ApiResponses({ - @ApiResponse( - responseCode = "204", - description = "프로필 초기 설정 성공", - content = @Content(mediaType = "application/json", - schema = @Schema(implementation = ApiResult.class)) - ) - }) + @ApiResponse(responseCode = "204", description = "프로필 초기 설정 성공", content = @Content()) @ApiErrorResponses({ ErrorCode.INVALID_INPUT_VALUE, ErrorCode.NICKNAME_INVALID_LENGTH, diff --git a/src/main/java/com/dduru/gildongmu/survey/controller/SurveyApiDocs.java b/src/main/java/com/dduru/gildongmu/survey/controller/SurveyApiDocs.java index ac362fc5..465575ee 100644 --- a/src/main/java/com/dduru/gildongmu/survey/controller/SurveyApiDocs.java +++ b/src/main/java/com/dduru/gildongmu/survey/controller/SurveyApiDocs.java @@ -24,11 +24,7 @@ public interface SurveyApiDocs { @ApiResponses({ @ApiResponse( responseCode = "201", - description = "설문 제출 성공", - content = @Content( - mediaType = "application/json", - schema = @Schema(implementation = SurveyResponse.class) - ) + description = "설문 제출 성공" ), @ApiResponse( responseCode = "400", @@ -89,11 +85,7 @@ ResponseEntity> submitSurvey( @ApiResponses({ @ApiResponse( responseCode = "200", - description = "조회 성공", - content = @Content( - mediaType = "application/json", - schema = @Schema(implementation = SurveyResponse.class) - ) + description = "조회 성공" ), @ApiResponse( responseCode = "404", diff --git a/src/main/java/com/dduru/gildongmu/survey/controller/SurveyController.java b/src/main/java/com/dduru/gildongmu/survey/controller/SurveyController.java index d6e93c54..f5c2ad8d 100644 --- a/src/main/java/com/dduru/gildongmu/survey/controller/SurveyController.java +++ b/src/main/java/com/dduru/gildongmu/survey/controller/SurveyController.java @@ -25,7 +25,7 @@ public ResponseEntity> submitSurvey( @RequestBody @Valid SurveyRequest request ) { SurveyResponse response = surveyService.submitSurvey(userId, request); - return ResponseEntity.status(HttpStatus.CREATED).body(ApiResult.ok(response)); + return ResponseEntity.status(HttpStatus.CREATED).body(ApiResult.created(response)); } @Override @@ -34,6 +34,6 @@ public ResponseEntity> getMySurveyResult( @CurrentUser Long userId ) { SurveyResponse response = surveyService.getMySurveyResult(userId); - return ResponseEntity.status(HttpStatus.OK).body(ApiResult.ok(response)); + return ResponseEntity.ok(ApiResult.ok(response)); } } diff --git a/src/main/java/com/dduru/gildongmu/verification/controller/PhoneVerificationApiDocs.java b/src/main/java/com/dduru/gildongmu/verification/controller/PhoneVerificationApiDocs.java index 690d3471..b345e592 100644 --- a/src/main/java/com/dduru/gildongmu/verification/controller/PhoneVerificationApiDocs.java +++ b/src/main/java/com/dduru/gildongmu/verification/controller/PhoneVerificationApiDocs.java @@ -1,18 +1,15 @@ package com.dduru.gildongmu.verification.controller; +import com.dduru.gildongmu.common.annotation.ApiErrorResponses; import com.dduru.gildongmu.common.dto.ApiResult; -import com.dduru.gildongmu.common.exception.ErrorResponse; +import com.dduru.gildongmu.common.exception.ErrorCode; import com.dduru.gildongmu.verification.dto.VerificationSendRequest; import com.dduru.gildongmu.verification.dto.VerificationSendResponse; import com.dduru.gildongmu.verification.dto.VerificationVerifyRequest; import com.dduru.gildongmu.verification.dto.VerificationVerifyResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.ExampleObject; -import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import org.springframework.http.ResponseEntity; @@ -21,72 +18,13 @@ public interface PhoneVerificationApiDocs { @Operation(summary = "인증번호 발송", description = "전화번호로 인증번호를 발송합니다.") - @ApiResponses({ - @ApiResponse( - responseCode = "200", - description = "인증번호 발송 성공", - content = @Content( - mediaType = "application/json", - schema = @Schema(implementation = VerificationSendResponse.class) - ) - ), - @ApiResponse( - responseCode = "409", - description = "이미 가입된 전화번호", - content = @Content( - mediaType = "application/json", - schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - name = "DuplicatePhoneNumber", - value = """ - { - "status": 409, - "data": { - "errorCode": "DUPLICATE_PHONE_NUMBER", - "field": null, - "message": "이미 가입된 전화번호입니다. 로그인해주세요." - } - } - """ - ) - ) - ), - @ApiResponse( - responseCode = "429", - description = "재발송 제한 또는 일일 발송 한도 초과", - content = @Content( - mediaType = "application/json", - schema = @Schema(implementation = ErrorResponse.class), - examples = { - @ExampleObject( - name = "ResendLimitExceeded", - value = """ - { - "status": 429, - "data": { - "errorCode": "TOO_MANY_REQUESTS", - "field": null, - "message": "재발송 제한 시간이 지나지 않았습니다." - } - } - """ - ), - @ExampleObject( - name = "DailyLimitExceeded", - value = """ - { - "status": 429, - "data": { - "errorCode": "DAILY_SMS_LIMIT_EXCEEDED", - "field": null, - "message": "일일 SMS 발송 한도를 초과했습니다." - } - } - """ - ) - } - ) - ) + @ApiResponse(responseCode = "200", description = "인증번호 발송 성공") + @ApiErrorResponses({ + ErrorCode.DUPLICATE_PHONE_NUMBER, + ErrorCode.TOO_MANY_REQUESTS, + ErrorCode.DAILY_SMS_LIMIT_EXCEEDED, + ErrorCode.SMS_SEND_FAILED, + ErrorCode.SMS_PROVIDER_ERROR }) ResponseEntity> sendVerificationCode( @Parameter(hidden = true) Long userId, @@ -94,93 +32,12 @@ ResponseEntity> sendVerificationCode( ); @Operation(summary = "인증번호 검증", description = "발송된 인증번호를 검증하고 인증 토큰을 발급합니다.") - @ApiResponses({ - @ApiResponse( - responseCode = "200", - description = "인증번호 검증 성공", - content = @Content( - mediaType = "application/json", - schema = @Schema(implementation = VerificationVerifyResponse.class) - ) - ), - @ApiResponse( - responseCode = "400", - description = "인증번호 불일치 또는 검증 시도 횟수 초과", - content = @Content( - mediaType = "application/json", - schema = @Schema(implementation = ErrorResponse.class), - examples = { - @ExampleObject( - name = "InvalidAuthCode", - value = """ - { - "status": 400, - "data": { - "errorCode": "INVALID_AUTH_CODE", - "field": null, - "message": "인증번호가 일치하지 않습니다." - } - } - """ - ), - @ExampleObject( - name = "AttemptsExceeded", - value = """ - { - "status": 400, - "data": { - "errorCode": "VERIFICATION_ATTEMPTS_EXCEEDED", - "field": null, - "message": "검증 시도 횟수를 초과했습니다." - } - } - """ - ) - } - ) - ), - @ApiResponse( - responseCode = "404", - description = "인증 정보를 찾을 수 없음 (만료 포함)", - content = @Content( - mediaType = "application/json", - schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - name = "VerificationNotFound", - value = """ - { - "status": 404, - "data": { - "errorCode": "VERIFICATION_NOT_FOUND", - "field": null, - "message": "인증 정보를 찾을 수 없습니다." - } - } - """ - ) - ) - ), - @ApiResponse( - responseCode = "409", - description = "이미 완료된 인증", - content = @Content( - mediaType = "application/json", - schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - name = "AlreadyVerified", - value = """ - { - "status": 409, - "data": { - "errorCode": "ALREADY_VERIFIED", - "field": null, - "message": "이미 완료된 인증입니다." - } - } - """ - ) - ) - ) + @ApiResponse(responseCode = "200", description = "인증번호 검증 성공") + @ApiErrorResponses({ + ErrorCode.INVALID_AUTH_CODE, + ErrorCode.VERIFICATION_ATTEMPTS_EXCEEDED, + ErrorCode.VERIFICATION_NOT_FOUND, + ErrorCode.ALREADY_VERIFIED }) ResponseEntity> verifyCode( @Parameter(hidden = true) Long userId,