Fix : 수정

This commit is contained in:
lsh9672 2025-06-12 18:34:02 +09:00
parent c281299d94
commit d92f6b7bac
7 changed files with 252 additions and 0 deletions

View File

@ -0,0 +1,33 @@
package com.ktds.hi.recommend.biz.domain;
import lombok.Builder;
import lombok.Getter;
/**
* 취향 태그 도메인 클래스
* 사용자 취향 태그 정보를 나타냄
*/
@Getter
@Builder
public class PreferenceTag {
private Long id;
private String tagName;
private String category;
private String icon;
private String description;
private boolean isActive;
/**
* 정적 팩토리 메서드 - 기본 태그 생성
*/
public static PreferenceTag of(String tagName, String category, String icon, String description) {
return PreferenceTag.builder()
.tagName(tagName)
.category(category)
.icon(icon)
.description(description)
.isActive(true)
.build();
}
}

View File

@ -1,9 +1,12 @@
package com.ktds.hi.recommend.biz.service; package com.ktds.hi.recommend.biz.service;
import com.ktds.hi.recommend.biz.domain.PreferenceTag;
import com.ktds.hi.recommend.biz.usecase.in.TasteAnalysisUseCase; import com.ktds.hi.recommend.biz.usecase.in.TasteAnalysisUseCase;
import com.ktds.hi.recommend.biz.usecase.out.PreferenceTagRepository;
import com.ktds.hi.recommend.biz.usecase.out.UserPreferenceRepository; import com.ktds.hi.recommend.biz.usecase.out.UserPreferenceRepository;
import com.ktds.hi.recommend.biz.domain.TasteProfile; import com.ktds.hi.recommend.biz.domain.TasteProfile;
import com.ktds.hi.recommend.biz.domain.TasteCategory; import com.ktds.hi.recommend.biz.domain.TasteCategory;
import com.ktds.hi.recommend.infra.dto.response.PreferenceTagResponse;
import com.ktds.hi.recommend.infra.dto.response.TasteAnalysisResponse; import com.ktds.hi.recommend.infra.dto.response.TasteAnalysisResponse;
import com.ktds.hi.common.exception.BusinessException; import com.ktds.hi.common.exception.BusinessException;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -26,6 +29,7 @@ import java.util.stream.Collectors;
public class TasteAnalysisInteractor implements TasteAnalysisUseCase { public class TasteAnalysisInteractor implements TasteAnalysisUseCase {
private final UserPreferenceRepository userPreferenceRepository; private final UserPreferenceRepository userPreferenceRepository;
private final PreferenceTagRepository preferenceTagRepository;
@Override @Override
@Transactional(readOnly = true) @Transactional(readOnly = true)
@ -76,4 +80,25 @@ public class TasteAnalysisInteractor implements TasteAnalysisUseCase {
throw new BusinessException("취향 프로필 업데이트 중 오류가 발생했습니다: " + e.getMessage()); throw new BusinessException("취향 프로필 업데이트 중 오류가 발생했습니다: " + e.getMessage());
} }
} }
@Override
public List<PreferenceTagResponse> getAvailablePreferenceTags() {
log.info("가용한 취향 태그 목록 조회");
try {
List<PreferenceTag> tags = preferenceTagRepository.findAllActiveTags();
return tags.stream()
.map(tag -> PreferenceTagResponse.builder()
.tagName(tag.getTagName())
.icon(tag.getIcon())
.description(tag.getDescription())
.build())
.collect(Collectors.toList());
} catch (Exception e) {
log.error("취향 태그 목록 조회 중 오류 발생", e);
throw new BusinessException("취향 태그 목록 조회에 실패했습니다");
}
}
} }

View File

@ -1,5 +1,8 @@
package com.ktds.hi.recommend.biz.usecase.in; package com.ktds.hi.recommend.biz.usecase.in;
import java.util.List;
import com.ktds.hi.recommend.infra.dto.response.PreferenceTagResponse;
import com.ktds.hi.recommend.infra.dto.response.TasteAnalysisResponse; import com.ktds.hi.recommend.infra.dto.response.TasteAnalysisResponse;
/** /**
@ -17,4 +20,9 @@ public interface TasteAnalysisUseCase {
* 취향 프로필 업데이트 * 취향 프로필 업데이트
*/ */
void updateTasteProfile(Long memberId); void updateTasteProfile(Long memberId);
/**
* 가용한 취향 태그 목록 조회
*/
List<PreferenceTagResponse> getAvailablePreferenceTags();
} }

View File

@ -0,0 +1,33 @@
package com.ktds.hi.recommend.biz.usecase.out;
import com.ktds.hi.recommend.biz.domain.PreferenceTag;
import java.util.List;
import java.util.Optional;
/**
* 취향 태그 Repository 인터페이스
* 취향 태그 관련 데이터 액세스 기능을 정의
*/
public interface PreferenceTagRepository {
/**
* 활성화된 모든 취향 태그 조회
*/
List<PreferenceTag> findAllActiveTags();
/**
* 태그 ID로 태그 조회
*/
Optional<PreferenceTag> findById(Long tagId);
/**
* 태그명으로 태그 조회
*/
Optional<PreferenceTag> findByTagName(String tagName);
/**
* 카테고리별 태그 조회
*/
List<PreferenceTag> findByCategory(String category);
}

View File

@ -0,0 +1,78 @@
package com.ktds.hi.recommend.infra.gateway;
import com.ktds.hi.recommend.biz.usecase.out.PreferenceTagRepository;
import com.ktds.hi.recommend.biz.domain.PreferenceTag;
import com.ktds.hi.recommend.infra.gateway.repository.PreferenceTagJpaRepository;
import com.ktds.hi.recommend.infra.gateway.entity.PreferenceTagEntity;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* 취향 태그 Repository 어댑터 클래스
* PreferenceTagRepository를 구현하여 취향 태그 데이터 액세스 기능을 제공
*/
@Component
@RequiredArgsConstructor
@Slf4j
public class PreferenceTagRepositoryAdapter implements PreferenceTagRepository {
private final PreferenceTagJpaRepository preferenceTagJpaRepository;
@Override
public List<PreferenceTag> findAllActiveTags() {
log.info("활성화된 모든 취향 태그 조회");
List<PreferenceTagEntity> entities = preferenceTagJpaRepository.findByIsActiveTrueOrderByTagName();
return entities.stream()
.map(this::toPreferenceTag)
.collect(Collectors.toList());
}
@Override
public Optional<PreferenceTag> findById(Long tagId) {
log.info("태그 ID로 태그 조회: tagId={}", tagId);
return preferenceTagJpaRepository.findById(tagId)
.filter(entity -> entity.getIsActive())
.map(this::toPreferenceTag);
}
@Override
public Optional<PreferenceTag> findByTagName(String tagName) {
log.info("태그명으로 태그 조회: tagName={}", tagName);
return preferenceTagJpaRepository.findByTagNameAndIsActiveTrue(tagName)
.map(this::toPreferenceTag);
}
@Override
public List<PreferenceTag> findByCategory(String category) {
log.info("카테고리별 태그 조회: category={}", category);
List<PreferenceTagEntity> entities = preferenceTagJpaRepository.findByCategoryAndIsActiveTrueOrderByTagName(category);
return entities.stream()
.map(this::toPreferenceTag)
.collect(Collectors.toList());
}
/**
* 엔티티를 도메인으로 변환
*/
private PreferenceTag toPreferenceTag(PreferenceTagEntity entity) {
return PreferenceTag.builder()
.id(entity.getId())
.tagName(entity.getTagName())
.category(entity.getCategory())
.icon(entity.getIcon())
.description(entity.getDescription())
.isActive(entity.getIsActive())
.build();
}
}

View File

@ -0,0 +1,44 @@
package com.ktds.hi.recommend.infra.gateway.entity;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
//TODO : BASEENtity 빠져있음. 추가 필요
/**
* 취향 태그 엔티티 클래스
* 데이터베이스 preference_tags 테이블과 매핑되는 JPA 엔티티
*/
@Entity
@Table(name = "preference_tags")
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PreferenceTagEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "tag_name", unique = true, nullable = false, length = 50)
private String tagName;
@Column(name = "category", length = 50)
private String category;
@Column(name = "icon", length = 10)
private String icon;
@Column(name = "description", length = 200)
private String description;
@Column(name = "is_active")
@Builder.Default
private Boolean isActive = true;
}

View File

@ -0,0 +1,31 @@
package com.ktds.hi.recommend.infra.gateway.repository;
import com.ktds.hi.recommend.infra.gateway.entity.PreferenceTagEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
/**
* 취향 태그 JPA 리포지토리 인터페이스
* 취향 태그 데이터의 CRUD 작업을 담당
*/
@Repository
public interface PreferenceTagJpaRepository extends JpaRepository<PreferenceTagEntity, Long> {
/**
* 활성화된 태그 목록 조회
*/
List<PreferenceTagEntity> findByIsActiveTrueOrderByTagName();
/**
* 태그명으로 태그 조회
*/
Optional<PreferenceTagEntity> findByTagNameAndIsActiveTrue(String tagName);
/**
* 카테고리별 활성화된 태그 조회
*/
List<PreferenceTagEntity> findByCategoryAndIsActiveTrueOrderByTagName(String category);
}