๐ŸŒธ [SPRING BOOT] | [JS] |๐ŸŽฎ๊ฒŒ์‹œ๋ฌผ ๊ธฐ๋Šฅ(๐Ÿ’ŽAJAX๋กœ ๊ตฌํ˜„) , ๐ŸŽฎ๋Œ“๊ธ€ ๊ธฐ๋Šฅ (๐Ÿ’ŽAJAX๋กœ ๊ตฌํ˜„) , feed.js , feedObj

0
post-thumbnail

๐Ÿ”น const param = { ...globalConstElem.dataset };

โœ… param์— dataset ๋ฐฐ์—ด๊ฐ’์ด ๋‹ด๊ฒจ์„œ ๊ฐ์ฒด๊ฐ€ ๋œ๋‹ค.


โœ… html์—์„œ feed๋ฅผ ์•ˆ๋งŒ๋“ค๊ณ  js์—์„œ ๋งŒ๋“  ์ด์œ ๋Š”

โœ… home.html์— ๋“ค์–ด๊ฐ€์ž ๋งˆ์ž ํ”ผ๋“œ๋“ค์ด ๋œจ๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋‹ค

โœ… infinite scroller๋ฅผ ์“ฐ๊ธฐ ์œ„ํ•œ ๊ฒƒ์ด๋‹ค

๐Ÿ”น home.html์— ๋“ค์–ด๊ฐ€์ž ๋งˆ์ž ํ”ผ๋“œ๋“ค์ด ๋œจ๋Š” ์ด์œ 

โœ… js์˜ ajaxํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œํ‚ค๊ธฐ ๋•Œ๋ฌธ

home2.js

feedObj.url = '/feed/list2';
feedObj.setScrollInfinity(window);
feedObj.getFeedList(1);

๐ŸŸฆ feed.js

const feedObj = {
    limit: 5,
    itemLength: 0,
    currentPage: 1,
    url: '',
    iuser: 0,
    swiper: null,
    containerElem: document.querySelector('#feedContainer'),
    loadingElem: document.querySelector('.loading'),
  • containerElem: document.querySelector('#feedContainer') : <div id="feedContainer"></div>
  • loadingElem: document.querySelector('.loading') : <div class="loading hide"><img th:src="@{/img/loading.gif}"></div>
    makeFeedList: function(data) {
        if(data.length == 0) { return; }

        for(let i=0; i<data.length; i++) {
            const item = data[i];

            const itemContainer = document.createElement('div');
            itemContainer.classList.add('item');

            // ๊ธ€์“ด์ด ์ •๋ณด ์˜์—ญ
            let imgTag = ``;
            if(item.mainProfile != null) {
                imgTag = `<img src="/pic/profile/${item.iuser}/${item.mainProfile}" class="pointer profile wh30" 
               token interpolation">${item.iuser});">`;
            }
            const regDtInfo = getDateTimeInfo(item.regdt);
            const topDiv = document.createElement('div');
            topDiv.classList.add('top')
            topDiv.innerHTML = `
            <div class="itemProfileCont">${imgTag}</div>
            <div>
                <div><span class="pointer"token interpolation">${item.iuser});">${item.writer}</span> - ${regDtInfo}</div>
                <div>${item.location == null ? '' : item.location}</div>
            </div>
            `;
            //์ด๋ฏธ์ง€์˜์—ญ
            const imgDiv = document.createElement('div');
            imgDiv.classList.add('itemImg');

            const swiperContainerDiv = document.createElement('div');
            swiperContainerDiv.classList.add('swiper-container');

            const swiperWrapperDiv = document.createElement('div');
            swiperWrapperDiv.classList.add('swiper-wrapper');

            swiperContainerDiv.append(swiperWrapperDiv);
            imgDiv.append(swiperContainerDiv);

            for(let z=0; z<item.imgList.length; z++) {
                const imgObj = item.imgList[z];

                const swiperSlideDiv = document.createElement('div');
                swiperSlideDiv.classList.add('swiper-slide');

                const img = document.createElement('img');
                img.src = `/pic/feed/${item.ifeed}/${imgObj.img}`;
                swiperSlideDiv.append(img);
                swiperWrapperDiv.append(swiperSlideDiv);
            }

            itemContainer.append(topDiv);
            itemContainer.append(imgDiv);
  • const itemContainer = document.createElement('div'); itemContainer.classList.add('item');
    <div class='item'></div>
    const topDiv = document.createElement('div');
    topDiv.classList.add('top')
    topDiv.innerHTML = `
    <div class="itemProfileCont">${imgTag}</div>
    <div>
        <div><span class="pointer"token interpolation">${item.iuser});">${item.writer}</span> - ${regDtInfo}</div>
        <div>${item.location == null ? '' : item.location}</div>
    </div>
    `;
[ topDiv ]

<div class='top'>
   <div class="itemProfileCont">
           <img src="/pic/profile/${item.iuser}/${item.mainProfile}" class="pointer profile wh30" 
                           onclick="moveToProfile(${item.iuser});" onerror="this.style.display='none';">
   </div>
   <div>
       <div>
           <span class="pointer" onclick="moveToProfile(${item.iuser});">${item.writer}</span> - ${regDtInfo}
       </div>
       <div>${item.location == null ? '' : item.location}</div>
   </div>
</div>
  • const imgDiv = document.createElement('div'); imgDiv.classList.add('itemImg');
    : <div class="itemImg"></div>
  • const swiperContainerDiv = document.createElement('div'); swiperContainerDiv.classList.add('swiper-container');
    : <div class="swiper-container"></div>
  • const swiperWrapperDiv = document.createElement('div'); swiperWrapperDiv.classList.add('swiper-wrapper');
    : <div class="swiper-wrapper"></div>
    const swiperSlideDiv = document.createElement('div');
    swiperSlideDiv.classList.add('swiper-slide');

    const img = document.createElement('img');
    img.src = `/pic/feed/${item.ifeed}/${imgObj.img}`;
    swiperSlideDiv.append(img);
    swiperWrapperDiv.append(swiperSlideDiv);
[ imgDiv ]

<div class="itemImg">
  <div class="swiper-container">
      <div class="swiper-wrapper">
        <div class="swiper-slide">
          <img src="/pic/feed/${item.ifeed}/${imgObj.img}">
        </div>
    </div>
  </div>
</div>
  • itemContainer.append(topDiv); itemContainer.append(imgDiv);
<div class='item'>  * ์—ฌ๋Ÿฌ๋ฒˆ ๋ฐ˜๋ณต 
  <div class='top'>
      <div class="itemProfileCont">
              <img src="/pic/profile/${item.iuser}/${item.mainProfile}" class="pointer profile wh30" 
                              onclick="moveToProfile(${item.iuser});" onerror="this.style.display='none';">
      </div>
      <div>
          <div>
              <span class="pointer" onclick="moveToProfile(${item.iuser});">${item.writer}</span> - ${regDtInfo}
          </div>
          <div>${item.location == null ? '' : item.location}</div>
      </div>
  </div>

  <div class="itemImg">
    <div class="swiper-container">
        <div class="swiper-wrapper">
          <div class="swiper-slide"> * ์—ฌ๋Ÿฌ๋ฒˆ ๋ฐ˜๋ณต 
            <img src="/pic/feed/${item.ifeed}/${imgObj.img}">
          </div>
      </div>
    </div>
  </div>
</div>

๐ŸŸฆ feed.js

            //์ข‹์•„์š” ์˜์—ญ
            const favDiv = document.createElement('div');
            favDiv.classList.add('favCont');
            const heartIcon = document.createElement('i');
            heartIcon.className = 'fa-heart pointer';
            if(item.isFav === 1) { //์ข‹์•„์š” O
                heartIcon.classList.add('fas');
            } else { //์ข‹์•„์š” X
                heartIcon.classList.add('far');
            }
            const heartCntSpan = document.createElement('span');
            heartCntSpan.innerText = item.favCnt;

            heartIcon.addEventListener('click', ()=> {
                item.isFav = 1 - item.isFav;
                fetch(`fav?ifeed=${item.ifeed}&type=${item.isFav}`)
                    .then(res => res.json())
                    .then(myJson => {
                        if(myJson === 1) {
                            switch (item.isFav) {
                                case 0: //O > X
                                    heartIcon.classList.remove('fas');
                                    heartIcon.classList.add('far');
                                    heartCntSpan.innerText--;
                                    break;
                                case 1: //X > O
                                    heartIcon.classList.remove('far');
                                    heartIcon.classList.add('fas');
                                    heartCntSpan.innerText++;
                                    break;
                            }
                        }
                    });
            });
            favDiv.append(heartIcon);
            favDiv.append(heartCntSpan);

            itemContainer.append(favDiv);
  • const favDiv = document.createElement('div'); favDiv.classList.add('favCont');
    : <div class="favCont"></div>
  • const heartIcon = document.createElement('i'); heartIcon.className = 'fa-heart pointer';
    : <i class="fa-heart pointer"></i>
  • const heartCntSpan = document.createElement('span'); heartCntSpan.innerText = item.favCnt;
    : <span>${item.favCnt}</span>
  • favDiv.append(heartIcon); favDiv.append(heartCntSpan);
<div class="favCont">
  <i class="fa-heart pointer"></i>
  <span>${item.favCnt}</span>
</div>
  • itemContainer.append(favDiv);
<div class='item'>  * ์—ฌ๋Ÿฌ๋ฒˆ ๋ฐ˜๋ณต 
   //๊ธ€์“ด์ด ์ •๋ณด ์˜์—ญ
  <div class='top'>
      <div class="itemProfileCont">
              <img src="/pic/profile/${item.iuser}/${item.mainProfile}" class="pointer profile wh30" 
                              onclick="moveToProfile(${item.iuser});" onerror="this.style.display='none';">
      </div>
      <div>
          <div>
              <span class="pointer" onclick="moveToProfile(${item.iuser});">${item.writer}</span> - ${regDtInfo}
          </div>
          <div>${item.location == null ? '' : item.location}</div>
      </div>
  </div>

  //์ด๋ฏธ์ง€ ์˜์—ญ
  <div class="itemImg">
    <div class="swiper-container">
        <div class="swiper-wrapper">
          <div class="swiper-slide"> * ์—ฌ๋Ÿฌ๋ฒˆ ๋ฐ˜๋ณต 
            <img src="/pic/feed/${item.ifeed}/${imgObj.img}">
          </div>
      </div>
    </div>
  </div>

   //์ข‹์•„์š” ์˜์—ญ
  <div class="favCont">
    <i class="fa-heart pointer"></i>   ๐Ÿ‘‰ click ๐Ÿ’จ fav?ifeed=${item.ifeed}&type=${item.isFav}
    <span>${item.favCnt}</span>
  </div>
</div>

๐ŸŸฆ FeedController

@ResponseBody
@GetMapping("/fav")
public int feedFavProc(FeedFavEntity param, int type) { //type: 1 - ins(๋“ฑ๋ก), 0 - del(์ทจ์†Œ)
    System.out.println(param);
    System.out.println("type: " + type);
    return service.feedFavProc(param, type);
}

๐ŸŸฆ FeedService

public int feedFavProc(FeedFavEntity param, int type) {
    param.setIuser(auth.getLoginUserPk());
    if(type == 1) {
        return mapper.insFeedFav(param);
    }
    return mapper.delFeedFav(param);
}

๐ŸŸฆ FeedMapper

int insFeedFav(FeedFavEntity param);
int delFeedFav(FeedFavEntity param);
<insert id="insFeedFav">
    INSERT INTO t_feed_fav
    ( ifeed, iuser )
    VALUES
    ( #{ifeed}, #{iuser} )
</insert>

<delete id="delFeedFav">
    DELETE FROM t_feed_fav
    WHERE ifeed = #{ifeed}
    AND iuser = #{iuser}
</delete>

๐ŸŸฆ feed.js

            if(item.ctnt != null) { // ๊ธ€๋‚ด์šฉ ์˜์—ญ
                const ctntDiv = document.createElement('div');
                ctntDiv.innerText = item.ctnt;
                ctntDiv.classList.add('itemCtnt');
                itemContainer.append(ctntDiv);
            }

            //๋Œ“๊ธ€ ์˜์—ญ
            const cmtDiv = document.createElement('div');
            const cmtListDiv = document.createElement('div');
            const cmtFormDiv = document.createElement('div');
            cmtDiv.append(cmtListDiv);
            if(item.cmt != null && item.cmt.isMore === 1) {
                const moreCmtDiv = document.createElement('div');
                const moreCmtSpan = document.createElement('span');
                moreCmtSpan.className = 'pointer';
                moreCmtSpan.innerText = '๋Œ“๊ธ€ ๋”๋ณด๊ธฐ';
                moreCmtSpan.addEventListener('click', () => {
                    moreCmtSpan.remove();
                    fetch(`cmt?ifeed=${item.ifeed}`)
                        .then(res => res.json())
                        .then(result => {
                            result.forEach(obj => {
                                const cmtItemContainerDiv = this.makeCmtItem(obj);
                                cmtListDiv.append(cmtItemContainerDiv);
                            })
                        });
                });
                moreCmtDiv.append(moreCmtSpan);
                cmtDiv.append(moreCmtDiv);
            }
            cmtDiv.append(cmtFormDiv);

            const cmtInput = document.createElement('input');
            cmtInput.type = 'text';
            cmtInput.placeholder = '๋Œ“๊ธ€์„ ์ž…๋ ฅํ•˜์„ธ์š”...';
            cmtInput.addEventListener('keyup', (e) => {
                if(e.key === 'Enter') {
                    cmtBtn.click();
                }
            });

            if(item.cmt != null) { //๋Œ“๊ธ€ ์žˆ์Œ
                const cmtItemContainerDiv = this.makeCmtItem(item.cmt);
                cmtListDiv.append(cmtItemContainerDiv);
            }

            const cmtBtn = document.createElement('input');
            cmtBtn.type = 'button';
            cmtBtn.value = '๋“ฑ๋ก';
            cmtBtn.addEventListener('click', () => {
               const cmt = cmtInput.value;
               if(cmt.length === 0) {
                   alert('๋Œ“๊ธ€ ๋‚ด์šฉ์„ ์ž‘์„ฑํ•ด ์ฃผ์„ธ์š”.');
                   return;
               }

               const param = {
                   ifeed: item.ifeed,
                   cmt: cmt
               }

               fetch('cmt', {
                   method: 'POST',
                   headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json'
                   },
                   body: JSON.stringify(param)
               })
                   .then(res => res.json())
                   .then(myJson => {
                       console.log(myJson);
                       switch(myJson) {
                           case 0:
                               alert('๋Œ“๊ธ€์„ ๋“ฑ๋กํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.');
                               break;
                           case 1:
                               //๋Œ“๊ธ€ ์ถ”๊ฐ€ํ•œ๋‹ค.
                               const globalConstElem = document.querySelector('#globalConst');

                               const param = { ...globalConstElem.dataset };
                               param.cmt = cmtInput.value;

                               const cmtItemDiv = this.makeCmtItem(param);
                               cmtListDiv.append(cmtItemDiv);

                               cmtInput.value = '';
                               break;
                       }
                   })
                   .catch(err => {
                       console.log(err);
                   });
            });

            cmtFormDiv.append(cmtInput);
            cmtFormDiv.append(cmtBtn);

            itemContainer.append(cmtDiv);
            this.containerElem.append(itemContainer);
        }
        if(this.swiper != null) { this.swiper = null; }
        this.swiper = new Swiper('.swiper-container', {
            direction: 'horizontal',
            loop: false,
        });
    },
  • makeCmtItem(obj)
    makeCmtItem: function({iuser, writerProfile, writer, cmt}) {
        const cmtItemContainerDiv = document.createElement('div');
        cmtItemContainerDiv.className = 'cmtItemCont';

        //ํ”„๋กœํ•„
        const cmtItemProfileDiv = document.createElement('div');
        cmtItemProfileDiv.className = 'cmtItemProfile';
        const cmtItemWriterProfileImg = document.createElement('img');
        cmtItemWriterProfileImg.src = `/pic/profile/${iuser}/${writerProfile}`;
        cmtItemWriterProfileImg.className = 'profile wh30 pointer';
        cmtItemWriterProfileImg.addEventListener('click', () => {
            moveToProfile(iuser);
        });

        cmtItemProfileDiv.append(cmtItemWriterProfileImg);
        cmtItemContainerDiv.append(cmtItemProfileDiv);

        //๋Œ“๊ธ€
        const cmtItemCtntDiv = document.createElement('div');
        cmtItemCtntDiv.className = 'cmtItemCtnt';
        cmtItemCtntDiv.innerHTML = `<div class="pointer"token interpolation">${iuser});">${writer}</div><div>${cmt}</div>`;
        cmtItemContainerDiv.append(cmtItemCtntDiv);

        return cmtItemContainerDiv;
    }

<div class='item'>  * ์—ฌ๋Ÿฌ๋ฒˆ ๋ฐ˜๋ณต 
   //๊ธ€์“ด์ด ์ •๋ณด ์˜์—ญ
  <div class='top'>
      <div class="itemProfileCont">
              <img src="/pic/profile/${item.iuser}/${item.mainProfile}" class="pointer profile wh30" 
                              onclick="moveToProfile(${item.iuser});" onerror="this.style.display='none';">
      </div>
      <div>
          <div>
              <span class="pointer" onclick="moveToProfile(${item.iuser});">${item.writer}</span> - ${regDtInfo}
          </div>
          <div>${item.location == null ? '' : item.location}</div>
      </div>
  </div>

  //์ด๋ฏธ์ง€ ์˜์—ญ
  <div class="itemImg">
    <div class="swiper-container">
        <div class="swiper-wrapper">
          <div class="swiper-slide"> * ์—ฌ๋Ÿฌ๋ฒˆ ๋ฐ˜๋ณต 
            <img src="/pic/feed/${item.ifeed}/${imgObj.img}">
          </div>
      </div>
    </div>
  </div>

   //์ข‹์•„์š” ์˜์—ญ
  <div class="favCont">
    <i class="fa-heart pointer"></i>   ๐Ÿ‘‰ click ๐Ÿ‘‰ fav?ifeed=${item.ifeed}&type=${item.isFav}
    <span>${item.favCnt}</span>
  </div>

   //๊ธ€ ๋‚ด์šฉ ์˜์—ญ
  <div class="itemCtnt">${item.ctnt}</div>

  //๋Œ“๊ธ€์˜์—ญ 
  <div>
    <div>
      <div>
          <div> ๐Ÿ‘‰ cmtListDiv
              <span>๋Œ“๊ธ€๋”๋ณด๊ธฐ</span> ๐Ÿ‘‰ click ๐Ÿ‘‰ remove() ๐Ÿ‘‰ cmt?ifeed=${item.ifeed}  
          </div>                                        ๐Ÿ‘‰ makeCmtItem(obj) * ๋ฐ˜๋ณต
      </div>
    </div>
  
    <input type="text" placeholder="๋Œ“๊ธ€..." onkeyup="์—”ํ„ฐโ†’cmtBtn.click()"></input>
    <input type="button" value="๋“ฑ๋ก"></input> ๐Ÿ‘‰ click ๐Ÿ‘‰ cmt(item.ifeed, cmtInput.value)
                                          ๐Ÿ‘‰ makeCmtItem({ ...globalConstElem.dataset }) ๐Ÿ‘‰  cmtListDiv.append()
  </div>
</div>

๐ŸŸฆ home.html


<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorator="basicLayout">
    <th:block layout:fragment="css">
        <link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.min.css">
        <link rel="stylesheet" th:href="@{/css/feed/home.css}">
    </th:block>

    <th:block layout:fragment="js">
        <script src="https://unpkg.com/swiper/swiper-bundle.min.js"></script>
        <script defer th:src="@{/js/feed.js}"></script>
        <script defer th:src="@{/js/feed/home2.js}"></script>
    </th:block>

    <th:block layout:fragment="content">
        <div id="feedContainer"></div>
        <div class="loading hide"><img th:src="@{/img/loading.gif}"></div>
    </th:block>
</html>

๐ŸŸฆ ๊ฒฐ๊ณผ

    <th:block layout:fragment="content">
        <div id="feedContainer">
            <div class='item'>  * ์—ฌ๋Ÿฌ๋ฒˆ ๋ฐ˜๋ณต 
               //๊ธ€์“ด์ด ์ •๋ณด ์˜์—ญ
              <div class='top'>
                  <div class="itemProfileCont">
                          <img src="/pic/profile/${item.iuser}/${item.mainProfile}" class="pointer profile wh30" 
          onclick="moveToProfile(${item.iuser});" onerror="this.style.display='none';">
                  </div>
                  <div>
                      <div>
                          <span class="pointer" onclick="moveToProfile(${item.iuser});">${item.writer}</span> - ${regDtInfo}
                      </div>
                      <div>${item.location == null ? '' : item.location}</div>
                  </div>
              </div>
            
              //์ด๋ฏธ์ง€ ์˜์—ญ
              <div class="itemImg">
                <div class="swiper-container">
                    <div class="swiper-wrapper">
                      <div class="swiper-slide"> * ์—ฌ๋Ÿฌ๋ฒˆ ๋ฐ˜๋ณต 
                        <img src="/pic/feed/${item.ifeed}/${imgObj.img}">
                      </div>
                  </div>
                </div>
              </div>
            
               //์ข‹์•„์š” ์˜์—ญ
              <div class="favCont">
                <i class="fa-heart pointer"></i>๐Ÿ‘‰ click ๐Ÿ‘‰ fav?ifeed=${item.ifeed}&type=${item.isFav}
                <span>${item.favCnt}</span>
              </div>
            
               //๊ธ€ ๋‚ด์šฉ ์˜์—ญ
              <div class="itemCtnt">${item.ctnt}</div>
            
              //๋Œ“๊ธ€์˜์—ญ 
              <div>
                <div>
                  <div>
                      <div> ๐Ÿ‘‰ cmtListDiv
                          <span>๋Œ“๊ธ€๋”๋ณด๊ธฐ</span> ๐Ÿ‘‰ click ๐Ÿ‘‰ remove() ๐Ÿ‘‰ cmt?ifeed=${item.ifeed}  
                      </div>                                        ๐Ÿ‘‰ makeCmtItem(obj) * ๋ฐ˜๋ณต
                  </div>
                </div>
              
                <input type="text" placeholder="๋Œ“๊ธ€..." onkeyup="์—”ํ„ฐโ†’cmtBtn.click()"></input>
                <input type="button" value="๋“ฑ๋ก"></input> ๐Ÿ‘‰ click ๐Ÿ‘‰ cmt(item.ifeed, cmtInput.value)
                     ๐Ÿ‘‰ makeCmtItem({ ...globalConstElem.dataset }) ๐Ÿ‘‰  cmtListDiv.append()
              </div>
            </div>
        </div>
        <div class="loading hide"><img th:src="@{/img/loading.gif}"></div>
    </th:block>

๐ŸŸฆ feed.js๊ฐ€ ๋Œ์•„๊ฐ€๋Š” ๊ตฌ์กฐ

  • ์ฒ˜์Œ getFeedList ํ˜ธ์ถœ
    โ†ณ ์—ฌ๊ธฐ์„œ makeFeedList ํ˜ธ์ถœ
  • ์Šคํฌ๋กค (์ด ๋ถ€๋ถ„์ด ๊ณ„์† ๋ฐ˜๋ณต)
    โ†ณ ์—ฌ๊ธฐ์„œ getFeedList ํ˜ธ์ถœ
    โ†ณ ์—ฌ๊ธฐ์„œ makeFeedList ํ˜ธ์ถœ

โœ… feed.js - getFeedList

    getFeedList: function(page) {
        this.showLoading();

        fetch(`${this.url}?iuserForMyFeed=${this.iuser}&page=${page}&limit=${this.limit}`)
            .then(res => res.json())
            .then(myJson => {
                console.log(myJson);
                this.itemLength = myJson.length;
                this.makeFeedList(myJson);
            }).catch(err => {
            console.log(err);
        }).then(() => {
            this.hideLoading();
        });
    },

โœ… FeedDTO

  • int page
  • int limit
  • int iuserForMyFeed
  • int iuserForFav
  • int getStarIdx() {return (page-1) * limit}

โœ… FeedController

@ResponseBody
@GetMapping("list2")
public List<FeedDomain2> selFeedList2(FeedDTO param) {
  return service.selFeedList2(param);
}

โœ… FeedService

public List<FeedDomain2> selFeedList2(FeedDTO param) {
  param.setIuserForFav(auth.getLoginUserPk());
  return mapper.selFeedList2(param);
}

โœ… FeedDomain2

  • int iFeed
  • String location
  • String ctnt
  • int iuser
  • String regdt
  • String writer
  • String mainProfile
  • int favCnt
  • int isFav
  • List<FeedImgEntity> imgList
  • FeedCmtDomain cmt

โœ… FeedMapper

List<FeedDomain2> selFeedList2(FeedDTO param);

  • iuserForMyFeed : 0
  • page : 1
  • limit : 5
  • iuserForFav : ๋‚˜
  • starIdx : 0 โ†’ 5 โ†’ 10 โ†’ 15...
SELECT
A.ifeed, A.location, A.ctnt, A.iuser, A.regdt
, C.nm AS writer, C.mainProfile, IFNULL(E.cnt, 0) AS favCnt
<if test="iuserForFav > 0"> ๐Ÿ‘‰๐ŸŸฆtrue๐ŸŸฆ
, CASE WHEN D.ifeed IS NULL THEN 0 ELSE 1 END AS isFav
</if>
FROM t_feed A
INNER JOIN t_user C
ON A.iuser = C.iuser  ๐Ÿ‘‰๐ŸŸฆ์–ด๋–ค ์‚ฌ๋žŒ๋“ค์ด(nm, mainProfile) ์“ด ๊ธ€๋“ค์˜ 
                        ifeed, location, ctnt, iuser, regdt, ์ข‹์•„์š”๊ฐฏ์ˆ˜์™€ ๊ฐ๊ฐ์˜ ๊ธ€๋“ค์— 
                        ๋‚ด๊ฐ€ ์ข‹์•„์š” ํ–ˆ๋Š”์ง€ ์—ฌ๋ถ€ isFav๊ฐ€ ๊ฐ๊ฐ ๋ชจ์—ฌ์„œLIST๊ฐ€ ๋œ๋‹ค.  ๐ŸŸฆ
<if teset="iuserForMyFeed > 0"> ๐Ÿ‘‰๐ŸŸฆfalse๐ŸŸฆ
AND C.iuser = ${iuserForMyFeed} ๐Ÿ‘‰๐ŸŸฆ๋งŒ์•ฝ true๋ผ๋ฉด ๋‚ด๊ฐ€ ํŒ”๋กœ์šฐํ•œ ์‚ฌ๋žŒ๋“ค์˜ ๊ธ€๋งŒ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.๐ŸŸฆ
</if>
LEFT JOIN (
SELECT ifeed, COUNT(ifeed) AS cnt
FROM t_feed_fav
GROUP BY ifeed
) E  ๐Ÿ‘‰๐ŸŸฆ๊ทธ ๊ธ€์˜ ์ข‹์•„์š” ๊ฐฏ์ˆ˜ , ์œ„์—์„œ E.cnt๋กœ ์“ฐ์ธ๋‹ค๐ŸŸฆ 
ON A.ifeed = E.ifeed
<if test="iuserForFav > 0"> ๐Ÿ‘‰๐ŸŸฆtrue๐ŸŸฆ
LEFT JOIN t_feed_fav D
ON D.iuser = ${iuserForFav} ๐Ÿ‘‰๐ŸŸฆ๊ทธ ๊ธ€์— ๋‚˜๋Š” ์ข‹์•„์š” ๋ˆŒ๋ €๋Š”์ง€ ์—ฌ๋ถ€๐ŸŸฆ
AND A.ifeed = D.ifeed   ๐Ÿ‘‰๐ŸŸฆ์œ„์—์„œ D.ifeed๋ผ๊ณ  ์“ฐ์ธ๋‹ค๐ŸŸฆ
</if>
ORDER BY ifeed DESC ๐Ÿ‘‰๐ŸŸฆ๋ฆฌ์ŠคํŠธ๋ฅผ ์ตœ์‹ ์ˆœ์œผ๋กœ ๋‚˜์—ดํ•œ๋‹ค๐ŸŸฆ
LIMIT #{starIds} , #{limit} ๐Ÿ‘‰๐ŸŸฆ0, 5 โ†’ ๊ฐ€์žฅ ์ฒ˜์Œ๋ถ€ํ„ฐ 5๊ฐœ๋ฅผ๐ŸŸฆ

<resultMap id="FeedDomainMap" type="FeedDomain2">
    <result property="ifeed" column="ifeed"></result>
    <association property="cmt" column="ifeed" select="selFeedCmt"></association>
    <collection property="imgList" column="ifeed" select="selFeedImgList"></collection>
</resultMap>

<select id="selFeedCmt" resultType="FeedCmtDomain">
    SELECT A.*, COUNT(A.icmt) - 1 AS isMore
    FROM (
        SELECT
            A.icmt, A.cmt, A.regdt, A.ifeed
            , B.iuser, B.nm as writer, B.mainProfile as writerProfile
        FROM t_feed_cmt A
        INNER JOIN t_user B
        ON A.iuser = B.iuser
        WHERE A.ifeed = ${ifeed}
        ORDER BY icmt ASC
        LIMIT 2
    ) A
    GROUP BY A.ifeed
</select>

<select id="selFeedImgList" resultType="FeedImgEntity">
    SELECT ifeedimg, ifeed, img FROM t_feed_img
    WHERE ifeed = #{ifeed}
</select>
profile
๋ช‡ ๋ฒˆ์„ ๋„˜์–ด์ ธ๋„ ์•ž์œผ๋กœ ๊ณ„์† ๋‚˜์•„๊ฐ€์ž

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