ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring Boot] 이미지 로딩 방식 고찰
    JAVA/Spring Boot 2021. 5. 26. 10:34

    토이프로젝트를 하면서 백앤드 로직에서는 문제를 못 느꼈지만, 프론트를 직접 구현하면서 느꼈던 문제를 리뷰해보겠다.

    아직 머리 속으로 프론트에서 어떤 것들이 필요한지 완벽하게는 그려지지 않았기 때문에 생겼던 문제 같다.

     

    아래의 그림과 같이 OrderList 테이블이 있다.

    OrderList 테이블

    여기서 보았을 때 OrderList 테이블에는 Picture의 사진이 저장되어 있지만 프론트에서 사진을 받을 때 img 태그의 src를

    받기 위해선 해당 Picture의 정보만 반환해 줄 수 있는 URL이 따로 필요 했다.

     

    img 태그의 src에 Picture의 정보를 넣어 봤을 때, 404 에러가 나면서 이미지가 로딩되지 않았다.

    ( <img src=" " /> 에서 해당 src 부분을 이야기 하는 것)

    이유는 해당 src에 Blob의 정보 즉 바이트 덩어리들이 들어가면서 오류가 났다.

     

    그래서 임시 방편으로 URL을 직접 만들어주어 DTO를 통해 반환 했다.

    package com.example.toy_project.order_list.application;
    
    import com.example.toy_project.order_list.domain.OrderList;
    import com.fasterxml.jackson.annotation.JsonFormat;
    import com.fasterxml.jackson.databind.PropertyNamingStrategy;
    import com.fasterxml.jackson.databind.annotation.JsonNaming;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
    import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
    
    @NoArgsConstructor
    @Getter
    @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
    public class OrderResponse {
        private Long orderId;
        private String orderName;
        private String url;
        private int price;
        private int count;
    
        public OrderResponse(OrderList list){
            this.orderId = list.getId();
            this.orderName = list.getName();
            this.price = list.getPrice();
            this.count = list.getCount();
    
            String fileUrl = ServletUriComponentsBuilder
                    .fromCurrentContextPath()
                    .path("/api/files/")
                    .path(String.valueOf(list.getId()))
                    .toUriString();
    
            this.url = fileUrl;
        }
    }
    

     

     

    임시로 반환 했던 url을 통해 Controller에서는 위의 반환 url을 맵핑해줄 수 있게

    @GetMapping("/files/{id}")
    public ResponseEntity<byte[]> findPictureById(@PathVariable Long id){
    	return orderListService.findPictureById(id);
    }

    Body 부분에 해당 Picture의 바이트를 반환 해줄 수 있게 했다.

     

    /file/{id}의 Service 로직에서 contentType을 png파일로 지정했고 OrderList테이블의 Picture 부분만 Body에 넣어 반환했다.

    @Transactional(readOnly = true)
    public ResponseEntity<byte []> findPictureById(Long id){
      OrderList orderList = orderListRepository.findById(id).get();
      return ResponseEntity.ok().contentType(MediaType.IMAGE_PNG).body(orderList.getPicture());
    }

     

    결과화면

     

    문제점

    1. 내가만약 OrderList의 사진을 가져오고 싶거나, 장바구니에 넣었을 때 사용자에게 사진을 보여주고 싶을 때 등

        사진이 필요한 경우는 매번 URL을 직접 만들어줘야 했다.

     

    따라서 URL이 필요한 경우가 많았기에 따로 URL String을 저장해두는 컬럼을 만들어야 했다.

     

    2. OrderList를 두번 조회함으로서 Pciture의 byte 덩어리들을 두번이나 호출하게 되고 만약 사용자가 증가 했을 때

        서버에 부담이 더욱 될 수 있었다.

    ( 두번 조회 : OrderListDto를 통해 반환할 때 조회, /file/{id}를 통해 조회 ) 

     

    따라서 Picture만 따로 보관하게 데이터 베이스를 수정해야함을 느꼈다. 

     

    데이터베이스 설계를 함에 있어 좀 더 고민을 해서 최대한 수정을 하지 않게 만드려 했지만 구현하면서 생기는 문제점을

    해결하기 위해선 어쩔 수 없었던것 같다.

    댓글

Designed by Tistory.