개발 기록 남기기✍️

타입스크립트로 블록체인 만들기 (4) 본문

Front-End/TypeScript

타입스크립트로 블록체인 만들기 (4)

너해동물원 2022. 12. 5. 13:48

[강의로 이동](https://nomadcoders.co/typescript-for-beginners)


vscode에서 환경 셋팅하기

typescript 설치하기

  • package.json 초기화
  • npm init -y
  • typescript 설치
  • npm i -D typescript
  • tsconfig.json 설정디렉터리에 tsconfig.json 파일이 있으면 해당 디렉터리가 typescript 프로젝트의 루트임을 나타낸다. tsconfig.json 파일은 프로젝트를 컴파일하는 데 필요한 루트 파일과 컴파일러 옵션을 지정한다.
  • MAC : touch tsconfig.json Window : code tsconfig.json // 이후 ctrl+S (저장)
  • package.json에 작성
  • // "main" 코드 삭제 // "scripts"에서 "test" 코드 삭제 // "scripts" 안에 "build" 코드 작성 "build" : "tsc"
  • tsconfig.json에 작성
{
  "include": [
    "src" // typescript가 src 폴더에 있는 모든 파일을 확인함
  ],
  "compilerOptions": {
    "outDir": "build", // build라는 폴더 안에 ts 파일을 js 파일로 변환해서 저장
    "target": "ES6" // 원하는 버전의 자바스크립트
  }
}
  • terminal에서 npm run build 실행 => js 파일 변환

 

Target

최신 브라우저는 모든 ES6 기능을 지원하므로 ES6는 좋은 선택이다. 코드가 이전 환경에 배포된 경우, 더 낮은 target을 설정하거나 최신 환경에서 코드 실행이 보장되는 경우 더 높은 target을 설정하도록 선택할 수 있다.

ex) 화살표 함수 ( ) => { }ES5 이하면 함수 표현식으로 바뀐다.

특별한 ESNext 값은 Typescript 버전이 지원하는 가장 높은 버전을 나타낸다. 이 설정은 다른 Typescript 버전 간에 동일한 의미가 아니며, 업그레이드를 예측하기 어렵게 만들 수 있으므로 주의해서 사용해야 한다.

Lib Configuration

Typescript에게 어떤 API를 사용하고 어떤 환경에서 코드를 실행하는 지를 지정할 수 있다. -> 자동완성 기능 제공

(target 런타임 환경이 무엇인지를 지정한다.)

프로그램이 브라우저에서 실행되면 lib에 "DOM" 유형 정의를 할 수 있다.

  • DOM : window, document 등

ex) "lib" : ["ES6", "DOM"]

Declaration Files

Typescript는 window, localStorage, Math 등의 타입을 이해하고 인지할 수 있다. Typescript는 내장된 javascript API를 위한 기본적인 타입 정의는 가지고 있다.

타입 정의는 Typescript가 몇몇 Javascript 코드와 API의 타입을 설명할 수 있도록 해준다.

Typescript는 Javascript와는 다르게 strongly-typed이기 때문에 Typescript에서 사용할 Javascript 라이브러리의 함수 모양을 설명해야 한다. 그리고 이 타입 정의를 서술한 파일이 Declaration File 이다.

  • tsconfig.json에서 strict : true를 통해 strict mode로 실행하면 declaration files가 없는 경우에 대해서도 에러를 띄워준다.

예제) Javascript 함수 Typescript에 불러와서 실행하기

// myFunction.js
export function init(config) {
  return true;
}
export function exit(code) {
  return code + 1;
}
// myFunction.d.ts
interface Config {
  url: string;
}

declare module "myPackage" {
  function init(config: Config): boolean;
  function exit(code: number): number;
}
// index.ts

import { init, exit } from "myPackage";

init({
  url: "true",
});

exit(1);

 

JSDoc

Javascript 소스코드 파일에 주석을 달기 위해 사용되는 마크업 언어이다.

JSDoc에 포함하는 주석을 사용하여 코드를 작성하고 인터페이스를 설명하는 문서를 생성할 수 있다.

 

@ts-check

Javascript 파일에서 오류를 활성화하려면 // @ts-check.js 파일의 첫 번째 줄에 추가하여 Typescript가 오류를 발생시키도록 한다. Typescript는 여러 오류를 제공할 수 있다.

이러한 오류를 무시하고 싶다면 // @ts-ignore 또는 // ts-expect-error를 추가하여 특정 줄의 오류를 무시할 수 있다.

 

JSDoc Reference

JSDoc 주석을 사용하여 .d.ts 파일을 만들지 않더라도 Javascript 파일에 type 정보를 제공할 수 있다.

[참고](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html)

 

@param, @returns

vscode에서는 해당 함수 바로 윗줄에 /** */ 주석을 입력하면 자동으로 해당 함수의 @param@returns를 띄워준다.

@param에서는 해당 함수의 변수의 타입을 지정할 수 있고, @returns에서는 함수의 리턴값 타입을 지정할 수 있다.

// @ts-check

/**
* @param {string} p1 - A string param.
* @param {string=} p2 - An optional param (Google Closure syntax)
* @param {string} [p3] - Another optional param (JSDoc syntax).
* @param {string} [p4="test"] - An optional param with a default value
* @returns {string} This is the result
*/
function stringsStringStrings(p1, p2, p3, p4) {
// 코드...
}
```

 

예제)

// myFunction.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;
}

/**
 * Exit the program
 * @param {number} code
 * @returns number
 */
export function exit(code) {
  return code + 1;
}
// index.ts

import { init, exit } from "./myPackage";

init({
});

exit(1);

Typescript에서 해당 함수에 대한 설명과 들어가야 할 타입을 볼 수 있는 것을 확인할 수 있다.

JSDoc와 d.ts 둘다 Typescript에게 타입을 선언한다는 점에서는 동일하지만, 다형성과 제너릭을 생각했을 때 d.ts를 사용하는 것이 유리하다.


Blockchain 만들기

환경 세팅

ts-node

ts-node는 Node.js 용 typescript 실행 엔진 및 REPL이다.

JIT는 typescript를 javascript로 변환하므로 사전 컴파일 없이 Node.js에서 typescript를 직접 실행할 수 있다.

 

nodemon

nodemon이 켜져 있으면, typescript에서 일어나는 변화를 자동으로 감지하여 build와 start까지 동시 실행한다.

npm i -D ts-node
npm i -D nodemon

 

blockchain이란?

blockchain은 편집, 삭제 불가하며 오로지 새로운 블록(DB) 추가만 가능하다. 탈중앙화 시스템 사용.

  • 탈중앙화 : 특정 개인이 DB 관리 불가 -- 분산된 db

block은 정보를 추가하는 방법이며 hash를 통해서 연결되어 있다.

  • hash : 한개의 인풋을 받으면 아웃풋을 준다. 일방향 함수이고 결정론적이다.
    • 일방향 함수 : 인풋을 가지고 아웃풋을 받을 수 있지만, 아웃풋을 가지고 인풋을 얻을 수는 없다.
    • 결정론적 : 조금이라도 값이 바뀌면 해쉬값은 아예 바뀌어버린다.
  • 작업증명 : 채굴 작업을 통해 들어오는 데이터가 참인지를 확인 가능.
    • 채굴자 : 블록체인에 들어오는 데이터를 확인하고 데이터를 블록 안에 넣어서 블록체인에 보내는 역할을 한다. 블록을 바로 블록체인에 보내는 것이 아니라, 네트워크에서 채굴자에게 퍼즐을 보내서 그것을 풀어서 Nonce를 입력해야 등록 가능 및 코인 생성됨.

 

blockchain 코드 만들기

Node.js의 crypto 라이브러리 사용해서 해쉬를 만들 수 있다.

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");

blockchain.getBlocks().push(new Block("xxxxx", 11111, "HACKEDDDDDD"));

console.log(blockchain.getBlocks());