차트 라이브러리 만들어보기 - 차트 라이브러리 구현

 

import template from './index.template';
import Chart from './lib/chart';

function main() {
  const conatiner = document.querySelector('#root');
  conatiner.innerHTML = template();

  const chart = new Chart('#chart');

  chart.percent = 75;
  chart.duration = 1000;
  chart.label = '충전중'

  chart.render();
}

document.addEventListener('DOMContentLoaded', main);

 

 

코드 진행은 기존의 구조와 비슷하다. index.js는 파일과 index.template.js라는 파일로 구성된다. 다른 웹앱과 마찬가지로 index.js 파일은 인스턴스를 생성하고 렌더링을 하는 등의 기능과 index.template.js는 html 태그들로 이루어진 template 파일이다. 템플릿 엔진은 handlebars를 사용한다.

 

const template = `
    <div class="min-h-screen bg-gray-100 py-6 flex flex-col justify-center sm:py-12">
    <!-- Container -->
    <div class="container mx-auto">
      <div class="flex justify-center px-6 my-12 ">
        <!-- Row -->
        <div class="w-full xl:w-3/4 lg:w-11/12 shadow-xl flex">
          <!-- Col -->
          <div
            class="w-full h-auto bg-gray-400 hidden lg:block lg:w-1/2 bg-cover rounded-l-lg"
            style="background-image: url('https://images.unsplash.com/photo-1602918386084-58983c3bafac?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1900&q=80')"            
          ></div>
          <!-- Col -->
          <div class="w-full lg:w-1/2 bg-white p-5 rounded-lg lg:rounded-l-none p-16">

            <h3 class="pt-4 text-2xl text-center mb-20">Javascript & Typescript Essential Chapter 5 - Chart</h3>

            <div id="chart"></div>
          </div>
        </div>
      </div>
    </div>
</div>
`;

export default Handlebars.compile(template);

main이라는 함수를 가지고 DOM 로드 이벤트를 통해 해당 페이지가 전부 로딩 됐을 때 main 함수를 실행한다. main 함수의 내용은 컨테이너의 템플릿을 지정하고 Chart라는 클래스에서 chart 인스턴스를 만들고 chart의 속성들을 지정해준 뒤 렌더링하는 과정을 거친다.

 

 

 

 

https://bit.ly/37BpXiC

 

패스트캠퍼스 [직장인 실무교육]

프로그래밍, 영상편집, UX/UI, 마케팅, 데이터 분석, 엑셀강의, The RED, 국비지원, 기업교육, 서비스 제공.

fastcampus.co.kr

 

본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.

 

#패스트캠퍼스 #패캠챌린지 #직장인인강 #직장인자기계발 #패스트캠퍼스후기 #김민태의프론트엔드아카데미:제1강JavaScript&TypeScriptEssential

차트 라이브러리 만들어보기 - 라이브러리 설계 원칙

 

코드를 생산하게 되면 코드를 사용하는 사람이 있기 마련이다. 그게 본인일 수도 있고 다른 사람이 될 수도 있다. 여기서 중요한 2가지의 관점이 있는데

 

첫번째로 인터페이스의 일관성이다. 여기서 인터페이스의 일관성이란 클래스나 함수부터 네이밍 처리하는 부분까지도 인터페이스의 영역이라 할 수 있다. 어느정도의 일관성이 있다면 사용하는 입장에서 꼭 매뉴얼을 보지 않고도 유추할 수 있다. 매뉴얼을 꼭 봐야하는 경우도 있겠지만 가능한 비슷한 기능이나 비슷한 처리를 하는 부분이라면 일관성있게 만드는 것은 중요하다.

 

두번 째는 오류처리의 일관성이다. 작동하는 도중에 에러가 발생 했을 시 해당하는 문제에 대해 예외를 던지거나 null 처리를 하는 등에 있어서 어떤 기준을 둘 것인지에 대한 일관성이 있어야 한다. 만약 같은 에러가 발생 하더라도 에러 처리하는 부분이 제각각이라면 사용자에게 불편함과 소프트웨어에 대한 거부감을 줄 수도 있다.

 

이러한 관점들 말고도 다른 부분도 있다. 프로그램을 개발하다보면 버전이라는 것이 생기게된다. 소프트웨어의 버그가 발생했거나 아니면 더 나은 방향으로의 소프트웨어를 개발하는데 있어서 버전은 꼭 필요할 것이다. 하지만 이 버전이 서로 정반대의 원칙을 가지고 있다면 이것은 또 다른 문제를 낳을 것이기 때문에 버전 관리에 대한 중요성도 필요하다. 

 

이에 관련해서 npm에서 관리하는 semantic versioning이라는 기법이 있다. 

 

https://docs.npmjs.com/about-semantic-versioning

 

About semantic versioning | npm Docs

Documentation for the npm registry, website, and command-line interface

docs.npmjs.com

 

여기서는 버전에 대한 어느정도의 규칙을 명명한다. 예를들어 1.1.2 등의 버전이 있다고하면 여기서 각각의 숫자들은 의미를 갖고있는데 첫번 째 숫자는 메이저 버전을 의미하고 가운데 숫자는 마이너 버전을 의미하고 마지막 숫자는 패치 버전을 의미한다. 패치 버전은 버그의 수정 등으로 기존의 사용자는 코드를 수정하지 않아도 사용할 수 있다. 마이너 버전은 라이브러리에 새로운 기능이 추가되거나 버그를 고쳤을 때다. 기존의 사용자 코드가 수정될 필요가 없을 수도 있고 있을 수도 있다. 메이저 버전은 새로운 기능이 추가 될 수도 있고 구조 자체가 변화 될 수도 있다는 의미이다.

 

따라서 이런 규칙을 보고 버전을 어떻게 관리할 것인지에 관해 정하고 소통하고 판단할 수 있어야 한다.

 

 

 

 

https://bit.ly/37BpXiC

 

패스트캠퍼스 [직장인 실무교육]

프로그래밍, 영상편집, UX/UI, 마케팅, 데이터 분석, 엑셀강의, The RED, 국비지원, 기업교육, 서비스 제공.

fastcampus.co.kr

 

본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.

 

#패스트캠퍼스 #패캠챌린지 #직장인인강 #직장인자기계발 #패스트캠퍼스후기 #김민태의프론트엔드아카데미:제1강JavaScript&TypeScriptEssential

차트 라이브러리 만들어보기 - 소프트웨어를 위한 소프트웨어

 

소프트웨어는 사용자들이 웹에 접속해서 여러가지 구현된 기능들을 사용하고 로그인이나 회원가입 등을 하는 일련의 과정 등의 서비스를 제공하는 것들이 될 수도 있고, 앱을 다운로드하여 그 앱에 구현된 기능들을 사용하고 그에 관련된 서비스를 제공 받는 앱이라고 할 수도 있다.

 

하지만 사용자의 관점에서 뿐만 아니라 개발자의 관점에서도 소프트웨어는 존재한다. 어떤 소프트웨어를 개발한다고 했을 때, A부터 Z까지 모든 기능을 개발하지는 않는다. 여러가지 소프트웨어들을 결합시키고 조합해서 더 나은 구조나 또 다른 소프트웨어를 만든다.

 

프로젝트 범위 내에서 사용하는 소프트웨어(해당하는 장에서 만드는 chart 등)나 프로젝트 범위만이 아닌 전체적으로 사용될 수 있다. 기능을 가져다 쓸 수 있는 소프트웨어는 라이브러리나 프레임워크가 될 것이다. 우리가 코딩해서 만드는 모든 것들이 소프트웨어다. 그렇기때문에 항상 어떤 생각으로 소프트웨어를 만들 것인가에 대한 마인드를 가지고 있는 것은 중요하다. 최소한으로 나만 쓸 기능이라고 하더라도 어떻게 하면 더 잘 쓸 수 있는 구조인가에 대해 생각해 볼 필요가 있다.

 

src
  |- lib
    |- out
      |- fonts
        ...
      |- scripts
        ...
      |- styles
        ...
      ...
      chart.js
      chart.min.js
      chart.template.js
  - index.js
  - index.template.js
- index.html
- readme.md

 

 

 

 

 

https://bit.ly/37BpXiC

 

패스트캠퍼스 [직장인 실무교육]

프로그래밍, 영상편집, UX/UI, 마케팅, 데이터 분석, 엑셀강의, The RED, 국비지원, 기업교육, 서비스 제공.

fastcampus.co.kr

 

본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.

 

#패스트캠퍼스 #패캠챌린지 #직장인인강 #직장인자기계발 #패스트캠퍼스후기 #김민태의프론트엔드아카데미:제1강JavaScript&TypeScriptEssential

차트 라이브러리 만들어보기 - 그래픽 시스템 Overview

 

이번 장에서는 그래픽 시스템에 관하여, 개발자를 위한 소프트웨어에 관해 설명한다. 간단한 차트 라이브러리를 만들기위해서 그래픽 시스템을 이용할 것인데 대체적으로 canvas, SVG, WebGL 등이 있다. 각각의 그래픽 시스템들은 차이가 있다.

 

canvas 같은 경우는 2D 그래픽 시스템으로 점과 선으로 이루어져 있다. canvas 태그를 이용한 다양한 API를 사용할 수 있다. 자바스크립트의 함수로 점 찍고 선 그리는 등의 작업을 한다. 점과 선이라고 하면 되게 아무것도 없는 것처럼 보이겠지만 사실 그래픽의 모든 것들은 점과 선으로 이루어져 있기때문에 모든걸 다 가진 것이다.

 

SVG는 벡터 그래픽 시스템으로 캔버스처럼 2D 그래픽 시스템을 다루지만 저 수준의 자바스크립트 api를 가지고 그래픽을 구사하는 것이 아니라 html 태그를 이용하여 구사할 수 있는 스펙이다. 상대적으로 다루기가 쉽다는 장점이 있다. 또한 여러가지의 스펙이 제공되기 때문에 로고나 아이콘, 차트 등의 여러가지를 만들 수 있으며 알고있다면 운영 범위가 넓기 때문에 상용하기도 좋다.

 

WebGL 같은 경우는 3D 그래픽 시스템을 다룬다. 작업을 하다보면 2D 그래픽 시스템으로 할 수 없는 부분이 있다. 2D 그래픽은 대량의 데이터를 그래픽으로 변경 시 성능이 너무 떨어지는 경우나 심하면 제대로된 작동이 안될 수 있다. 그럴 때는 WebGL 같은 3D 그래픽 시스템을 이용하여 GPU를 사용하여 2D 그래픽 시스템으로 할 수 없는 부분을 동작하게 할 수도 있을 것이다.

 

이번 장에서는 SVG를 사용하여 그래픽 시스템을 구사한다.

 

 

 

 

https://bit.ly/37BpXiC

 

패스트캠퍼스 [직장인 실무교육]

프로그래밍, 영상편집, UX/UI, 마케팅, 데이터 분석, 엑셀강의, The RED, 국비지원, 기업교육, 서비스 제공.

fastcampus.co.kr

 

본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.

 

#패스트캠퍼스 #패캠챌린지 #직장인인강 #직장인자기계발 #패스트캠퍼스후기 #김민태의프론트엔드아카데미:제1강JavaScript&TypeScriptEssential

로그인 병렬 - 예외 처리 흐름 설계

 

로그인을 처리하는 부분에서 오류가 났을 때의 처리에 대해 추가적으로 생각해봐야 할 부분이 있다. 먼저 현재 #onSubmit 메소드 부분의 코드를 확인해 보면

 

import template from './login.template';
import TextField from '../views/text-field';
import axios  from 'axios';

export default class Login {
  #template = template;
  #data;
  #container;
  #loginFail = false;
  #fields = [];

  constructor(container, data) {
    ...
  }

  #initialize = () => {
    ...
  }

  #onSubmit = e => {
    e.preventDefault();

    const loginData = this.#fields
      .map(field => ({ [field.name]: field.value }))
      .reduce((a, b) => ({ ...a, ...b }), {});

    axios.post('/api/authentication', loginData)
      .then(result => {
        return result.data.result;
      })
      .then(({ id, token }) => {
        const options = { headers: { token } };
        this.#data.store.token = token;

        return axios.all([
          axios.get(`/api/user/${id}`, options),
          axios.get(`/api/user/${id}/posts`, options),
        ]);
      })
      .then(([profile, posts]) => {
        this.#data.store.userProfile = profile.data.result;
        this.#data.store.userPosts = posts.data.results;

        location.href = '/#/profile';
      })
      .catch(error => {      
        this.#loginFail = true;
        this.render();
      });
  }

  render = () => {
    ...
  }
}

데이터를 처리하는 부분의 Promise리턴을 3번에 걸쳐서 한다. 여기서 한번 주의해서 봐야할 점은 catch() 부분이 하나라는 것이다. 그 말은 로그인을 실패해도 하나 있는 catch() 부분에 걸리고 로그인은 성공하더라도 사용자의 정보를 받아오는 부분, axios의 데이터를 가져오는 부분에서 실패하게되도 하나의 catch()에서 걸리게 된다. 따라서, 동작이 실패가 됐을 때, 어디에서 실패를 했는지 정확하게 알 수가 없다는 것이다. 

 

이 작업에서 로그인이 실패했을 경우, 로그인이 실패했다는 정보나 데이터를 가져오는 부분에서 실패 했을 시에 데이터를 가져오는 부분에서 실패를 했다고 나타내주는 로직이 추가되면 좋을 것이다.

 

import template from './login.template';
import TextField from '../views/text-field';
import axios  from 'axios';

export default class Login {
  #template = template;
  #data;
  #container;
  #loginFail = false;
  #fields = [];

  constructor(container, data) {
    ...
  }

  #initialize = () => {
    ...
  }

  #onSubmit = e => {
    e.preventDefault();

    const loginData = this.#fields
      .map(field => ({ [field.name]: field.value }))
      .reduce((a, b) => ({ ...a, ...b }), {});

    axios.post('/api/authentication', loginData)
      .then(result => {
        return result.data.result;
      })
      .then(({ id, token }) => {
        const options = { headers: { token } };
        this.#data.store.token = token;

        axios.all([
          axios.get(`/api/user/${id}`, options),
          axios.get(`/api/user/${id}/posts`, options),
        ]).then(([profile, posts]) => {
          this.#data.store.userProfile = profile.data.result;
          this.#data.store.userPosts = posts.data.results;
  
          location.href = '/#/profile';
        }).catch(error => {      
          this.#loginFail = true;
          this.render();
        });
      })
      .catch(error => {      
        this.#loginFail = true;
        this.render();
      });
  }

  render = () => {
    ...
}

로그인 처리가 발생 했을 때 성공인지 에러인지의 처리와 데이터를 가져오는 부분에서의 성공과 에러의 처리를 나눴다. axios.all 메소드를 통해서 데이터를 불러 올때 return 하는 것이 아니라 또 다른 하나의 Promise를 반환하여 성공 시 then()을 통해 데이터를 반환하고 실패시 데이터를 불러오는 부분에서 실패하는 로직을 구현하면 두 작업을 구분해서 실행 할 수 있다.

 

 

 

 

https://bit.ly/37BpXiC

 

패스트캠퍼스 [직장인 실무교육]

프로그래밍, 영상편집, UX/UI, 마케팅, 데이터 분석, 엑셀강의, The RED, 국비지원, 기업교육, 서비스 제공.

fastcampus.co.kr

 

본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.

 

#패스트캠퍼스 #패캠챌린지 #직장인인강 #직장인자기계발 #패스트캠퍼스후기 #김민태의프론트엔드아카데미:제1강JavaScript&TypeScriptEssential

로그인 병렬 - 연속적 비동기 API 처리의 이해

 

로그인 처리를 하는 서버와의 통신에는 비동기 처리가 필요하다. 단순히 화면이 바뀌는 동작만이 아니라면 서버와의 통신간에 연결이 끊어질 수도 있고 다른 에러가 발생할 경우가 있기 때문에 비동기 처리를 이용한다.

 

하지만 이번 로그인 처리에선 2가지의 API를 병렬적으로 처리한다. 그렇게 데이터를 받기 위해서 axios 라이브러리를 사용한다. axios에서 지원하는 메소드중에 all 메소드를 통해 2가지의 API 데이터를 받아서 두가지의 서버 비동기 처리를 한 후에 완료 후에 데이터를 반환 받아서 사용한다.

 

import template from './login.template';
import TextField from '../views/text-field';
import axios  from 'axios';

export default class Login {
  #template = template;
  #data;
  #container;
  #loginFail = false;
  #fields = [];

  constructor(container, data) {
    this.#container = document.querySelector(container);
    this.#data = data;

    this.#initialize();
  }

  #initialize = () => {
    ...
  }

  #onSubmit = e => {
    e.preventDefault();

    const loginData = this.#fields
      .map(field => ({ [field.name]: field.value }))
      .reduce((a, b) => ({ ...a, ...b }), {});

    axios.post('/api/authentication', loginData)
      .then(result => {
        return result.data.result;
      })
      .then(({ id, token }) => {
        const options = { headers: { token } };
        this.#data.store.token = token;

        return axios.all([
          axios.get(`/api/user/${id}`, options),
          axios.get(`/api/user/${id}/posts`, options),
        ]);
      })
      .then(([profile, posts]) => {
        this.#data.store.userProfile = profile.data.result;
        this.#data.store.userPosts = posts.data.results;

        location.href = '/#/profile';
      })
      .catch(error => {      
        this.#loginFail = true;
        this.render();
      });
  }

  render = () => {
    ...
  }
}

#onSubmit 메소드를 실행하게되면 고유의 submit 메소드의 동작은 막는다. 기존의 submit 기능은 페이지의 전환이 일어나는데 페이지의 이동을 막기 위해 사용한다. fields 배열에 데이터를 배열로 해당하는 데이터는 Promise 패턴을 이용해서 then의 실행이 완료 될때마다 Promise를 반환하는 형식이다. 

 

 

 

 

https://bit.ly/37BpXiC

 

패스트캠퍼스 [직장인 실무교육]

프로그래밍, 영상편집, UX/UI, 마케팅, 데이터 분석, 엑셀강의, The RED, 국비지원, 기업교육, 서비스 제공.

fastcampus.co.kr

 

본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.

 

#패스트캠퍼스 #패캠챌린지 #직장인인강 #직장인자기계발 #패스트캠퍼스후기 #김민태의프론트엔드아카데미:제1강JavaScript&TypeScriptEssential

로그인 앱 설계

 

로그인을 하기위해 서버에서는 로그인 할 당시에 권한처리나, 토큰 유지, API를 통해서 프로필 데이터를 JSON 형식으로 받아오는 등의 데이터 처리나 라우팅에 관한 작업들을 진행했다.

 

이번에는 클라이언트에서 서버에서 가져오는 데이터에 맞게 또는 라우팅이 변함에 따라 화면 부분을 변경하는 작업을 할 것이다.

 

import Store from './store';
import Login from './page/login';
import Profile from './page/profile';
import PageNotFound from './page/page-not-found';

const store = new Store();

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

  switch(path) {
    case '':
    case '#/login':
      const login = new Login('#root', {
        store,
        title: 'JS & TS Essential'
      });
      login.render();
      break;
    case '#/profile':
      const profile = new Profile('#root', { store });
      profile.render();
      break;
    default:
      const pageNotFound = new PageNotFound('#root');
      pageNotFound.render();
      break;
  }
}

window.addEventListener('hashchange', router);
document.addEventListener('DOMContentLoaded', router);

클라이어트에서 라우팅 처리를 하기위해서 hash 형식을 사용한다. 이벤트리스너에 hashChange를 등록하고 해시가 변경됨에 따라 화면을 변경하는 방식인데 SPA를 구현하는 하나의 방식이다. 또한 Store 객체를 선언해서 전역적으로 Store에 관련된 필드나 변수 등을 사용한다. 로그인 페이지와 프로필 페이지로 나뉘고 해당하는 해시 값으로 url이 변경 될때마다 각각 해당하는 Login, Profile 인스턴스가 생성되고 render 메소드로 렌더링을 한다. 만약 처리하는 페이지에 url이 다른 값이 입력 됐을 시 미리 만들어 둔 pageNotFound 를 불러온다.

 

 

 

 

https://bit.ly/37BpXiC

 

패스트캠퍼스 [직장인 실무교육]

프로그래밍, 영상편집, UX/UI, 마케팅, 데이터 분석, 엑셀강의, The RED, 국비지원, 기업교육, 서비스 제공.

fastcampus.co.kr

 

본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.

 

#패스트캠퍼스 #패캠챌린지 #직장인인강 #직장인자기계발 #패스트캠퍼스후기 #김민태의프론트엔드아카데미:제1강JavaScript&TypeScriptEssential

로그인 앱 설계

 

server를 다루는 index.js 파일엔 인증처리를 하는 부분 말고 로그인한 유저의 프로필을 반환하는 API가 있다. 해당 API는 GET 방식을 사용하고 불러온 유저 아이디의 값을 통해 그에 맞는 데이터를 반환 해주는 역할을 한다.

 

const path = require('path');
const express = require('express');
const morgan = require('morgan');
const { urlencoded, json } = require('body-parser');
const { v4 } = require('uuid');
const axios = require('axios');
const app = express();

app.use(express.static('dist'));
app.use(morgan('dev'));
app.use(urlencoded({ extended: false }))
app.use(json())

app.get('/api/user/:id', (req, res) => {
  if(!req.headers['token']) {
  	return res.status(403).send({
	  status: 'Error'
    });
  }
  
  axios.get('https://randomuser.me/api')
    .then(result => {
      const {userProfile} = result.data.results;
      const {name, picture, phone, email, country} = userProfile;
      
      res.status(200).send({
        status: 'OK',
        result: {
          name, picture, phone, email, country
        }
      })
    })
    .catch(e => {
      res.status(400).send({
        status: 'Error'
      });
    });
});

app.get('/api/user/:id/posts', (req, res) => {
  ...
});

app.post('/api/authentication', (req, res) => {
  ...
});

app.listen(8080, () => {
  console.log('ready to dumy signup server');

 

/api/user/:id 에서 :id 부분에 입력 받은 아이디의 데이터를 가져온다. 해당 API로 진입 시 req(request)의 header에 토큰이 있는지 없는지를 체크하고 토큰 값이 존재하지 않는다면 403에러를 반환한다. 여기서 프로필은 무작위로 가상의 프로필을 제공해주는 API를 이용할 것이고, 서버에 요청을 보내는 것으로 axios 라이브러리를 사용한다. axios는 xmlHttpRequest나 fetch와 같은 기능을 하고 node.js 등의 서버 환경에서 편리한 기능을 가지고 사용할 수 있다. 이어서 axios로 받아온 API에서 사용할 데이터를 변수로 만들고 res(resopnse)로 상태값 성공(2xx)과 해당하는 데이터를 반환하고 이 과정에서 어떠한 이유로 전송이 되지 않으면 실패(4xx)를 반환한다.

 

 

 

 

https://bit.ly/37BpXiC

 

패스트캠퍼스 [직장인 실무교육]

프로그래밍, 영상편집, UX/UI, 마케팅, 데이터 분석, 엑셀강의, The RED, 국비지원, 기업교육, 서비스 제공.

fastcampus.co.kr

 

본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.

 

#패스트캠퍼스 #패캠챌린지 #직장인인강 #직장인자기계발 #패스트캠퍼스후기 #김민태의프론트엔드아카데미:제1강JavaScript&TypeScriptEssential

+ Recent posts