From 777bde7708ae79778a022f984d3c35ce9f9571d8 Mon Sep 17 00:00:00 2001 From: yumzen Date: Tue, 6 Aug 2024 00:50:52 +0900 Subject: [PATCH 1/2] =?UTF-8?q?#92=20Feat:=20Techstack=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EA=B8=B0=EB=8A=A5=20=EA=B0=9C=EB=B0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/converter/MemberConverter.java | 12 +++++++++- .../domain/entity/mapping/TechStacks.java | 12 +++++++--- .../global/domain/enums/TechStack.java | 11 +++++++++ .../global/repository/MemberRepository.java | 5 ++++ .../MemberService/MemberCommandService.java | 2 ++ .../MemberCommandServiceImpl.java | 23 +++++++++++++++++-- .../web/controller/MemberController.java | 13 ++++++++--- .../web/dto/Member/MemberResponseDTO.java | 13 +++++++++-- 8 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/codiary/backend/global/domain/enums/TechStack.java diff --git a/src/main/java/com/codiary/backend/global/converter/MemberConverter.java b/src/main/java/com/codiary/backend/global/converter/MemberConverter.java index 3d4b679..f3b1fe5 100644 --- a/src/main/java/com/codiary/backend/global/converter/MemberConverter.java +++ b/src/main/java/com/codiary/backend/global/converter/MemberConverter.java @@ -4,7 +4,7 @@ import com.codiary.backend.global.domain.entity.Follow; import com.codiary.backend.global.domain.entity.Member; import com.codiary.backend.global.domain.entity.mapping.MemberCategory; -import com.codiary.backend.global.web.dto.Bookmark.BookmarkResponseDTO; +import com.codiary.backend.global.domain.entity.mapping.TechStacks; import com.codiary.backend.global.web.dto.Member.FollowResponseDto; import com.codiary.backend.global.web.dto.Member.MemberResponseDTO; import com.codiary.backend.global.web.dto.Member.MemberSumResponseDto; @@ -36,6 +36,16 @@ public MemberSumResponseDto toFollowResponseDto(Member member) { .build(); } + public MemberResponseDTO.TechStacksDTO toTechStacksResponseDto(Member member) { + return MemberResponseDTO.TechStacksDTO.builder() + .memberId(member.getMemberId()) + .techStackList(member.getTechStackList() + .stream() + .map(TechStacks::getName) + .collect(Collectors.toList())) + .build(); + } + // 회원별 북마크 리스트 조회 diff --git a/src/main/java/com/codiary/backend/global/domain/entity/mapping/TechStacks.java b/src/main/java/com/codiary/backend/global/domain/entity/mapping/TechStacks.java index cb5ab03..9eaf199 100644 --- a/src/main/java/com/codiary/backend/global/domain/entity/mapping/TechStacks.java +++ b/src/main/java/com/codiary/backend/global/domain/entity/mapping/TechStacks.java @@ -1,7 +1,7 @@ package com.codiary.backend.global.domain.entity.mapping; import com.codiary.backend.global.domain.entity.Member; -import com.codiary.backend.global.domain.entity.Post; +import com.codiary.backend.global.domain.enums.TechStack; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Getter; @@ -16,11 +16,17 @@ public class TechStacks { @Column(name = "tech_stack_id", nullable = false, columnDefinition = "bigint") private Long techStackId; - //우선 String으로 설정, techStack 나오면 enum으로 변경 필요 + @Enumerated(EnumType.STRING) @Column(name = "name", nullable = false, columnDefinition = "varchar(50)") - private String name; + private TechStack name; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id") private Member member; + + // 생성자 추가 + public TechStacks(TechStack name, Member member) { + this.name = name; + this.member = member; + } } diff --git a/src/main/java/com/codiary/backend/global/domain/enums/TechStack.java b/src/main/java/com/codiary/backend/global/domain/enums/TechStack.java new file mode 100644 index 0000000..75c1d06 --- /dev/null +++ b/src/main/java/com/codiary/backend/global/domain/enums/TechStack.java @@ -0,0 +1,11 @@ +package com.codiary.backend.global.domain.enums; + +public enum TechStack { + JAVA, + SPRING, + JAVA_SCRIPT, + REACT, + CSS, + HTML, + NODE_JS, +} diff --git a/src/main/java/com/codiary/backend/global/repository/MemberRepository.java b/src/main/java/com/codiary/backend/global/repository/MemberRepository.java index 75eb2a8..3e01cd5 100644 --- a/src/main/java/com/codiary/backend/global/repository/MemberRepository.java +++ b/src/main/java/com/codiary/backend/global/repository/MemberRepository.java @@ -20,4 +20,9 @@ public interface MemberRepository extends JpaRepository { @Query("SELECT m FROM Member m LEFT JOIN FETCH m.followers WHERE m.memberId = :toId") Optional findByToIdWithFollowers(@Param("toId") long id); + + @Query("SELECT m FROM Member m LEFT JOIN FETCH m.techStackList WHERE m.memberId = :memberId") + Member findMemberWithTechStacks(@Param("memberId") Long memberId); + + } diff --git a/src/main/java/com/codiary/backend/global/service/MemberService/MemberCommandService.java b/src/main/java/com/codiary/backend/global/service/MemberService/MemberCommandService.java index 6559a16..bfb8f32 100644 --- a/src/main/java/com/codiary/backend/global/service/MemberService/MemberCommandService.java +++ b/src/main/java/com/codiary/backend/global/service/MemberService/MemberCommandService.java @@ -3,6 +3,7 @@ import com.codiary.backend.global.apiPayload.ApiResponse; import com.codiary.backend.global.domain.entity.Member; import com.codiary.backend.global.domain.entity.mapping.MemberCategory; +import com.codiary.backend.global.domain.enums.TechStack; import com.codiary.backend.global.web.dto.Member.MemberRequestDTO; import com.codiary.backend.global.web.dto.Member.MemberResponseDTO; @@ -21,4 +22,5 @@ public interface MemberCommandService { public ApiResponse setProfileImage(Member member, MemberRequestDTO.MemberProfileImageRequestDTO request); + public Member setTechStacks(Long memberId, TechStack techstack); } diff --git a/src/main/java/com/codiary/backend/global/service/MemberService/MemberCommandServiceImpl.java b/src/main/java/com/codiary/backend/global/service/MemberService/MemberCommandServiceImpl.java index d333f74..ee27f22 100644 --- a/src/main/java/com/codiary/backend/global/service/MemberService/MemberCommandServiceImpl.java +++ b/src/main/java/com/codiary/backend/global/service/MemberService/MemberCommandServiceImpl.java @@ -5,12 +5,12 @@ import com.codiary.backend.global.apiPayload.code.status.SuccessStatus; import com.codiary.backend.global.apiPayload.exception.GeneralException; import com.codiary.backend.global.apiPayload.exception.handler.MemberHandler; -import com.codiary.backend.global.converter.PostFileConverter; import com.codiary.backend.global.domain.entity.Member; import com.codiary.backend.global.domain.entity.MemberImage; -import com.codiary.backend.global.domain.entity.PostFile; import com.codiary.backend.global.domain.entity.Uuid; import com.codiary.backend.global.domain.entity.mapping.MemberCategory; +import com.codiary.backend.global.domain.entity.mapping.TechStacks; +import com.codiary.backend.global.domain.enums.TechStack; import com.codiary.backend.global.jwt.JwtTokenProvider; import com.codiary.backend.global.jwt.SecurityUtil; import com.codiary.backend.global.jwt.TokenInfo; @@ -29,6 +29,7 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; +import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -134,4 +135,22 @@ public ApiResponse setProfileImage(Member memb return ApiResponse.onSuccess(SuccessStatus.MEMBER_OK, response); } + @Override + public Member setTechStacks(Long memberId, TechStack techstack) { + Member member = memberRepository.findMemberWithTechStacks(memberId); + + List techStackList = member.getTechStackList(); + if (techStackList == null) { + techStackList = new ArrayList<>(); + } + + TechStacks newTechStack = new TechStacks(techstack, member); + techStackList.add(newTechStack); + + member.setTechStackList(techStackList); + + memberRepository.save(member); + + return member; + } } diff --git a/src/main/java/com/codiary/backend/global/web/controller/MemberController.java b/src/main/java/com/codiary/backend/global/web/controller/MemberController.java index c73a185..b1984a4 100644 --- a/src/main/java/com/codiary/backend/global/web/controller/MemberController.java +++ b/src/main/java/com/codiary/backend/global/web/controller/MemberController.java @@ -1,17 +1,15 @@ package com.codiary.backend.global.web.controller; import com.codiary.backend.global.apiPayload.ApiResponse; -import com.codiary.backend.global.converter.BookmarkConverter; import com.codiary.backend.global.converter.MemberConverter; import com.codiary.backend.global.converter.PostConverter; import com.codiary.backend.global.domain.entity.Member; import com.codiary.backend.global.domain.entity.Post; import com.codiary.backend.global.domain.entity.Bookmark; import com.codiary.backend.global.domain.entity.mapping.MemberCategory; +import com.codiary.backend.global.domain.enums.TechStack; import com.codiary.backend.global.service.MemberService.MemberCommandService; -import com.codiary.backend.global.service.MemberService.MemberCommandServiceImpl; import com.codiary.backend.global.service.MemberService.MemberQueryService; -import com.codiary.backend.global.web.dto.Bookmark.BookmarkResponseDTO; import com.codiary.backend.global.web.dto.Member.MemberRequestDTO; import com.codiary.backend.global.web.dto.Member.MemberResponseDTO; import com.codiary.backend.global.web.dto.Post.PostResponseDTO; @@ -44,6 +42,7 @@ public class MemberController { private final MemberCommandService memberCommandService; private final FollowService followService; private final MemberQueryService memberQueryService; + private final MemberConverter memberConverter; @PostMapping("/sign-up") @Operation( @@ -183,4 +182,12 @@ public ApiResponse getUserProfile(@PathVariabl Member member = memberCommandService.getRequester(); return ApiResponse.onSuccess(SuccessStatus.MEMBER_OK, memberQueryService.getUserProfile(userId, member)); } + + @PostMapping(path = "/techstacks") + @Operation(summary = "기술 스택 추가하기", description = "기술 스택 하나씩 추가") + public ApiResponse setTechStacks(@RequestParam(value = "techstack") TechStack techstack) { + Member member = memberCommandService.getRequester(); + member = memberCommandService.setTechStacks(member.getMemberId(), techstack); + return ApiResponse.onSuccess(SuccessStatus.MEMBER_OK, memberConverter.toTechStacksResponseDto(member)); + } } diff --git a/src/main/java/com/codiary/backend/global/web/dto/Member/MemberResponseDTO.java b/src/main/java/com/codiary/backend/global/web/dto/Member/MemberResponseDTO.java index 04b23c1..65c5a3d 100644 --- a/src/main/java/com/codiary/backend/global/web/dto/Member/MemberResponseDTO.java +++ b/src/main/java/com/codiary/backend/global/web/dto/Member/MemberResponseDTO.java @@ -1,5 +1,6 @@ package com.codiary.backend.global.web.dto.Member; +import com.codiary.backend.global.domain.enums.TechStack; import com.codiary.backend.global.jwt.TokenInfo; import lombok.*; @@ -20,7 +21,6 @@ public static class MemberTokenResponseDTO { } - // 회원별 북마크 리스트 조회 @Builder @Getter @@ -94,9 +94,18 @@ public static class UserProfileDTO { String linkedinUrl; String discordUrl; String introduction; - List techStacksList; + List techStacksList; List teamList; Boolean myPage; } + @Builder + @AllArgsConstructor + @NoArgsConstructor // 기본 생성자 추가 + @Getter + @Setter + public static class TechStacksDTO { + private Long memberId; + private List techStackList; + } } From 9fbc432cf2b0e0fb8e2734bf4dccea1a6fbf98eb Mon Sep 17 00:00:00 2001 From: yumzen Date: Tue, 6 Aug 2024 00:50:58 +0900 Subject: [PATCH 2/2] Chore: cors --- .../backend/global/config/WebConfig.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/main/java/com/codiary/backend/global/config/WebConfig.java diff --git a/src/main/java/com/codiary/backend/global/config/WebConfig.java b/src/main/java/com/codiary/backend/global/config/WebConfig.java new file mode 100644 index 0000000..c633a15 --- /dev/null +++ b/src/main/java/com/codiary/backend/global/config/WebConfig.java @@ -0,0 +1,19 @@ +package com.codiary.backend.global.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + @Override + public void addCorsMappings(final CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("http://localhost:3000") + .allowedMethods("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS") // 허용할 HTTP 메소드 + .allowedHeaders("*") // 허용할 헤더 + .allowCredentials(true); // 자격 증명 허용 + } +} + +