댓글 시스템 만들기 3편 블로그에 댓글창 커스터마이징 방법

댓글 시스템 만들기 3편 블로그에 댓글창 커스터마이징 방법

이번 글에서는 블로그 댓글창 커스터마이징, 자바스크립트 댓글 시스템 구축, Supabase 댓글 연동, 광고 진단 스크립트 삽입, 블로그 UX 개선까지 한 번에 해결하는 방법을 정리했습니다. 특히 플러그인에 의존하지 않고 내 코드로 직접 댓글 시스템을 만드는 방법이라서, SEO와 속도, 디자인 자유도까지 모두 챙길 수 있습니다.

오늘 작업의 핵심: ‘자체 댓글 대신 ‘내 코드’

블로그의 기본 댓글창은 디자인 수정이 어렵고, 매크로 공격이나 보안 문제에 취약할 수 있습니다. 우리가 직접 만드는 댓글 시스템은 디자인을 원하는 대로 꾸밀 수 있고, 데이터도 안전하게 관리할 수 있으며, 무엇보다 내 입맛에 맞게 자유롭게 수정할 수 있다는 강력한 장점이 있습니다.

1. 댓글창 위치 지정용 HTML 코드

먼저 댓글을 적용할 블로그(사이트) 글 본문 하단(또는 원하는 위치)에 아래 한 줄만 딱 넣어주면 됩니다.

<div id="comm"></div>

1. 이 코드는 무엇인가요?<div> 태그는 일종의 ‘빈 바구니’입니다. 우리가 작성한 자바스크립트 코드가 id="comm"이라는 이름을 가진 바구니를 찾아서, 그 안에 댓글창 레이아웃과 댓글 목록을 채워넣게 됩니다.

2. 어디에 넣어야 하나요?

방법 B (직접 입력): 글을 쓸 때 HTML 모드로 들어가서 맨 아랫부분에 이 코드를 직접 붙여넣어도 되고, 고정으로 사용할 경우에는 스킨 편집을 통해 본문 하단 또는 원하는 위치에 적용하면 됩니다.

자체-댓글시스템-솔루션

3. 티스토리에 적용하는 방법

  1. 티스토리 [관리자 페이지]에 접속합니다.
  2. 왼쪽 메뉴에서 [꾸미기] > [스킨 편집]을 클릭하세요.
  3. 오른쪽 상단의 [html 편집] 버튼을 누릅니다.
  4. HTML 코드 창에서 가장 아래쪽으로 내려가 </body> 태그 바로 위에 아래 코드를 통째로 붙여넣으세요.
  5. [적용] 버튼을 누르면 끝!

나만의 댓글 시스템 최종 코드


<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js"></script>
<script>
    const SUPABASE_URL = ' 주소입력';
    const SUPABASE_KEY = 'sb_publishable_012455555I';

    const client = supabase.createClient(SUPABASE_URL, SUPABASE_KEY);

    function initCommentLayout() {
        const commContainer = document.getElementById('comm');
        if (!commContainer) return;

        const layoutHtml = `
            <div id="supabase-comment-box" style="border: 1px solid #edf2f7; padding: clamp(15px, 5%, 30px); border-radius: 16px; background-color: #ffffff; max-width: 800px; margin: 40px auto; font-family: 'Pretendard', sans-serif; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);">
                <div style="display: flex; align-items: center; gap: 10px; margin-bottom: 25px; border-bottom: 2px solid #3ecf8e; padding-bottom: 15px;">
                    <h2 style="margin: 0; color: #1a202c; font-size: 1.5rem; font-weight: 800;">댓글</h2>
                    <span style="background: #e6fffa; color: #234e52; padding: 2px 8px; border-radius: 12px; font-size: 0.75rem; font-weight: 600;">Comments</span>
                </div>
                
                <div id="comment-list-area" style="margin-bottom: 30px; min-height: 20px;"></div>

                <div style="background: #f7fafc; padding: clamp(15px, 4%, 20px); border-radius: 12px; border: 1px solid #e2e8f0;">
                    <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 12px;">
                        <div>
                            <label style="display: block; font-size: 0.875rem; font-weight: 600; color: #4a5568; margin-bottom: 5px;">닉네임 *</label>
                            <input type="text" id="author-name" placeholder="이름 입력" style="width: 100%; padding: 12px; border: 1.5px solid #e2e8f0; border-radius: 8px; font-size: 14px; box-sizing: border-box; outline: none;">
                        </div>
                        <div>
                            <label style="display: block; font-size: 0.875rem; font-weight: 600; color: #4a5568; margin-bottom: 5px;">링크 (선택)</label>
                            <input type="url" id="author-link" placeholder="https://..." style="width: 100%; padding: 12px; border: 1.5px solid #e2e8f0; border-radius: 8px; font-size: 14px; box-sizing: border-box; outline: none;">
                        </div>
                    </div>
                    <div style="margin-bottom: 15px;">
                        <label style="display: block; font-size: 0.875rem; font-weight: 600; color: #4a5568; margin-bottom: 5px;">내용 *</label>
                        <textarea id="comment-text" placeholder="메시지를 입력하세요" style="width: 100%; height: 100px; padding: 12px; border: 1.5px solid #e2e8f0; border-radius: 8px; font-size: 15px; box-sizing: border-box; resize: none; outline: none;"></textarea>
                    </div>
                    <button id="submit-btn" style="width: 100%; background-color: #097c4a; color: #ffffff; border: none; padding: 14px; border-radius: 8px; cursor: pointer; font-weight: 700; font-size: 16px;">등록</button>
                </div>
            </div>`;

        commContainer.innerHTML = layoutHtml;
        document.getElementById('submit-btn').onclick = saveToSupa;
        getComments();
    }

    async function getComments() {
        const { data, error } = await client
            .from('blog_comments')
            .select('*')
            .eq('page_url', window.location.href)
            .order('created_at', { ascending: false });

        const listArea = document.getElementById('comment-list-area');
        if (!listArea) return;

        if (data && data.length > 0) {
            listArea.innerHTML = data.map(c => {
                // 링크가 있으면 이름에 링크를 걸어줌
                const nameTag = c.author_link 
                    ? `<a href="${c.author_link}" target="_blank" style="color: #097c4a; text-decoration: underline;">${c.name}</a>` 
                    : `<span style="color: #1a202c;">${c.name}</span>`;

                return `
                    <div style="margin-bottom: 20px; padding: 18px; background: #fff; border: 1px solid #f0f0f0; border-radius: 12px;">
                        <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
                            <strong style="font-size: 15px; font-weight: 700;">${nameTag}</strong>
                            <span style="color: #a0aec0; font-size: 12px;">${new Date(c.created_at).toLocaleString()}</span>
                        </div>
                        <p style="margin: 0; color: #2d3748; font-size: 15px; line-height: 1.6;">${c.content}</p>
                    </div>`;
            }).join('');
        } else {
            listArea.innerHTML = '';
        }
    }

    async function saveToSupa() {
        const nameVal = document.getElementById('author-name').value.trim();
        const linkVal = document.getElementById('author-link').value.trim();
        const bodyVal = document.getElementById('comment-text').value.trim();

        if (!nameVal || !bodyVal) {
            alert('이름과 내용을 모두 입력해 주세요.');
            return;
        }

        const { error } = await client
            .from('blog_comments')
            .insert([{ 
                name: nameVal, 
                author_link: linkVal, // 사용자가 입력한 링크 저장
                content: bodyVal, 
                page_url: window.location.href 
            }]);

        if (error) {
            alert('오류 발생: ' + error.message);
        } else {
            document.getElementById('author-name').value = '';
            document.getElementById('author-link').value = '';
            document.getElementById('comment-text').value = '';
            getComments();
        }
    }

    window.onload = initCommentLayout;
</script>

이제 블로그 하단에는 방문자들과 대화할 수 있는 깔끔한 댓글창과, 상태를 체크해주는 똑똑한 진단 도구가 자리 잡았습니다.

댓글 남기기