diff --git a/build.gradle b/build.gradle index 992cd08..1330a42 100644 --- a/build.gradle +++ b/build.gradle @@ -26,9 +26,12 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-validation' + compileOnly 'org.projectlombok:lombok' runtimeOnly 'mysql:mysql-connector-java:8.0.33' annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } diff --git a/build/resources/main/application.properties b/build/resources/main/application.properties deleted file mode 100644 index 2109a44..0000000 --- a/build/resources/main/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.application.name=demo diff --git a/src/main/java/com/m0omoo/demo/controller/UserController.java b/src/main/java/com/m0omoo/demo/controller/UserController.java new file mode 100644 index 0000000..943a397 --- /dev/null +++ b/src/main/java/com/m0omoo/demo/controller/UserController.java @@ -0,0 +1,34 @@ +package com.m0omoo.demo.controller; + +import com.m0omoo.demo.dto.SignUpRequest; +import com.m0omoo.demo.service.UserService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +/** + * 회원 관련 HTTP 요청을 처리하는 컨트롤러 클래스 + * 클라이언트의 요청을 받아 서비스 로직을 호출한 뒤, 응답을 반환하는 역할 + */ +@RestController // 해당 클래스가 REST API 요청을 처리하는 컨트롤러임을 선언 +@RequiredArgsConstructor // final 필드를 자동으로 생성자 주입하는 Lombok 어노테이션 +@RequestMapping("/api/v1/users") // 이 컨트롤러 내 모든 요청의 기본 경로 설정 +public class UserController { + + // 회원 관련 비즈니스 로직을 처리하는 서비스 의존성 + private final UserService userService; + + /** + * 회원가입 요청 처리 핸들러 + * HTTP POST 방식으로 /signup 경로에 들어온 요청을 처리 + * 요청 본문에는 SignUpRequest 형태의 JSON 데이터 포함 + * + * @param request 클라이언트로부터 받은 회원가입 요청 DTO + * @return 성공 메시지를 담은 HTTP 응답 + */ + @PostMapping("/signup") + public ResponseEntity signUp(@RequestBody SignUpRequest request) { + userService.register(request); // 회원가입 처리 수행 + return ResponseEntity.ok("회원가입 성공"); // 성공 메시지 반환 + } +} diff --git a/src/main/java/com/m0omoo/demo/domain/User.java b/src/main/java/com/m0omoo/demo/domain/User.java new file mode 100644 index 0000000..b625fab --- /dev/null +++ b/src/main/java/com/m0omoo/demo/domain/User.java @@ -0,0 +1,36 @@ +package com.m0omoo.demo.domain; + +// JPA 관련 어노테이션들을 불러 +import jakarta.persistence.*; + +// Lombok 어노테이션: 반복되는 코드 생성을 줄여 +import lombok.*; + +/** + * User 엔티티 클래스 + * 이 클래스는 데이터베이스 테이블과 매핑되는 객체 + */ +@Entity // 이 클래스가 JPA의 엔티티임을 나타냄. 즉, DB 테이블로 매핑 +@Getter // Lombok: 모든 필드의 Getter 메서드를 자동 생성 +@Setter // Lombok: 모든 필드의 Setter 메서드를 자동 생성 +@NoArgsConstructor // Lombok: 파라미터가 없는 기본 생성자를 생성 +@AllArgsConstructor // Lombok: 모든 필드를 매개변수로 받는 생성자를 생성 +@Builder // Lombok: 객체를 쉽게 생성할 수 있는 빌더 패턴을 자동으로 생성 +public class User { + + @Id // 이 필드가 테이블의 기본 키(PK)라는 것을 명시 + @GeneratedValue(strategy = GenerationType.IDENTITY) + // 기본 키를 DB가 자동으로 생성하게 함 (보통 AUTO_INCREMENT처럼) + private Long id; + + @Column(nullable = false, unique = true) + // DB 컬럼: null을 허용하지 않으며, 중복을 허용하지 않음 (이메일은 고유해야 하므로) + private String email; + + @Column(nullable = false) + // DB 컬럼: null을 허용하지 않음 (비밀번호는 반드시 입력되어야 함) + private String password; + + // 닉네임은 null 가능. 특별한 제약 조건이 없기 때문에 @Column 생략 + private String nickname; +} diff --git a/src/main/java/com/m0omoo/demo/dto/SignUpRequest.java b/src/main/java/com/m0omoo/demo/dto/SignUpRequest.java new file mode 100644 index 0000000..612b970 --- /dev/null +++ b/src/main/java/com/m0omoo/demo/dto/SignUpRequest.java @@ -0,0 +1,28 @@ +package com.m0omoo.demo.dto; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; +/** + * 회원가입 요청 데이터를 담는 DTO 클래스 + * 클라이언트가 전달한 이메일, 비밀번호, 닉네임 정보를 담는 용도 + * 컨트롤러 → 서비스로 데이터를 전달할 때 사용하는 중간 객체 + */ +@Getter // 각 필드에 대한 Getter 메서드 자동 생성 (예: getEmail()) +@Setter // 각 필드에 대한 Setter 메서드 자동 생성 (예: setEmail()) +public class SignUpRequest { + + // 사용자 이메일 정보 + @NotBlank(message = "이메일은 필수 입력입니다.") + @Email(message = "올바른 이메일 형식이 아닙니다.") + private String email; + + // 사용자 비밀번호 정보 + @NotBlank(message = "비밀번호는 필수 입력입니다.") + private String password; + + // 사용자 닉네임 정보 + @NotBlank(message = "닉네임은 필수 입력입니다.") + private String nickname; +} diff --git a/src/main/java/com/m0omoo/demo/repository/UserRepository.java b/src/main/java/com/m0omoo/demo/repository/UserRepository.java new file mode 100644 index 0000000..eb2a88d --- /dev/null +++ b/src/main/java/com/m0omoo/demo/repository/UserRepository.java @@ -0,0 +1,19 @@ +package com.m0omoo.demo.repository; + +import com.m0omoo.demo.domain.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +/** + * User 엔티티와 관련된 데이터베이스 접근 기능 정의 인터페이스 + * Spring Data JPA에서 제공하는 JpaRepository를 상속하여 기본적인 CRUD 기능 제공 + */ +public interface UserRepository extends JpaRepository { + + /** + * 이메일을 기준으로 사용자 정보를 조회하는 메서드 + * 반환값은 Optional 형태로, 값이 없을 경우를 안전하게 처리할 수 있음 + */ + Optional findByEmail(String email); +} diff --git a/src/main/java/com/m0omoo/demo/service/UserService.java b/src/main/java/com/m0omoo/demo/service/UserService.java new file mode 100644 index 0000000..d795072 --- /dev/null +++ b/src/main/java/com/m0omoo/demo/service/UserService.java @@ -0,0 +1,40 @@ +package com.m0omoo.demo.service; + +import com.m0omoo.demo.domain.User; +import com.m0omoo.demo.dto.SignUpRequest; +import com.m0omoo.demo.repository.UserRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * 사용자 관련 비즈니스 로직을 처리하는 서비스 클래스 + * 회원가입 로직을 중심으로 구현 + */ +@Service +@RequiredArgsConstructor +public class UserService { + + // User 엔티티에 접근하기 위한 JPA 리포지토리 의존성 주입 + private final UserRepository userRepository; + + /** + * 회원가입 처리 로직 + * 이메일 중복 여부 확인 후 사용자 엔티티 저장 + */ + public void register(SignUpRequest dto) { + // 이메일 중복 여부 확인 + if (userRepository.findByEmail(dto.getEmail()).isPresent()) { + throw new IllegalArgumentException("이미 존재하는 이메일"); + } + + // 전달받은 DTO를 기반으로 User 엔티티 생성 + User user = User.builder() + .email(dto.getEmail()) + .password(dto.getPassword()) // 추후 비밀번호 암호화 필요 + .nickname(dto.getNickname()) + .build(); + + // DB에 사용자 정보 저장 + userRepository.save(user); + } +}