템플릿 방식 vs 기존 DOM 방식, tailwind 스타일링 하기

dev__bokyoung·2022년 9월 2일
0

해커뉴스 클론코딩

목록 보기
5/12
post-thumbnail

프롤로그

마크업을 그릴 때 js 로 하다보니 DOM 을 많이 건드리는 방식을 사용했다. id=root 를 잡아서 createElement를 하고 appendChild 를 하고.. 그런데 이 방식의 단점은 직관적으로 마크업의 구조를 볼 수 없다는 것이다. (개발자 입장에서)

그래서 문자열을 사용하는 방식으로 조금 개선을 했었다. 빽틱(``)을 활용한 템플릿 방식을 사용했는데 이 부분도 li 처럼 반복되는 부분이 있으면 배열을 사용해야 했고, 배열의 사용도 여전히 한계가 존재 했다.

코드가 간단할때야 문제가 없지만 코드가 복잡해 지기 시작하면 코드상 ui 구조 파악이 쉽지 않기 때문이다. 그래서 조금 더 코드를 명확하게 볼 수 있는 템플릿 구조를 사용해 보고자 한다.

템플릿 방식으로 변경을 하고 나서 tailwind 를 이용해서 UI 를 스타일링 하기로 한다.

1. 템플릿 방식

function newsFeed() {
  const newsFeed = getData(NEWS_URL);
  const newsList = [];
  let template = `
    <div class="container mx-auto p-4">
      <h1>Hacker News</h1>
      <ul>
        {{__news_feed__}}      
      </ul>
      <div>
        <a href="#/page/{{__prev_page__}}">이전 페이지</a>
        <a href="#/page/{{__next_page__}}">다음 페이지</a>
      </div>
    </div>
  `;

  for(let i = (store.currentPage - 1) * 10; i < store.currentPage * 10; i++) {
    newsList.push(`
      <li>
        <a href="#/show/${newsFeed[i].id}">
          ${newsFeed[i].title} (${newsFeed[i].comments_count})
        </a>
      </li>
    `);
  }

  template = template.replace('{{__news_feed__}}', newsList.join(''));
  template = template.replace('{{__prev_page__}}', store.currentPage > 1 ? store.currentPage - 1 : 1);
  template = template.replace('{{__next_page__}}', store.currentPage + 1);
  
  container.innerHTML = template;
}

전체 코드를 작성해 놓고 데이터가 들어갈 부분을 {{__news__feed__}} 이런 식으로 작성해서 이후에 replace 해준다. (오호 이 부분은 좀 신선했다.🧐)

템플릿 사용의 장점은 이것이다.

  • 코드 상 ui 를 알아보기 쉽다.
  • 어떤 데이터가 들어가는 지 한눈에 파악하기 쉽다.

하지만, 이 부분도 여전한 한계가 존재 한다.

2. tailwind 로 ui 스타일링 하기

사용된 스펙

fontawsome
tailwind

function newsFeed() {
  const newsFeed = getData(NEWS_URL);
  const newsList = [];
  let template = `
    <div class="bg-gray-600 min-h-screen">
      <div class="bg-white text-xl">
        <div class="mx-auto px-4">
          <div class="flex justify-between items-center py-6">
            <div class="flex justify-start">
              <h1 class="font-extrabold">Hacker News</h1>
            </div>
            <div class="items-center justify-end">
              <a href="#/page/{{__prev_page__}}" class="text-gray-500">
                Previous
              </a>
              <a href="#/page/{{__next_page__}}" class="text-gray-500 ml-4">
                Next
              </a>
            </div>
          </div> 
        </div>
      </div>
      <div class="p-4 text-2xl text-gray-700">
        {{__news_feed__}}        
      </div>
    </div>
  `;

    for(let i = (store.currentPage - 1) * 10; i < store.currentPage * 10; i++) {
    newsList.push(`
      <div class="p-6 bg-white mt-6 rounded-lg shadow-md transition-colors duration-500 hover:bg-green-100">
        <div class="flex">
          <div class="flex-auto">
            <a href="#/show/${newsFeed[i].id}">${newsFeed[i].title}</a>  
          </div>
          <div class="text-center text-sm">
            <div class="w-10 text-white bg-green-300 rounded-lg px-0 py-2">${newsFeed[i].comments_count}</div>
          </div>
        </div>
        <div class="flex mt-3">
          <div class="grid grid-cols-3 text-sm text-gray-500">
            <div><i class="fas fa-user mr-1"></i>${newsFeed[i].user}</div>
            <div><i class="fas fa-heart mr-1"></i>${newsFeed[i].points}</div>
            <div><i class="far fa-clock mr-1"></i>${newsFeed[i].time_ago}</div>
          </div>  
        </div>
      </div>    
    `);
  }

  template = template.replace('{{__news_feed__}}', newsList.join(''));
  template = template.replace('{{__prev_page__}}', store.currentPage > 1 ? store.currentPage - 1 : 1);
  template = template.replace('{{__next_page__}}', store.currentPage + 1);
  
  container.innerHTML = template;
}

목록 부분 이미지 결과

function newsDetail() {
  const id = location.hash.substr(7);
  const newsContent = getData(CONTENT_URL.replace('@id', id))
  let template = `
    <div class="bg-gray-600 min-h-screen pb-8">
      <div class="bg-white text-xl">
        <div class="mx-auto px-4">
          <div class="flex justify-between items-center py-6">
            <div class="flex justify-start">
              <h1 class="font-extrabold">Hacker News</h1>
            </div>
            <div class="items-center justify-end">
              <a href="#/page/${store.currentPage}" class="text-gray-500">
                <i class="fa fa-times"></i>
              </a>
            </div>
          </div>
        </div>
      </div>

      <div class="h-full border rounded-xl bg-white m-6 p-4 ">
        <h2>${newsContent.title}</h2>
        <div class="text-gray-400 h-20">
          ${newsContent.content}
        </div>

        {{__comments__}}

      </div>
    </div>
  `;

  
}

상세 페이지 부분

에필로그

tailwind 같은 라이브러리는 클래스 명이 정해져 있어 관리자 페이지 같이 깔끔하거나 카드 박스 형태의 디자인이 있을 때에는 사용 하기 좋을 것 같다. 하지만 디자인 작업이 많이 들어갔다면 조금 한계가 있을 듯 하다.

profile
개발하며 얻은 인사이트들을 공유합니다.

0개의 댓글