[Spring Boot] 이미지를 포함하는 게시글 작성 API에 대한 생각

hellonayeon·2021년 12월 20일
0
post-thumbnail

✏️ 구현한 방식

프론트에서는 Form Data에 요청하는 데이터들을 key-value 형식으로 차곡차곡 넣어 보내고, 서버측에서는 요청에 담긴 파라미터를 하나씩 꺼내왔다. 이렇게 구현을 하니 메서드의 파라미터 많아지고 Controller 뿐만 아니라 Service 에도 값을 넘겨줘야 하기 때문에 약간의 수정만 있어도 두 계층을 변경해줘야돼서 번거로웠다.

@PostMapping("/articles")
public void createArticle(@AuthenticationPrincipal UserDetailsImpl userDetails,
                          @RequestParam("text") String text,
                          @RequestParam("location") String locationJsonString,
                          @RequestParam("tagNames") List<String> tagNames,
                          @RequestParam("imageFiles") List<MultipartFile> imageFiles) {

    articleService.createArticle(userDetails.getUser(), text, new LocationRequestDto(locationJsonString), tagNames, imageFiles);
}

하지만 파라미터를 하나씩 꺼내오는 불편함은 @ModelAttribute 어노테이션을 통해 해결할 수 있었다.

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class ArticleCreateRequestDto {
    private String text;
    private String location;
    private List<String> tagNames;
    private List<MultipartFile> imageFiles;
}
@PostMapping("/articles")
public Article createArticle(@AuthenticationPrincipal UserDetailsImpl userDetails,
                             @ModelAttribute ArticleCreateRequestDto articleCreateRequestDto) {
                             
    return articleService.createArticle(userDetails.getUser(), articleCreateRequestDto);
}

☠️ 문제

⏱ 이미지 업로드 시간

요청 데이터를 꺼내는 방법은 어느정도 깔끔하게(?) 해결 됐지만, 게시글 API를 변경하게 된 가장 큰 이유가 남아있다! 게시물 내용 위치 정보 태그 이미지를 하나의 API로 처리하여 하나의 서비스 계층에서 모든걸 처리하도록 구현하다보니, 이미지 개수가 많아지고 크기가 커질 수록 게시물이 업로드 되기까지 시간이 오래 걸렸다. 프론트에서 게시물 이미지 업로드 처리를 하는 동안 로딩창이 돌아서 사용자에게 알려주기는 했다만 이게 이렇게까지 기다려야할 일인가 싶었다.

🔨 가능한 방법

[방법1]
1. 게시물 등록 API 호출
   ├── 등록할때 이미지 파일 이름(이미지 URL) 생성
   ├── Image 도메인 객체 생성
   └── Article과 Image 연관관계 설정
2. 게시물 아이디 리턴

3. 모든 게시물 조회 API 호출
4. 프론트 뷰의 내용을 비우고, 모든 게시물 리스트 출력
   └── 게시물 리스트 출력 시 <img> src 속성 지정

5. 이미지 업로드 API 호출
   └── ID에 해당되는 게시물의 Image 리스트에서 이미지 파일 이름을 찾아 업로드

[방법2]
1. 게시물 등록 API 호출
2. 게시물 아이디 리턴

3. 모든 게시물 조회 API 호출
4. 프론트 뷰의 내용을 비우고, 모든 게시물 리스트 출력

5. 이미지 업로드 API 호출
   └── ID에 해당되는 게시물의 Image 리스트에서 이미지 파일 이름을 찾아 업로드
   
6. 모든 이미지 조회 API 호출
  └── 이미지의 FK로 저장된 게시물 ID <img>를 찾아 src 속성 지정

"이미지가 업로드 될 때까지 게시물 등록을 기다려야한다" 라는 문제를 해결하고자 이미지 업로드 API 분리를 생각했었다. 이미지 관련 API 처리를 따로 분리할거면 이미지 조회/삭제 API도 게시글 API로 부터 분리해야하는게 아닐까 라는 생각에 [방법2]로 가기로 했다. 하지만 어떤 방법이 더 좋은건지 결과를 내기 어려워 튜터님께 헬프를 외쳤다!

튜터님이 말씀하시길.. Case by case.. 서비스에서 정하기 나름이라고 하셨다. 이미지를 게시글과 한 번에 올리는 곳도 있고, Slack 처럼 미리 올려두는 경우도 있다고 한다. 이미지를 첨부해놓고 다시 지울 수도 있고 게시물을 올리려다 안 올릴 수도 있는데 왜 미리 올려두는건지 이해가 안됐었다. 그때 마침 팀원분께서 내 고민을 들어보시고 하신 말씀이 떠올랐다. 이미지 업로드 API를 나중에 호출하면, 업로드하다가 오류나면 게시물은 어떻게 되는거죠? 그러고보니 게시물은 이미 게시물 리스트에 출력되어 보여진 상태인데 이미지에서 오류나버리면 있었는데요, 없었습니다. 가 되는건가😱 Slack 처럼 미리 올려둔 경우면 게시물 작성을 취소할 경우, 이미지 첨부를 취소했을 경우 이미지를 찾아서 삭제해야하는 추가적인 처리가 필요하지만 어떤 성능에 중점을 둘 것이며 거기에 따라오는 마이너스를 감수할지는 정하기 나름이다.

게시글 작성 API는 웹 개발을 공부하고 있다면 또는 서비스를 개발한다면 한번쯤은 꼭 구현하는 API라 생각해서 일종의 모범 답안이 있을거라 생각했는데 큰 착각이었다. 개발에 정답이 어디있을까.. 이미지를 먼저 업로드하기나 나중에 업로드하기나 이미지가 업로드 될 때까지 온전한 게시물을 보려면 기다려야하는건 마찬가지였다. 다만 글을 작성하며 기다리냐 다 작성해놓고 기다리냐의 사용자 입장에서 느끼는 차이가 있을뿐이다.

👩🏻‍💻 생각정리

팀원분들의 의견과 튜터님의 의견을 종합해봤을때 이미지를 선택할 때마다 이미지를 미리 업로드 해두는 방향이 좋을 것 같다고 생각했다. 그렇다면 결국 게시물을 등록되길 기다리는 시간이 짧아질테니까! 그렇다면 이제 게시물 도메인과 이미지 도메인을 어떻게 매핑시킬까에 대한 고민이 생겼다.

[문제]
게시물을 작성하며 이미지를 하나씩 첨부하는 시점에는, 게시물 관련 엔티티가 없다.
왜? 아직 게시물을 안 만들었으니까!

[방법1]
1. 게시물 작성 시작 버튼을 누름과 동시에 '일단' 게시물 PK를 발급받기
2. 게시물 작성하며 업로드하는 이미지에 게시물 PK 연결하기

[방법2]
1. 이미지 업로드 시 이미지 개체를 만들고 PK를 리턴하기
2. 최종적으로 게시물 작성 시 이미지 PK 리스트들과 게시물 PK를 가지고 이미지와 게시물 관계를 매핑하는 API 호출하기

이미지 업로드 API를 분리하고 게시물 작성 중간에 업로드 로직이 수행된다면 게시물 등록까지 대기 시간이 확연히 감소된다. 하지만 ArticleImage 연관관계를 어떻게 매핑해야할지 감이 잡히지 않아.. JPA 공부를 하고 게시판이나 쇼핑몰 토이 프로젝트로 구현해봐야겠다.

2개의 댓글

comment-user-thumbnail
2022년 3월 31일

안녕하세여
만약 프론트에서 게시글 작성중에 이미지를 첨부하면, 저도 이미지 업로드 api를 호출해서 이미지를 업로드하는 동안 게시글을 작성하도록 구현했는데, 만약 게시글 등록을 안하고 뒤로가기를 누르면 서버에는 안쓰이는 이미지가 저장되는 문제가 발생하지않나요? 이에대한 해결책이 있을까요?

1개의 답글