From 60172ae84d121ea699f338317dcba4b14444a70e Mon Sep 17 00:00:00 2001 From: Klaus Date: Thu, 7 Aug 2025 23:10:36 +0900 Subject: [PATCH] =?UTF-8?q?feat(character):=20=EC=BA=90=EB=A6=AD=ED=84=B0?= =?UTF-8?q?=20=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20API=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 캐릭터 ID로 상세 정보를 조회하는 API 엔드포인트 추가 - 캐릭터 상세 정보 조회 서비스 메서드 구현 - 캐릭터 상세 정보 응답 DTO 클래스 추가 --- .../controller/ChatCharacterController.kt | 78 +++++++++++++++++++ .../character/dto/CharacterDetailResponse.kt | 38 +++++++++ .../character/service/ChatCharacterService.kt | 21 +++++ 3 files changed, 137 insertions(+) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/chat/character/dto/CharacterDetailResponse.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/controller/ChatCharacterController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/controller/ChatCharacterController.kt index 5b024e4..5bee186 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/controller/ChatCharacterController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/controller/ChatCharacterController.kt @@ -1,18 +1,24 @@ package kr.co.vividnext.sodalive.chat.character.controller import kr.co.vividnext.sodalive.chat.character.dto.Character +import kr.co.vividnext.sodalive.chat.character.dto.CharacterBackgroundResponse import kr.co.vividnext.sodalive.chat.character.dto.CharacterBannerResponse +import kr.co.vividnext.sodalive.chat.character.dto.CharacterDetailResponse import kr.co.vividnext.sodalive.chat.character.dto.CharacterMainResponse +import kr.co.vividnext.sodalive.chat.character.dto.CharacterMemoryResponse +import kr.co.vividnext.sodalive.chat.character.dto.CharacterPersonalityResponse import kr.co.vividnext.sodalive.chat.character.dto.CurationSection import kr.co.vividnext.sodalive.chat.character.dto.RecentCharacter import kr.co.vividnext.sodalive.chat.character.service.ChatCharacterBannerService import kr.co.vividnext.sodalive.chat.character.service.ChatCharacterService import kr.co.vividnext.sodalive.common.ApiResponse +import kr.co.vividnext.sodalive.common.SodaException import kr.co.vividnext.sodalive.member.Member import org.springframework.beans.factory.annotation.Value import org.springframework.data.domain.PageRequest import org.springframework.security.core.annotation.AuthenticationPrincipal import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController @@ -85,4 +91,76 @@ class ChatCharacterController( ) ) } + + /** + * 캐릭터 상세 정보 조회 API + * 캐릭터 ID를 받아 해당 캐릭터의 상세 정보를 반환합니다. + */ + @GetMapping("/{characterId}") + fun getCharacterDetail( + @PathVariable characterId: Long, + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + if (member.auth == null) throw SodaException("본인인증을 하셔야 합니다.") + + // 캐릭터 상세 정보 조회 + val character = service.getCharacterDetail(characterId) + ?: throw SodaException("캐릭터를 찾을 수 없습니다.") + + // 태그, 가치관, 취미, 목표 추출 + val tags = character.tagMappings.map { it.tag.tag } + val values = character.valueMappings.map { it.value.value } + val hobbies = character.hobbyMappings.map { it.hobby.hobby } + val goals = character.goalMappings.map { it.goal.goal } + + // 메모리, 성격, 배경, 관계 변환 + val memories = character.memories.map { + CharacterMemoryResponse( + title = it.title, + content = it.content, + emotion = it.emotion + ) + } + + val personalities = character.personalities.map { + CharacterPersonalityResponse( + trait = it.trait, + description = it.description + ) + } + + val backgrounds = character.backgrounds.map { + CharacterBackgroundResponse( + topic = it.topic, + description = it.description + ) + } + + val relationships = character.relationships.map { it.relationShip } + + // 응답 생성 + ApiResponse.ok( + CharacterDetailResponse( + characterId = character.id!!, + name = character.name, + description = character.description, + age = character.age, + gender = character.gender, + mbti = character.mbti, + speechPattern = character.speechPattern, + speechStyle = character.speechStyle, + appearance = character.appearance, + imageUrl = "$imageHost/${character.imagePath ?: "profile/default-profile.png"}", + memories = memories, + personalities = personalities, + backgrounds = backgrounds, + relationships = relationships, + tags = tags, + values = values, + hobbies = hobbies, + goals = goals + ) + ) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/dto/CharacterDetailResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/dto/CharacterDetailResponse.kt new file mode 100644 index 0000000..d9f2492 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/dto/CharacterDetailResponse.kt @@ -0,0 +1,38 @@ +package kr.co.vividnext.sodalive.chat.character.dto + +data class CharacterDetailResponse( + val characterId: Long, + val name: String, + val description: String, + val age: Int?, + val gender: String?, + val mbti: String?, + val speechPattern: String?, + val speechStyle: String?, + val appearance: String?, + val imageUrl: String, + val memories: List = emptyList(), + val personalities: List = emptyList(), + val backgrounds: List = emptyList(), + val relationships: List = emptyList(), + val tags: List = emptyList(), + val values: List = emptyList(), + val hobbies: List = emptyList(), + val goals: List = emptyList() +) + +data class CharacterMemoryResponse( + val title: String, + val content: String, + val emotion: String +) + +data class CharacterPersonalityResponse( + val trait: String, + val description: String +) + +data class CharacterBackgroundResponse( + val topic: String, + val description: String +) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/service/ChatCharacterService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/service/ChatCharacterService.kt index 574ee72..0f9f626 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/service/ChatCharacterService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/service/ChatCharacterService.kt @@ -172,6 +172,27 @@ class ChatCharacterService( return chatCharacterRepository.findById(id).orElse(null) } + /** + * 캐릭터 ID로 상세 정보를 조회합니다. + * 태그, 가치관, 취미, 목표 등의 관계 정보도 함께 조회합니다. + */ + @Transactional(readOnly = true) + fun getCharacterDetail(id: Long): ChatCharacter? { + val character = findById(id) ?: return null + + // 지연 로딩된 관계 데이터 초기화 + character.tagMappings.size + character.valueMappings.size + character.hobbyMappings.size + character.goalMappings.size + character.memories.size + character.personalities.size + character.backgrounds.size + character.relationships.size + + return character + } + /** * 캐릭터 생성 및 관련 엔티티 연결 */