From ae8c111de1fd21defadc7c67c9d7cdc4faa01425 Mon Sep 17 00:00:00 2001 From: mino Date: Sun, 21 Dec 2025 13:41:26 +0900 Subject: [PATCH] =?UTF-8?q?feat=20:=20=EB=AA=A8=EC=A7=91=20=EC=9D=B4?= =?UTF-8?q?=EB=A9=94=EC=9D=BC=20=EC=A0=84=EC=86=A1=20=EC=9D=B4=EB=A9=94?= =?UTF-8?q?=EC=9D=BC=20=EC=A0=80=EC=9E=A5=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/blog/service/BlogService.java | 4 -- .../kusitms/website/domain/email/Email.java | 22 +++++++++ .../email/controller/EmailController.java | 47 ++++++++++++++++++ .../email/dto/response/EmailResponse.java | 16 +++++++ .../email/repository/EmailRepository.java | 11 +++++ .../domain/email/service/EmailService.java | 48 +++++++++++++++++++ .../exception/GlobalExceptionHandler.java | 14 ++++++ 7 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/kusitms/website/domain/email/Email.java create mode 100644 src/main/java/com/kusitms/website/domain/email/controller/EmailController.java create mode 100644 src/main/java/com/kusitms/website/domain/email/dto/response/EmailResponse.java create mode 100644 src/main/java/com/kusitms/website/domain/email/repository/EmailRepository.java create mode 100644 src/main/java/com/kusitms/website/domain/email/service/EmailService.java diff --git a/src/main/java/com/kusitms/website/domain/blog/service/BlogService.java b/src/main/java/com/kusitms/website/domain/blog/service/BlogService.java index 38f43c1..bf19791 100644 --- a/src/main/java/com/kusitms/website/domain/blog/service/BlogService.java +++ b/src/main/java/com/kusitms/website/domain/blog/service/BlogService.java @@ -1,18 +1,14 @@ package com.kusitms.website.domain.blog.service; import com.kusitms.website.domain.blog.dto.response.BlogResponse; -import com.kusitms.website.domain.blog.entity.BlogPost; import com.kusitms.website.domain.blog.entity.Category; import com.kusitms.website.domain.blog.entity.Position; -import com.kusitms.website.domain.blog.repository.BlogPostQueryRepository; import com.kusitms.website.domain.blog.repository.BlogPostRepository; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; -import java.util.List; -import java.util.stream.Collectors; @Service @RequiredArgsConstructor diff --git a/src/main/java/com/kusitms/website/domain/email/Email.java b/src/main/java/com/kusitms/website/domain/email/Email.java new file mode 100644 index 0000000..75f0b43 --- /dev/null +++ b/src/main/java/com/kusitms/website/domain/email/Email.java @@ -0,0 +1,22 @@ +package com.kusitms.website.domain.email; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Email { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "email_id", nullable = false) + private Long id; + + @Column(nullable = false, unique = true) + private String email; +} diff --git a/src/main/java/com/kusitms/website/domain/email/controller/EmailController.java b/src/main/java/com/kusitms/website/domain/email/controller/EmailController.java new file mode 100644 index 0000000..06d284f --- /dev/null +++ b/src/main/java/com/kusitms/website/domain/email/controller/EmailController.java @@ -0,0 +1,47 @@ +package com.kusitms.website.domain.email.controller; + +import com.kusitms.website.domain.email.dto.response.EmailResponse; +import com.kusitms.website.domain.email.service.EmailService; +import com.kusitms.website.domain.introduction.IntroService; +import com.kusitms.website.domain.introduction.dto.response.IntroResponse; +import com.kusitms.website.global.common.BaseResponse; +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.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/api") +@RequiredArgsConstructor +@Tag(name = "Email", description = "이메일 API Document") +public class EmailController { + + private final EmailService emailService; + + @PostMapping("/emails") + @Operation(summary = "이메일 저장 API", description = "학회 모집 소식 전송 이메일을 저장합니다.") + @ApiResponses(value = { + @ApiResponse( + responseCode = "200", + description = "저장 성공", + content = @Content(schema = @Schema(implementation = EmailResponse.class)) + ), + @ApiResponse( + responseCode = "400", + description = "잘못된 요청 (이메일 형식 오류, 중복 이메일 등)", + content = @Content(schema = @Schema(implementation = BaseResponse.class)) + ) + }) + public ResponseEntity> saveEmail( + @RequestParam String email + ) { + return ResponseEntity.ok( + new BaseResponse<>(emailService.saveEmail(email)) + ); + } +} diff --git a/src/main/java/com/kusitms/website/domain/email/dto/response/EmailResponse.java b/src/main/java/com/kusitms/website/domain/email/dto/response/EmailResponse.java new file mode 100644 index 0000000..11b0c54 --- /dev/null +++ b/src/main/java/com/kusitms/website/domain/email/dto/response/EmailResponse.java @@ -0,0 +1,16 @@ +package com.kusitms.website.domain.email.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@Schema +public class EmailResponse { + @Schema(description = "Id") + private String id; + + @Schema(description = "이메일") + private String email; +} diff --git a/src/main/java/com/kusitms/website/domain/email/repository/EmailRepository.java b/src/main/java/com/kusitms/website/domain/email/repository/EmailRepository.java new file mode 100644 index 0000000..f8feb6b --- /dev/null +++ b/src/main/java/com/kusitms/website/domain/email/repository/EmailRepository.java @@ -0,0 +1,11 @@ +package com.kusitms.website.domain.email.repository; + +import com.kusitms.website.domain.email.Email; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface EmailRepository extends JpaRepository { + boolean existsByEmail(String email); + +} diff --git a/src/main/java/com/kusitms/website/domain/email/service/EmailService.java b/src/main/java/com/kusitms/website/domain/email/service/EmailService.java new file mode 100644 index 0000000..7854dd2 --- /dev/null +++ b/src/main/java/com/kusitms/website/domain/email/service/EmailService.java @@ -0,0 +1,48 @@ +package com.kusitms.website.domain.email.service; + +import com.kusitms.website.domain.email.Email; +import com.kusitms.website.domain.email.dto.response.EmailResponse; +import com.kusitms.website.domain.email.repository.EmailRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.regex.Pattern; + +@Service +@RequiredArgsConstructor +public class EmailService { + + private final EmailRepository emailRepository; + + private static final Pattern EMAIL_PATTERN = Pattern.compile( + "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$" + ); + + @Transactional + public EmailResponse saveEmail(String email) { + + if (email == null || email.trim().isEmpty()) { + throw new IllegalArgumentException("이메일은 필수 입력값입니다."); + } + + if (!EMAIL_PATTERN.matcher(email).matches()) { + throw new IllegalArgumentException("유효하지 않은 이메일 형식입니다."); + } + + if (emailRepository.existsByEmail(email)) { + throw new IllegalArgumentException("이미 등록된 이메일입니다."); + } + + Email savedEmail = emailRepository.save( + Email.builder() + .email(email) + .build() + ); + + return EmailResponse.builder() + .id(String.valueOf(savedEmail.getId())) + .email(savedEmail.getEmail()) + .build(); + } +} diff --git a/src/main/java/com/kusitms/website/global/exception/GlobalExceptionHandler.java b/src/main/java/com/kusitms/website/global/exception/GlobalExceptionHandler.java index 704dc34..01228a3 100644 --- a/src/main/java/com/kusitms/website/global/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/kusitms/website/global/exception/GlobalExceptionHandler.java @@ -1,13 +1,27 @@ package com.kusitms.website.global.exception; +import com.kusitms.website.global.common.BaseException; import com.kusitms.website.global.common.BaseExceptionStatus; import com.kusitms.website.global.common.BaseResponse; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @RestControllerAdvice public class GlobalExceptionHandler { + @ExceptionHandler(IllegalArgumentException.class) + public ResponseEntity> handleIllegalArgument( + IllegalArgumentException ex + ) { + return ResponseEntity + .badRequest() + .body(BaseResponse.error( + BaseExceptionStatus.BAD_REQUEST, + ex.getMessage() + )); + } + @ExceptionHandler(RuntimeException.class) public BaseResponse handleException(RuntimeException ex) { return BaseResponse.error(BaseExceptionStatus.INTER_SERVER_ERROR);