Develop

TinyMCE 에디터 사용 방법과 이미지 첨부 커스텀마이징

issuemaker99 2025. 1. 22. 17:18
728x90

TinyMCE는 강력하고 커스터마이징 가능한 WYSIWYG 에디터로, 블로그, CMS, 그리고 다양한 웹 애플리케이션에서 텍스트 편집 기능을 구현하는 데 사용됩니다. 이 글에서는 TinyMCE를 설정하는 방법과 이미지 첨부 기능을 커스터마이징하는 방법을 예제로 자세히 설명합니다.


1. TinyMCE 기본 설치 및 설정

TinyMCE를 사용하려면 다음 단계를 따라 설정합니다.

1.1. 설치

TinyMCE는 CDN 또는 npm을 통해 설치할 수 있습니다.

CDN 사용:

<script src="https://cdn.tiny.cloud/1/your-api-key/tinymce/6/tinymce.min.js" referrerpolicy="origin"></script>

 

npm 사용:

npm install tinymce

 

1.2. 기본 초기화

TinyMCE를 적용할 HTML 요소를 설정합니다. 아래는 textarea를 에디터로 변환하는 기본 예제입니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdn.tiny.cloud/1/your-api-key/tinymce/6/tinymce.min.js" referrerpolicy="origin"></script>
    <title>TinyMCE Example</title>
</head>
<body>
    <h1>TinyMCE 에디터</h1>
    <textarea id="editor"></textarea>

    <script>
        tinymce.init({
            selector: '#editor', // 에디터를 적용할 요소 선택자
            height: 500,
            menubar: false, // 메뉴바 숨김
            plugins: [
                'advlist autolink lists link image charmap preview anchor',
                'searchreplace visualblocks code fullscreen',
                'insertdatetime media table paste code help wordcount'
            ],
            toolbar: 'undo redo | formatselect | bold italic backcolor | \
                      alignleft aligncenter alignright alignjustify | \
                      bullist numlist outdent indent | removeformat | help',
        });
    </script>
</body>
</html>

 


2. 이미지 첨부 기능 추가 및 커스텀마이징

TinyMCE는 기본적으로 이미지를 업로드하거나 URL로 삽입할 수 있는 기능을 제공합니다. 이를 더 발전시키려면 이미지 업로드와 관리 기능을 커스터마이징할 수 있습니다.

2.1. 이미지 업로드 기능 활성화

TinyMCE는 기본적으로 파일 업로드 기능을 제공합니다. 아래 설정을 통해 활성화할 수 있습니다.

tinymce.init({
    selector: '#editor',
    plugins: 'image',
    toolbar: 'insertfile image link',
    image_title: true,
    automatic_uploads: true,
    file_picker_types: 'image',
    file_picker_callback: function (callback, value, meta) {
        if (meta.filetype === 'image') {
            const input = document.createElement('input');
            input.setAttribute('type', 'file');
            input.setAttribute('accept', 'image/*');

            input.onchange = function () {
                const file = this.files[0];
                const reader = new FileReader();
                reader.onload = function () {
                    callback(reader.result, { alt: file.name });
                };
                reader.readAsDataURL(file);
            };

            input.click();
        }
    },
});

 

이 코드는 이미지 버튼을 클릭했을 때 파일 선택 창을 띄우고, 선택한 이미지를 Base64 형식으로 에디터에 삽입합니다.


2.2. 서버로 이미지 업로드

이미지를 Base64로 저장하는 대신 서버로 업로드하려면, 아래와 같이 API 호출을 추가합니다.

tinymce.init({
    selector: '#editor',
    plugins: 'image',
    toolbar: 'insertfile image link',
    image_title: true,
    automatic_uploads: true,
    images_upload_url: '/upload-image', // 서버 업로드 엔드포인트
    images_upload_handler: function (blobInfo, success, failure) {
        const formData = new FormData();
        formData.append('file', blobInfo.blob(), blobInfo.filename());

        fetch('/upload-image', {
            method: 'POST',
            body: formData,
        })
        .then(response => response.json())
        .then(data => {
            if (data && data.location) {
                success(data.location); // 업로드된 이미지 URL 반환
            } else {
                failure('이미지 업로드 실패');
            }
        })
        .catch(() => {
            failure('네트워크 오류');
        });
    },
});

 


2.3. 이미지 첨부 UI 커스터마이징

TinyMCE의 파일 선택기를 직접 변경하거나 추가적인 UI를 구현할 수 있습니다.

file_picker_callback: function (callback, value, meta) {
    if (meta.filetype === 'image') {
        const input = document.createElement('input');
        input.setAttribute('type', 'file');
        input.setAttribute('accept', 'image/*');

        input.onchange = function () {
            const file = this.files[0];
            const formData = new FormData();
            formData.append('file', file);

            fetch('/upload-image', {
                method: 'POST',
                body: formData,
            })
            .then(response => response.json())
            .then(data => {
                if (data && data.location) {
                    callback(data.location, { alt: file.name });
                } else {
                    alert('이미지 업로드 실패');
                }
            })
            .catch(() => {
                alert('네트워크 오류');
            });
        };

        input.click();
    }
},
LIST