타입스크립트로 블록체인 만들기 – 노마드 코더 Nomad Coders

이 포스트는 노마드 코더의 강의 <타입스크립트로 블록체인 만들기> 강의를 공부하며 정리한 노트입니다.




# 5.1

타입스크립트 프로젝트 세팅

  1. package.json 생성

    npm init -y
    
  2. typescript 설치

    npm i -D typescript
    
  3. tsconfig.json 생성

    • 프로젝트의 루트 디렉터리에 tsconfig.json 을 생성한다. tsconfig.json 파일은 프로젝트를 컴파일하는 데 필요한 루트 파일과 컴파일러 옵션을 지정한다.
    • include : 컴파일할 TS 파일들을 탐색할 디렉터리 지정.
    • compilerOptions : 컴파일러 옵션 지정
      • outDir : 컴파일한 파일이 저장될 디렉터리 지정
      • target : 컴파일할 JS 버전 지정. (기본 : ES3, 권장 : ES6)
    //tsconfig.json
    {
      "include": ["src"],
      "compilerOptions": {
        "outDir": "build",
        "target": "ES3"
      }
    }
    
  4. package.json 수정

    • scripts 내용 모두 지우고 “build” : “tsc” 넣기




# 5.2

  • tsconfig.json 의 lib : target 런타임 환경이 무엇인지 지정. (어떤 API 를 사용하고 어떤 환경에서 코드를 실행하는지 지정할 수 있다.)
  • “lib”: [”ES6”, “DOM”] : 이렇게 지정하면, typescript 런타임 환경은 ES6를 지원하며, DOM 의 여러 기능들(document, window, localStorage…등)을 지원한다. (지원한다 = 빨간 줄 없고, 자동완성 된다 = 타입스크립트가 뭔지 안다.)




# 5.3

TSConfig Reference - Docs on every TSConfig option

lib 의 정의에서 a default set of type definitions 라는 표현이 나온다. 말 그대로 built-in APIs 의 타입을 미리 정리해 놓은 것이다. 이것을 declaration files 라고 한다. 보통 nodemodules 안의 lib~.d.ts 안에 존재.

임의의 모듈을 만들고 그 모듈의 declaration file 을 만들어 보자

//myPackage.js
export function init(config) {
  return true;
}
export function exit(code) {
  return code + 1;
}
//myPackage.d.ts
interface Config {
  url: string;
}
declare module "myPackage" {
  function init(config: Config): boolean;
  function exit(code: number): number;
}

물론, 직접 declaration file 을 작성할 일은 많지 않을 것이다.

그 외의 여러 tsconfig의 compilerOptions 옵션들

TSConfig Reference - Docs on every TSConfig option




# 5.4

  • JSDoc 은 js 파일을 ts로 오류를 체크할 수 있게 한다.
  • 독특한 문법을 가졌다
  • src/myPackage.js

    // @ts-check
    /**
     * Initializes the project
     * @param {object} config
     * @param {boolean} config.debug
     * @param {string} config.url
     * @returns boolean
     */
    export function init(config) {
      return true;
    }
    
    /**
     * Exits the program
     * @param {number} code
     * @returns number
     */
    export function exit(code) {
      return code + 1;
    }
    

    ⇒ 맨 위에 // @ts-check ⇒ @params 로 매개변수 타입 설정 ⇒ @returns 로 반환값의 타입 설정 ⇒ 그리고 ts 파일로 가서 import 하면, 정상적으로 타입이 정의된 것을 볼 수 있다. (tsconfig.json 에서 compilerOptions 의 allowJs: true 로 설정해야함)




# 5.5

ts-node : typescript 파일을 빌드 없이 빠르게 실행할 수 있게 해줌 (개발환경에서 사용.)

npm i -D ts-node

설치가 끝나면 package.json 파일의 scripts 에 다음 코드 넣어주기 (여기서 src/index 파일은 typescript 파일)

"dev": "ts-node src/index"

nodemon 설치 : node.js 실행환경에서 자동으로 새로고침해줌.

npm i nodemon

package.json 의 scripts 수정

"dev": "nodemon --exec ts-node src/index"

tsconfig.json 의 compilerOptions의 esModuleInterop: true 로 설정하면, CommonJS 모듈을 코드베이스로 가져오려고 할 때 발생하는 문제를 해결한다. ES6 모듈 사양을 준수하여 CommonJS 모듈을 정상적으로 가져올 수 있게 해준다.

TSConfig Reference - Docs on every TSConfig option




# 5.6

https://github.com/DefinitelyTyped/DefinitelyTyped

Definitely Typed 는 npm 패키지에 대한 타입 정의들을 모아 놓은 레포이다.

npm i -D @type/npm 패키지 이름

위와 같은 명령어 형식으로 지정된 npm 패키지의 타입을 설치할 수 있다.

또는,

npm i -D @type/node

로 모든 패키지의 type을 설치할 수 있다.

//src/index.ts
import crypto from "crypto";
interface BlockShape {
  hash: string;
  prevHash: string;
  height: number;
  data: string;
}
class Block implements BlockShape {
  public hash: string;
  constructor(
    public prevHash: string,
    public height: number,
    public data: string
  ) {
    this.hash = Block.calculateHash(prevHash, height, data);
  }
  static calculateHash(prevHash: string, height: number, data: string) {
    const toHash = `${prevHash}${height}${data}`;
    return crypto.createHash("sha256").update(toHash).digest("hex");
  }
}




# 5.7

드디어 블록체인을 구현한다…. 그러나 많이 부족해보임. 블록체인을 설명하기 위한 강의가 아니고, typescript 로 무언가를 구현해보는 데 초점이 맞춰져 있다. 그래도 코드는…. 여기!

먼저 블록체인의 개념에 대해서 짚고 넘어가자

블록체인

https://www.youtube.com/watch?v=Ca7Meu4z-F4&ab_channel=노마드코더NomadCoders

최종 코드!

import crypto from "crypto";
interface BlockShape {
  hash: string;
  prevHash: string;
  height: number;
  data: string;
}
class Block implements BlockShape {
  public hash: string;
  constructor(
    public prevHash: string,
    public height: number,
    public data: string
  ) {
    this.hash = Block.calculateHash(prevHash, height, data);
  }
  static calculateHash(prevHash: string, height: number, data: string) {
    const toHash = `${prevHash}${height}${data}`;
    return crypto.createHash("sha256").update(toHash).digest("hex");
  }
}
class Blockchain {
  private blocks: Block[];
  constructor() {
    this.blocks = [];
  }
  private getPrevHash() {
    if (this.blocks.length === 0) return "";
    return this.blocks[this.blocks.length - 1].hash;
  }
  public addBlock(data: string) {
    const newBlock = new Block(
      this.getPrevHash(),
      this.blocks.length + 1,
      data
    );
    this.blocks.push(newBlock);
  }
  public getBlocks() {
    return [...this.blocks];
  }
}

const blockchain = new Blockchain();

blockchain.addBlock("First one");
blockchain.addBlock("Second one");
blockchain.addBlock("Third one");
blockchain.addBlock("Fourth one");

console.log(blockchain.getBlocks());




# 후기

  1. 이 정도로 얕게 블록체인 내용을 다룰 줄은 몰랐다.
  2. TS 를 빠른 시간에 체득한 것 같아 효용은 충분한 것 같다.
  3. 꼭 공식 문서를 읽어보자

    Handbook - The TypeScript Handbook