본문 바로가기

블록체인_9기/💙 TYPESCRIPT

53강_230830_TypeScript(TypeScript란?, ts-node & tsconfig & tsc-alias 설치 및 사용방법, JS와 TS 문법

728x90

 
 
 
 


TypeScript란?

 

🧐 TypeScript, 왜 사용해야 할까?

Javascript는 동적 타입 언어로, 개발환경에서 타입에러가 종종 발생한다. 하지만 TypeScript를 사용하면 컴파일 단계에서 미리 타입체크를 할 수 있어 타입오류를 최소화 할 수 있다. 그 외에 별칭을 사용하여 자동완성 및 작성이 편리하며 에러를 방지할 수 있다고 한다. 한 번 TypeScript를 알아보고자 한다.
 
 

TypeScript는 JavaScript를 포함하는 수퍼셋으로 브라우저, 운영체제에 상관없이 이용가능한 오픈소스이다.

 

  • JS에서 타입 검사가 확장, 추가된 언어이다.
  • JS의 상위 확장(수퍼셋)으로, 대형 프로젝트를 진행할 때 오류검사가 쉽다.
  • 객체지향 프로그래밍에 특화된 프로그래밍 패턴을 지원한다.
  • 함수형 프로그래밍에서 타입검사나 추론 등의 기능을 사용한다.
  • typescript를 사용하면 JS 작업할 때 보다 개발에서 생기는 에러를 사전에 방지하며 코드의 품질 개발 생산성을 높일 수 있다.
  • 런타임이 존재하지 않는 컴파일 언어이다.

 

🤷‍♀️ 런타임이 존재하지 않는 언어?

TypeScript컴파일 언어이다.
 우선 결론을 먼저 말하면 TypeScript는 컴파일 단계를 통해 TypeScript 코드를 JavaScript코드로 변환해 실행되는 언어를 말한다. TypeScript는 정적 검사와 인터페이스, 클래스 및 여러가지 JS에 없는 구조를 제공한다. 하지만 Node나 브라우저에서 이해할 수 있는 언어의 형태가 아니므로 실행하기 전 컴파일 과정을 거쳐 JS 코드로 변환되어야 한다. 
 컴파일 과정을 거쳐 코드를 실행시키지만, JavaScript의 런타임 환경과 호환성을 유지하기 위해 별도의 런타임이 존재하지 않는다. TypeScript의 중점은 개발 경험을 향상시키고 오류를 초기에 감지하여 더 나은 코드 구성과 유지 관리성을 제공하는데 있기 때문이다.
 

 

 


TypeScript의 특징

컴파일 언어, 정적 타입 언어

  • 자바스크립트는 동적 타입의 인터프리터 언어로, 런타임에서 오류를 발견할 수 있다.
  • 하지만 타입스크립트는 정적 타입의 컴파일 언어이며, 타입스크립트 컴파일러 또는 바벨(Babel)을 통해 자바스크립트 코드로 변환된다.
  • 코드 작성 단계에서 타입을 체크해 오류를 확인할 수 있고 미리 타입을 결정하기 때문에 실행 속도가 매우 빠르다는 장점이 있다.
  • 코드 작성 시 매번 타입을 결정하기 때문에 번거롭고 코드량이 증가하며 컴파일 시간이 오래 걸린다는 단점이 있다.

 

자바스크립트 슈퍼셋 (Superset)

  • 타입스크립트는 자바스크립트의 슈퍼셋, 즉 자바스크립트의 기본 문법에 타입스크립트 문법을 추가한 언어이다.
  • 유효한 자바스크립트로 작성한 코드는 확장자를 .js => .ts 로 변경하고 타입스트립트로 컴파일해 변환할 수 있다.

 

객체 지향 프로그래밍 지원

  • 타입스크립트는 ES6에서 새롭게 사용된 문법을 포함하고 있으며, 클래스, 인터페이스, 상속, 모듈 등과 같은 객체지향 프로그래밍을 제공한다.

 

 

TypeScript 변수 지정 타입

JS의 경우, ' 변수명 = 초기값 ' 해딩 방법으로 변수를 선언했었지만, TS의 경우에는  ' 변수명 : 타입명 = 초기값 '의 형태로 변수를 선언한다.

const msg = "javascript"; // JS에서 사용했던 변수 선언식

const msgg: string = "message string type";

console.log(msgg);	// 결과 : message string type

 


TypeScript 설치

# package.json 초기화
npm init -y
# 개발 단계에서 사용 -D => --save-dev와 동일
npm install -D typescript

# 설치가 되었는지 버전 확인
npx tsc --version

 
 
 


TypeScript 사용하기

개발 환경에서 확인하기 위해서 node에서 실행하기 위해서는 ts-node를 사용해야 한다. 그렇다면 ts-node가 무엇일까??
 
 


🤷‍♀️ ts-node?

  • Javascript로 컴파일하기 전에 node환경에서 직접 실행해볼 수 있는 도구이다.
  • 기존 JS 파일은 node를 통해 실행시켰는데, TS 파일은 node가 해석할 수 없기 때문에 타입 해석이 가능한 ts-node로 실행해줘야 한다. 
  • TypeScript 코드를 실시간으로 변환하여 실행한다. 코드를 실행할 때 타임스크립트 코드를 메모리에 있는 JS로 컴파일 하는 것이다.

 

ts-node TypeScript 실행환경

  • typescript를 컴파일 내부 컴파일러를 통해 메모리 상에 js코드로 변환한다.
    • js 파일을 만들지 않고 컴파일한 js코드로 메모리상에 갖고 있는다.
  • 컴파일된 js 코드를 nodejs 런타임 환경으로 실행하고 코드 실행 결과를 출력한다.
    • 컴파일 단계에서 타입 검사로 코드에서 발생할 오류를 사전에 알려줌으로써 런타임 이전에 잠재적인 문제를 발견할 수 있다.

 

ts-node 사용하기

# 설치 명령어
# node.js는 js 런타임 환경인데 내장 함수 및 모듈에 대한 타입 정보가 필요하다. 
# @types/node: nodejs 타입 정보를 패키지로 설치해서 사용

npm install ts-node @types/node
# 실행 가이드
# js => node 환경에서는 ' node app.js '로 실행했었는데,

# typescript => ts-node 환경에서는 아래와 같은 방법으로 사용한다.
npx ts-node app.ts

 
tsconfig.json은 타입스크립트를 자바스크립트로 변환 시키는 컴파일 설정을 한꺼번에 정의 해놓는 파일인데, 프로젝트를 컴파일 하는데 필요한 루트 파일, 컴파일러 옵션 등을 상세히 설정할 수 있다. 이 아래에서는 tsconfig에 대해서 알아보고자 한다.
 
 
 


tsconfig.json

  • typescript의 컴파일 과정 옵션을 설정할 수 있는 파일이다.
  • 보통 tsconfig.json 파일은 TypeScript 프로젝트의 루트 디렉토리에 위치한다.
  • tsconfig에서 옵션들을 미리 정의해 놓으면 컴파일 할 때 명령어에 일일히 대상 파일이나 옵션을 지정하지 않아도 된다.
  • tscts-node 명령어를 실행하게 되면, 현재 폴더에 있는 tsconfig 설정 내용을 기준으로 프로젝트에서 소스들을 컴파일 진행하게 된다.
  • 잔소리꾼이다. 하위 경로에 규칙이 맞지 않는 구문을 발견하면 수정하라고 알려준다.

 

# tsconfig.json 생성 명령어
npx tsc --init

tsconfig 설치 후 초기 설정화면

 


디렉토리 지정 방법

./ 현재 디렉토리에서 모든 파일의 경로. 즉 현재 폴더에 모든 파일을 컴파일 대상을 지정한다.
/** 모든 폴더를 가리킨다.
/* 모든 파일을 가리킨다.
ex src/**/* src 폴더의 하위 폴더와 폴더 안에 있는 모든 파일의 경로를 지정한다.

 

 


tsconfig.json 파일에서 컴파일 옵션을 설정한다. 

  • tsconfig 속성은 굉장히 많은 종류가 있지만 아래의 속성은 수업에서 나온 속성으로 다른 속성은 수업을 진행하면서 천천히 숙지하고자 한다.
{
  // include : 컴파일을 진행할 폴더를 지정할 수 있다.
  "include": ["./*"],

  // exclude : 컴파일에서 제외 시킬 폴더를 지정할 수 있다.
  "exclude": [],

  // compilerOptions : typescript 파일을 컴파일 진행 시 어떤 옵션으로, 어떤 형태로 컴파일을 진행할지 속성을 정의
  "compilerOptions": {
    // 컴파일된 파일을 내보낼 경로 지정
    "outDir": "./dist"
  }
}

 
 

tsconfig 전역 속성

tsconfig 전역 속성이란, 파일의 최상위에 위치하고 있는 속성들을 일컫는다.

  • compilerOptions : typeScript 파일을 컴파일 진행 시 어떤 형태로 컴파일을 진행할 지 속성 정의하는 부분
  • include : 컴파일을 진행할 폴더를 지정
  • exclude : 컴파일에서 제외할 폴더 지정

 

compilerOptions 자주 사용하는 속성

  • module : 모듈 시스템 지정
  • outDir : 내보낼 경로 지정
  • target : 번들링 문법 지정
    • 예) es5, es6 ... 등의 문법을 지정한다.
  • esModuleInterop : true
    • (import/export 문법을 자연스럽게 변경 해주는 행위)
    • 주로 true로 설정한다.
    • (CommonJS 형식과 ES6 형식의 혼용을 자연스럽게 통합 해주는 속성이다.)
  • strict : true로 두자. 엄격
  • baseUrl : 모듈의 상대 경로를 지정한다.
  • paths : 'baseUrl' 경로를 기준으로 상대 위치를 가져오는 매핑 값 (경로를 변수처럼 사용한다.)

 

package.json 파일에서 명령어를 추가한다.

  • tsc 명령어는  typescript 컴파일을 실행하는 명령어이다.
  • typescript 코드를 tsconfig.json 파일 설정 값을 가지고 js 코드로 변환해준다.
 "scripts" : {
   "build" : "tsc"
 }

 

👩‍🏫 동작예시

src/message.ts 파일

import a from "@user/server/user.service";

const message: string = "hello world";

console.log(message);
console.log(a);

src/message.test.ts 파일

const message2: string = "test";
console.log(message2);

src/user/server/user.service.ts 파일

const variable: string = "user";
export default variable;

⬇️

VSC 의 터미널에서 아래의 순서대로 파일 생성 및 패키지 설치

# 새로운 package.json 파일을 생성
npm init -y

# typescript 패키지 설치 (프로젝트 시작 시 1회만 설치)
npm install -D typescript

# tsconfig.json 파일을 생성
npm tsc --init

⬇️

tsconfig.json 파일에서 타입스크립트 컴파일 속성 정의

tsconfig.json 파일

{
  "compilerOptions": {
    "module": "CommonJS",
    "outDir": "./dist",
    "target": "ES6",
    "esModuleInterop": true,
    "strict": true,
    "baseUrl": "./src",
    "paths": {
      "@user/*": ["user/*"]
    }
  },
  "include": ["src/**/*"],
  "exclude": ["**/*.test.ts"]
}

⬇️

package.json에 빌드 속성 추가

....
"scripts": {
    ...
    "build": "tsc"
  },
....

⬇️

VSC 의 터미널에서 타입스크립트 컴파일 진행

# 타입스크립트 컴파일
npm run build

⬇️

컴파일된 파일의 내용이다.

dist/message.js 파일

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const user_service_1 = __importDefault(require("@user/server/user.service"));
const message = "hello world";
console.log(message);
console.log(user_service_1.default);

dist/user/server/user.service.js 파일

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const variable = "user";
exports.default = variable;

 
tsconfig.json 파일에서 설정했던  ' "exclude": ["**/*.test.ts"] '의 내용이 적용되어, message.test.ts 파일이 컴파일되지 않았음을 확인할 수 있다.
dist/message.js 파일의 코드를 보면, 

const user_service_1 = __importDefault(require("@user/server/user.service"));

이런 구문을 확인할 수 있다. 하지만, JS 코드 문법으로는 ' @user/server/user.service ' 라는 경로는 읽어올 수 없는 문법 형식이다. 이런 별칭을 사용한 것을 빌드 시에는 컴파일 되지 않고 그대로 들어가게 되는데 이 별칭을 컴파일 시 JS 문법으로 변환해주는 패키지가 있다. tsc-alias 모듈이다.
 

* 별칭?  

  • 모듈 별칭은 TypeScript 프로젝트 내에서 모듈에 대한 더 짧거나 의미 있는 경로를 생성하는 것을 의미한다.
  • 긴 상대 경로(../../../)나 절대 경로 대신 별칭을 정의하여 특정 디렉터리 경로에 매핑할 수 있다.
  • 별칭을 설정하면 코드가 더 읽기 쉽고 유지 관리가 용이하다.

 

 


tsc-alias로 별칭 설정하기

tsc-alias은 내장된 TypeScript나 Node.js의 기능은 아니며, TypeScript 프로젝트에서 모듈 별칭을 사용하는 방식을 나타낸다. 특히 대규모 프로젝트에서 가독성을 높이고 경로 참조를 간결하게 관리하기 위해 모듈 경로에 별칭을 설정하는 일반적인 방법이다.

# tsc-alias 모듈 설치
npm install -D tsc-alias
// package.json 추가. 별칭 수정 경로 추가
....
"scripts": {
    ...
    "build": "tsc && tsc-alias"
  },
....

 
다시 터미널에서 ' npm run build ' 후 빌드된 파일을 확인해보면,

dist/message.js 파일

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const user_service_1 = __importDefault(require("./user/server/user.service"));
const message = "hello world";
console.log(message);
console.log(user_service_1.default);

해당 코드로 변경되었다. 아까 확인할 수 없었던 경로 부분이

const user_service_1 = __importDefault(require("./user/server/user.service"));

이렇게 변경되어 JS 문법으로 확인할 수 있는 코드임을 확인할 수 있다.
 
 
 


JS와 TS 문법

// javascript
let num = 20;
const str = "javascript";
const nan = NaN;
const infinity = Infinity;
const bool = true;
const nullValue = null;
const nudefinedValue = undefined;

const obj = {};
const arr = [];

const fn = (a: any) => {
  console.log(a);
};

const sum = (a: any, b: any) => {
  return a + b;
};

let any;

let unknown;

// typescript
let num2: number = 20;
const str2: string = "javascript";
const nan2: number = NaN;
const infinity2: number = Infinity;
const bool2: boolean = true;
const nullValue2: null = null;
const undefinedValue: undefined = undefined;

const obj2: object = {};
// <> : 제네릭 타입 설정. 배열의 요소가 number라고 지정. (데이터 타입을 매개변수 시킬 수 있다.)
    // ex. <number | string> : number 또는 string 타입을 사용할 수 있다는 뜻.
const arr2: Array<number | string> = ["a", 1];

// void: 함수 실행 시 비어있다는 것을 의미. 반환 값이 없는 함수라는 것이다.
// void는 생략할 수 있다.
const fn2 = (a: number): void => {
  console.log(a);
};

// 함수명 = ():return의 타입을 지정 => {}
const sum2 = (a: number, b: number): number => {
  return a + b;
};

// any: 어떤 타입이든 할당할 수 있다. 되도록 남발하지 말자. 타입의 안정성이 보장 되지 않는다.
const any2: any = "";
console.log(any2.length); // length가 있던, 없던 실행된다.

// unknown : 어떤 타입이든 할당 가능. 타입의 안정성 보장
const unknown2: unknown = "";
if (typeof unknown2 === "string") {
  console.log(unknown2.length); // 타입을 알 수 없으니 length의 여부를 알 수가 없어 조건안에서 동작이 가능하다.
}

 
 
 
 
 
 
 

728x90