시작하기

선언적 렌더링(Declarative Rendering)방식으로 시작하기

지후아빠
12-15 15:55

요약

  1. 선언적 렌더링은 Vue.js를 이용해 프론트엔드를 간단히 구성하는 방법입니다.
  2. 빠른 프로토타입 제작에 유용하며, 학습 및 테스트 환경에서 적합합니다.
  3. 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+**를 가장 빠르게 경험할 수 있는 방법은 선언적 렌더링 방식을 이용해 프론트엔드를 구현하는 것입니다.

선언적 렌더링의 활용 대상
  1. Vue.js로 프론트엔드 개발을 학습하는 사용자
  2. 빠른 프로토타입을 구현하려는 중소기업 또는 에이전시
주의사항

선언적 렌더링 방식은 보안적 위험(예: 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 디렉터리에서 확인할 수 있습니다.