• [Next] Next.js에 React-Quill 에디터 이미지 처리하기

    2023. 9. 26.

    by. 지은이: 김지은

    728x90

    이전 글

    이제 이미지를 서버에 저장 후 URL을 가져올 건데 부하를 분산시키기 위해서 S3에 직접 요청하지 않고 CloudFront에 배포 후 연결하려고 한다.

     

    import AWS from 'aws-sdk';
    
    AWS.config.update({
        region: process.env.NEXT_PUBLIC_S3_REGION,
        accessKeyId: process.env.NEXT_PUBLIC_S3_ACCESS_ID,
        secretAccessKey: process.env.NEXT_PUBLIC_S3_ACCESS_KEY,
    });
    
    const cloudFront_url = process.env.NEXT_PUBLIC_CLOUD_FRONT_URL;

    npm i aws-sdk 라이브러리를 설치해주고 불러오기

    S3 region, Accescc id, Access key, cloudfront url을 환경변수 설정해주기

     

    const modules = useMemo(
            () => ({
                toolbar: {
                    ...
                    handlers: {
                        image: imageHandler,
                    },
                },
            }),
            []
        );

    이미지 처리를 하기 위해 핸들러함수를 추가해주고 useMemo를 해준 이유는 이미지를 삽입할 때 마다 modules가 리렌더링 되기 때문에 

    막아주기. 그리고 핸들러 함수는 반드시 modules 위에 작성해줘야한다.

     

    const imageHandler = async () => {
    	// input 동적 생성
            const input = document.createElement("input");
            input.setAttribute("type", "file");
            input.setAttribute("accept", "image/*");
            input.click();
    		
            //change 이벤트 발생 시 
            input.addEventListener("change", async () => {
                const file = input.files?.[0];
                const fileName = file?.name; // 파일 이름 사용
                
                // AWS S3 업로드
                try {
                    if (quillRef.current) {
                        const upload = new AWS.S3.ManagedUpload({
                            params: {
                                ACL: "public-read",
                                Bucket: "버킷 명",
                                Key: `upload/${fileName}`,
                                Body: file,
                            },
                        })
                        // 업로드 완료 시 업로드 된 이미지 S3 키 얻어오기
                        const url_key = await upload.promise().then((res) => res.Key);
    
                        // Quill 에디터에서 현재 커서 위치 (range) 가져와서 커서 위치에 이미지 삽입
                        const range = quillRef.current?.getEditor().getSelection()?.index;
                        if (range !== null && range !== undefined) {
                            let quill = quillRef.current?.getEditor();
                            quill?.setSelection(range, 1);
                            quill?.clipboard.dangerouslyPasteHTML(
                                range,
                                `<img src="${cloudFront_url}/${url_key}" alt="image" />`
    
                            );
                        }
                    }
                } catch (err) {
                    console.log(err)
                }
            })
        }

     

     

    하지만 Quill 에디터를 dynamic으로 가져왔기 때문에 직접 ref를 사용하려고 하면 에러가 난다.

    그래서 위에 컴포넌트를 감싸서 에디터 컴포넌트를 dynamic으로 가져오도록 아래처럼 코드를 작성하고

    Quill 에디터에 useRef를 사용하도록 한다.

    // 상위 컴포넌트
    import dynamic from 'next/dynamic';
    
    const Editor = dynamic(() => import('../textEditor/TextEditor'), { ssr: false });

     

    // 에디터 컴포넌트 
    import ReactQuill from 'react-quill';
    
    const Component = (() => {
        const quillRef = useRef<ReactQuill>(null);
        ...
        
    return (
            <div className={styles.container}>
                <ReactQuill ref={quillRef} theme="snow" value={value} onChange={setValue} modules={modules} />
            </div >
    )

     

     

     

    참고: https://velog.io/@stakbucks/React-Quill-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%B2%98%EB%A6%AC%ED%95%98%EA%B8%B0-2

    댓글