[SpringBoot][SpringDataJPA] 게시판 구현 (3)

yu-jin-song님의 게시판 구현 게시물을 참고하였습니다.


MultipartFile

✔️ 구현기능

  • 게시글 작성 및 파일 업로드 동시 처리
  • 다중 파일 업로드
  • DB에 파일 자체를 저장하지 않고 파일 관련 정보만 저장. 실제 파일은 서버 내 지정 경로에 저장

파일 용량 설정

// application.yml

spring:
  servlet:
    multipart:
      maxFileSize: 10MB
      maxRequestSize: 20MB

의존성 주입

// build.gradle

dependencies {
	...
	implementation 'commons-io:commons-io:2.6'
}

IOUtils 패키지는 대부분 static 메소드이기 때문에 객체를 생성하지 않고 바로 사용 가능하다.
IOUtils 패키지 중 org.apache.commons.io.FileUtils를 사용해 파일 관련 처리를 수행한다.


Entity

: 파일 정보가 저장될 entity

Board entity와의 관계는 다대일관계(N:1)이다.
(하나의 게시글이 여러 파일을 가짐)

⚠️ File 이 자체를 클래스 명으로 사용하지 않도록 주의하기

⌨️ 코드

추후 수정

  • @JsonBackReference
    : 순환참조를 방어하기 위한 어노테이션

사용방법은 부모 클래스에 @JsonManagedReference,
자식 클래스에 @JsonBackReference 어노테이션을 추가해주면 된다.

// Board.java 코드 중
...
    @OneToMany(
            mappedBy = "board",
            cascade = {CascadeType.PERSIST, CascadeType.REMOVE},
            orphanRemoval = true
    )
...

✔️ @OneToMany 옵션

  • optional
    : 해당 객체에 null이 들어갈 수 있는지
    (@Column 어노테이션에서도 nullable=true로 세팅해도 null이 들어갈 수 있음)
  • fetch
    : 엔티티의 로딩 방식
    - EAGER: 연관된 엔티티를 바로 로딩
    - LAZY: 바로 로딩하지 않고 실제 해당 객체를 조회할 때 해당 엔티티를 로딩

✔️ default값
@ManyToOne: FetchType.EAGER
@OneToMany: FetchType.LAZY

  • cascade
    : 영속성 전이 설정
    - PERSIST: 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장
    - REMOVE: 부모 엔티티를 삭제하면 자식 엔티티도 함께 삭제
    - DETACH: 부모 엔티티가 Detach되면 자식 엔티티도 함께 detach. 즉, 변경사항이 반영되지 않는 상태가 됨
    - REFRESH: 부모 엔티티가 DB로부터 데이터를 다시 로드하면 자식 엔티티도 DB로부터 데이터를 다시 로딩
    - MERGE: 부모 엔티티가 detach 상태에서 자식 엔티티를 추가/변경한 이후 부모 엔티티가 merge를 수행하면 자식 엔티티도 변경 사항이 적용
    - ALL: 모든 cascade 옵션이 적용
  • orphanRemoval
    : 고아 객체를 삭제
    이 옵션이 true라면 기존 null 처리된 자식을 delete

Repository

⌨️ 코드

PhotoRepository.java

추후 수정


Controller

  • @RequestBody: body로 전달받은 JSON 형태의 데이터를 파싱

Content-Type이 multipart/form-data로 전달되어 올 때는 예외 발생
➡️ 그런데 파일/이미지는 multipart/form-data 형태로 요청하기 때문에 @RequestBody사용할 수 없다.

해결 1 (@RequestPart)

yu-jin-song님의 블로그 Controller 부분 참고하기

해결 2 (@RequestParam)

yu-jin-song님의 블로그 Controller 부분 참고하기

실무에서는 두 방법을 혼합하여 사용하기도 한다고 한다.

⌨️ 코드

추후 수정


Service

⌨️ 코드

추후 수정


- File.separator
: 이 API를 통해 각 OS에 호환되는 파일 경로를 구함

📌 List의 null vs isEmpty()

  • null
    : List의 변수가 그 어떤 주솟값도 참조하지 않은 상태
    (인스턴스가 존재하지 않는 상태)
  • isEmpty()
    : 인스턴스는 생성된 상태 또는 주솟값을 참조하고는 있지만 아무런 데이터가 적재되어 있지 않은 상태

순환참조 참고
@OneToMany 옵션 참고
@OneToMany orphanRemoval 참고
게시판 구현 참고

좋은 웹페이지 즐겨찾기