managing images separately instead of at the SKU level (ProductEntity, ProductColorVariantEntity)
I understand that in the product list, SKUs with the same size used to share the same image, and individual images weren't registered for each SKU. Now, this has been changed so that SKUs with the same color use the same image. SKUs no longer directly own images; instead, they refer to productColorVariant to fetch the image corresponding to that color.
현재는 productEntity가 sku를 리스트로, sku가 이미지를 리스트로 가지고 있다.
따라서 이미지를 각 sku마다 등록해줘야 하는 일이 생기고 말았다...
굉장히 귀찮은 작업은 둘째로 치고.. 각각의 sku마다 이미지를 등록하게 되면 엄청난 자원을 소모하게 된다.
따라서..... 구조를 변경하기로 했다.
슈퍼 대공사였다...
일단, 상품의 색상을 옵션관리에서 하고 있었는데, 따로 input 필드로 빼냈다.
리액트쪽에서는 useState 안에 저장하고, 백엔드로 보내기 전에 , 단위로 나눠서 색상을 배열로 만들어주고 백으로 보냈다.
const colorsArray = productColors.split(',').map(color => color.trim()).filter(color => color !== '');
if (colorsArray.length === 0) {
setError("상품 색상을 최소 한 가지 이상 입력해야 합니다. (예: white, black, red)");
return;
}
이제 백엔드인데.. 처음에는 굉장히 간단할 줄 알았는데.. 아니였다.
처음에는 product, sku, image 엔티티 정도만 손 봐주고 새롭게 productColor? 엔티티 정도만 만들어서 엮어주면 될거라고 생각했는데 로직 처리해야 할 것도 너무 많고, 이거저거 엮여있는 DTO도 손봐줘야했다.
product entity 에 추가
@OneToMany(mappedBy = "product", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
private List<ProductColorVariantEntity> colorVariants;
sku entity 에 추가
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "color_variant_id", nullable = false) // 어떤 색상 변형에 속하는지 연결 (핵심!)
private ProductColorVariantEntity colorVariant;
image entity에 추가
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "color_variant_id", nullable = false) // 어떤 ColorVariant에 속하는지 연결
private ProductColorVariantEntity colorVariant;
그리고 이제 더 이상 sku 가 직접 image entity를 리스트로 소유하지 않는다.
productColorVariantEntity를 통해서 참조만 할뿐이다.
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OrderBy;
import java.util.ArrayList;
import java.util.List;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class ProductColorVariantEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // 색상 변형 고유 ID
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "product_id", nullable = false) // ProductEntity의 ID를 참조
private ProductEntity product; // 어떤 제품의 색상 변형인지 연결
@Column(nullable = false, length = 50)
private String colorName; // 색상명 (예: White, Black, Red)
@OneToMany(mappedBy = "colorVariant", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
@OrderBy("displayOrder ASC") // displayOrder 필드를 기준으로 정렬
private List<ImageUrlEntity> images = new ArrayList<>(); // ImageUrlEntity 리스트로 변경
public ProductColorVariantEntity(ProductEntity product, String colorName) {
this.product = product;
this.colorName = colorName;
}
// 편의메서드
public void setThumbnail(ImageUrlEntity image) {
if(image!=null) {
image.setAsThumbnail(true);
}
}
public void addImage(ImageUrlEntity imageEntity) {
if (imageEntity != null && !this.images.contains(imageEntity)) {
this.images.add(imageEntity);
imageEntity.setColorVariant(this);
}
}
public void removeImage(ImageUrlEntity image) {
if (image != null && this.images.contains(image)) {
this.images.remove(image);
image.setColorVariant(null);
}
}
entity의 관계설정을 잘 했고, 이제 다음으로 Controller, service, repository 쪽을 보면..
먼저 postMapping으로 넘어오는 파라미터를 매칭되는 dto에 colors를 추가해줘야 했다.
@NotNull(message = "색상은 필수입니다.")
private List<String> Colors;
그 다음 productService 에서 colorvariant를 저장하고, 설정된 옵션을 반복문으로 돌 때, for문을 colorVariant 용으로 넣어주면 된다. 다른 옵션들 * 색상 옵션이 되야 하기 때문.
그 다음은 response...dto 들만 변경해주면 됐다.
가면 갈수록 코드 하나 고치는게 너무 힘이 든다.
처음에 구조를 많이 고민하고 짰다고 생각을 했는데도 불구하고, 계속해서 무언가가 나온다...