Market Kurly

์ „ํƒœ์ˆ˜ยท2023๋…„ 7์›” 7์ผ
0

project

๋ชฉ๋ก ๋ณด๊ธฐ
2/7
post-thumbnail

๐Ÿ“‚ ๋งˆ์ผ“์ปฌ๋ฆฌ ํด๋ก ์ฝ”๋”ฉ

  • ์‚ฌ์ดํŠธ๋ช…: ๋งˆ์ผ“์ปฌ๋ฆฌ
  • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ: swiper, jquery
  • ์œ ํ˜•: PC

โœ… Check Point

  • ๋งˆ์ผ“์ปฌ๋ฆฌ PC ํด๋ก ์ฝ”๋”ฉ
  • fetch() ํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•˜์—ฌ json ๋ฐ์ดํ„ฐ๋ฅผ ํ˜ธ์ถœํ•œ '๋ฐ์ดํ„ฐ๋ฐ”์ธ๋”ฉ'์„ ์ฃผ๋กœ ์ด๋ฃฌ ํ”„๋กœ์ ํŠธ
  • SWIPER ์‚ฌ์šฉํ•œ ์Šฌ๋ผ์ด๋“œ
  • ์ƒํ’ˆ ๊ฐ€๊ฒฉ ์‰ผํ‘œ ์ฒ˜๋ฆฌ(์ •๊ทœ์‹ ํ™œ์šฉ)
  • ์„œ๋ธŒ์นดํ…Œ๊ณ ๋ฆฌ ์ด๋ฏธ์ง€ hover์‹œ ๋ณ€๊ฒฝ๋˜๋Š” ์ด๋ฏธ์ง€ ์ฃผ์†Œ๊ฐ’ src ๋ณ€๊ฒฝํ•˜๋Š” script ๊ตฌํ˜„
  • ํ• ์ธ๊ฐ€๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š๋Š” ์›๊ฐ€ ๊ทธ๋Œ€๋กœ์˜ ์ƒํ’ˆ์ผ ๊ฒฝ์šฐ discount(%) ์ˆจ๊ธฐ๋Š” script ๊ตฌํ˜„
  • '์ผ์ผํŠน๊ฐ€','์ฃผ๋งํŠน๊ฐ€' ๋“ฑ์„ ๋„ฃ๋Š” .badge๋ฅผ ์ƒํ’ˆ์˜ ํŠน๊ฐ€ ์œ ๋ฌด์— ๋”ฐ๋ผ ๋„ฃ๊ณ  ๋นผ๋Š” script ๊ตฌํ˜„

1. ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ (fetch(), json)

โŒจ ๋งˆ์ผ“์ปฌ๋ฆฌ ์‚ฌ์ดํŠธ์˜ ์ƒํ’ˆ ์˜์—ญ์€ ๋Œ€๋ถ€๋ถ„ ๊ฐ™์€ ๋ ˆ์ด์•„์›ƒ์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์–ด, ๋ฐ˜๋ณต๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜์˜ product.json ํŒŒ์ผ์„ ํ™œ์šฉํ•˜์—ฌ, ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ์ถ”์ถœํ•ด fetch๋ฌธ์— ์žฌ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์„ฑํ•˜์˜€๋‹ค.

๐Ÿ”ถ JSON

{
    "items":[
        {
            "id":0,
            "sort":[1,3,7,11,12],
            "cate":[1],
            "snippet":{
                "thumbnail":"../assets/images/product-img1.jpg",
                "title": "[๋ฅด๋„คํœ˜ํ…Œ๋ฅด] ํฌํ‹ฐ์ƒค ๋‘ํ”ผ&๋ชจ๋ฐœ๊ฐ•ํ™” ์ƒดํ‘ธ 250ml",
                "price":{
                    "discount":15,
                    "curr":22100,
                    "ori":26000
                },
                "badge":"์ผ์ผํŠน๊ฐ€",
                "review":5000
            }
        },
        {
            "id":0,
            "sort":[3,4,7,11,12],
            "cate":[16],
            "snippet":{
                "thumbnail":"../assets/images/product-img2.jpg",
                "title": "[๋งˆ๋น„์Šค] ์น˜์•ฝ 85mL 6์ข… ์„ ๋ฌผ์„ธํŠธ (+ ํด๋ž˜์‹ ๋ฏผํŠธ ์น˜10ml 3๊ฐœ ์ฆ์ •)"
                "price":{
                    "discount":20,
                    "curr":95500,
                    "ori":119400
                },
                "badge":"์ผ์ผํŠน๊ฐ€",
                "review":5000 
            }
        },
        ....
    ]
}

๐Ÿ”ถ SCRIPT(fetch)

function productList(frame,sortNum,cateNum){
    fetch('./assets/data/product.json')
    .then((response)=> response.json())
    .then((json) => {
      data=json.items; //๋ชจ๋“ ๋ฐ์ดํ„ฐ

      
      var result = data.filter(function (parm) {
        return parm.sort.indexOf(sortNum) >= 0
      });
    
      if(cateNum){
        var result = result.filter(function (parm) {
          return parm.cate.indexOf(cateNum) >= 0
        });
      }
      
      let html='';
      result.forEach(element => {
        reviewCnt = (element.snippet.review >=999) ? '999+' : element.snippet.review;

        saleEl = (element.snippet.price.ori === element.snippet.price.curr) ? 'hide':'';

        html+=`<div class="swiper-slide">
        <div class="img-wrap">
            <a href="">
              <img src="${element.snippet.thumbnail}" alt="์ƒํ’ˆ์ด๋ฏธ์ง€">
              <em class="badge">${element.snippet.badge}</em>
            </a>
            <button class="btn-cart">
              <span class="blind">์žฅ๋ฐ”๊ตฌ๋‹ˆ</span>
            </button>
        </div>
        <a href="" class="txt-wrap">
          <p class="title">${element.snippet.title}</p>
          <div class="price-box">
            <div class="wrap">
                <strong class="discount ${saleEl}">${element.snippet.price.discount}%</strong>
                <strong class="curr">${price(element.snippet.price.curr)}์›</strong>
            </div>
            <span class="ori ${saleEl}">${price(element.snippet.price.ori)}์›</span>
          </div>
          <div class="review">
            <div class="review-icon"></div>
            <span>ํ›„๊ธฐ ${reviewCnt}</span>
          </div> </a> </div>`;
      });
      $(frame).html(html);
    });
  }

  productList('#list1',1);
  productList('#list2',2);
  .
  .
  .
  
  • fetch('./assets/data/product.json') ๋ถˆ๋Ÿฌ์˜ฌ json ๋ฐ์ดํ„ฐ ํŒŒ์ผ (์‹ค๋ฌด์—์„œ๋Š” ์ฃผ์†Œ๋ฅผ ๋ฐ›์•„์„œ ์“ฐ๋Š” ๋ถ€๋ถ„)
  • ${element.snippet.thumbnail} - json์—์„œ ๋ถ„๋ฅ˜ํ•œ ์•„์ดํ…œ๋“ค์„ ํ˜ธ์ถœํ•˜๋Š” ์ฝ”๋“œ.
  • saleEl = (element.snippet.price.ori === element.snippet.price.curr) ? 'hide':'';
    ํ• ์ธ๊ฐ€๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š๋Š” ์›๊ฐ€ ๊ทธ๋Œ€๋กœ์˜ ์ƒํ’ˆ์ผ ๊ฒฝ์šฐ [ 'ori'๊ธˆ์•ก๊ณผ 'curr'์˜ ๊ธˆ์•ก์ด ๊ฐ™์„ ๋•Œ 'hide'ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•ด๋ผ ] ๋ผ๋Š” ์กฐ๊ฑด๋ฌธ์„ ๊ฑธ์–ด, CSS์—์„œ .ori, .discount(%)๋ฅผ display:none; ํ•ด์ฃผ์—ˆ๋‹ค.
  • reviewCnt = (element.snippet.review >=999) ? '999+' : element.snippet.review
    ํ›„๊ธฐ๊ฐ€ 999๊ฐœ๋ณด๋‹ค ํฌ๊ฑฐ๋‚˜ ๊ฐ™๋‹ค๋ฉด, 999+๋กœ ํ‘œ๊ธฐํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ์‹ค์ œ ํ›„๊ธฐ ๊ฐฏ์ˆ˜๊ฐ€ ๋‚˜์˜ค๋Š” ์กฐ๊ฑด๋ฌธ.

๐Ÿ“ˆ ์ฒœ ๋‹จ์œ„ ์ฝค๋งˆ ์ •๊ทœ์‹

function price(num){
  let price = num;
  result = price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); 
  return result; 
}
 
  • replace ์ •๊ทœํ‘œํ˜„์‹์ด ๋งค์นญ๋˜๋Š” ํ•ญ๋ชฉ์„ ""์•ˆ์— ์žˆ๋Š” ๊ฐ’์œผ๋กœ ๋ณ€ํ™˜ ์‹œ์ผœ์ค€๋‹ค.
  • g(global) ๋ฌธ์ž์—ด ๋‚ด์˜ ๋ชจ๋“  ํŒจํ„ด์„ ๊ฒ€์ƒ‰ํ•˜์—ฌ ์ฒœ ๋‹จ์œ„๋กœ ์ฝค๋งˆ๋ฅผ ๋„ฃ์–ด์ค€๋‹ค.
  • ๋ฐฐ์—ด์˜ ์š”์†Œ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฌธ์ž์—ด์„ ๋ฐ˜ํ™˜ํ•˜๋Š” toString() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ์ •๊ทœ์‹ ํŒจํ„ด์„ ์™„์„ฑํ–ˆ๋‹ค.

2. TAB ๋ฉ”๋‰ด (๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ)

  • ๊ฐ TAB ๋ฉ”๋‰ด ๋ฒ„ํŠผ์„ ํด๋ฆญ ํ–ˆ์„ ๋•Œ ๊ทธ์— ๋งž๋Š” ๋ฐ์ดํ„ฐ๋“ค์ด ์ถœ๋ ฅ๋œ๋‹ค.

๐Ÿ”ท HTML

<ul class="tabnav">
	<li><a href="#" data-cate="1">์ฑ„์†Œ</a></li>
	<li><a href="#" data-cate="2">๊ณผ์ผยท๊ฒฌ๊ณผยท์Œ€</a></li>
	<li><a href="#" data-cate="3">์ˆ˜์‚ฐยทํ•ด์‚ฐยท๊ฑด์–ด๋ฌผ</a></li>
	<li><a href="#" data-cate="4">์ •์œกยท๊ณ„๋ž€</a></li>
	<li><a href="#" data-cate="5">๊ตญยท๋ฐ˜์ฐฌยท๋ฉ”์ธ์š”๋ฆฌ</a></li>
	<li><a href="#" data-cate="6">์ƒ๋Ÿฌ๋“œยท๊ฐ„ํŽธ์‹</a></li>
	<li><a href="#" data-cate="7">๋ฉดยท์–‘๋…ยท์˜ค์ผ</a></li>
	<li><a href="#" data-cate="8">์ƒ์ˆ˜ยท์Œ๋ฃŒยท์šฐ์œ ยท์ปคํ”ผ</a></li>
	<li><a href="#" data-cate="9">๊ฐ„์‹ยท๊ณผ์žยท๋–ก</a></li>
	<li><a href="#" data-cate="10">๋ฒ ์ด์ปค๋ฆฌยท์น˜์ฆˆยท๋ธ๋ฆฌ</a></li>
	<li><a href="#" data-cate="11">๊ฑด๊ฐ•์‹ํ’ˆ</a></li>
	<li><a href="#" data-cate="12">์™€์ธ</a></li>
	<li><a href="#" data-cate="13">์ „ํ†ต์ฃผ</a></li>
	<li><a href="#" data-cate="14">์ƒํ™œ์šฉํ’ˆยท๋ฆฌ๋น™ยท์บ ํ•‘</a></li>
	<li><a href="#" data-cate="15">์Šคํ‚จ์ผ€์–ดยท๋ฉ”์ดํฌ์—…</a></li>
	<li><a href="#" data-cate="16">ํ—ค์–ดยท๋ฐ”๋””ยท๊ตฌ๊ฐ•</a></li>
	<li><a href="#" data-cate="17">์ฃผ๋ฐฉ์šฉํ’ˆ</a></li>
	<li><a href="#" data-cate="18">๊ฐ€์ „์ œํ’ˆ</a></li>
	<li><a href="#" data-cate="19">์„ ๋ฌผํ•˜๊ธฐ</a></li>
	<li><a href="#" data-cate="20">๋ฐ˜๋ ค๋™๋ฌผ</a></li>
	<li><a href="#" data-cate="21">๋ฒ ์ด๋น„ยทํ‚ค์ฆˆยท์™„๊ตฌ</a></li>
	<li><a href="#" data-cate="22">์—ฌํ–‰ยทํ‹ฐ์ผ“</a></li>
</ul>
  • ๊ฐ ํƒญ์— data-cate="" ๋ฅผ ๋„ฃ์–ด์ฃผ์–ด ๊ฐ๊ฐ์˜ ์ผ์น˜ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋“ค์ด ๋‚˜์˜ฌ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•ด์ฃผ์—ˆ๋‹ค.

๐Ÿ”ถ SCRIPT (data-cate)

$('.md-recomm .tabnav a').click(function(e){
      e.preventDefault();

      cateIndex = $(this).data('cate');

      $('.tabnav a').removeClass('active');
      $(this).addClass('active');
    
      productList('#list12',12,cateIndex);
       
 })
  • ๋‚ด๊ฐ€ ์„ ํƒํ•œ data-cate๋ฅผ ๋ฐ›์•„์„œ cateIndex ๋ผ๊ณ  ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์•„ ๋†“๊ณ , ๋ฐ›์•„ ๋†“์€cateIndex๋ฅผ productList('#list12',12,cateIndex)์— ์ „๋‹ฌ์„ ํ•ด์„œ ๊ฐ๊ฐ์˜ data-cate ์— ๋ถ€์—ฌ๋ฐ›์€ ๋ฒˆํ˜ธ์— ํ•ด๋‹นํ•˜๋Š” ๋ฐ์ดํ„ฐ๋“ค์„ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.

๐Ÿ”ถ SCRIPT (๊ฐ•์ œํŠธ๋ฆฌ๊ฑฐ ์„ ํƒ)

$('.md-recomm .tabnav li:first-child a').trigger('click');
  • ๊ฐ•์ œ๋กœ ์ฒซ๋ฒˆ์งธ ํƒญ์ด ํด๋ฆญ์ด๋ฒคํŠธ๊ฐ€ ์‹คํ–‰์ด ๋˜๊ฒŒ ํ•œ๋‹ค.

3. ๋ฐ์ดํ„ฐ ํ•„ํ„ฐ๋ง ์ •๋ฆฌ

// ๋ฐ์ดํ„ฐ ํ•„ํ„ฐ๋ง ํ•ด์ค„ ํ•จ์ˆ˜
  function productList(frame,sortNum,cateNum){
    fetch('./assets/data/product.json')
    .then((response)=> response.json())
    .then((json) => {
      data=json.items; //๋ชจ๋“ ๋ฐ์ดํ„ฐ

      
      var result = data.filter(function (parm) {
        return parm.sort.indexOf(sortNum) >= 0
      });
    
      if(cateNum){
        var result = result.filter(function (parm) {
          return parm.cate.indexOf(cateNum) >= 0
        });
      }
      
      let html='';
      result.forEach(element => {
        reviewCnt = (element.snippet.review >=999) ? '999+' : element.snippet.review;

        saleEl = (element.snippet.price.ori === element.snippet.price.curr) ? 'hide':'';

        html+=`
        
	        ... 
            
        `; //์ค‘๋ณต์œผ๋กœ ์ƒ๋žต
      });
      $(frame).html(html);
    });
  }
  • filter() ๋ฉ”์„œ๋“œ๋ž€? ์ฃผ์–ด์ง„ ํ•จ์ˆ˜์˜ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ต๊ณผํ•˜๋Š” ๋ชจ๋“  ์š”์†Œ๋ฅผ ๋ชจ์•„ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค.

    ๋ฒ„ํŠผ ํด๋ฆญ์‹œ ๊ฐ ๋ฐ์ดํ„ฐ์— ๋งž๋Š” ์ƒํ’ˆ์„ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด(sort-๋ถ„๋ฅ˜) fetch๋ฌธ์„ ํ•จ์ˆ˜์— ๋„ฃ์–ด์ฃผ๊ณ  filter() ๋ฉ”์„œ๋“œ๋กœ ๋ฐ์ดํ„ฐ ํ•„ํ„ฐ๋ง์„ ํ•˜์˜€๋‹ค.

4. SWIPER

๐Ÿ”ท HTML

<section class="sc-product">
	<div class="common-inner">
		<div class="group-title">
           <h2 class="title">์ด ์ƒํ’ˆ ์–ด๋•Œ์š”?</h2>
        </div>
        <div class="group-product">
           <div class="swiper">
              <div class="swiper-wrapper" id="list1">
                 <!-- jsonํŒŒ์ผ ์‚ฌ์šฉ์œผ๋กœ swiper-slide ์ƒ๋žต -->
              </div>
          </div>
          <div class="btn-nav prev"></div>
          <div class="btn-nav next"></div>
        </div>                
	</div>
</section>

๐Ÿ”ถ SCRIPT

const productSlide = new Swiper('.group-product .swiper', {
      slidesPerView: 4, //ํ•œ ์Šฌ๋ผ์ด๋“œ์— ๋ณด์—ฌ์ค„ ๊ฐฏ์ˆ˜
      spaceBetween: 20, //์Šฌ๋ผ์ด๋“œ ์‚ฌ์ด ์—ฌ๋ฐฑ

      navigation: { //๋ฒ„ํŠผ
          nextEl: ".next",
          prevEl: ".prev",
      },
});
  • swiper slide์—์„œ๋Š” ์Šฌ๋ผ์ด๋“œ ์‚ฌ์ด ์—ฌ๋ฐฑ์„ CSS์˜ margin ๊ฐ’์ด ์•„๋‹Œ, spaceBetween ์†์„ฑ์„ ํ†ตํ•ด ์—ฌ๋ฐฑ์„ ์ค€๋‹ค.

๐ŸŒŸ Swiper ์‚ฌ์šฉ์‹œ ์ฃผ์˜ํ•  ์ 

  1. swiper-wrapper, swiper-slide ํด๋ž˜์Šค ์ด๋ฆ„ ์ œ๋Œ€๋กœ ๋“ค์–ด๊ฐ”๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ
  2. ์Šฌ๋ผ์ด๋“œ๋ฅผ ์—ฌ๋Ÿฌ ๊ฐœ ๋งŒ๋“ค ๋•Œ ๊ฐ๊ฐ์˜ ๋ณ€์ˆ˜๋ช…๊ณผ ํด๋ž˜์Šค ์ด๋ฆ„์„ ์ „๋ถ€ ๊ตฌ๋ถ„์ง€์–ด์ฃผ๊ธฐ

0๊ฐœ์˜ ๋Œ“๊ธ€