From 01f9c11a6bcf2a49914b8f0f020d395b562f1b3e Mon Sep 17 00:00:00 2001 From: KTH1007 Date: Mon, 22 Dec 2025 01:34:18 +0900 Subject: [PATCH] =?UTF-8?q?feat/#186:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=8A=A4=ED=81=AC=EB=A6=AC=EB=84=88=20=EC=A7=88=EB=AC=B8=20?= =?UTF-8?q?=ED=8F=AC=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Post에 스크리너 질문 필드 포함 - Post 생성, 수정, 업데이트 DTO 수정 - Post 관련 엔티티 BatchSize 어노테이션 추가 --- .../app/post/controller/PostController.java | 11 ++++++ .../controller/doc/PostControllerDoc.java | 9 +++++ .../dto/request/PostCreateRequest.java | 6 ++-- .../dto/request/PostUpdateRequest.java | 4 +-- .../dto/response/PostRequirementResponse.java | 5 +-- .../response/PostRightSidebarResponse.java | 4 +-- .../PostScreenerQuestionResponse.java | 15 ++++++++ .../example/nexus/app/post/domain/Post.java | 10 ++++++ .../nexus/app/post/domain/PostContent.java | 19 ++++++++-- .../nexus/app/post/domain/PostFeedback.java | 25 ++++++++++--- .../app/post/domain/PostRequirement.java | 36 +++++++++++++++---- .../nexus/app/post/domain/PostSchedule.java | 14 ++++++-- .../nexus/app/post/service/PostService.java | 22 ++++++++++-- .../nexus/app/reward/domain/PostReward.java | 2 ++ 14 files changed, 152 insertions(+), 30 deletions(-) create mode 100644 src/main/java/com/example/nexus/app/post/controller/dto/response/PostScreenerQuestionResponse.java diff --git a/src/main/java/com/example/nexus/app/post/controller/PostController.java b/src/main/java/com/example/nexus/app/post/controller/PostController.java index 24908629..be6fe64d 100644 --- a/src/main/java/com/example/nexus/app/post/controller/PostController.java +++ b/src/main/java/com/example/nexus/app/post/controller/PostController.java @@ -9,6 +9,7 @@ import com.example.nexus.app.post.controller.dto.response.PostDetailResponse; import com.example.nexus.app.post.controller.dto.response.PostMainViewDetailResponse; import com.example.nexus.app.post.controller.dto.response.PostRightSidebarResponse; +import com.example.nexus.app.post.controller.dto.response.PostScreenerQuestionResponse; import com.example.nexus.app.post.controller.dto.response.PostSummaryResponse; import com.example.nexus.app.post.controller.dto.response.SimilarPostResponse; import com.example.nexus.app.post.service.PostService; @@ -193,4 +194,14 @@ public ResponseEntity> getPostRightSidebar return ResponseEntity.ok(ApiResponse.onSuccess(response)); } + + @Override + @GetMapping("/{postId}/questions") + public ResponseEntity> getPostScreenerQuestion( + @PathVariable Long postId) { + + PostScreenerQuestionResponse response = postService.findQuestions(postId); + + return ResponseEntity.ok(ApiResponse.onSuccess(response)); + } } diff --git a/src/main/java/com/example/nexus/app/post/controller/doc/PostControllerDoc.java b/src/main/java/com/example/nexus/app/post/controller/doc/PostControllerDoc.java index 3ba16ac7..44182e39 100644 --- a/src/main/java/com/example/nexus/app/post/controller/doc/PostControllerDoc.java +++ b/src/main/java/com/example/nexus/app/post/controller/doc/PostControllerDoc.java @@ -251,4 +251,13 @@ ResponseEntity> getPostRightSidebar( @Parameter(description = "게시글 ID", required = true) @PathVariable Long postId ); + + @Operation( + summary = "게시글 추가 조건 조회", + description = "게시글의 추가 요구사항을 조회합니다." + ) + ResponseEntity> getPostScreenerQuestion( + @Parameter(description = "게시글 ID", required = true) + @PathVariable Long postId + ); } diff --git a/src/main/java/com/example/nexus/app/post/controller/dto/request/PostCreateRequest.java b/src/main/java/com/example/nexus/app/post/controller/dto/request/PostCreateRequest.java index ecec0f98..9c6cc06b 100644 --- a/src/main/java/com/example/nexus/app/post/controller/dto/request/PostCreateRequest.java +++ b/src/main/java/com/example/nexus/app/post/controller/dto/request/PostCreateRequest.java @@ -69,8 +69,8 @@ public record PostCreateRequest( @Schema(description = "최대 나이", example = "35") Integer ageMax, - @Schema(description = "추가 요구사항", example = "모바일 앱 사용 경험이 있으신 분") - String additionalRequirements, + @Schema(description = "추가 조건", example = "[\"모바일 앱 사용 경험이 있으신 분\", \"ios\"]") + List screenerQuestions, @Schema(description = "리워드 타입", example = "GIFT_CARD") RewardType rewardType, @@ -141,7 +141,7 @@ public PostRequirement toPostRequirementEntity(Post post) { .genderRequirement(genderRequirement) .ageMin(ageMin) .ageMax(ageMax) - .additionalRequirements(additionalRequirements) + .screenerQuestions(screenerQuestions) .build(); } diff --git a/src/main/java/com/example/nexus/app/post/controller/dto/request/PostUpdateRequest.java b/src/main/java/com/example/nexus/app/post/controller/dto/request/PostUpdateRequest.java index 253d2bed..dce3e02d 100644 --- a/src/main/java/com/example/nexus/app/post/controller/dto/request/PostUpdateRequest.java +++ b/src/main/java/com/example/nexus/app/post/controller/dto/request/PostUpdateRequest.java @@ -61,8 +61,8 @@ public record PostUpdateRequest( @Schema(description = "최대 나이", example = "40") Integer ageMax, - @Schema(description = "추가 요구사항", example = "마케팅 업무 경험자 우대") - String additionalRequirements, + @Schema(description = "추가 조건", example = "[\"모바일 앱 사용 경험이 있으신 분\", \"ios\"]") + List screenerQuestions, @Schema(description = "리워드 타입", example = "CASH") RewardType rewardType, diff --git a/src/main/java/com/example/nexus/app/post/controller/dto/response/PostRequirementResponse.java b/src/main/java/com/example/nexus/app/post/controller/dto/response/PostRequirementResponse.java index 61659349..935584fa 100644 --- a/src/main/java/com/example/nexus/app/post/controller/dto/response/PostRequirementResponse.java +++ b/src/main/java/com/example/nexus/app/post/controller/dto/response/PostRequirementResponse.java @@ -2,6 +2,7 @@ import com.example.nexus.app.post.domain.PostRequirement; import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; public record PostRequirementResponse( @Schema(description = "최대 참여자 수") @@ -17,7 +18,7 @@ public record PostRequirementResponse( Integer ageMax, @Schema(description = "추가 요구사항") - String additionalRequirements + List screenerQuestions ) { public static PostRequirementResponse from(PostRequirement requirement) { @@ -26,7 +27,7 @@ public static PostRequirementResponse from(PostRequirement requirement) { requirement.getGenderRequirement(), requirement.getAgeMin(), requirement.getAgeMax(), - requirement.getAdditionalRequirements() + requirement.getScreenerQuestions() ); } } diff --git a/src/main/java/com/example/nexus/app/post/controller/dto/response/PostRightSidebarResponse.java b/src/main/java/com/example/nexus/app/post/controller/dto/response/PostRightSidebarResponse.java index ef9fd6b2..ac2dccb5 100644 --- a/src/main/java/com/example/nexus/app/post/controller/dto/response/PostRightSidebarResponse.java +++ b/src/main/java/com/example/nexus/app/post/controller/dto/response/PostRightSidebarResponse.java @@ -56,9 +56,9 @@ public static PostRightSidebarResponse from(Post post, User user) { if (!targetBuilder.isEmpty()) targetBuilder.append(", "); targetBuilder.append(post.getRequirement().getAgeMax()).append("세 이하"); } - if (post.getRequirement().getAdditionalRequirements() != null && !post.getRequirement().getAdditionalRequirements().isBlank()) { + if (post.getRequirement().getScreenerQuestions() != null && !post.getRequirement().getScreenerQuestions().isEmpty()) { if (!targetBuilder.isEmpty()) targetBuilder.append(", "); - targetBuilder.append(post.getRequirement().getAdditionalRequirements()); + targetBuilder.append(post.getRequirement().getScreenerQuestions()); } if (!targetBuilder.isEmpty()) { participationTarget = targetBuilder.toString(); diff --git a/src/main/java/com/example/nexus/app/post/controller/dto/response/PostScreenerQuestionResponse.java b/src/main/java/com/example/nexus/app/post/controller/dto/response/PostScreenerQuestionResponse.java new file mode 100644 index 00000000..8d002210 --- /dev/null +++ b/src/main/java/com/example/nexus/app/post/controller/dto/response/PostScreenerQuestionResponse.java @@ -0,0 +1,15 @@ +package com.example.nexus.app.post.controller.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; + +@Schema(description = "게시글 추가 조건") +public record PostScreenerQuestionResponse( + @Schema(description = "추가 조건", example = "[\"모바일 앱 사용 경험이 있으신 분\", \"ios\"]") + List screenerQuestions +) { + + public static PostScreenerQuestionResponse of(List questions) { + return new PostScreenerQuestionResponse(questions); + } +} diff --git a/src/main/java/com/example/nexus/app/post/domain/Post.java b/src/main/java/com/example/nexus/app/post/domain/Post.java index f33948ee..d38b1dc4 100644 --- a/src/main/java/com/example/nexus/app/post/domain/Post.java +++ b/src/main/java/com/example/nexus/app/post/domain/Post.java @@ -6,10 +6,12 @@ import com.example.nexus.app.global.code.status.ErrorStatus; import com.example.nexus.app.global.exception.GeneralException; import com.example.nexus.app.reward.domain.PostReward; +import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.*; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.BatchSize; import org.springframework.data.annotation.CreatedBy; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedBy; @@ -54,18 +56,21 @@ public class Post { @Enumerated(EnumType.STRING) @CollectionTable(name = "post_main_category", joinColumns = @JoinColumn(name = "post_id")) @Column(name = "main_category", nullable = false) + @BatchSize(size = 100) private Set mainCategory; @ElementCollection @Enumerated(EnumType.STRING) @CollectionTable(name = "post_platform_category", joinColumns = @JoinColumn(name = "post_id")) @Column(name = "platform_category") + @BatchSize(size = 100) private Set platformCategory; @ElementCollection @Enumerated(EnumType.STRING) @CollectionTable(name = "post_genres", joinColumns = @JoinColumn(name = "post_id")) @Column(name = "genre") + @BatchSize(size = 100) private Set genreCategories = new HashSet<>(); @Enumerated(EnumType.STRING) @@ -86,18 +91,23 @@ public class Post { @Column(name = "team_member_count") private Integer teamMemberCount; + @JsonIgnore @OneToOne(mappedBy = "post", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private PostSchedule schedule; + @JsonIgnore @OneToOne(mappedBy = "post", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private PostRequirement requirement; + @JsonIgnore @OneToOne(mappedBy = "post", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private PostReward reward; + @JsonIgnore @OneToOne(mappedBy = "post", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private PostFeedback feedback; + @JsonIgnore @OneToOne(mappedBy = "post", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private PostContent postContent; diff --git a/src/main/java/com/example/nexus/app/post/domain/PostContent.java b/src/main/java/com/example/nexus/app/post/domain/PostContent.java index fd639495..1ff7afcf 100644 --- a/src/main/java/com/example/nexus/app/post/domain/PostContent.java +++ b/src/main/java/com/example/nexus/app/post/domain/PostContent.java @@ -1,11 +1,23 @@ package com.example.nexus.app.post.domain; -import jakarta.persistence.*; +import jakarta.persistence.CollectionTable; +import jakarta.persistence.Column; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import java.util.ArrayList; +import java.util.List; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import java.util.List; -import java.util.ArrayList; +import org.hibernate.annotations.BatchSize; @Entity @Table(name = "post_contents", uniqueConstraints = @UniqueConstraint(columnNames = "post_id")) @@ -30,6 +42,7 @@ public class PostContent { @ElementCollection @CollectionTable(name = "post_media_urls", joinColumns = @JoinColumn(name = "post_content_id")) @Column(name = "media_url") + @BatchSize(size = 100) private List mediaUrls = new ArrayList<>(); @Builder diff --git a/src/main/java/com/example/nexus/app/post/domain/PostFeedback.java b/src/main/java/com/example/nexus/app/post/domain/PostFeedback.java index 5cbeb31b..faee9cac 100644 --- a/src/main/java/com/example/nexus/app/post/domain/PostFeedback.java +++ b/src/main/java/com/example/nexus/app/post/domain/PostFeedback.java @@ -1,14 +1,27 @@ package com.example.nexus.app.post.domain; -import jakarta.persistence.*; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - +import jakarta.persistence.CollectionTable; +import jakarta.persistence.Column; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.BatchSize; @Entity @Table(name = "post_feedbacks", uniqueConstraints = @UniqueConstraint(columnNames = "post_id")) @@ -30,12 +43,14 @@ public class PostFeedback { @ElementCollection(fetch = FetchType.EAGER) @CollectionTable(name = "post_feedback_items", joinColumns = @JoinColumn(name = "post_feedback_id")) @Column(name = "feedback_item") + @BatchSize(size = 100) private List feedbackItems = new ArrayList<>(); @ElementCollection(fetch = FetchType.EAGER) @Enumerated(EnumType.STRING) @CollectionTable(name = "post_privacy_item", joinColumns = @JoinColumn(name = "post_feedback_id")) @Column(name = "privacy_item") + @BatchSize(size = 100) private Set privacyItems = new HashSet<>(); private String privacyPurpose; diff --git a/src/main/java/com/example/nexus/app/post/domain/PostRequirement.java b/src/main/java/com/example/nexus/app/post/domain/PostRequirement.java index 826c121e..31218dd5 100644 --- a/src/main/java/com/example/nexus/app/post/domain/PostRequirement.java +++ b/src/main/java/com/example/nexus/app/post/domain/PostRequirement.java @@ -1,9 +1,23 @@ package com.example.nexus.app.post.domain; -import jakarta.persistence.*; +import jakarta.persistence.CollectionTable; +import jakarta.persistence.Column; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import java.util.ArrayList; +import java.util.List; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.BatchSize; @Entity @Table(name = "post_requirements", uniqueConstraints = @UniqueConstraint(columnNames = "post_id")) @@ -31,18 +45,23 @@ public class PostRequirement { @Column(name = "age_max") private Integer ageMax; - @Column(name = "additional_requirements", columnDefinition = "TEXT") - private String additionalRequirements; + @ElementCollection(fetch = FetchType.EAGER) + @CollectionTable(name = "post_screener_questions", joinColumns = @JoinColumn(name = "post_requirement_id")) + @Column(name = "screener_question") + @BatchSize(size = 100) + private List screenerQuestions = new ArrayList<>(); @Builder public PostRequirement(Post post, Integer maxParticipants, String genderRequirement, - Integer ageMin, Integer ageMax, String additionalRequirements) { + Integer ageMin, Integer ageMax, List screenerQuestions) { this.post = post; this.maxParticipants = maxParticipants; this.genderRequirement = genderRequirement; this.ageMin = ageMin; this.ageMax = ageMax; - this.additionalRequirements = additionalRequirements; + if (screenerQuestions != null) { + this.screenerQuestions = new ArrayList<>(screenerQuestions); + } } public void updateMaxParticipants(Integer maxParticipants) { @@ -61,7 +80,10 @@ public void updateAgeMax(Integer ageMax) { this.ageMax = ageMax; } - public void updateAdditionalRequirements(String additionalRequirements) { - this.additionalRequirements = additionalRequirements; + public void updateScreenerQuestions(List screenerQuestions) { + this.screenerQuestions.clear(); + if (screenerQuestions != null) { + this.screenerQuestions.addAll(screenerQuestions); + } } } diff --git a/src/main/java/com/example/nexus/app/post/domain/PostSchedule.java b/src/main/java/com/example/nexus/app/post/domain/PostSchedule.java index c97e55f9..b7489f9c 100644 --- a/src/main/java/com/example/nexus/app/post/domain/PostSchedule.java +++ b/src/main/java/com/example/nexus/app/post/domain/PostSchedule.java @@ -1,12 +1,20 @@ package com.example.nexus.app.post.domain; -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import java.time.LocalDateTime; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import java.time.LocalDateTime; - @Entity @Table(name = "post_schedules", uniqueConstraints = @UniqueConstraint(columnNames = "post_id")) @Getter diff --git a/src/main/java/com/example/nexus/app/post/service/PostService.java b/src/main/java/com/example/nexus/app/post/service/PostService.java index c2b63af1..3df1e6bf 100644 --- a/src/main/java/com/example/nexus/app/post/service/PostService.java +++ b/src/main/java/com/example/nexus/app/post/service/PostService.java @@ -16,6 +16,7 @@ import com.example.nexus.app.post.controller.dto.response.PostDetailResponse; import com.example.nexus.app.post.controller.dto.response.PostMainViewDetailResponse; import com.example.nexus.app.post.controller.dto.response.PostRightSidebarResponse; +import com.example.nexus.app.post.controller.dto.response.PostScreenerQuestionResponse; import com.example.nexus.app.post.controller.dto.response.PostSummaryResponse; import com.example.nexus.app.post.controller.dto.response.SimilarPostResponse; import com.example.nexus.app.post.domain.Post; @@ -42,12 +43,14 @@ import java.util.Set; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +@Slf4j @Service @RequiredArgsConstructor @Transactional(readOnly = true) @@ -266,6 +269,19 @@ public void deletePost(Long postId, Long userId) { postRepository.delete(post); } + public PostScreenerQuestionResponse findQuestions(Long postId) { + PostRequirement postRequirement = getPostRequirement(postId); + List questions = postRequirement.getScreenerQuestions(); + PostScreenerQuestionResponse response = PostScreenerQuestionResponse.of(questions); + return response; + } + + private PostRequirement getPostRequirement(Long postId) { + PostRequirement postRequirement = postRequirementRepository.findByPostId(postId) + .orElseThrow(() -> new GeneralException(ErrorStatus.POST_NOT_FOUND)); + return postRequirement; + } + private void createAndSaveRelatedEntitiesWithImage(PostCreateRequest request, Post post, List imageFiles) { PostSchedule schedule = PostSchedule.builder() .post(post) @@ -282,7 +298,7 @@ private void createAndSaveRelatedEntitiesWithImage(PostCreateRequest request, Po .genderRequirement(request.genderRequirement()) .ageMin(request.ageMin()) .ageMax(request.ageMax()) - .additionalRequirements(request.additionalRequirements()) + .screenerQuestions(request.screenerQuestions()) .build(); postRequirementRepository.save(requirement); @@ -367,8 +383,8 @@ private void updateRequirement(PostUpdateRequest request, PostRequirement requir if (request.ageMax() != null) { requirement.updateAgeMax(request.ageMax()); } - if (request.additionalRequirements() != null) { - requirement.updateAdditionalRequirements(request.additionalRequirements()); + if (request.screenerQuestions() != null) { + requirement.updateScreenerQuestions(request.screenerQuestions()); } } diff --git a/src/main/java/com/example/nexus/app/reward/domain/PostReward.java b/src/main/java/com/example/nexus/app/reward/domain/PostReward.java index 916dd6e3..816fc37d 100644 --- a/src/main/java/com/example/nexus/app/reward/domain/PostReward.java +++ b/src/main/java/com/example/nexus/app/reward/domain/PostReward.java @@ -1,6 +1,7 @@ package com.example.nexus.app.reward.domain; import com.example.nexus.app.post.domain.Post; +import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.*; import lombok.Builder; import lombok.Getter; @@ -18,6 +19,7 @@ public class PostReward { @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "post_id", nullable = false) + @JsonIgnore private Post post; @Enumerated(EnumType.STRING)