관련 포스팅
2024.06.16 - [React] - [React] 웹 에디터 React-Quill 사용하기 (1)
이전 글에서 React-Quill에 대한 전반적인 사용법을 알아보고 구현해 보았다.
이번엔 이미지 적용에 대해 상세하게 구현해보고자 한다.
글을 작성할 때 이미지를 함께 사용하면 <img> html 태그로 생성이 되고 저장이 될 것이다. 그러나 이렇게 작성한 글을 DB에 저장하고 불러오면 이미지는 보이지 않을 것이다. DB에 들어간 이미지 경로는 존재하지 않기 때문이다.
그래서 이미지를 사용한 글 작성을 할 땐 이미지를 이미지 서버에 저장을 하고 경로를 설정해 주어야 나중에 불러올 때 정상적으로 나타날 것이다.
여기에 필요한 Handler와 기능들을 구현해보겠다.
1. 이미지 Handler 구현하기
우선 React-Quill에 있는 이미지 추가 버튼을 눌렀을 때 동작할 Handler를 생성해 주고 지정해 주자
아래와 같이 Handler를 만들어주고 module에서 해당 Handler를 추가하여 지정해 주면 된다.
그러면 해당 Handler가 동작되어 Quill에 추가한 이미지의 정보를 얻어낼 수 있다.
// reactEditor.tsx
...
const changeImageHandler = ():void => {
const input:HTMLInputElement = document.createElement("input");
input.setAttribute("type", "file");
input.setAttribute("accept", "image/jpg,image/png,image/jpeg");
input.setAttribute("multiple", "multiple");
input.click();
}
...
const modules:{} = useMemo(() => ({
toolbar: {
container: "#toolBar",
handlers: {
image: changeImageHandler
}
},
}), []);
...
이 상태로 이미지를 추가하면 이미지를 선택하는 화면은 동작하지만 Quill에는 추가되지 않을 것이다.
그렇기에 input.onChange를 통해 추가한 이미지를 이미지 서버에 올리고 업로드된 이미지 주소를 가져와 출력해 주면 된다. 우선 이미지 서버를 이용하기 전 FileReader를 사용해서 미리 보기를 구현해 보겠다.
// reactEditor.tsx
...
const changeImageHandler = ():void => {
const input:HTMLInputElement = document.createElement("input");
input.setAttribute("type", "file");
input.setAttribute("accept", "image/jpg,image/png,image/jpeg");
input.setAttribute("multiple", "multiple");
input.click();
input.onchange = async ():Promise<void> => { // onChange 추가
let file:FileList|null = input.files;
const editor:any = quillRef.current.getEditor();
const range:any = editor.getSelection();
if(file !== null) {
const reader = new FileReader();
for(let i:number=0; i<file.length; i++) {
reader.readAsDataURL(file[0]);
reader.onloadend = () => {
editor.insertEmbed(range.index, 'image', reader.result);
editor.setSelection(range.index + 1);
};
}
}
}
}
...
const modules:{} = useMemo(() => ({
toolbar: {
container: "#toolBar",
handlers: {
image: changeImageHandler
}
},
}), []);
...
우선 useRef를 사용하여 Quill의 정보를 가져와서 이곳에 input 사용하여 추가한 이미지를 넣어준다.
아래 사진처럼 잘 동작하는 걸 확인할 수 있다.
FileReader를 통해 미리 보기 형태로 출력이 되기에 html 태그가 적용되기 전 내용을 확인을 해보면 src에 base64 형태로 입력이 된다.
아직 확인은 안 해봤지만 base64 형태로 DB에 넣고 사용하면 이미지 출력은 아마 될 것이다.
하지만 어떤 이미지인지 특정할 수도 없고 무엇보다 base64 String 값이 너무 길기에 저장하고 사용하기엔 별로다.
그러니 따로 이미지 서버를 이용해서 구현을 하는 게 나중에 사용하기에도 구별하기에도 좀 더 좋을 것이다.
2. 서버로 이미지 전달
onChange에서 추가한 FileList을 사용해서 formData에 file을 넣어 서버로 전달을 해보겠다.
// reactEditor.tsx
...
const changeImageHandler = ():void => {
const input:HTMLInputElement = document.createElement("input");
input.setAttribute("type", "file");
input.setAttribute("accept", "image/jpg,image/png,image/jpeg");
input.setAttribute("multiple", "multiple");
input.click();
input.onchange = async ():Promise<void> => { // onChange 추가
let file:FileList|null = input.files;
const editor:any = quillRef.current.getEditor();
const range:any = editor.getSelection();
if(file !== null) {
const reader = new FileReader();
for(let i:number=0; i<file.length; i++) {
reader.readAsDataURL(file[0]);
reader.onloadend = () => {
editor.insertEmbed(range.index, 'image', reader.result);
editor.setSelection(range.index + 1);
};
// formData 추가
const formData:FormData = new FormData();
formData.append('files', file[i]);
await axios({
method: "POST",
url: "/board/boardUploadImage",
data: formData,
headers: { 'Content-Type': 'multipart/form-data' }
}).then((res):void => {
}).catch((err):void => {
console.log(err.message);
})
}
}
}
}
...
const modules:{} = useMemo(() => ({
toolbar: {
container: "#toolBar",
handlers: {
image: changeImageHandler
}
},
}), []);
...
위와 같이 append를 통해 formData에 file을 추가하고 axios를 작성해 준다.
그리고 컨트롤러는 아래와 같이 작성해 주고 사용해 주면 된다.
@RequiredArgsConstructor
@RestController
@RequestMapping("/board")
public class BoardController {
@PostMapping("/boardUploadImage")
public String boardUploadImage(@RequestPart("files") MultipartFile multipartFile) {
return "Upload Success";
}
}
추후엔 S3를 사용해서 이미지 서버를 구현하고 적용하여 이미지를 사용해 보겠다.
'JavaScript > React' 카테고리의 다른 글
[React] 리뷰 별점 기능 구현하기 (0) | 2024.07.17 |
---|---|
[React] 웹 에디터 React-Quill 사용하기 (1) (0) | 2024.06.16 |
[React] CORS 오류 해결하기 (1) | 2024.06.10 |
[React] Swiper 사용하기 (0) | 2024.05.22 |
[React] Jotai로 상태 전역으로 관리하기 (2) | 2024.04.28 |