thinkingofnickname 2025. 4. 20. 05:54
반응형

7일차

- index.html에 테스트 게시글 불러오기 

 

8일차

- 글쓰기 버튼 만들고 작성해보기 

- 글 상세보기 ( 업로드 파일 다운로드 ) 

 

9일차

- 댓글 가져오기 

<!-- 댓글 영역 -->
<h3>💬 댓글</h3>
<div id="commentSection"></div>
<script>
    const postId = [[${post.id}]];/* 게시글 id를 여기서 가져와야 함 (예: URL 파싱) */;
    console.log('postId?? ' + postId);
    const userIsAdmin = false; // 나중에 로그인 시스템 연동되면 바꿔야 함

    // 댓글 불러오기
    async function loadComments() {
      const response = await fetch(`/api/comments?postId=${postId}`);
      const comments = await response.json();

      const container = document.getElementById('commentSection');
      container.innerHTML = ''; // 초기화

      // 댓글 트리 구조로 구성
      const commentMap = {};
      comments.forEach(c => {
        commentMap[c.id] = { ...c, children: [] };
      });
      const rootComments = [];

      comments.forEach(c => {
        if (c.parentId) {
          commentMap[c.parentId].children.push(commentMap[c.id]);
        } else {
          rootComments.push(commentMap[c.id]);
        }
      });

      rootComments.forEach(c => renderComment(c, container));
    }

    // 댓글 렌더링 함수
    function renderComment(comment, container, depth = 0) {
      const div = document.createElement('div');
      div.style.marginLeft = `${depth * 20}px`; // 들여쓰기

      // const ipDisplay = userIsAdmin ? comment.ip : comment.ip.replace(/\.\d+$/, '.xxx');
      const ipDisplay = userIsAdmin  ? comment.ip || 'unknown'  : (comment.ip ? comment.ip.replace(/\.\d+$/, '.xxx') : 'unknown');
      console.log('댓글 내용:', comment);

      div.innerHTML = `
        <div style="border-bottom:1px solid #ccc; padding:5px 0;">
          <strong>${comment.writer}</strong> (${ipDisplay}) - ${new Date(comment.createdAt).toLocaleString()}<br>
          ${comment.content}
          <button onclick="showReplyForm(${comment.id})">답글</button>
          <div id="replyForm-${comment.id}"></div>
        </div>
      `;

      container.appendChild(div);

      comment.children.forEach(child => renderComment(child, container, depth + 1));
    }

    // 대댓글 입력 폼 표시
    function showReplyForm(parentId) {
      const replyDiv = document.getElementById(`replyForm-${parentId}`);
      replyDiv.innerHTML = `
        <textarea id="replyContent-${parentId}" rows="2" cols="50"></textarea><br>
        <input type="text" id="replyWriter-${parentId}" placeholder="작성자"/><br>
        <button onclick="submitReply(${parentId})">등록</button>
      `;
    }

    // 대댓글 전송
    async function submitReply(parentId) {
      const content = document.getElementById(`replyContent-${parentId}`).value;
      const writer = document.getElementById(`replyWriter-${parentId}`).value;

      await fetch('/comments', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          postId: postId,
          content: content,
          writer: writer,
          parentId: parentId
        })
      });

      loadComments(); // 다시 불러오기
    }

    // 페이지 로딩 시 실행
    window.onload = loadComments;
</script>

 

🔍 차이점 요약

문법사용 위치설명
${post.id} HTML 태그의 속성, 텍스트 등에서 사용 일반적인 표현식 (예: th:text, th:href 등)
[[${post.id}]] <script> 태그 안의 JavaScript 코드에서 사용 JS 변수에 값을 주입할 때

 


✅ 왜 [[ ]] 를 써야 하냐면?

Thymeleaf는 기본적으로 HTML을 렌더링할 때 서버에서 값을 채워주는데, JavaScript 안에서는 "자바스크립트 코드처럼 보이게" 렌더링해야 하기 때문이야!

 

🧠 꼭 기억할 것!

  • [[ ]] 는 JavaScript 안에서 타입 그대로 출력할 때 사용 (숫자는 숫자로, 문자열은 따옴표까지!)
  • th:inline="javascript" 이 있어야만 이 [[ ]] 구문이 작동함!

 


let response = await fetch("/comments?postId=1");
let comments = await response.json();
console.log("댓글:", comments);  // ✅ 이제 진짜 데이터가 들어있음!

✅ 문법        뜻                                                         한 줄 설명

await "기다려!" 비동기 작업이 끝날 때까지 기다렸다가 다음 줄 실행해!
fetch() 서버에 요청 보내기 브라우저에서 GET/POST 요청 보낼 때 사용
await fetch() 서버에 요청 보내고 응답이 올 때까지 기다려! 비동기 통신 완성판

→ await 덕분에 fetch가 완료될 때까지 기다렸다가 다음 줄 실행!

 

💡 이걸 쉽게 말하면…

🍔 햄버거집 예시

let burger = fetchBurger();       // fetch(): 햄버거 주문함
console.log("먹는다:", burger);   // ❌ 아직 안 나왔어 (Promise 상태)

let burger = await fetchBurger(); // ✅ 햄버거 나올 때까지 기다림
console.log("먹는다:", burger);   // 🍔 진짜 햄버거 먹을 수 있음

 

⛏ fetch + await는 언제 쓰냐?

  • API 서버에서 데이터를 가져오거나
  • 댓글 저장/조회, 로그인 요청 보낼 때
  • 파일 업로드, 삭제할 때 등등…

🚨 await 쓰려면?

반드시 함수 앞에 async 키워드가 있어야 돼!

async function loadComments() {
  const response = await fetch("/comments?postId=1");
  const data = await response.json();
}

 

 

- 댓글 쓰기 , 댓글 수

 

반응형