From 04ebdb02891f639a05aeeb3c09019b76adc08518 Mon Sep 17 00:00:00 2001 From: yxhwxn Date: Mon, 29 Jul 2024 21:12:59 +0900 Subject: [PATCH] =?UTF-8?q?Feat:=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85,?= =?UTF-8?q?=20=EC=95=84=EC=9D=B4=EB=94=94=20=EC=A4=91=EB=B3=B5=EC=B2=B4?= =?UTF-8?q?=ED=81=AC=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../suppin/member/controller/MemberApi.java | 44 ++++++++++++++++ .../controller/dto/MemberRequestDTO.java | 42 ++++++++++++++++ .../controller/dto/MemberResponseDTO.java | 31 ++++++++++++ .../com/cmc/suppin/member/converter/.gitkeep | 0 .../member/converter/MemberConverter.java | 36 +++++++++++++ .../com/cmc/suppin/member/domain/Member.java | 15 +++--- .../domain/repository/MemberRepository.java | 4 +- .../com/cmc/suppin/member/service/.gitkeep | 0 .../service/command/MemberCommandService.java | 11 ++++ .../command/MemberCommandServiceImpl.java | 50 +++++++++++++++++++ src/main/resources/application.yml | 2 + 11 files changed, 227 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/cmc/suppin/member/controller/MemberApi.java create mode 100644 src/main/java/com/cmc/suppin/member/controller/dto/MemberRequestDTO.java create mode 100644 src/main/java/com/cmc/suppin/member/controller/dto/MemberResponseDTO.java delete mode 100644 src/main/java/com/cmc/suppin/member/converter/.gitkeep create mode 100644 src/main/java/com/cmc/suppin/member/converter/MemberConverter.java delete mode 100644 src/main/java/com/cmc/suppin/member/service/.gitkeep create mode 100644 src/main/java/com/cmc/suppin/member/service/command/MemberCommandService.java create mode 100644 src/main/java/com/cmc/suppin/member/service/command/MemberCommandServiceImpl.java diff --git a/src/main/java/com/cmc/suppin/member/controller/MemberApi.java b/src/main/java/com/cmc/suppin/member/controller/MemberApi.java new file mode 100644 index 0000000..3262214 --- /dev/null +++ b/src/main/java/com/cmc/suppin/member/controller/MemberApi.java @@ -0,0 +1,44 @@ +package com.cmc.suppin.member.controller; + +import com.cmc.suppin.global.presentation.ApiResponse; +import com.cmc.suppin.member.controller.dto.MemberRequestDTO; +import com.cmc.suppin.member.controller.dto.MemberResponseDTO; +import com.cmc.suppin.member.converter.MemberConverter; +import com.cmc.suppin.member.domain.Member; +import com.cmc.suppin.member.service.command.MemberCommandService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +@RestController +@Slf4j +@RequiredArgsConstructor +@Validated +@Tag(name = "Member", description = "Member 관련 API") +@RequestMapping("/api/members") +public class MemberApi { + + private final MemberCommandService memberCommandService; + + + @PostMapping("/join") + @Operation(summary = "회원가입 API", description = "request 파라미터 : id, password, name, phone, email") + public ApiResponse join(@RequestBody @Valid MemberRequestDTO.JoinDTO request) { + Member member = memberCommandService.join(request); + + return ApiResponse.onSuccess(MemberConverter.toJoinResultDTO(member)); + + } + + @GetMapping("/checkUserId") + @Operation(summary = "아이디 중복 체크 API", description = "request : userId, response: 중복이면 false, 중복 아니면 true") + public ApiResponse checkUserId(@RequestBody MemberRequestDTO.IdConfirmDTO request) { + boolean checkUserId = memberCommandService.confirmUserId(request); + + return ApiResponse.onSuccess(MemberConverter.toIdConfirmResultDTO(checkUserId)); + } +} diff --git a/src/main/java/com/cmc/suppin/member/controller/dto/MemberRequestDTO.java b/src/main/java/com/cmc/suppin/member/controller/dto/MemberRequestDTO.java new file mode 100644 index 0000000..023208f --- /dev/null +++ b/src/main/java/com/cmc/suppin/member/controller/dto/MemberRequestDTO.java @@ -0,0 +1,42 @@ +package com.cmc.suppin.member.controller.dto; + +import jakarta.persistence.Id; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +public class MemberRequestDTO { + + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class JoinDTO { + @NotBlank(message = "아이디를 입력해주세요") + @Id + private String userId; + + @NotBlank(message = "이름을 입력해주세요") + private String name; + + @NotBlank(message = "비밀번호를 입력해주세요") + @Pattern(regexp = "(?=.*[0-9])(?=.*[a-zA-Z])(?=.*\\W)(?=\\S+$).{8,16}", message = "비밀번호는 8~16자 영문, 숫자, 특수문자를 사용하세요.") + private String password; + + @NotBlank(message = "이메일을 입력해주세요") + @Email(message = "이메일 형식이 올바르지 않습니다.") + private String email; + + @NotBlank(message = "휴대폰 번호를 입력해주세요") + private String phone; + } + + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class IdConfirmDTO { + private String userId; + } +} diff --git a/src/main/java/com/cmc/suppin/member/controller/dto/MemberResponseDTO.java b/src/main/java/com/cmc/suppin/member/controller/dto/MemberResponseDTO.java new file mode 100644 index 0000000..febf818 --- /dev/null +++ b/src/main/java/com/cmc/suppin/member/controller/dto/MemberResponseDTO.java @@ -0,0 +1,31 @@ +package com.cmc.suppin.member.controller.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +public class MemberResponseDTO { + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class JoinResultDTO { + Long memberId; + String userId; + String name; + String email; + LocalDateTime createdAt; + } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class IdConfirmResultDTO { + Boolean checkUserId; + } +} diff --git a/src/main/java/com/cmc/suppin/member/converter/.gitkeep b/src/main/java/com/cmc/suppin/member/converter/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/cmc/suppin/member/converter/MemberConverter.java b/src/main/java/com/cmc/suppin/member/converter/MemberConverter.java new file mode 100644 index 0000000..65cab45 --- /dev/null +++ b/src/main/java/com/cmc/suppin/member/converter/MemberConverter.java @@ -0,0 +1,36 @@ +package com.cmc.suppin.member.converter; + +import com.cmc.suppin.member.controller.dto.MemberRequestDTO; +import com.cmc.suppin.member.controller.dto.MemberResponseDTO; +import com.cmc.suppin.member.domain.Member; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +public class MemberConverter { + + public Member toEntity(MemberRequestDTO.JoinDTO request, BCryptPasswordEncoder encoder) { + return Member.builder() + .userId(request.getUserId()) + .name(request.getName()) + .password(encoder.encode(request.getPassword())) + .email(request.getEmail()) + .phoneNumber(request.getPhone()) + .build(); + } + + public static MemberResponseDTO.JoinResultDTO toJoinResultDTO(Member member) { + return MemberResponseDTO.JoinResultDTO.builder() + .memberId(member.getId()) + .userId(member.getUserId()) + .name(member.getName()) + .email(member.getEmail()) + .createdAt(member.getCreatedAt()) + .build(); + } + + public static MemberResponseDTO.IdConfirmResultDTO toIdConfirmResultDTO(boolean checkUserId) { + return MemberResponseDTO.IdConfirmResultDTO.builder() + .checkUserId(checkUserId) + .build(); + } + +} diff --git a/src/main/java/com/cmc/suppin/member/domain/Member.java b/src/main/java/com/cmc/suppin/member/domain/Member.java index cfb630d..32adfdb 100644 --- a/src/main/java/com/cmc/suppin/member/domain/Member.java +++ b/src/main/java/com/cmc/suppin/member/domain/Member.java @@ -3,15 +3,18 @@ import com.cmc.suppin.event.domain.Event; import com.cmc.suppin.global.domain.BaseDateTimeEntity; import jakarta.persistence.*; -import lombok.Getter; -import lombok.Setter; +import lombok.*; +import org.hibernate.annotations.DynamicInsert; import java.util.ArrayList; import java.util.List; @Entity @Getter -@Setter +@Builder +@DynamicInsert +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor public class Member extends BaseDateTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -21,12 +24,12 @@ public class Member extends BaseDateTimeEntity { @OneToMany(mappedBy = "member") private List eventList = new ArrayList<>(); + @Column(columnDefinition = "VARCHAR(30)", nullable = false) + private String userId; + @Column(columnDefinition = "VARCHAR(20)", nullable = false) private String name; - @Column(columnDefinition = "VARCHAR(30)", nullable = false) - private String nickname; - @Column(columnDefinition = "VARCHAR(30)", nullable = false) private String email; diff --git a/src/main/java/com/cmc/suppin/member/domain/repository/MemberRepository.java b/src/main/java/com/cmc/suppin/member/domain/repository/MemberRepository.java index f113cd5..0b3296e 100644 --- a/src/main/java/com/cmc/suppin/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/cmc/suppin/member/domain/repository/MemberRepository.java @@ -5,7 +5,7 @@ public interface MemberRepository extends JpaRepository { - Boolean existsByName(String name); + Boolean existsByUserId(String userId); - Member findByName(String name); + Member findByUserId(String userId); } diff --git a/src/main/java/com/cmc/suppin/member/service/.gitkeep b/src/main/java/com/cmc/suppin/member/service/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/cmc/suppin/member/service/command/MemberCommandService.java b/src/main/java/com/cmc/suppin/member/service/command/MemberCommandService.java new file mode 100644 index 0000000..54b2855 --- /dev/null +++ b/src/main/java/com/cmc/suppin/member/service/command/MemberCommandService.java @@ -0,0 +1,11 @@ +package com.cmc.suppin.member.service.command; + +import com.cmc.suppin.member.controller.dto.MemberRequestDTO; +import com.cmc.suppin.member.domain.Member; + +public interface MemberCommandService { + + Member join(MemberRequestDTO.JoinDTO request); + + Boolean confirmUserId(MemberRequestDTO.IdConfirmDTO request); +} diff --git a/src/main/java/com/cmc/suppin/member/service/command/MemberCommandServiceImpl.java b/src/main/java/com/cmc/suppin/member/service/command/MemberCommandServiceImpl.java new file mode 100644 index 0000000..c962341 --- /dev/null +++ b/src/main/java/com/cmc/suppin/member/service/command/MemberCommandServiceImpl.java @@ -0,0 +1,50 @@ +package com.cmc.suppin.member.service.command; + +import com.cmc.suppin.member.controller.dto.MemberRequestDTO; +import com.cmc.suppin.member.converter.MemberConverter; +import com.cmc.suppin.member.domain.Member; +import com.cmc.suppin.member.domain.repository.MemberRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Slf4j +@RequiredArgsConstructor +@Transactional +public class MemberCommandServiceImpl implements MemberCommandService { + + private final MemberRepository memberRepository; + private final BCryptPasswordEncoder bCryptPasswordEncoder; + private final MemberConverter memberConverter; + + /** + * 회원가입 + */ + @Override + public Member join(MemberRequestDTO.JoinDTO request) { + // 중복된 아이디 체크 + if (memberRepository.existsByUserId(request.getUserId())) { + throw new IllegalArgumentException("이미 존재하는 유저입니다."); + } + + // DTO를 Entity로 변환 + Member member = memberConverter.toEntity(request, bCryptPasswordEncoder); + + // 회원 정보 저장 + memberRepository.save(member); + + return member; + } + + /** + * ID 중복 확인 + */ + @Override + public Boolean confirmUserId(MemberRequestDTO.IdConfirmDTO request) { + // 아이디 중복 체크 + return !memberRepository.existsByUserId(request.getUserId()); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 82665d1..9d59683 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,4 +1,6 @@ spring: + server: + port: 8080 datasource: url: ${DB_URL} username: ${DB_USER}