공청
개발하는 금융인
공청
전체 방문자
오늘
어제
  • 분류 전체보기 (102)
    • 개인적인 이야기 (27)
    • IT에 관한 글 (15)
    • 경제, 금융 (12)
    • Python (2)
    • Javascript (6)
    • golang (2)
    • 비전공자를 위한 IT 지식 (0)
    • SQL (SQLD,SQLP) (1)
    • React (Front-end) (29)
    • 정보처리기사 (0)
    • Typescript (4)
    • (study) 모던 자바스크립트 Deep Dive (0)

블로그 메뉴

  • 홈
  • 태그
  • 미디어로그
  • 방명록
  • 글쓰기

공지사항

인기 글

태그

  • react
  • 트래블카드
  • 짧은생각
  • python
  • Fira Code
  • 언섹시비즈니스
  • Effective Typescript
  • vite
  • useref
  • next.js
  • vscode
  • go
  • approute
  • HTTP
  • 일기
  • 프로그래밍
  • 창업
  • 웹개발
  • 기술스택
  • 조건부렌더링
  • sql
  • 인터넷
  • 트래블월렛
  • WSGI
  • typescript
  • react-router
  • Golang
  • javascript
  • 미국주식
  • ChatGPT

최근 댓글

최근 글

티스토리

반응형
공청

개발하는 금융인

0. Hackers News 자바스크립트 코드 타입스크립트로 마이그레이션 시작
Typescript

0. Hackers News 자바스크립트 코드 타입스크립트로 마이그레이션 시작

2022. 12. 24. 22:51

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."

"블로그 내의 광고와 쿠팡 링크를 클릭해주시면 블로그 운영에 큰 힘이 됩니다."

반응형

 

타입스크립트 로고

1. 타입스크립트란?

타입스크립트(Typescript)는 타입이 유연한 자바스크립트에 좀 더 엄격하게 타입을 줄 수 있는 언어이다. 타입을 명시할 수 있는 버전의 자바스크립트라고 생각하면 되고, 여러 실수를 잡기 위해서 타입스크립트로 코딩한 다음에 자바스크립트로 변환해서 사용한다.

 

2. 변환할 코드

타입스크립트 공부를 위해서 Hackers News API를 통해 간단하게 구현한 예제를 사용할 것이다.

아래 예제를 타입스크립트로 부분적으로 바꿔볼 것이고, 바꾸면서 장점에 대해서도 함께 기술할 예정이다.

 

본 수업은 패스트캠퍼스의 "김민태의 프론트엔드 아카데미 : 제 1강 JS & TS Essential"의 내용을 따왔다.

 

 

예제 코드:

 

index.html

<!doctype html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
	<title>HN client</title>
	<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet" crossorigin="anonymous">
	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" />
</head>
<body>
	<noscript>
		You need to enable JavaScript to run this app.
	</noscript>
  <div id="root">
  </div>
  <script src="./app.js" type="module"></script>
</body>
</html>

 

app.js

const container = document.getElementById('root');
const ajax = new XMLHttpRequest();
const NEWS_URL = 'https://api.hnpwa.com/v0/news/1.json';
const CONTENT_URL = 'https://api.hnpwa.com/v0/item/@id.json';
const store = {
  currentPage: 1,
  feeds: [],
};

function getData(url) {
  ajax.open('GET', url, false);
  ajax.send();

  return JSON.parse(ajax.response);
}

function makeFeeds(feeds) {
  for (let i = 0; i < feeds.length; i++) {
    feeds[i].read = false;
  }

  return feeds;
}

function newsFeed() {
  let newsFeed = store.feeds;
  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>
  `;

  if (newsFeed.length === 0) {
    newsFeed = store.feeds = makeFeeds(getData(NEWS_URL));
  }

  for(let i = (store.currentPage - 1) * 10; i < store.currentPage * 10; i++) {
    newsList.push(`
      <div class="p-6 ${newsFeed[i].read ? 'bg-red-500' : '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>
  `;

  for(let i=0; i < store.feeds.length; i++) {
    if (store.feeds[i].id === Number(id)) {
      store.feeds[i].read = true;
      break;
    }
  }

  function makeComment(comments, called = 0) {
    const commentString = [];

    for(let i = 0; i < comments.length; i++) {
      commentString.push(`
        <div style="padding-left: ${called * 40}px;" class="mt-4">
          <div class="text-gray-400">
            <i class="fa fa-sort-up mr-2"></i>
            <strong>${comments[i].user}</strong> ${comments[i].time_ago}
          </div>
          <p class="text-gray-700">${comments[i].content}</p>
        </div>      
      `);

      if (comments[i].comments.length > 0) {
        commentString.push(makeComment(comments[i].comments, called + 1));
      }
    }

    return commentString.join('');
  }

  container.innerHTML = template.replace('{{__comments__}}', makeComment(newsContent.comments));
}

function router() {
  const routePath = location.hash;

  if (routePath === '') {
    newsFeed();
  } else if (routePath.indexOf('#/page/') >= 0) {
    store.currentPage = Number(routePath.substr(7));
    newsFeed();
  } else {
    newsDetail()
  }
}

window.addEventListener('hashchange', router);

router();

 

본 코드에 대한 설명은 "Javascript" 카테고리에 향후 게시할 예정이다.

 

예시코드를 실행하기 위해서는 "웹 번들링"을 진행해야한다.

이 코드는 parcel.js를 통해서 번들링을 진행했다.

 

기본적으로 parcel.js를 사용하는 방법을 알아야 한다.

 

 

3. 참고할만한 글

1) 타입스크립트 핸드북 (공식)

https://www.typescriptlang.org/docs/handbook/intro.html

 

Handbook - The TypeScript Handbook

Your first step to learn TypeScript

www.typescriptlang.org

 

2) Parcel.js 사용하기

https://ko.parceljs.org/getting_started.html

 

🚀 시작하기

 

ko.parceljs.org

 

끝!

반응형
    'Typescript' 카테고리의 다른 글
    • (Effective Typescript) 이펙티브 타입스크립트 스터디 시작!
    • 2. Parcel.js로 타입스크립트 컴파일
    • 1. 타입스크립트(Typescript) 세팅하기 - tsconfig.json
    공청
    공청
    투자, 프로그래밍, IT에 대한 글을 씁니다.

    티스토리툴바