From 46fe20ec232bd1b08e9169c62ed8f6488131ef72 Mon Sep 17 00:00:00 2001
From: loading1031 <tjdans1031@gmail.com>
Date: Fri, 16 Feb 2024 23:05:33 +0900
Subject: [PATCH 1/4] :sparkles: Feat: create apiPayLoad

---
 .../common/apiPayload/ApiResult.java          |  36 +++++
 .../common/apiPayload/code/BaseCode.java      |   7 +
 .../common/apiPayload/code/BaseErrorCode.java |   6 +
 .../apiPayload/code/ErrorReasonDTO.java       |  17 +++
 .../common/apiPayload/code/ReasonDTO.java     |  17 +++
 .../apiPayload/code/status/ErrorStatus.java   |  61 +++++++++
 .../apiPayload/code/status/SuccessStatus.java |  40 ++++++
 .../apiPayload/exception/ExceptionAdvice.java | 128 ++++++++++++++++++
 .../exception/GeneralException.java           |  18 +++
 9 files changed, 330 insertions(+)
 create mode 100644 src/main/java/umc/beanstalk/common/apiPayload/ApiResult.java
 create mode 100644 src/main/java/umc/beanstalk/common/apiPayload/code/BaseCode.java
 create mode 100644 src/main/java/umc/beanstalk/common/apiPayload/code/BaseErrorCode.java
 create mode 100644 src/main/java/umc/beanstalk/common/apiPayload/code/ErrorReasonDTO.java
 create mode 100644 src/main/java/umc/beanstalk/common/apiPayload/code/ReasonDTO.java
 create mode 100644 src/main/java/umc/beanstalk/common/apiPayload/code/status/ErrorStatus.java
 create mode 100644 src/main/java/umc/beanstalk/common/apiPayload/code/status/SuccessStatus.java
 create mode 100644 src/main/java/umc/beanstalk/common/apiPayload/exception/ExceptionAdvice.java
 create mode 100644 src/main/java/umc/beanstalk/common/apiPayload/exception/GeneralException.java

diff --git a/src/main/java/umc/beanstalk/common/apiPayload/ApiResult.java b/src/main/java/umc/beanstalk/common/apiPayload/ApiResult.java
new file mode 100644
index 0000000..2f21ebe
--- /dev/null
+++ b/src/main/java/umc/beanstalk/common/apiPayload/ApiResult.java
@@ -0,0 +1,36 @@
+package umc.beanstalk.common.apiPayload;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import umc.beanstalk.common.apiPayload.code.BaseCode;
+import umc.beanstalk.common.apiPayload.code.status.SuccessStatus;
+
+@Getter
+@AllArgsConstructor
+@JsonPropertyOrder({"isSuccess","code","message","result"})
+public class ApiResult<T> {
+    @JsonProperty("isSuccess")
+    private final Boolean isSuccess;
+    private final String code;
+    private final String message;
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    private T result;
+
+    // 실패한 경우 응답 생성
+    public static <T> ApiResult<T> onFailure(String code, String message, T data){
+        return new ApiResult<>(true, code, message, data);
+    }
+
+    //성공한 경우 응답 생성
+    public static <T> ApiResult<T> onSuccess(T result){
+        return new ApiResult<>(true, SuccessStatus._OK.getCode() , SuccessStatus._OK.getMessage(), result);
+    }
+
+     public static <T> ApiResult<T> of(BaseCode code, T result){
+        return new ApiResult<>(true, code.getReasonHttpStatus().getCode(), code.getReasonHttpStatus().getMessage(), result);
+    }
+
+}
diff --git a/src/main/java/umc/beanstalk/common/apiPayload/code/BaseCode.java b/src/main/java/umc/beanstalk/common/apiPayload/code/BaseCode.java
new file mode 100644
index 0000000..bf6e032
--- /dev/null
+++ b/src/main/java/umc/beanstalk/common/apiPayload/code/BaseCode.java
@@ -0,0 +1,7 @@
+package umc.beanstalk.common.apiPayload.code;
+
+public interface BaseCode {
+    public ReasonDTO getReason();
+
+    public ReasonDTO getReasonHttpStatus();
+}
diff --git a/src/main/java/umc/beanstalk/common/apiPayload/code/BaseErrorCode.java b/src/main/java/umc/beanstalk/common/apiPayload/code/BaseErrorCode.java
new file mode 100644
index 0000000..8cb9ac7
--- /dev/null
+++ b/src/main/java/umc/beanstalk/common/apiPayload/code/BaseErrorCode.java
@@ -0,0 +1,6 @@
+package umc.beanstalk.common.apiPayload.code;
+
+public interface BaseErrorCode {
+    public ErrorReasonDTO getReason();
+    public ErrorReasonDTO getReasonHttpStatus();
+}
diff --git a/src/main/java/umc/beanstalk/common/apiPayload/code/ErrorReasonDTO.java b/src/main/java/umc/beanstalk/common/apiPayload/code/ErrorReasonDTO.java
new file mode 100644
index 0000000..4bc2886
--- /dev/null
+++ b/src/main/java/umc/beanstalk/common/apiPayload/code/ErrorReasonDTO.java
@@ -0,0 +1,17 @@
+package umc.beanstalk.common.apiPayload.code;
+
+import lombok.Builder;
+import lombok.Getter;
+import org.springframework.http.HttpStatus;
+
+@Getter
+@Builder
+public class ErrorReasonDTO {
+    private HttpStatus httpStatus;
+
+    private final Boolean isSuccess;
+    private final String code;
+    private final String message;
+
+    public boolean getIsSuccess(){return isSuccess;}
+}
diff --git a/src/main/java/umc/beanstalk/common/apiPayload/code/ReasonDTO.java b/src/main/java/umc/beanstalk/common/apiPayload/code/ReasonDTO.java
new file mode 100644
index 0000000..ec72c20
--- /dev/null
+++ b/src/main/java/umc/beanstalk/common/apiPayload/code/ReasonDTO.java
@@ -0,0 +1,17 @@
+package umc.beanstalk.common.apiPayload.code;
+
+import lombok.Builder;
+import lombok.Getter;
+import org.springframework.http.HttpStatus;
+@Getter
+
+@Builder
+public class ReasonDTO {
+    private HttpStatus httpStatus;
+
+    private final boolean isSuccess;
+    private final String code;
+    private final String message;
+
+    public boolean getIsSuccess(){return isSuccess;}
+}
diff --git a/src/main/java/umc/beanstalk/common/apiPayload/code/status/ErrorStatus.java b/src/main/java/umc/beanstalk/common/apiPayload/code/status/ErrorStatus.java
new file mode 100644
index 0000000..75a1289
--- /dev/null
+++ b/src/main/java/umc/beanstalk/common/apiPayload/code/status/ErrorStatus.java
@@ -0,0 +1,61 @@
+package umc.beanstalk.common.apiPayload.code.status;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.springframework.http.HttpStatus;
+import umc.study.apiPayload.code.BaseErrorCode;
+import umc.study.apiPayload.code.ErrorReasonDTO;
+
+@Getter
+@AllArgsConstructor
+public enum ErrorStatus implements BaseErrorCode {
+    // 가장 일반적인 응답
+    _INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR,"COMMON500","서버 에러, 관리자에게 문의 바랍니다."),
+    _BAD_REQUEST(HttpStatus.BAD_REQUEST,"COMMON400","잘못된 요청입니다."),
+    _UNAUTHORIZED(HttpStatus.UNAUTHORIZED,"COMMON401","인증이 필요합니다."),
+    _FORBIDDEN(HttpStatus.FORBIDDEN, "COMMON403", "금지된 요청입니다."),
+    // 멤버 관련 응답
+    MEMBER_NOT_FOUND(HttpStatus.BAD_REQUEST,"MEMBER4001","사용자가 없습니다."),
+    NICKNAME_NOT_EXIST(HttpStatus.BAD_REQUEST,"MEMBER4002", "닉네임은 필수 입니다."),
+    // 멤버 선호 음식
+    FOOD_CATEGORY_NOT_FOUND(HttpStatus.BAD_REQUEST,"PREFER4001","음식 카테고리가 없습니다."),
+    // 유저 미션
+    ACCEPT_MISSION_NOT_FOUND(HttpStatus.BAD_REQUEST,"USERMISSION4001","유저가 수락한 미션이 없습니다."),
+    //식당 관련 응답
+    STORE_NOT_FOUND(HttpStatus.BAD_REQUEST,"STORER4002","식당명은 필수 입니다."),
+    STORE_NOT_EXIST(HttpStatus.BAD_REQUEST,"STORE4001", "식당이 없습니다."),
+    // 지역 관련 응답
+    REGION_NOT_FOUND(HttpStatus.BAD_REQUEST,"REGION4001","해당 지역이 없습니다."),
+    //미션 관련 응답
+    MISSION_NOT_EXIST(HttpStatus.BAD_REQUEST,"MISSION4001", "미션이 없습니다."),
+    Mission_Already_Accept(HttpStatus.BAD_REQUEST,"MISSION4002", "이미 수락한 미션입니다."),
+    MISSION_COMPLETE(HttpStatus.BAD_REQUEST,"MISSION4003", "이미 완료한 미션입니다."),
+    //페이지 관련
+    PAGE_NOT_FOUND(HttpStatus.BAD_REQUEST,"PAGE4001","해당 페이지가 없습니다."),
+    // 예시 ...
+    ARTICLE_NOT_FOUND(HttpStatus.NOT_FOUND, "ARTICLE4001", "게시글이 없습니다."),
+    TEMP_EXCEPTION(HttpStatus.BAD_REQUEST,"TEMP40001","이거는 테스트");
+
+    private final HttpStatus httpStatus;
+    private final String code;
+    private final String message;
+
+    @Override
+    public ErrorReasonDTO getReason(){
+        return ErrorReasonDTO.builder()
+                .message(message)
+                .code(code)
+                .isSuccess(false)
+                .build();
+    }
+    @Override
+    public ErrorReasonDTO getReasonHttpStatus() {
+        return ErrorReasonDTO.builder()
+                .message(message)
+                .code(code)
+                .isSuccess(false)
+                .httpStatus(httpStatus)
+                .build()
+                ;
+    }
+}
diff --git a/src/main/java/umc/beanstalk/common/apiPayload/code/status/SuccessStatus.java b/src/main/java/umc/beanstalk/common/apiPayload/code/status/SuccessStatus.java
new file mode 100644
index 0000000..961dc94
--- /dev/null
+++ b/src/main/java/umc/beanstalk/common/apiPayload/code/status/SuccessStatus.java
@@ -0,0 +1,40 @@
+package umc.beanstalk.common.apiPayload.code.status;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.springframework.http.HttpStatus;
+import umc.study.apiPayload.code.BaseCode;
+import umc.study.apiPayload.code.ReasonDTO;
+
+@Getter
+@AllArgsConstructor
+public enum SuccessStatus implements BaseCode{
+    // 일반적인 응답
+    _OK(HttpStatus.OK, "COMMON200", "성공입니다.");
+
+    // 멤버 관련 응답
+
+    // ~~ 관련 응답
+    private final HttpStatus httpStatus;
+    private final String code;
+    private final String message;
+
+    @Override
+    public ReasonDTO getReason() {
+        return ReasonDTO.builder()
+                .message(message)
+                .code(code)
+                .isSuccess(true)
+                .build();
+    }
+
+    @Override
+    public ReasonDTO getReasonHttpStatus() {
+        return ReasonDTO.builder()
+                .message(message)
+                .code(code)
+                .isSuccess(true)
+                .httpStatus(httpStatus)
+                .build();
+    }
+}
diff --git a/src/main/java/umc/beanstalk/common/apiPayload/exception/ExceptionAdvice.java b/src/main/java/umc/beanstalk/common/apiPayload/exception/ExceptionAdvice.java
new file mode 100644
index 0000000..cde3da6
--- /dev/null
+++ b/src/main/java/umc/beanstalk/common/apiPayload/exception/ExceptionAdvice.java
@@ -0,0 +1,128 @@
+package umc.beanstalk.common.apiPayload.exception;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.context.request.ServletWebRequest;
+import org.springframework.web.context.request.WebRequest;
+import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
+import umc.beanstalk.common.apiPayload.ApiResult;
+import umc.beanstalk.common.apiPayload.code.ErrorReasonDTO;
+import umc.beanstalk.common.apiPayload.code.status.ErrorStatus;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+@Slf4j
+@RestControllerAdvice(annotations = {RestController.class})
+public class ExceptionAdvice extends ResponseEntityExceptionHandler {
+
+    @ExceptionHandler(ConstraintViolationException.class)
+    public ResponseEntity<Object> handleConstraintViolationException(ConstraintViolationException e, WebRequest request) {
+        String errorMessage = e.getConstraintViolations().stream()
+                .map(ConstraintViolation::getMessage)
+                .collect(Collectors.joining("; "));
+
+        return handleExceptionInternalConstraint(e, ErrorStatus.valueOf(errorMessage), HttpHeaders.EMPTY, request);
+    }
+
+    @Override
+    public ResponseEntity<Object> handleMethodArgumentNotValid(
+            MethodArgumentNotValidException e, HttpHeaders headers, HttpStatus status, WebRequest request) {
+
+        Map<String, String> errors = new LinkedHashMap<>();
+
+        e.getBindingResult().getFieldErrors().stream()
+                .forEach(fieldError -> {
+                    String fieldName = fieldError.getField();
+                    String errorMessage = Optional.ofNullable(fieldError.getDefaultMessage()).orElse("");
+                    errors.merge(fieldName, errorMessage, (existingErrorMessage, newErrorMessage) -> existingErrorMessage + ", " + newErrorMessage);
+                });
+
+        return handleExceptionInternalArgs(e, HttpHeaders.EMPTY, ErrorStatus.valueOf("_BAD_REQUEST"), request, errors);
+    }
+
+    @ExceptionHandler
+    public ResponseEntity<Object> exception(Exception e, WebRequest request) {
+        e.printStackTrace();
+
+        return handleExceptionInternalFalse(e, ErrorStatus._INTERNAL_SERVER_ERROR, HttpHeaders.EMPTY, ErrorStatus._INTERNAL_SERVER_ERROR.getHttpStatus(), request, e.getMessage());
+    }
+
+    @ExceptionHandler(value = GeneralException.class)
+    public ResponseEntity onThrowException(GeneralException generalException, HttpServletRequest request) {
+        ErrorReasonDTO errorReasonHttpStatus = generalException.getErrorReasonHttpStatus();
+        return handleExceptionInternal(generalException, errorReasonHttpStatus, null, request);
+    }
+    /*
+    @ExceptionHandler(ConstraintViolationException.class)
+    public ResponseEntity<Object> handleConstraintViolationException(ConstraintViolationException ex) {
+        // 여기서 ConstraintViolationException에서 얻은 정보를 활용하여 적절한 응답을 생성
+        // ex.getMessage() 등을 활용하여 에러 메시지를 추출할 수 있음
+        String errorMessage = "Validation failed: " + ex.getMessage();
+        return new ResponseEntity<>(errorMessage, HttpStatus.BAD_REQUEST);
+    }
+
+     */
+    private ResponseEntity<Object> handleExceptionInternal(Exception e, ErrorReasonDTO reason,
+                                                           HttpHeaders headers, HttpServletRequest request) {
+
+        ApiResult<Object> body = ApiResult.onFailure(reason.getCode(), reason.getMessage(), null);
+//        e.printStackTrace();
+
+        WebRequest webRequest = new ServletWebRequest(request);
+        return super.handleExceptionInternal(
+                e,
+                body,
+                headers,
+                reason.getHttpStatus(),
+                webRequest
+        );
+    }
+
+    private ResponseEntity<Object> handleExceptionInternalFalse(Exception e, ErrorStatus errorCommonStatus,
+                                                                HttpHeaders headers, HttpStatus status, WebRequest request, String errorPoint) {
+        ApiResult<Object> body = ApiResult.onFailure(errorCommonStatus.getCode(), errorCommonStatus.getMessage(), errorPoint);
+        return super.handleExceptionInternal(
+                e,
+                body,
+                headers,
+                status,
+                request
+        );
+    }
+
+    private ResponseEntity<Object> handleExceptionInternalArgs(Exception e, HttpHeaders headers, ErrorStatus errorCommonStatus,
+                                                               WebRequest request, Map<String, String> errorArgs) {
+        ApiResult<Object> body = ApiResult.onFailure(errorCommonStatus.getCode(), errorCommonStatus.getMessage(), errorArgs);
+        return super.handleExceptionInternal(
+                e,
+                body,
+                headers,
+                errorCommonStatus.getHttpStatus(),
+                request
+        );
+    }
+
+    private ResponseEntity<Object> handleExceptionInternalConstraint(Exception e, ErrorStatus errorCommonStatus,
+                                                                     HttpHeaders headers, WebRequest request) {
+        ApiResult<Object> body = ApiResult.onFailure(errorCommonStatus.getCode(), errorCommonStatus.getMessage(), null);
+        return super.handleExceptionInternal(
+                e,
+                body,
+                headers,
+                errorCommonStatus.getHttpStatus(),
+                request
+        );
+    }
+}
diff --git a/src/main/java/umc/beanstalk/common/apiPayload/exception/GeneralException.java b/src/main/java/umc/beanstalk/common/apiPayload/exception/GeneralException.java
new file mode 100644
index 0000000..3ed6de4
--- /dev/null
+++ b/src/main/java/umc/beanstalk/common/apiPayload/exception/GeneralException.java
@@ -0,0 +1,18 @@
+package umc.beanstalk.common.apiPayload.exception;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import umc.beanstalk.common.apiPayload.code.BaseErrorCode;
+import umc.beanstalk.common.apiPayload.code.ErrorReasonDTO;
+
+@Getter
+@AllArgsConstructor
+public class GeneralException extends RuntimeException{
+    private BaseErrorCode code;
+    public ErrorReasonDTO getErrorReason(){
+        return this.code.getReason();
+    }
+    public ErrorReasonDTO getErrorReasonHttpStatus(){
+        return this.code.getReasonHttpStatus();
+    }
+}

From 7cfd83db90bcc932b05bf99332fa67259631262e Mon Sep 17 00:00:00 2001
From: loading1031 <tjdans1031@gmail.com>
Date: Fri, 16 Feb 2024 23:11:12 +0900
Subject: [PATCH 2/4] :heavy_plus_sign: Add: validation

---
 build.gradle | 1 +
 1 file changed, 1 insertion(+)

diff --git a/build.gradle b/build.gradle
index 3e0de46..279d3e5 100644
--- a/build.gradle
+++ b/build.gradle
@@ -33,6 +33,7 @@ dependencies {
 	implementation 'io.springfox:springfox-swagger-ui:2.9.2'
 	//aws
 	implementation group: 'io.awspring.cloud', name: 'spring-cloud-starter-aws', version: '2.4.4'
+	implementation 'org.springframework.boot:spring-boot-starter-validation'
 
 }
 jar {

From f5eac15355310b145cf6121946f243961dba9abf Mon Sep 17 00:00:00 2001
From: loading1031 <tjdans1031@gmail.com>
Date: Fri, 16 Feb 2024 23:11:42 +0900
Subject: [PATCH 3/4] :bug: Fix: status

---
 .../common/apiPayload/code/status/ErrorStatus.java          | 4 ++--
 .../common/apiPayload/code/status/SuccessStatus.java        | 6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/main/java/umc/beanstalk/common/apiPayload/code/status/ErrorStatus.java b/src/main/java/umc/beanstalk/common/apiPayload/code/status/ErrorStatus.java
index 75a1289..f2961e5 100644
--- a/src/main/java/umc/beanstalk/common/apiPayload/code/status/ErrorStatus.java
+++ b/src/main/java/umc/beanstalk/common/apiPayload/code/status/ErrorStatus.java
@@ -3,8 +3,8 @@
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 import org.springframework.http.HttpStatus;
-import umc.study.apiPayload.code.BaseErrorCode;
-import umc.study.apiPayload.code.ErrorReasonDTO;
+import umc.beanstalk.common.apiPayload.code.BaseErrorCode;
+import umc.beanstalk.common.apiPayload.code.ErrorReasonDTO;
 
 @Getter
 @AllArgsConstructor
diff --git a/src/main/java/umc/beanstalk/common/apiPayload/code/status/SuccessStatus.java b/src/main/java/umc/beanstalk/common/apiPayload/code/status/SuccessStatus.java
index 961dc94..7f6961b 100644
--- a/src/main/java/umc/beanstalk/common/apiPayload/code/status/SuccessStatus.java
+++ b/src/main/java/umc/beanstalk/common/apiPayload/code/status/SuccessStatus.java
@@ -3,12 +3,12 @@
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 import org.springframework.http.HttpStatus;
-import umc.study.apiPayload.code.BaseCode;
-import umc.study.apiPayload.code.ReasonDTO;
+import umc.beanstalk.common.apiPayload.code.BaseCode;
+import umc.beanstalk.common.apiPayload.code.ReasonDTO;
 
 @Getter
 @AllArgsConstructor
-public enum SuccessStatus implements BaseCode{
+public enum SuccessStatus implements BaseCode {
     // 일반적인 응답
     _OK(HttpStatus.OK, "COMMON200", "성공입니다.");
 

From 0c14863b45d179f80125ab7097d47a6451c8a289 Mon Sep 17 00:00:00 2001
From: loading1031 <tjdans1031@gmail.com>
Date: Fri, 16 Feb 2024 23:17:01 +0900
Subject: [PATCH 4/4] :sparkles: Feat: create Choice and BaseEntity

---
 .../beanstalk/common/domain/BaseEntity.java   | 23 +++++++++++++++++++
 .../user_choice/data/domain/UserChoice.java   | 19 +++++++++++++++
 2 files changed, 42 insertions(+)
 create mode 100644 src/main/java/umc/beanstalk/common/domain/BaseEntity.java
 create mode 100644 src/main/java/umc/beanstalk/user_choice/data/domain/UserChoice.java

diff --git a/src/main/java/umc/beanstalk/common/domain/BaseEntity.java b/src/main/java/umc/beanstalk/common/domain/BaseEntity.java
new file mode 100644
index 0000000..741a433
--- /dev/null
+++ b/src/main/java/umc/beanstalk/common/domain/BaseEntity.java
@@ -0,0 +1,23 @@
+package umc.beanstalk.common.domain;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.data.annotation.CreatedDate;
+import org.springframework.data.annotation.LastModifiedDate;
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+
+import javax.persistence.EntityListeners;
+import javax.persistence.MappedSuperclass;
+import java.time.LocalDateTime;
+
+@MappedSuperclass
+@EntityListeners(AuditingEntityListener.class)
+@Getter
+public class BaseEntity {
+    @CreatedDate
+    private LocalDateTime createdAt;
+
+    @Setter
+    @LastModifiedDate
+    private LocalDateTime updatedAt;
+}
diff --git a/src/main/java/umc/beanstalk/user_choice/data/domain/UserChoice.java b/src/main/java/umc/beanstalk/user_choice/data/domain/UserChoice.java
new file mode 100644
index 0000000..17f9004
--- /dev/null
+++ b/src/main/java/umc/beanstalk/user_choice/data/domain/UserChoice.java
@@ -0,0 +1,19 @@
+package umc.beanstalk.user_choice.data.domain;
+
+import lombok.*;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
+@Getter
+@Builder
+@NoArgsConstructor(access = AccessLevel.PROTECTED)
+@AllArgsConstructor
+public class UserChoice {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    Long id;
+}