선언적 렌더링(Declarative Rendering)방식으로 시작하기
요약선언적 렌더링은 Vue.js를 이용해 프론트엔드를 간단히 구성하는 방법입니다.빠른 프로토타입 제작에 유용하며, 학습 및 테스트 환경에서 적합합니다.H:Dev+ 샘플 코드를 활용하여 직접 구현하고 실행해볼 수 있습니다. 선언적 렌더링(Declarative Rendering) '선언적 렌더링(Declarative Rendering)'은 HTML에 출력될 요소를 직접 선언하는 방식입니다. Vue.js 공식 문서에서는 아래와 같은 방식을 선언적 렌더링으로 설명하고 있습니다. JS 예제 코드 import { createApp } from 'vue' createApp({ data() { return { count: 0 } } }).mount('#app') Template<div id="app"> <button @click="count++"> Count is: {{ count }} </button> </div> H:Dev+와 선언적 렌더링 H:Dev+**를 가장 빠르게 경험할 수 있는 방법은 선언적 렌더링 방식을 이용해 프론트엔드를 구현하는 것입니다. 선언적 렌더링의 활용 대상 Vue.js로 프론트엔드 개발을 학습하는 사용자 빠른 프로토타입을 구현하려는 중소기업 또는 에이전시 주의사항 선언적 렌더링 방식은 보안적 위험(예: SECORE_KEY 노출) 및 기능 제한이 있을 수 있으므로 프로덕션 환경에서는 권장되지 않습니다.그러나, 빠른 프로토타입 제작에는 매우 유용합니다. H:Dev+ 콘솔에서 SECORE_KEY를 재 설정 할 수 있습니다.. 샘플 코드 Git Repository git clone https://github.com/zmania/HDevPlus-example.git 디렉터리 구조 nuxt3 php spring-boot vue-dr vue vue-dr 디렉터리에는 선언적 렌더링 방식으로 작성된 Vue.js 코드가 포함되어 있습니다. 실행 방법vue-dr 디렉터리의 index.html 파일을 크롬 또는 엣지 브라우저에서 열면 실제로 H:Dev+와 연동된 페이지를 확인할 수 있습니다. 선언적 렌더링 샘플 코드HTML 페이지 상단에 데이터를 요청하는 스크립트(<!--Request Data -->영역)를 정의하고, 페이지 내부에서 Vue.js의 데이터 바인딩 기능을 사용하여 데이터를 출력합니다. 코드 예시 <!doctype html> <html lang="en" data-bs-theme="auto"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors"> <meta name="generator" content="Hugo 0.111.3"> <title>H:Dev+ Sample Code</title> <!-- BOOTSTRAP OPTIONAL --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous"> <!-- REQUEST DATA --> <script> const requestData = {'dataID': 'GET_POST_LIST', 'list_per_page': 2, 'page_link_url':'list.html','search_keyword': new URLSearchParams(window.location.search).get('search_keyword'), 'page': new URLSearchParams(window.location.search).get('page') ? new URLSearchParams(window.location.search).get('page') : 1}; </script> <style> [v-cloak] { display: none; } </style> </head> <body> <div id="app" v-cloak> <gnb-comp :output="output"></gnb-comp> <div class="container"> <main> <div class="row g-5"> <div class="col-12"> <div class="text-center"> <h2 class="mt-5 mb-3">게시물 목록</h2> </div> <div class="py-2 d-flex justify-content-between align-items-center"> <small class="smaller text-black"> Result {{output.pagination.total_result_num}} post / total {{output.total_post_count}} post </small> <a :href="output.user.auth_flg ? './add.html' : '../member/login.html'" class="btn btn-sm btn-dark d-flex justify-content-between align-items-center lh-1"><small class="smaller">ADD</small></a> </div> <div id="post_list" data-load-type="vue-pagination" class="row h-post-list"> <div class="col-12 my-3" v-if="output.post_list.length>0" v-for="post in output.post_list"> <div class="card h-100"> <div class="card-body"> <div class="d-flex justify-content-between align-items-center"> <small>{{post.reg_name}}</small><small>{{post.create_date}}</small> </div> <hr/> <h1 class="fs-3 card-title py-3"><a :href="'./view.html?post_key='+post.post_key" v-html="post.subject"></a></h1> <p class="card-text" v-html="post.content"></p> </div> </div> </div> <div class="col-12" v-else> <div class="my-2 d-flex justify-content-center align-items-center alert alert-light"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bell" viewBox="0 0 16 16"> <path d="M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2zM8 1.918l-.797.161A4.002 4.002 0 0 0 4 6c0 .628-.134 2.197-.459 3.742-.16.767-.376 1.566-.663 2.258h10.244c-.287-.692-.502-1.49-.663-2.258C12.134 8.197 12 6.628 12 6a4.002 4.002 0 0 0-3.203-3.92L8 1.917zM14.22 12c.223.447.481.801.78 1H1c.299-.199.557-.553.78-1C2.68 10.2 3 6.88 3 6c0-2.42 1.72-4.44 4.005-4.901a1 1 0 1 1 1.99 0A5.002 5.002 0 0 1 13 6c0 .88.32 4.2 1.22 6z"/> </svg> <span class="ms-2">게시물이 없습니다.</span> </div> </div> </div> </div> </div> </main> <bottom :output="output"></bottom> </div> </div> <!-- JQUERY REQUIRED --> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.form/4.3.0/jquery.form.min.js"></script> <!-- VUE --> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.47/vue.global.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/4.1.6/vue-router.global.js"></script> <!-- BOOTSTRAP OPTIONAL --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script> <!-- CONNECTOR --> <script src="../_connector/yellow.501.js"></script> <script src="../components/gnb.js"></script> <script src="../components/bottom.js"></script> </body> </html> 명령형 렌더링(Imperative Rendering)위에서 작성한 선언적 렌더링 방식은 이후 명령형 렌더링 방식으로 확장해도 활용이 용이합니다. 명령형 렌더링의 예제는 vue 디렉터리에서 확인할 수 있습니다.
페이지 내 위젯을 통해 특정 게시물 노출하기
사이트 내 특정 페이지에서 새로 등록된 게시글, 좋아요 수가 많은 게시글 등 특정 조건에 맞는 게시물을 노출하려면, 관리 콘솔에서 해당 조건에 맞는 위젯(Widget)을 생성한 뒤 원하는 페이지에 적용할 수 있습니다.콘솔에서 위젯 생성하기다음 절차에 따라 위젯을 생성할 수 있습니다:H:Dev+에 로그인한 후 콘솔로 이동합니다.콘솔 화면의 왼쪽 메뉴에서 Widget > Widget Management로 이동합니다.위젯 목록 상단의 Add 버튼을 클릭하여 새 위젯의 정보를 입력합니다.위젯 정보를 입력한 뒤 Save 버튼을 클릭하면 위젯이 생성됩니다.위젯 입력 정보1. 위젯 이름위젯 목록에서 쉽게 구분할 수 있는 이름을 입력합니다.2. 위젯 코드프론트엔드에서 위젯 호출 시 사용할 고유 코드입니다.숫자, 알파벳, 언더바(_)로 구성최대 20자 이하로 설정 가능3. 위젯 설명해당 위젯의 특징이나 사용 목적을 간략히 적습니다.4. 위젯 구분노출할 게시물 유형을 지정합니다:사용자 지정 게시물: 특정 게시물을 수동으로 지정등록 일자 순 게시물: 최신 순으로 게시물 노출일간 조회 비율 순: 조회수/등록일 기준으로 일간 조회 수가 높은 게시물 순서로 노출좋아요 순 게시물: 좋아요 수가 많은 게시물 순으로 노출5. 위젯 아이템 수노출할 게시물(아이템)의 수를 지정합니다.6. 게시판특정 게시판의 게시물만 노출하고 싶다면 해당 게시판을 지정합니다. 지정하지 않을 경우, 모든 게시판의 게시물이 대상이 됩니다.7. 위젯 아이템 정렬노출될 게시물의 정렬 기준을 설정합니다.프론트엔드에서 위젯 사용하기페이지에 위젯을 노출하려면 프론트엔드에서 해당 페이지의 DataID에 위젯 항목을 추가해야 합니다.예를 들어, most_view_post와 new_post 두 개의 위젯을 노출하려면 아래와 같이 정의합니다:{ "dataID": "GET_POST", "widget": ["most_view_post", "new_post"] } dataID는 노출하려는 페이지에 따라 변경할 수 있습니다. 위와 같이 Request Data를 지정하면, 프론트엔드에서 해당 위젯들이 정상적으로 노출됩니다.추가 참고 자료위젯 관련 Request/Response 정보 및 상세 설정 방법은 공식 문서 에서 확인하실 수 있습니다.
Nuxt3 Service Side Rendering 환경으로 프론트앤드 개발 시작하기
이 문서는 샘플 코드를 활용하여 Nuxt3 기반의 SSR(Server Side Rendering) 방식 프론트엔드 개발을 시작하는 방법을 안내합니다. 내용은 크게 개발 환경 구성하기와 샘플 코드 구현하기 두 부분으로 나뉘어 있습니다.'H:Dev+'와 직접적으로 관련되지 않은 Nuxt3나 Node.js 등의 기술적인 내용에 대해서는 각 공식 사이트 문서를 참고할 수 있도록 링크를 제공합니다.개발 환경 구성하기H:Dev+를 이용한 프론트엔드 개발 환경을 구성하기 위해서는 Node.js와 Nuxt3가 필요합니다.Node.js 설치Node.js는 Node.js 공식 사이트 의 다운로드 페이지에서 개발 환경에 맞게 설치할 수 있습니다.본 예시에서는 Docker를 사용하였으며, Linux(WLS2 기반의 Windows) 환경에 Node.js v22.12.0(LTS)를 설치했습니다.참고 사항Docker는 Node.js 패키지 관리자가 아닙니다.시스템에 Docker가 설치되어 있는지 확인한 후, Docker 공식 문서 를 참고하여 설정하세요.공식 Node.js Docker 이미지는 nodejs/docker-node에서 제공됩니다.아래와 같이 Docker 이미지를 가져와 Node.js 버전을 확인할 수 있습니다.# Node.js Docker 이미지를 가져옵니다. docker pull node:22-alpine # 환경에 올바른 Node.js 버전이 있는지 확인합니다. docker run node:22-alpine node -v # `v22.12.0`이 출력되어야 합니다. # 환경에 올바른 npm 버전이 있는지 확인합니다. docker run node:22-alpine npm -v # `10.9.0`이 출력되어야 합니다. 샘플코드 구현하기Node.js 설치가 완료되면 소스 코드를 클론합니다.git clone https://github.com/zmania/HDevPlus-example.git 클론한 뒤 디렉터리 구조는 다음과 같습니다.nuxt3 php spring-boot vue-dr vue 이 중 nuxt3 디렉터리로 이동하여 npm install을 실행하면 필요한 Node 패키지가 설치되며, 이 과정에서 Nuxt3도 함께 설치됩니다.설치 완료 후 nuxt3/.env 파일을 생성하고 다음 내용을 추가합니다.NODE_TLS_REJECT_UNAUTHORIZED=0 SECURE_KEY=ee9d2d324e261c42e5372a20b19c85b5ac7db7908dce804c59c911c2ae6624e1 API_URL=https://api.hdevplus.com/request.js NODE_TLS_REJECT_UNAUTHORIZED: SSL 인증서 검증 여부를 설정합니다. 0이면 인증서 검증을 무시하고, 1이면 공인된 CA에서 발급받은 SSL 인증서를 검증합니다.SECURE_KEY: API 접속을 위한 키입니다. 위의 키는 데모용으로, H:Dev+ 관리자 콘솔의 System > Setting 메뉴에서 별도의 도메인 & IP 설정 없이 사용할 수 있습니다.API_URL: 호출할 API 주소를 지정합니다..env 파일에는 민감한 정보가 포함될 수 있으므로, Git이나 SVN 등의 버전 관리 시스템을 통해 외부로 유출되지 않도록 주의해야 합니다.데모용 SECURE_KEY는 예고 없이 변경될 수 있습니다. 최신 키는 H:Dev+ 공식 사이트를 통해 확인하시기 바랍니다.설정이 완료되면 브라우저에서 http://localhost:8086에 접속하여 샘플 페이지를 확인할 수 있습니다.추후 본인만의 API를 사용하려면, H:Dev+에 가입한 뒤 콘솔의 System > Setting 메뉴에서 Secure key를 확인하여 .env 파일의 SECURE_KEY 값을 해당 키로 변경하십시오. 또한 Setting > Domain & IP 메뉴에서 본인의 IP와 사용할 도메인(http://localhost:8086)을 등록할 수 있습니다.http://localhost:8086 도메인을 계속 사용하는 것은 보안에 취약할 수 있으므로 실제 사용 시에는 도메인을 설정하는 것을 권장합니다.이후 nuxt3/components와 nuxt3/pages 디렉터리의 .vue 파일을 참고하여 페이지를 자유롭게 생성하고 수정할 수 있습니다.