본문 바로가기
TIL

Plmography 프로젝트 작업 로그 #42 - 배열로 된 데이터 서버로 보내기 (23.02.01 TIL)

by winteringg 2023. 2. 1.

DB 에 있는 @ElementCollection 으로 묶어준 데이터를 프론트로 보내야 하는 일이 생겼다. 객체로 보낼 수도 있지만 그 객체 안에 담겨있는 id 값을 다시 사용하기 위해서는 배열로 보내는 편이 훨씬 낫다. 

일단 원본은 User 엔티티에서 VO(값 객체) 타입으로 되어 있는 Set 배열 데이터이다. 

// User Entity

@ElementCollection
private Set<WishContentId> wishContentIds = new HashSet<>();

@ElementCollection
private Set<WatchedContentId> watchedContentIds = new HashSet<>();

@ElementCollection
private Set<FavoriteContentId> favoriteContentIds = new HashSet<>();

프론트에서 특정 유저 아이디를 넘겨주면, 서버에서는 그 아이디를 통해 JPA Repository 를 조회한다. 그리고 다시 프론트로 유저의 데이터를 보내주는데 이 때 DTO 에 담아서 반환한다. 이 때 DTO 에서 VO 타입을 Long 형의 Wrapper 클래스로 변환해주는 것이다.

코드는 아래와 같다. 

public class UserDto {
    private Long id;
    private Set<Long> wishContentIds;  // 변환한 데이터를 받을 필드 변수

    public UserDto(Long id, Set<WishContentId> wishContentIds) {
        this.id = id;
        setWishContentIds(wishContentIds);  // 값객체 변환해주는 메서드
    }
    
    private void setWishContentIds(Set<WishContentId> wishContentIds) {
    	this.wishContentIds = wishContentIds
        	.stream()
    		.map(WishContentId::getValue)
    		.collect(Collectors.toSet());
    }

생성자에서 VO 타입으로 되어 있는 파라미터를 setWishContentIds 라는 메서드의 인자값으로 받는다. 그 메서드는 Set<Long> 타입으로 되어 있는 필드 변수에 값 객체 형태의 파라미터를 대입해 주는 역할을 한다.

Long 타입으로 변환하기 위해서는 당연히 값 객체의 value 값을 Long 형으로 해놓아야 한다.

// WishContentId

@Embeddable
public class WishContentId {
    @Column(name = "wish_content_id")
    private Long value;

    public WishContentId() {
    }

    public WishContentId(Long value) {
        this.value = value;
    }

    public Long getValue() {
        return value;
    }

그리고 프론트로 보낸 특정 유저가 가진 배열 데이터를 어떻게 서버로 다시 받을 지 고민하고 있었는데 동기분께서 배열을 String 형태로 만든 후 받아서 split 한 후에 id 값을 사용하면 된다는 조언을 주셔서 시도해 보았는데 아주 잘 동작하였고 방법은 아래와 같다.

프론트에서 배열 데이터를 join() 메서드를 활용해 String 형태로 만든 후 서버로 보내면 서버에서는 @RequestParam 으로 String 데이터를 받아서 사용하는 것이다.

// 프론트에서 보낸 문자열 id 값
const wishContentId = wishContentIds?.join(',');


// 서버에서 받은 문자열을 split 해서 사용
public UserProfileContentsDto wishContents(Long userId, String wishContentId) {
    String[] contentIds = wishContentId.split(",");

    List<UserProfileContentDto> contentDtos = Arrays.stream(contentIds)
            .map(contentId -> {
                User user = userRepository.findById(userId)
                        .orElseThrow(() -> new UserNotFound());

                Content content = contentRepository.findByTmdbId(Long.parseLong(contentId))
                        .orElseThrow(() -> new ContentNotFound());

                return new UserProfileContentDto(
                        user.getId(),
                        content.getTmdbId(),
                        content.getImageUrl(),
                        content.getKorTitle());
            }).toList();

    return new UserProfileContentsDto(contentDtos);
    }

 

댓글