-
Sneakers Mania - Summernote 이미지 파일 업로드 시 고유 URL 생성Projects/Problem & Solution 2022. 1. 29. 12:09
개요
문제점
Summernote는 이미지 파일 업로드 시 base64로 인코딩을 한 후 저장하는 방식이기 때문에, 보안성은 뛰어나지만 이미지 파일 관리가 매우 어렵다는 단점이 있다. 예를 들어서, 고화질의 이미지 파일을 업로드했을 때 DB의 용량을 많이 차지한다는 점과 해당 이미지 파일을 조회할 경우 업로드 시간이 많이 소요된다는 점이다.
해결 방안
Summernote가 제공하는 callback 함수를 이용하여, 이미지를 특정 경로에 업로드한 후 고유한 URL을 리턴하는 방식으로 해결해 보았다. 추가로, URL을 통한 외부 리소스 접근을 위해 톰캣 설정도 별도로 필요하다.
구현 방법
1. Summernote callback 함수
<script> $('.summernote').summernote({ placeholder: '내용을 입력해주세요.', tabsize: 2, height: 250, callbacks: { onImageUpload: function (files) { uploadSummernoteImageFile(files[0], this); } } }); function uploadSummernoteImageFile(file, editor) { data = new FormData(); data.append("file", file); $.ajax({ data: data, type: "POST", url: "/uploadSummernoteImageFile", contentType: false, processData: false, success: function (data) { $(editor).summernote('insertImage', data.url); } }); } </script>
ㆍ Summernote에서는 몇 개의 callback 함수를 지원한다.
ㆍ 그중 onImageUpload 함수는 Summernote에 이미지를 업로드할 때마다 자동으로 실행되는 함수이다.
ㆍ 이미지를 업로드할 때마다 onImageUpload 함수가 호출되며, 해당 이미지는 Ajax를 통해 컨트롤러로 전송되는 방식이다.
2. 의존성 추가
<!-- https://mvnrepository.com/artifact/commons-io/commons-io --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency> <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.6</version> </dependency>
ㆍ 파일 업로드 로직과 JSON을 리턴하기 위해 위와 같은 의존성을 추가한다.
3. application.properties 설정
spring.http.converters.preferred-json-mapper=gson
ㆍ JsonObject 리턴을 위해 application.properties 파일에 JSON 컨버터를 gson으로 설정한다.
ㆍ 위 설정을 생략할 시 JsonObject를 리턴하면 오류가 발생하는 문제가 생긴다.
4. Controller 내 파일 업로드 로직 구현
@PostMapping(value = "/uploadSummernoteImageFile", produces = "application/json; charset=utf8") public JsonObject uploadSummernoteImageFile(@RequestParam("file") MultipartFile multipartFile, HttpServletRequest request) { JsonObject jsonObject = new JsonObject(); String fileRoot = "C:\\summernote_image\\"; // 저장될 외부 파일 경로 String originalFileName = multipartFile.getOriginalFilename(); // 오리지날 파일명 String extension = originalFileName.substring(originalFileName.lastIndexOf(".")); // 파일 확장자 String savedFileName = UUID.randomUUID() + extension; // 저장될 파일명 File targetFile = new File(fileRoot + savedFileName); try { InputStream fileStream = multipartFile.getInputStream(); FileUtils.copyInputStreamToFile(fileStream, targetFile); // 파일 저장 jsonObject.addProperty("url", "/summernoteImage/" + savedFileName); jsonObject.addProperty("responseCode", "success"); } catch (IOException e) { FileUtils.deleteQuietly(targetFile); //저장된 파일 삭제 jsonObject.addProperty("responseCode", "error"); e.printStackTrace(); e.printStackTrace(); } return jsonObject; }
ㆍ 이미지 업로드 시 호출되는 컨트롤러이다.
ㆍ 해당 컨트롤러가 호출이 되면, 고유한 URL이 생성되며, 개발자가 지정한 외부 경로에 파일이 저장된다.
ㆍ 이미지 파일이 외부 경로에 저장되면, 해당 파일의 URL이 JSON 형태로 리턴된다.
5. 외부 리소스 경로 접근 설정
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/summernoteImage/**") .addResourceLocations("file:///C:/summernote_image/"); } }
ㆍ 외부 경로에 있는 리소스를 URL로 불러올 수 있도록 설정을 해주는 코드이다.
ㆍ 예를 들어, localhost://8000/summernoteImage/1234.jpg로 접속을 하게 되면, C:/summernote_image/1234.jpg 파일을 불러온다.
6. 이미지 파일 업로드
ㆍ Summernote에 이미지 파일을 업로드하게 되면, 위 사진과 같이 고유한 URL을 통해 생성됨을 확인할 수 있다.
728x90'Projects > Problem & Solution' 카테고리의 다른 글
Sneakers Mania - 더티 체킹(Dirty Checking) (0) 2022.01.04 Sneakers Mania - @ControllerAdvice, @ExceptionHandler를 이용한 전역 예외 처리 (0) 2022.01.03 Sneakers Mania - ENUM 타입을 이용한 사용자 권한 처리 (0) 2021.12.31 Sneakers Mania - 카카오 로그인(4) (0) 2021.12.28 Sneakers Mania - 카카오 로그인(3) (0) 2021.12.27