IT 프로젝트/쇼핑몰 만들기

[Spring Boot] 스프링 부트 프로젝트/쇼핑몰 만들기 - 화면 동적 로딩

happygram 2020. 1. 7. 22:07

설명

보통 상품 상세를 보기 위해서 상품의 이미지 혹은 글자를 클릭하여 상세 페이지로 이동을 합니다.
main.html 페이지에서 상품 클릭 시 상품 상세를 보기 위해서 product.html 페이지로 이동하도록 해볼게요.


Front-End

index.html 일부

...
<!-- Content Wrapper. Contains page content -->
<th:block th:include="${template}"></th:block>
<!-- /.content-wrapper -->
...

기존에는 th:include 부분에 html 페이지 경로를 직접 주었습니다.
화면을 동적으로 로딩하기 위해서 Back-End 에서 template 라는 Key 로 저장이 되어 전달 받은 값을 받도록 변경 하였습니다.

main.html 일부

...
<div class="text-center">
  <a th:href="@{/product}">
    <img class="img-fluid" th:src="@{/static/images/clothing-2.png}" alt="Product picture">
  </a>
</div>
<a th:href="@{/product}">
  <h3 class="text-dark profile-username text-center">Color T-shirts</h3>
  <p class="text-muted text-center">[90-105]</p>
  <p class="text-dark text-center">19,800원</p>
</a>
...

이미지 혹은 글자 클릭 시 Back-End 에서 /product URL을 호출하도록 합니다.

product.html

<!-- Content Wrapper. Contains page content -->
<div class="content-wrapper">
  <!-- Content Header (Page header) -->
  <section class="content-header">
    <div class="container-fluid">
      <div class="row mb-2">
        <div class="col-sm-6">
          <h1>티셔츠</h1>
        </div>
        <div class="col-sm-6">
          <ol class="breadcrumb float-sm-right">
            <li class="breadcrumb-item"><a href="#">Home</a></li>
            <li class="breadcrumb-item active">티셔츠</li>
          </ol>
        </div>
      </div>
    </div><!-- /.container-fluid -->
  </section>

  <!-- Main content -->
  <section class="content">

    <!-- Default box -->
    <div class="card card-solid">
      <div class="card-body">
        <div class="row">
          <div class="col-12 col-sm-6">
            <h3 class="d-inline-block d-sm-none">Color T-shirts</h3>
            <div class="col-12">
              <img th:src="@{/static/images/clothing-2.png}" class="product-image" alt="Product Image">
            </div>
            <div class="col-12 product-image-thumbs">
              <div class="product-image-thumb active"><img th:src="@{/static/images/clothing-2.png}" alt="Product Image"></div>
              <div class="product-image-thumb" ><img th:src="@{/static/images/clothing-2.png}" alt="Product Image"></div>
              <div class="product-image-thumb" ><img th:src="@{/static/images/clothing-2.png}" alt="Product Image"></div>
              <div class="product-image-thumb" ><img th:src="@{/static/images/clothing-2.png}" alt="Product Image"></div>
              <div class="product-image-thumb" ><img th:src="@{/static/images/clothing-2.png}" alt="Product Image"></div>
            </div>
          </div>
          <div class="col-12 col-sm-6">
            <h3 class="my-3">Color T-shirts</h3>
            <p>
              남녀 공용으로 누구나 입을 수 있는 티셔츠 입니다. 사이즈가 넉넉히 나왔으니 선택하실 때 참조 하세요.
            </p>
            <hr>
            <h4>색상</h4>
            <div class="btn-group btn-group-toggle" data-toggle="buttons">
              <label class="btn btn-default text-center active">
                <input type="radio" name="color_option" id="color_option1" autocomplete="off" checked="">
                Green
                <br>
                <i class="fas fa-circle fa-2x text-green"></i>
              </label>
              <label class="btn btn-default text-center">
                <input type="radio" name="color_option" id="color_option2" autocomplete="off">
                Blue
                <br>
                <i class="fas fa-circle fa-2x text-blue"></i>
              </label>
              <label class="btn btn-default text-center">
                <input type="radio" name="color_option" id="color_option3" autocomplete="off">
                Purple
                <br>
                <i class="fas fa-circle fa-2x text-purple"></i>
              </label>
              <label class="btn btn-default text-center">
                <input type="radio" name="color_option" id="color_option4" autocomplete="off">
                Red
                <br>
                <i class="fas fa-circle fa-2x text-red"></i>
              </label>
              <label class="btn btn-default text-center">
                <input type="radio" name="color_option" id="color_option5" autocomplete="off">
                Orange
                <br>
                <i class="fas fa-circle fa-2x text-orange"></i>
              </label>
            </div>

            <h4 class="mt-3">사이즈</h4>
            <div class="btn-group btn-group-toggle" data-toggle="buttons">
              <label class="btn btn-default text-center">
                <input type="radio" name="color_option" id="color_option1" autocomplete="off">
                <span class="text-xl">90</span>
                <br>
                Small
              </label>
              <label class="btn btn-default text-center">
                <input type="radio" name="color_option" id="color_option1" autocomplete="off">
                <span class="text-xl">95</span>
                <br>
                Medium
              </label>
              <label class="btn btn-default text-center">
                <input type="radio" name="color_option" id="color_option1" autocomplete="off">
                <span class="text-xl">100</span>
                <br>
                Large
              </label>
              <label class="btn btn-default text-center">
                <input type="radio" name="color_option" id="color_option1" autocomplete="off">
                <span class="text-xl">105</span>
                <br>
                Xtra-Large
              </label>
            </div>

            <div class="bg-gray py-2 px-3 mt-4">
              <h4 class="mt-0">
                <small><del>29,800원</del></small>
              </h4>
              <h2 class="mb-0">
                19,800원
              </h2>
            </div>

            <div class="mt-4">
              <div class="btn btn-primary btn-lg btn-flat">
                <i class="fas fa-cart-plus fa-lg mr-2"></i> 
                Add to Cart
              </div>

              <div class="btn btn-default btn-lg btn-flat">
                <i class="fas fa-heart fa-lg mr-2"></i> 
                Add to Wishlist
              </div>
            </div>

            <div class="mt-4 product-share">
              <a href="#" class="text-gray">
                <i class="fab fa-facebook-square fa-2x"></i>
              </a>
              <a href="#" class="text-gray">
                <i class="fab fa-twitter-square fa-2x"></i>
              </a>
              <a href="#" class="text-gray">
                <i class="fas fa-envelope-square fa-2x"></i>
              </a>
              <a href="#" class="text-gray">
                <i class="fas fa-rss-square fa-2x"></i>
              </a>
            </div>

          </div>
        </div>
        <div class="row mt-4">
          <nav class="w-100">
            <div class="nav nav-tabs" id="product-tab" role="tablist">
              <a class="nav-item nav-link active" id="product-desc-tab" data-toggle="tab" href="#product-desc" role="tab" aria-controls="product-desc" aria-selected="true">설명</a>
              <a class="nav-item nav-link" id="product-comments-tab" data-toggle="tab" href="#product-comments" role="tab" aria-controls="product-comments" aria-selected="false">리뷰</a>
              <a class="nav-item nav-link" id="product-rating-tab" data-toggle="tab" href="#product-rating" role="tab" aria-controls="product-rating" aria-selected="false">평가</a>
            </div>
          </nav>
          <div class="tab-content p-3" id="nav-tabContent">
            <div class="tab-pane fade show active" id="product-desc" role="tabpanel" aria-labelledby="product-desc-tab">상세 설명</div>
            <div class="tab-pane fade" id="product-comments" role="tabpanel" aria-labelledby="product-comments-tab">리뷰</div>
            <div class="tab-pane fade" id="product-rating" role="tabpanel" aria-labelledby="product-rating-tab">평가</div>
          </div>
        </div>
      </div>
      <!-- /.card-body -->
    </div>
    <!-- /.card -->

  </section>
  <!-- /.content -->
</div>
<!-- /.content-wrapper -->

AdminLTE v3 소스를 참조하여 약간 변형 하였습니다.
이미지 및 한글화, 사이즈, 가격 등을 조절 하였습니다.

AdminLTE v3 > Pages > E-commerce


Back-End

WebController.java 일부

...
@RequestMapping(value = "/product")
public String index(Model model) {
  model.addAttribute("template", "fragments/content/product");
  return "index";
}
...

/product URL을 호출하는 경우 model 객체에 keytemplate 로 하여 호출할 html 페이지 경로를 입력합니다.
그리고 index 값을 리턴하여 index.html 페이지를 호출하도록 합니다.

Spring MVC and Thymeleaf: how to access data from templates


지금까지는 대부분 정적인 부분을 위주로 화면 레이아웃을 위주로 구현을 하였습니다.
추후 데이터베이스 환경 구축과 함께 데이터베이스 연동을 진행하고 초기 데이터가 어느 정도 만들어지면 더 많은 코드와 좋은 그림이 그려질 것으로 보입니다.