Spring Boot 쇼핑몰 프로젝트 진행중 상품 등록을 구현할 때 , Django 에서 구현했던 상품 등록처럼 간단할 줄 알았지만 상품만 저장하는 것이 아니라 상품, 상품 이미지 정보, 이미지 파일
이렇게 3개의 객체를 저장하는 구조에다가 서비스 계층도 각각 분리되어서, 이해하는데 굉장히 어려움이 있었음. 상품 등록의 전체적인 구조와 흐름을 이해하기 위해서 정리함
상품을 등록한다고 해서 상품 Entity
만 있으면 되는 것이 아니라 상품을 보여줄 이미지도 필요함. 그렇다고해서 상품과 이미지 정보를 하나의 객체로 구현하지말고 각각 따로 구현해야 올바른 설계임. 추가적으로 상품과 상품 이미지 정보는 DB에 저장되지만 실제 이미지 File 은 로컬내에 저장되는 구조기 때문에 아래처럼 총 3개의 부분으로 나눠야함
상품 Entity
상품 이미지 정보 Entity
상품 이미지 File
3개의 부분으로 나눴다면 Service 로직도 3개로 나눠야하고, 상품 이미지 File 은 DB 에 저장되는 것이 아니기 때문에 Repository 가 아닌 FileOutputStream 으로 저장
상품 Entity -> 상품 Service -> 상품 Repository
상품 이미지 정보 Entity -> 상품 이미지 Service -> 상품 이미지 Repository
상품 이미지 File -> File Service -> FileOutputStream
즉, 상품을 등록한다고 했을 때 상품 객체 하나만을 구현하는 것이 아니라 최대한 세분화 한 뒤에 Service 로직도 나눠서 구현해야함
(소스코드는 상품 등록 부분을 참고)
① "ADMIN" 권한을 가진 아이디로 상품 등록 페이지 Get 요청
② Item Controller 에서 상품 등록 페이지를 반환하면서 itemFormDto 객체도 넘김
③ 상품 등록 페이지에서 상품 정보 및 이미지를 입력하고 "저장" (POST 요청)
④ Item Controller 에서 입력값을 검증하고 itemService.saveItem() 메소드를 수행
- 이 때, 파라미터는 입력받은 itemFormDto 객체와 이미지 정보를 담고있는 itemImgFileList 를 넘김
⑤ itemService 에서 itemFormDto 객체를 item 엔티티로 변환하고 itemRepository.save() 메소드 수행
⑥ itemService 에서 itemImg 객체를 생성하고 itemImgService.saveItemImg() 메소드 수행
- 이 때, 파라미터는 itemImg 객체와 이미지 정보를 담고있는 itemImgFileList.get(i) 객체 하나를 지정
⑦ ItemImgService 에서 상품 이미지가 존재한다면 fileService.uploadFile() 메소드 수행
- 이 때, 파라미터는 "저장위치", "원래 파일명", "이미지 Byte 파일"
⑧ FileService 에서 UUID 객체를 이용해 파일명을 새로 만들고 FileOutputStream 을 이용하여 저장
⑨ ItemImgService 에서 itemImgRepository.save() 메소드 수행
위에 코드처럼 상품 등록을 위한 dto 객체에서 상품 가격 부분을 Integer 타입으로 설정했을 때 @NotBlank 어노테이션을 지정하면 아래처럼 에러가 발생함. Integer 타입은 " " 처럼 Blank 가 들어올 수 없기 때문에 발생하는 에러 같음. 따라서 Integer 타입은 @NotNull 어노테이션을 지정해야함