티스토리 뷰

 

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>공지사항 상세보기</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <style>
        :root { --primary-color: #007bff; --border-color: #dee2e6; }
        body { font-family: 'Pretendard', sans-serif; background: #f8f9fa; padding: 20px; color: #333; }
        .container { max-width: 900px; margin: 0 auto; background: #fff; padding: 40px; border-radius: 12px; box-shadow: 0 4px 15px rgba(0,0,0,0.05); }

        /* 상세보기 헤더 영역 */
        .view-header { border-bottom: 2px solid #333; padding-bottom: 20px; margin-bottom: 30px; }
        .category { color: var(--primary-color); font-weight: bold; font-size: 14px; margin-bottom: 10px; display: block; }
        .title { font-size: 28px; margin: 0 0 15px 0; line-height: 1.4; }
        .meta-info { display: flex; gap: 20px; color: #888; font-size: 14px; border-top: 1px solid #f1f3f5; padding-top: 15px; }
        .meta-info span b { color: #333; margin-right: 5px; }

        /* 본문 영역 */
        .view-content { min-height: 350px; line-height: 1.8; font-size: 16px; color: #444; white-space: pre-wrap; padding: 10px 0; }

        /* 하단 버튼 영역 */
        .view-footer { margin-top: 50px; padding-top: 25px; border-top: 1px solid var(--border-color); display: flex; justify-content: space-between; align-items: center; }
        .btn { padding: 10px 20px; border: none; border-radius: 6px; cursor: pointer; font-weight: 600; font-size: 14px; text-decoration: none; display: inline-block; }
        .btn-list { background: #6c757d; color: white; }
        .btn-edit { background: var(--primary-color); color: white; margin-right: 5px; }
        .btn-delete { background: #dc3545; color: white; }

        /* 에러 메시지 */
        #error-msg { display: none; text-align: center; padding: 50px; color: #dc3545; }
    </style>
</head>
<body>

<div class="container">
    <div id="content-area" style="display:none;">
        <div class="view-header">
            <span class="category">NOTICE</span>
            <h1 class="title" id="det-title">제목을 불러오는 중입니다...</h1>
            <div class="meta-info">
                <span><b>작성자</b> <span id="det-author">-</span></span>
                <span><b>작성일</b> <span id="det-date">-</span></span>
                <span><b>조회수</b> <span id="det-views">0</span></span>
            </div>
        </div>

        <div class="view-content" id="det-content">
            내용을 불러오는 중입니다...
        </div>

        <div class="view-footer">
            <a href="list.html" class="btn btn-list">목록으로</a>
            <div class="admin-area">
                <button class="btn btn-edit" onclick="alert('수정 페이지로 이동합니다.')">수정</button>
                <button class="btn btn-delete" onclick="confirmDelete()">삭제</button>
            </div>
        </div>
    </div>

    <div id="error-msg">
        <h3>존재하지 않는 게시글입니다.</h3>
        <p>삭제되었거나 잘못된 접근입니다.</p>
        <br>
        <a href="list.html" class="btn btn-list">목록으로 돌아가기</a>
    </div>
</div>

<script>
$(document).ready(function() {
    // 1. URL 파라미터에서 ID 추출 (예: view.html?id=3)
    const urlParams = new URLSearchParams(window.location.search);
    const postId = urlParams.get('id');

    // 2. 가상의 JSON 데이터 (실제로는 $.getJSON("api/notice/" + postId, ...)로 호출)
    const mockNoticeData = [
        { id: "1", title: "2026년 설 연휴 고객센터 휴무 안내", author: "관리자", date: "2026-01-20", views: 452, content: "안녕하세요. 관리자입니다.\n\n2026년 설 연휴 기간 동안 고객센터 업무가 일시 중단됩니다.\n급한 용무는 이메일로 남겨주시기 바랍니다.\n\n새해 복 많이 받으세요!" },
        { id: "2", title: "시스템 점검에 따른 서비스 일시 중단 안내", author: "IT팀", date: "2026-01-22", views: 120, content: "안정적인 서비스 제공을 위해 서버 점검을 실시합니다.\n\n점검 시간: 2026년 1월 25일 새벽 02:00 ~ 04:00 (2시간)\n해당 시간에는 접속이 원활하지 않을 수 있습니다." }
    ];

    // 3. 데이터 로드 및 바인딩 함수
    function loadDetail() {
        if (!postId) {
            showError();
            return;
        }

        // 실제 환경에서는 AJAX 통신을 사용합니다.
        // $.getJSON('notice_data.json', function(data) { ... });
        
        // 여기서는 샘플 데이터에서 ID가 일치하는 것을 찾습니다.
        const post = mockNoticeData.find(item => item.id === postId);

        if (post) {
            $('#det-title').text(post.title);
            $('#det-author').text(post.author);
            $('#det-date').text(post.date);
            $('#det-views').text(post.views);
            $('#det-content').text(post.content); // \n을 줄바꿈으로 인식하도록 pre-wrap 스타일 적용됨
            
            $('#content-area').fadeIn(300);
            $('#error-msg').hide();
        } else {
            showError();
        }
    }

    function showError() {
        $('#content-area').hide();
        $('#error-msg').show();
    }

    window.confirmDelete = function() {
        if (confirm("정말로 이 게시글을 삭제하시겠습니까?")) {
            alert("게시글이 삭제되었습니다.");
            location.href = "list.html";
        }
    }

    // 실행
    loadDetail();
});
</script>

</body>
</html>

 

JSON 연동 공지사항 상세보기 (HTML_JS).html
0.01MB

 

💡 주요 구현 설명

  1. URL 파라미터 연동: URLSearchParams를 사용하여 사용자가 어떤 게시물을 클릭하고 들어왔는지 ID 값을 읽어옵니다. (예: view.html?id=1)
  2. 데이터 바인딩: JSON 데이터 배열에서 해당 ID를 가진 객체를 찾은 뒤, $('#det-title').text(...)와 같은 방식으로 HTML 요소에 값을 주입합니다.
  3. 줄바꿈 처리 (white-space: pre-wrap): JSON 데이터의 텍스트 안에 있는 \n(엔터)이 화면에서 실제 줄바꿈으로 보이도록 CSS 설정을 추가했습니다. 별도의 에디터를 쓰지 않는 일반 텍스트 기반 게시판에서 필수적인 설정입니다.
  4. 예외 처리: 만약 잘못된 ID로 접속하거나 데이터가 없는 경우를 대비해 error-msg 영역을 만들어 사용자 경험을 개선했습니다.
  5. 페이드인 효과: 데이터가 모두 바인딩된 후 화면에 부드럽게 나타나도록 fadeIn()을 적용하여 시각적 완성도를 높였습니다.

이 코드를 활용하여 이전의 목록(List) 코드에서 각 제목에 <a href="view.html?id=${item.id}"> 링크를 걸어주시면 완벽하게 작동하는 게시판 시스템이 됩니다! 😊

 

※ 해당 내용은 Google Gmini3.0에서 작성되었습니다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함