[Typescript] Typescript로 블록체인 구현 (2/3)

Lee_Sangmin·2022년 7월 8일
0

personal

목록 보기
2/9

TypeScript의 본질

본격적인 강의에 앞서 TypeScript를 사용하는 이유와 얻을 수 있는 이점, 그리고 동작하는 방식에 대해 알아보도록 한다.

1) TypeScript를 사용하는 이유

TypeScript는 JavaScript의 상위집합. 즉 슈퍼셋으로써 대형 프로젝트를 진행할 때 보이는 약점을 어느정도 해결할 수 있다.

깊이가 깊어지면 타입이 추론되지않는 JavaScript의 타입에 대한 에러를 어느정도 보완할 수 있다.

절차지향, 객체지향, 함수형 등의 여러가지 패러다임을 활용할 수 있다.
그중 특히 클래스, 인터페이스, 상속, 모듈과 같은 객체지향 특화 프로그래밍 패턴을 지원한다.

높은 수준의 코드 탐색과 디버깅을 통해 생산성을 높힐 수 있다.
모든 자바스크립트 버그의 15%를 사전에 타입스크립트를 통해 잡을 수 있다는 연구가 있다.

JavaScript와 100% 호환되면 마찬가지로 브라우저의 엔진을 지원한다.


2) 객체지향 프로그래밍과 함수형 프로그래밍

  • 객체지향 프로그래밍

오늘날 많은 유명 프로그래밍 언어(Java,C++,C#,Python 등)이 객체지향 프로그래밍을 지원한다.

객체 지향 프로그래밍은 컴퓨터 프로그래밍 패러다임중 하나로, 프로그래밍에서 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체를 만들고 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법이다.

쉽게 말하면, 우리가 객체를 생각하는 관점과 그 객체들간의 연계성을 생각하는 관점을 프로그래밍에 적용하여 모델링하는 패러다임을 뜻한다.

해당 관점은 함수들의 집합이나 변수들 일련의 목록을 관련있는 객체들의 집합으로 분류하고, 각 분류들이 메시지를 주고받거나 데이터를 주고받을 수 있게 만드는 것이다.
그리고 이러한 분류 하나하나를 객체라고 한다.

객체지향 프로그래밍은 보다 유연하고 유지보수하기 유리하게 의도된 기법이라고 볼 수 있다.

이를 위해 캡슐화, 정보은닉, 추상화, 상속성 등의 특징등을 갖고있다.

  • 함수형 프로그래밍

TypeScript는 객체지향 프로그래밍에 특화된 프로그래밍 패턴을 지원하지만,
현재는 함수형 프로그래밍이 대세이므로, 타입검사 및 추론등의 기능을 사용하는 것에 그친다.


3) TypeScript 컴파일 과정

  • 개요 및 차이

TypeScript는 컴파일 언어이며 JavaScript는 인터프리터 언어이다.

컴파일 언어는 소스코드 전체를 한번에 검사해서 실행 프로그램으로 만들어주는 언어이고,
인터프리터 언어는 소스코드를 한줄한줄 읽어가며 실행하는 언어이다.

  • 일반적인 컴파일 과정

프로그래머가 다수의 텍스트 파일을 작성하여 임의의 소스코드를 작성한다.

일반적인 프로그램의 경우(JavaScript의 경우도 포함) 컴파일러가 텍스트 파일을 파싱하여 추상 문법 트리(Abstract Syntax Tree) 자료구조로 변환한다.

컴파일러는 AST를 바이트코드(bytecode)라는 하위수준의 표현으로 변환한다.

바이트코드가 만들어졌으면 런타임이라는 다른 프로그램에 바이트코드를 입력해 평가하고 결과를 얻을 수 있다.

source code =(compiler)=> AST =(compiler)=> bytecode =(runtime)=> evaluate


  • TypeScript 컴파일 과정

TypeScript의 컴파일 과정이 위의 경우와 다른점은 다음과 같다.

타입 시스템 기능JavaScriptTypeScript
타입 결정 방식동적정적
타입이 자동 변환 여부OX
타입 확인 타이밍런타임컴파일타임
에러 검출 타이밍런타임(대부분)컴파일타임(대부분)

source code(TS) =(TS compiler)=> AST(TS) =(TS compiler)=> JavaScript =(compiler)=> AST(JS) =(compiler)=> bytecode =(runtime)=> evaluate


강의 내용

해당 강의에서는 TypeScript를 통해 객체지향 설계를 중심으로 설명한다.

현재는 함수형 패더라임이 강세지만, 위에서 언급하였듯이 객체지향 설계가 유리한 경우도 있고 다른 사람의 객체지향 설계 기반 코드를 유지보수 해야하는 일이 생길 수도 있기 때문에 해당 패러다임을 등한시 해서는 안된다.

이전과 마찬가지로 코드 블럭을 통해 모두 이해할 수 있도록 간결하게 작성한다.


Classes

// 추상 클래스는 다른 클래스가 상속받을 수 있는 클래스
abstract class AbstractName {
  // 접근지정자는 객체지향 프로그래밍 언어들의 특징
  constructor(
    // 하단 접근 지정자들은 컴파일 이후 JS에서는 의미를 잃는다.
    private firstName: string,
    protected lastName: string, // 외부에서의 접근은 여전히 막지만, 상속받은 클래스에서는 접근 가능하도록 지정
    public nickname: string,
  ) {}
  getFullName() {
    console.log(`${this.firstName} ${this.lastName}`);
  }
  // 추상 메소드 작성법 : 추상 클래스 내에 call signature만 작성해둔다.
  // 메소드 또한 접근지정자로 보호가 가능하다.(default: public)
  abstract getNickname(): void;
}

class Name extends AbstractName {
  // 추상 메소드가 작성되어있는 경우, 상속 클래스에서 반드시 작성 되어야 함.
  getNickname() {
    console.log(this.nickname);
  }
}

// 추상 클래스로 인스턴스를 만들 수는 없음
const sangmin = new AbstractName('sangmin', 'lee', 'DL'); // error : 추상 클래스의 인스턴스를 만들 수 없습니다.ts(2511)

const sangmin2 = new Name('sangmin', 'lee', 'DL');
// 접근지정자 private에는 접근 불가능
sangmin2.firstName(); // error : 'firstName' 속성은 private이며 'Name' 클래스 내에서만 액세스할 수 있습니다.ts(2341)
sangmin2.getFullName(); // sangmin lee
sangmin2.getNickname(); // DL

console.log(sangmin2.lastName); // error : 'lastName' 속성은 보호된 속성이며 'AbstractName' 클래스 및 해당 하위 클래스 내에서만 액세스할 수 있습니다.ts(2445)
type WordType = {
  // object 내부 인자 형 설정도 가능
  [key: string]: string;
};

class Dictionary {
  // property를 만들고 초기화
  private words: WordType;
  constructor() {
    this.words = {};
  }
  // class를 type처럼 사용 가능
  addToDict(word: Word) {
    if (this.words[word.term] === undefined) {
      this.words[word.term] = word.def;
    }
  }
  showDef(term: string) {
    return this.words[term];
  }
}

class Word {
  // readonly는 접근 지정자와 마찬가지로 JavaScript로 컴파일시 보이지 않게됨.
  constructor(public readonly term: string, public readonly def: string) {}
}

const dict = new Dictionary();

const korea = new Word('Korea', '한국');

dict.addToDict(korea);
dict.showDef('korea');

Interfaces

// type에서 다양한 방식의 형 지정
type HpType = number;
type FriendsList = Array<string>;
type Gender = 'Man' | 'Woman';

type Character = {
  nackname: string;
  gender: Gender;
  hp: HpType;
};
type Character2 = Character & {
  friends: FriendsList;
}

const sangmin: Character2 = {
  nackname: 'sangmin',
  gender: 'Man',
  hp: 100,
  friends: ['saahoP', 'Myunghoon'],
};

// 아래는 type구조를 interface 구조로 수정한 것.

// interface로는 단순 타입 지정 불가능.
interface Gender2 = 'Man' | 'Woman'; // error

interface Character {
  nackname: string;
}
interface Character {
  gender: Gender;
  hp: HpType;
}
interface Character2 extends Character {
  friends: FriendsList;
}

const sangmin2: Characters2 = {
  nackname: 'sangmin',
  gender: 'Man',
  hp: 100,
  friends: ['saahoP', 'Myunghoon'],
};

// type이 좀 더 쓰임이 많음. 더 유연함.
// interface는 객체 지향 프로그래밍 개념을 활용하여 디자인 되었다. class를 다루는 느낌.
// abstract class 대신에 interface를 사용할 수도 있다. (JavaScript 코드로 컴파일 되지 않음)
interface User {
  firstName: string;
  lastName: string;
  fullName(): string;
  sayHi(name: string): string;
}
// private property를 사용할 수 없음
// constructor를 사용할 수 없음

// interface상속에는 extends대신에 implements를 사용
class Player implements User {
  constructor(public firstName: string, public lastName: string) {}
  fullName() {
    return `${this.firstName} ${this.lastName}`;
  }
  sayHi(name: string): string {
    return `Hello ${name}. My name is ${this.fullName()}`;
  }
}
type PlayerA = {
  name: string;
};
type PlayerA2 = PlayerA & {
  power: number;
};

// type대신에 interface를 사용하는 것 또한 가능하다.
interface PlayerB {
  name: string;
}
interface PlayerB {
  condition: number;
}
interface PlayerB2 extends PlayerB {
  power: number;
}

const player: PlayerB2 = {
  name: 'sangmin',
  condition: 100,
  power: 999,
};

Polymorphism

interface MyStorage<T> {
  [ket: string]: T;
}

class LocalStorage<T> {
  // interface를 섞어 generic이 한단계 더 전달되는 형태
  private storage: MyStorage<T> = {};
  set(key: string, value: T) {
    this.storage[key] = value;
  }
  remove(key: string) {
    delete this.storage[key];
  }
  get(key: string): T {
    return this.storage[key];
  }
  clear() {
    this.storage = {};
  }
}

const stringStorage = new LocalStorage<string>();
stringStorage.set('sangmin', 'good');

const bolleanStorage = new LocalStorage<boolean>();
bolleanStorage.set('sangmin', 'bad'); // error : 'string' 형식의 인수는 'boolean' 형식의 매개 변수에 할당될 수 없습니다.ts(2345)


ETC

https://imraccoon-developer.tistory.com/11

https://www.samsungsds.com/kr/insights/typescript.html


https://velog.io/@huurray/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EA%B3%BC-%ED%95%A8%EC%88%98%ED%98%95-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D


https://blckchainetc.tistory.com/364
https://00h0.tistory.com/17

profile
FE developer

0개의 댓글