diff --git a/src/main/java/com/moongeul/backend/api/member/controller/MemberController.java b/src/main/java/com/moongeul/backend/api/member/controller/MemberController.java
index d598c4a..bf383f2 100644
--- a/src/main/java/com/moongeul/backend/api/member/controller/MemberController.java
+++ b/src/main/java/com/moongeul/backend/api/member/controller/MemberController.java
@@ -27,7 +27,8 @@ public class MemberController {
@Operation(
summary = "구글 로그인 API",
- description = "구글 인가코드을 통해 사용자의 정보를 등록 및 토큰 + 역할을 발급합니다. (ROLE -> 처음사용자 : GUEST, 일반사용자 : USER, 관리자 : ADMIN)"
+ description = "구글 인가코드을 통해 사용자의 정보를 등록 및 토큰 + 역할을 발급합니다. " +
+ "
[enum]ROLE -> 처음사용자 : GUEST, 일반사용자 : USER, 관리자 : ADMIN"
)
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "로그인 성공"),
@@ -61,7 +62,16 @@ public ResponseEntity> loginWithKakao(@Valid @Requ
@Operation(
summary = "사용자 정보 조회 API",
- description = "토큰을 통해 인증된 사용자의 정보를 반환합니다."
+ description = "토큰을 통해 인증된 사용자의 정보를 반환합니다." +
+ "
[enum]독서 취향 유형 ->" +
+ "
- EMOTIONAL_REFLECTOR: 감성 사색 정리러" +
+ "
- CHATTY_READER: 수다쟁이 책러" +
+ "
- TREND_HUNTER: 신상 헌터" +
+ "
- SYSTEMATIC_READER: 정리왕 서평러" +
+ "
- IMMERSIVE_READER: 넷플릭스급 몰입러" +
+ "
- SECRET_DIARIST: 비밀 일기장 주인" +
+ "
- GENRE_SPECIALIST: 장르 고인물" +
+ "
- RANDOM_PICKER: 랜덤 피커"
)
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "사용자 정보 조회 성공"),
diff --git a/src/main/java/com/moongeul/backend/api/member/controller/ReadingTasteController.java b/src/main/java/com/moongeul/backend/api/member/controller/ReadingTasteController.java
new file mode 100644
index 0000000..58616a7
--- /dev/null
+++ b/src/main/java/com/moongeul/backend/api/member/controller/ReadingTasteController.java
@@ -0,0 +1,62 @@
+package com.moongeul.backend.api.member.controller;
+
+import com.moongeul.backend.api.member.dto.TestRequestDTO;
+import com.moongeul.backend.api.member.dto.TestResponseDTO;
+import com.moongeul.backend.api.member.service.ReadingTasteService;
+import com.moongeul.backend.common.response.ApiResponse;
+import com.moongeul.backend.common.response.SuccessStatus;
+import io.swagger.v3.oas.annotations.Operation;
+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.security.core.annotation.AuthenticationPrincipal;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.web.bind.annotation.*;
+
+@Tag(name = "ReadingTaste", description = "ReadingTaste(독서취향테스트) 관련 API 입니다.")
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/api/v2/reading-taste")
+public class ReadingTasteController {
+
+ private final ReadingTasteService readingTasteService;
+
+
+ @Operation(
+ summary = "독서 취향 테스트 API",
+ description = "독서 취향 테스트 결과를 계산하여 유형을 반환하는 API 입니다." +
+ "
요청 형식:" +
+ "
- answers: 질문 번호(1-12)와 답변(A or B)의 Map으로 전달바랍니다." +
+ "
**예시:**\n" +
+ "```json\n" +
+ "{\n" +
+ " \"answers\": {\n" +
+ " \"1\": \"A\",\n" +
+ " \"2\": \"B\",\n" +
+ " \"3\": \"A\",\n" +
+ " \"4\": \"B\",\n" +
+ " \"5\": \"A\",\n" +
+ " \"6\": \"B\",\n" +
+ " \"7\": \"A\",\n" +
+ " \"8\": \"B\",\n" +
+ " \"9\": \"A\",\n" +
+ " \"10\": \"B\",\n" +
+ " \"11\": \"A\",\n" +
+ " \"12\": \"B\"\n" +
+ "}\n" +
+ " "
+ )
+ @ApiResponses({
+ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "독서 취향 테스트 결과 계산 성공"),
+ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "답변이 비어있습니다.")
+ })
+ @PostMapping
+ public ResponseEntity> calculateReadingTasteType(@AuthenticationPrincipal UserDetails userDetails,
+ @RequestBody TestRequestDTO testRequestDTO) {
+
+ TestResponseDTO response = readingTasteService.calculateReadingTasteType(testRequestDTO, userDetails.getUsername());
+ return ApiResponse.success(SuccessStatus.CALCULATE_READING_TASTE_SUCCESS, response);
+ }
+
+}
diff --git a/src/main/java/com/moongeul/backend/api/member/dto/TestRequestDTO.java b/src/main/java/com/moongeul/backend/api/member/dto/TestRequestDTO.java
new file mode 100644
index 0000000..f20375d
--- /dev/null
+++ b/src/main/java/com/moongeul/backend/api/member/dto/TestRequestDTO.java
@@ -0,0 +1,24 @@
+package com.moongeul.backend.api.member.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.util.Map;
+
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class TestRequestDTO {
+
+ @Schema(
+ description = "질문 번호(1-12)와 답변(A or B) 매핑",
+ example = "{\"1\":\"A\",\"2\":\"A\",\"3\":\"A\",\"4\":\"A\",\"5\":\"A\",\"6\":\"A\",\"7\":\"A\",\"8\":\"A\",\"9\":\"A\",\"10\":\"A\",\"11\":\"A\",\"12\":\"A\"}"
+ )
+ @NotNull(message = "테스트 답변 입력은 필수입니다")
+ private Map answers; // {1: "A", 2: "B", ...}
+}
diff --git a/src/main/java/com/moongeul/backend/api/member/dto/TestResponseDTO.java b/src/main/java/com/moongeul/backend/api/member/dto/TestResponseDTO.java
new file mode 100644
index 0000000..37a736b
--- /dev/null
+++ b/src/main/java/com/moongeul/backend/api/member/dto/TestResponseDTO.java
@@ -0,0 +1,16 @@
+package com.moongeul.backend.api.member.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class TestResponseDTO {
+
+ private String readingTasteType; // 독서 취향 유형
+ private String intro; // 한줄 소개
+}
diff --git a/src/main/java/com/moongeul/backend/api/member/dto/UserInfoDTO.java b/src/main/java/com/moongeul/backend/api/member/dto/UserInfoDTO.java
index 409f0d6..6102b22 100644
--- a/src/main/java/com/moongeul/backend/api/member/dto/UserInfoDTO.java
+++ b/src/main/java/com/moongeul/backend/api/member/dto/UserInfoDTO.java
@@ -1,5 +1,6 @@
package com.moongeul.backend.api.member.dto;
+import com.moongeul.backend.api.member.entity.ReadingTasteType;
import lombok.Builder;
import lombok.Getter;
@@ -11,4 +12,5 @@ public class UserInfoDTO {
private final String name; // 회원 이름(실명)
private final String profileImage; // 회원 이미지
private final String nickname; //닉네임 (초기랜덤생성)
+ private ReadingTasteType readingTasteType; // 독서 취향 유형
}
diff --git a/src/main/java/com/moongeul/backend/api/member/entity/Member.java b/src/main/java/com/moongeul/backend/api/member/entity/Member.java
index 7e36452..a4aa9ec 100644
--- a/src/main/java/com/moongeul/backend/api/member/entity/Member.java
+++ b/src/main/java/com/moongeul/backend/api/member/entity/Member.java
@@ -27,6 +27,9 @@ public class Member extends BaseTimeEntity {
private String nickname; //닉네임 (초기랜덤생성)
private String password;
+ @Enumerated(EnumType.STRING)
+ private ReadingTasteType readingTasteType; // 독서 취향 유형
+
@Column(unique = true)
private String socialId; // 소셜 로그인 ID (고유값)
@@ -53,7 +56,17 @@ public Member update(String name, String picture) {
return this;
}
+ /**
+ * 리프레시 토큰 업데이트
+ */
public void updateRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
+
+ /**
+ * 독서 취향 유형 업데이트
+ */
+ public void updateReadingTasteType(ReadingTasteType readingTasteType) {
+ this.readingTasteType = readingTasteType;
+ }
}
diff --git a/src/main/java/com/moongeul/backend/api/member/entity/ReadingTasteType.java b/src/main/java/com/moongeul/backend/api/member/entity/ReadingTasteType.java
new file mode 100644
index 0000000..f61b23e
--- /dev/null
+++ b/src/main/java/com/moongeul/backend/api/member/entity/ReadingTasteType.java
@@ -0,0 +1,22 @@
+package com.moongeul.backend.api.member.entity;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+@Getter
+@RequiredArgsConstructor
+public enum ReadingTasteType {
+
+ EMOTIONAL_REFLECTOR("감성 사색 정리러", "감성 새벽 독거노인"),
+ CHATTY_READER("수다쟁이 책러", "문화센터 전도사"),
+ TREND_HUNTER("신상 헌터", "신간과 트렌드만이 답이다"),
+ SYSTEMATIC_READER("정리왕 서평러", "안 쓰면 안 읽은 거다"),
+ IMMERSIVE_READER("넷플릭스급 몰입러", "드라마 오타쿠 몽상가"),
+ SECRET_DIARIST("비밀 일기장 주인", "내 기록은 흑역사, 공개 불가"),
+ GENRE_SPECIALIST("장르 고인물", "난 같은 장르만 조진다"),
+ RANDOM_PICKER("랜덤 피커", "책 선택은 운명이다");
+
+
+ private final String name;
+ private final String intro;
+}
diff --git a/src/main/java/com/moongeul/backend/api/member/service/MemberService.java b/src/main/java/com/moongeul/backend/api/member/service/MemberService.java
index 63cfd9a..8ffdd4d 100644
--- a/src/main/java/com/moongeul/backend/api/member/service/MemberService.java
+++ b/src/main/java/com/moongeul/backend/api/member/service/MemberService.java
@@ -111,6 +111,7 @@ public UserInfoDTO getUserInfo(String email){
.name(member.getName())
.profileImage(member.getProfileImage())
.nickname(member.getNickname())
+ .readingTasteType(member.getReadingTasteType())
.build();
}
diff --git a/src/main/java/com/moongeul/backend/api/member/service/ReadingTasteService.java b/src/main/java/com/moongeul/backend/api/member/service/ReadingTasteService.java
new file mode 100644
index 0000000..0d9dbec
--- /dev/null
+++ b/src/main/java/com/moongeul/backend/api/member/service/ReadingTasteService.java
@@ -0,0 +1,236 @@
+package com.moongeul.backend.api.member.service;
+
+import com.moongeul.backend.api.member.dto.TestRequestDTO;
+import com.moongeul.backend.api.member.dto.TestResponseDTO;
+import com.moongeul.backend.api.member.entity.Member;
+import com.moongeul.backend.api.member.entity.ReadingTasteType;
+import com.moongeul.backend.api.member.repository.MemberRepository;
+import com.moongeul.backend.common.exception.BadRequestException;
+import com.moongeul.backend.common.exception.NotFoundException;
+import com.moongeul.backend.common.response.ErrorStatus;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class ReadingTasteService {
+
+ private final MemberRepository memberRepository;
+
+ private static final String ANSWER_A = "A";
+ private static final String ANSWER_B = "B";
+
+ @Transactional
+ public TestResponseDTO calculateReadingTasteType(TestRequestDTO testRequestDTO, String email){
+
+ Member member = memberRepository.findByEmail(email)
+ .orElseThrow(() -> new NotFoundException(ErrorStatus.USER_NOTFOUND_EXCEPTION.getMessage()));
+
+ // 테스트 결과 계산 (가장 높은 유형 반환)
+ ReadingTasteType type = findTopType(calculateScore(testRequestDTO.getAnswers()));
+
+ // member 필드 readingTasteType 저장
+ member.updateReadingTasteType(type);
+ memberRepository.save(member);
+
+ return TestResponseDTO.builder()
+ .readingTasteType(type.getName())
+ .intro(type.getIntro())
+ .build();
+ }
+
+ // 점수표 - 입력
+ private Map calculateScore(Map answers){
+
+ // 테스트 요청 데이터 검증(에러처리)
+ validateAnswers(answers);
+
+ Map typeScores = new HashMap<>();
+
+ for(Map.Entry entry : answers.entrySet()){
+ int questionNo = entry.getKey();
+ String answer = entry.getValue();
+
+ switch (questionNo) {
+ case 1:
+ if(answer.equals(ANSWER_A)){
+ addScore(typeScores, ReadingTasteType.EMOTIONAL_REFLECTOR, 6.01);
+ addScore(typeScores, ReadingTasteType.SECRET_DIARIST, 3.99);
+ } else if(answer.equals(ANSWER_B)){
+ addScore(typeScores, ReadingTasteType.IMMERSIVE_READER, 6.50);
+ addScore(typeScores, ReadingTasteType.GENRE_SPECIALIST, 2.50);
+ }
+ break;
+ case 2:
+ if(answer.equals(ANSWER_A)){
+ addScore(typeScores, ReadingTasteType.GENRE_SPECIALIST, 6.01);
+ addScore(typeScores, ReadingTasteType.SECRET_DIARIST, 4.99);
+ } else if(answer.equals(ANSWER_B)){
+ addScore(typeScores, ReadingTasteType.TREND_HUNTER, 6.01);
+ addScore(typeScores, ReadingTasteType.CHATTY_READER, 3.99);
+ addScore(typeScores, ReadingTasteType.RANDOM_PICKER, 2.99);
+ }
+ break;
+ case 3:
+ if(answer.equals(ANSWER_A)){
+ addScore(typeScores, ReadingTasteType.RANDOM_PICKER, 6.01);
+ addScore(typeScores, ReadingTasteType.TREND_HUNTER, 2.99);
+ } else if(answer.equals(ANSWER_B)){
+ addScore(typeScores, ReadingTasteType.SYSTEMATIC_READER, 6.01);
+ addScore(typeScores, ReadingTasteType.GENRE_SPECIALIST, 3.99);
+ }
+ break;
+ case 4:
+ if(answer.equals(ANSWER_A)){
+ addScore(typeScores, ReadingTasteType.TREND_HUNTER, 6.01);
+ addScore(typeScores, ReadingTasteType.RANDOM_PICKER, 3.99);
+ } else if(answer.equals(ANSWER_B)){
+ addScore(typeScores, ReadingTasteType.GENRE_SPECIALIST, 6.01);
+ addScore(typeScores, ReadingTasteType.EMOTIONAL_REFLECTOR, 4.49);
+ }
+ break;
+ case 5:
+ if(answer.equals(ANSWER_A)){
+ addScore(typeScores, ReadingTasteType.EMOTIONAL_REFLECTOR, 6.51);
+ addScore(typeScores, ReadingTasteType.IMMERSIVE_READER, 4.49);
+ } else if(answer.equals(ANSWER_B)){
+ addScore(typeScores, ReadingTasteType.CHATTY_READER, 6.51);
+ addScore(typeScores, ReadingTasteType.RANDOM_PICKER, 3.49);
+ }
+ break;
+ case 6:
+ if(answer.equals(ANSWER_A)){
+ addScore(typeScores, ReadingTasteType.SYSTEMATIC_READER, 5.51);
+ addScore(typeScores, ReadingTasteType.EMOTIONAL_REFLECTOR, 4.49);
+ } else if(answer.equals(ANSWER_B)){
+ addScore(typeScores, ReadingTasteType.TREND_HUNTER, 5.51);
+ addScore(typeScores, ReadingTasteType.RANDOM_PICKER, 4.49);
+ }
+ break;
+ case 7:
+ if(answer.equals(ANSWER_A)){
+ addScore(typeScores, ReadingTasteType.SYSTEMATIC_READER, 7.01);
+ addScore(typeScores, ReadingTasteType.SECRET_DIARIST, 3.99);
+ } else if(answer.equals(ANSWER_B)){
+ addScore(typeScores, ReadingTasteType.CHATTY_READER, 6.01);
+ addScore(typeScores, ReadingTasteType.TREND_HUNTER, 2.50);
+ }
+ break;
+ case 8:
+ if(answer.equals(ANSWER_A)){
+ addScore(typeScores, ReadingTasteType.SECRET_DIARIST, 7.50);
+ addScore(typeScores, ReadingTasteType.SYSTEMATIC_READER, 3.50);
+ } else if(answer.equals(ANSWER_B)){
+ addScore(typeScores, ReadingTasteType.CHATTY_READER, 7.50);
+ addScore(typeScores, ReadingTasteType.TREND_HUNTER, 2.50);
+ }
+ break;
+ case 9:
+ if(answer.equals(ANSWER_A)){
+ addScore(typeScores, ReadingTasteType.CHATTY_READER, 6.01);
+ addScore(typeScores, ReadingTasteType.GENRE_SPECIALIST, 4.01);
+ } else if(answer.equals(ANSWER_B)){
+ addScore(typeScores, ReadingTasteType.IMMERSIVE_READER, 6.01);
+ addScore(typeScores, ReadingTasteType.SECRET_DIARIST, 4.01);
+ }
+ break;
+ case 10:
+ if(answer.equals(ANSWER_A)){
+ addScore(typeScores, ReadingTasteType.RANDOM_PICKER, 5.51);
+ addScore(typeScores, ReadingTasteType.GENRE_SPECIALIST, 3.49);
+ } else if(answer.equals(ANSWER_B)){
+ addScore(typeScores, ReadingTasteType.SYSTEMATIC_READER, 7.51);
+ addScore(typeScores, ReadingTasteType.SECRET_DIARIST, 3.49);
+ }
+ break;
+ case 11:
+ if(answer.equals(ANSWER_A)){
+ addScore(typeScores, ReadingTasteType.IMMERSIVE_READER, 6.01);
+ addScore(typeScores, ReadingTasteType.GENRE_SPECIALIST, 3.99);
+ } else if(answer.equals(ANSWER_B)){
+ addScore(typeScores, ReadingTasteType.EMOTIONAL_REFLECTOR, 6.00);
+ addScore(typeScores, ReadingTasteType.SECRET_DIARIST, 4.00);
+ }
+ break;
+ case 12:
+ if(answer.equals(ANSWER_A)){
+ addScore(typeScores, ReadingTasteType.TREND_HUNTER, 6.01);
+ addScore(typeScores, ReadingTasteType.RANDOM_PICKER, 4.99);
+ } else if(answer.equals(ANSWER_B)){
+ addScore(typeScores, ReadingTasteType.IMMERSIVE_READER, 6.00);
+ addScore(typeScores, ReadingTasteType.EMOTIONAL_REFLECTOR, 4.00);
+ }
+ break;
+ default:
+ log.error("잘못된 questionNo(1-12) 입력: {}번", questionNo);
+ throw new BadRequestException(
+ String.format(ErrorStatus.INVALID_QUESTION_NUMBER.getMessage(), questionNo)
+ );
+ }
+ }
+
+ return typeScores;
+ }
+
+ // 검증 로직(에러처리) 분리
+ private void validateAnswers(Map answers){
+ // 비어 있는 답변(null 또는 empty 체크)
+ if(answers == null || answers.isEmpty()){
+ log.error("테스트 요청 데이터가 비어있음.");
+ throw new BadRequestException(ErrorStatus.EMPTY_TEST_ANSWERS.getMessage());
+ }
+
+ // 답변 개수 체크
+ if(answers.size() != 12) {
+ log.error("테스트 답변 개수(총 12개) 부족 (현재 답변 개수: {}개)", answers.size());
+ throw new BadRequestException(
+ String.format(ErrorStatus.INCOMPLETE_TEST_ANSWERS.getMessage(), answers.size())
+ );
+ }
+
+ // A/B 체크
+ for(Map.Entry entry : answers.entrySet()){
+ int questionNo = entry.getKey();
+ String answer = entry.getValue();
+
+ if(!answer.equals(ANSWER_A) && !answer.equals(ANSWER_B)){
+ log.error("테스트 답변은 A 또는 B여야 합니다.(현재 질문번호: {}, 답변: {})", questionNo, answer);
+ throw new BadRequestException(
+ String.format(ErrorStatus.INVALID_ANSWER_VALUE.getMessage(), questionNo, answer)
+ );
+ }
+ }
+ }
+
+ // 점수 계산
+ private void addScore(Map typeScores,
+ ReadingTasteType type, double score){
+ typeScores.put(type, typeScores.getOrDefault(type, 0.0) + score);
+ }
+
+ // 가장 점수가 높은 type 찾기
+ private ReadingTasteType findTopType(Map typeScores){
+ ReadingTasteType topType = null;
+ double maxScore = Double.MIN_VALUE; // 가장 작은 값으로 시작
+
+ for (Map.Entry entry : typeScores.entrySet()) {
+ if (entry.getValue() > maxScore) {
+ maxScore = entry.getValue();
+ topType = entry.getKey();
+ }
+ }
+
+ if (topType == null) {
+ log.info("점수 계산 결과가 없음, topType = {}", topType);
+ throw new BadRequestException("점수 계산 결과가 없습니다.");
+ }
+
+ return topType;
+ }
+}
diff --git a/src/main/java/com/moongeul/backend/common/response/ErrorStatus.java b/src/main/java/com/moongeul/backend/common/response/ErrorStatus.java
index 747953d..e6ab88b 100644
--- a/src/main/java/com/moongeul/backend/common/response/ErrorStatus.java
+++ b/src/main/java/com/moongeul/backend/common/response/ErrorStatus.java
@@ -19,6 +19,12 @@ public enum ErrorStatus {
INVALID_TOKEN_REQUEST(HttpStatus.BAD_REQUEST, "잘못된 토큰 요청입니다."),
INVALID_INFO_REQUEST(HttpStatus.BAD_REQUEST, "잘못된 로그인 인증 요청입니다."),
+ EMPTY_TEST_ANSWERS(HttpStatus.BAD_REQUEST, "답변이 비어있습니다."),
+ INCOMPLETE_TEST_ANSWERS(HttpStatus.BAD_REQUEST, "12개 질문에 모두 답변해야 합니다. (현재: %d개)"),
+ INVALID_QUESTION_NUMBER(HttpStatus.BAD_REQUEST, "테스트에 잘못된 questionNo(질문번호)가 입력되었습니다. (질문번호: %d)"),
+ INVALID_ANSWER_VALUE(HttpStatus.BAD_REQUEST, "테스트 답변은 A 또는 B여야 합니다. (질문번호: %d, 현재답변: %s)"),
+ NO_SCORE_RESULT(HttpStatus.BAD_REQUEST, "테스트 점수 계산 결과가 없습니다."),
+
/**
* 401 UNAUTHORIZED
*/
diff --git a/src/main/java/com/moongeul/backend/common/response/SuccessStatus.java b/src/main/java/com/moongeul/backend/common/response/SuccessStatus.java
index 0059761..cd8fa20 100644
--- a/src/main/java/com/moongeul/backend/common/response/SuccessStatus.java
+++ b/src/main/java/com/moongeul/backend/common/response/SuccessStatus.java
@@ -18,6 +18,7 @@ public enum SuccessStatus {
SEND_LOGIN_SUCCESS(HttpStatus.OK, "로그인 성공"),
GET_USERINFO_SUCCESS(HttpStatus.OK, "사용자 정보 조회 성공"),
REISSUE_TOKEN_SUCCESS(HttpStatus.OK, "토큰 재발급 성공"),
+ CALCULATE_READING_TASTE_SUCCESS(HttpStatus.OK, "독서 취향 테스트 결과 계산 성공"),
/* BOOK */
SEARCH_BOOK_SUCCESS(HttpStatus.OK, "도서 검색 성공"),