본문 바로가기
내일배움캠프_게임서버(202410)/분반 수업 Basic-A

베이직 250121 타입스크립트

by GREEN나무 2025. 1. 21.
728x90

베이직 250121

https://teamsparta.notion.site/TypeScript-2ffe288e7dcf4b728e508b08274a3592
TypeScript란 : 타입스크립트는 자바스크립트에 타입을 부여한 언어
   자바스크립트의 확장판

// Types: string (데이터의 종류)
// Annotation: : string (타입을 표시하는 방법)
let message: string = "Hello"; // : string 이 부분이 typescript여서 type을 명시(Annotation)

타입 종류
Never : 애러나는데 넣어서 through 처럼 쓰는 것



TypeScript를 위한 셋팅
# typescript를 Global하게 설치
npm install -g typescript

# typescript 설치가 되었는지 체크
tsc –v


 TSC(TypsScript Compiler)를 통해서 JS파일로 변환
 TypeScript 코드를 JavaScript 코드로 변환하는 도구
 JavaScript로 변환하여 브라우저/node에서 실행 가능한 코드로 만든다. 
 이것을 트랜스파일 이라고 부릅니다.

TS 파일을 JS로 변환하기 위해서 두 가지 방법을 살펴보겠습니다. 

1. 직접 트랜스파일 후 실행 – js파일 수정 하면 실행 전에 tsc test.ts 다시 해야함
tsc test.ts    // TypeScript를 JavaScript로 트랜스파일 (test.js 파일 생성)
node test.js   // 생성된 js 파일 실행

2. ts-node 사용 (자동으로 트랜스파일 후 실행) - 세세한 설정 필요
npm install -g ts-node    // ts-node 설치. 
ts-node test.ts           // 자동으로 트랜스 파일 후 코드 실행

그냥 복사해서 쓰기
// tsconfig.json
//  TypeScript에 프로젝트를 어떻게 이해하고 변환해야 할지 알려주는 역할
{
  "compilerOptions": {
    "target": "ES2022", // 최신 ES2022 기능을 모두 사용하기 위해 설정
    "module": "NodeNext", // 최신 Node.js ESM 지원
    "moduleResolution": "nodeNext", // 모듈을 찾는 방식을 결정하는 옵션
    "strict": true, // 엄격 모드
    "esModuleInterop": true // CommonJS와 ESM 간의 호환성을 위한 설정
  }
}


// test.ts
let count:number =5;console.log("count: ", count);


ts 파일을 js파일로 변환(트랜스파일) 후 실행하기
1. 
tsc test.ts //변환
node test.js // 실행

2.
ts-node test.ts // TypeScript 파일을 JavaScript로 변환(트랜스파일)한 후 Node.js 환경에서 실행 (메모리 상에서 수행)



기본 타입
타입 추론: count에 type을 작성하지 않아도 tsc는 알아서 타입을 추론해 줍니다.
변수 이름 위에 마우스를 올리면 타입을 표시해 줍니다
기본타입은 값을 주면 타입을 따로 적지 않아도 됨


1. 숫자, 문자열, 불리언
let count:number =5;let name:string ="TypeScript";let isCompleted:boolean =false;// 간단한 변수들은 타입추론(Type Inference)을 이용해도 됩니다!let count =5;let name ="TypeScript";let isCompleted =false;

2. 배열
let numbers: number[] = [1, 2, 3, 4, 5];
let names: Array<string> = ["피카츄", "펭수", "라이츄"];
let grades: Array<number> = [90, 85, 95, 100];

제네릭 타입 : <string>, <number>
 < >안에 들어가는 것은 그 배열 넣을 수 있는 종류를 알려준다
F11 누르면 수정하는 곳으로 들어갈 수 있음

제네릭 여러개 지정
 let grades: Array<string | number>
 Array<T, G>

3.튜플
튜플은 정해진 개수와 타입의 요소를 가진 특별한 배열
정확한 자리가 정해져 있음.

let pokemon: [string, number] = ["이상해씨", 1]; // O
// let pokemon: [string, number] = ["이상해씨", 1, 100]; // X

4. 열거형
열거형(enum)은 관련된 상수들을 하나의 그룹으로 묶어 이름을 붙인 것
Red는 사실 0부터 시작해서Red = 0, Green = 1, Blue = 2 와 같다지만 코드 읽을때 0이 무엇인지 모르니 Red라는 이름을 붙여준다

enum Color {
  Red,
  Green,
  Blue
}
// let c: Color = Color["1"] // X
let c: Color = Color.Green; // O


5.
1. any와 unknown
2. 
any: 어떤 타입이든 허용하는 만능 타입. 타입 검사를 완전히 무시해서 위험.사용 지양
unknown: any처럼 모든 타입을 받을 수 있지만 사용할 때는 타입을 확인해야 해서 더 안전.

let anyValue: any = "Hello";
let unknownValue: unknown = "Hello";

// any는 어떤 연산이든 허용 (하지만 위험할 수 있음)
console.log(anyValue.toUpperCase());  // 작동함

// unknown은 타입 확인 후에만 사용 가능 (더 안전함)
// 여기에 if문 없으면 에러남
if (typeof unknownValue === "string") {
    console.log(unknownValue.toUpperCase());  // 작동함
} else {
    console.log("unknownValue는 string이 아닙니다!");
}

// 이건 에러 발생
// console.log(unknownValue.toUpperCase());  // 컴파일 에러

6. void, null, undefined
void: 함수가 아무것도 반환하지 않을 때 사용하는 타입. "아무 결과도 없음"을 의미.
null: 의도적으로 값이 없음을 나타내는 타입. "비어있음"을 명시적으로 표현.
undefined: 값이 할당되지 않은 상태를 나타내는 타입 "아직 정해지지 않음"을 의미.

function logMessage(): void { // 반환값의 타입을 기제. 반환값이 없으면 void
  console.log("이건 긴 메세지 입니다.");
}

let n: null = null;
let u: undefined = undefined;

_____________________________
함수타입 지정
//x, y 모두 숫자가 들어와야 한다
// return 값은 number(숫자)다
function add(x: number, y: number): number {
  return x + y;
}

______________________

2. 선택적 매개변수와 기본 매개변수
선택적 매개변수: 선택(Optional)적 변수. 값이 있어도 없어도 괜찮음.
   greeting?: string ?가 있는 greeting이 선택적 매개변수.

기본 매개변수: 값이 안들어왔을때 기본적으로 사용되는 변수.
   start: number = 10 이 = 10 코드가 기본 매개변수.

function greet(name: string, greeting?: string): string {
  if (!greeting) {
    greeting = "Hello";
  }
  return `${greeting}, ${name}!`;
}

function countdown(start: number = 10): void {
  console.log(start);
}

3. 화살표 함수
하나만 반환할 때 return 생략 가능
const multiply = (a: number, b: number): number => a * b;


____________________________
TypeScript를 왜 적용해야 하는 이유

1. 정적 타입 검사로 오류 예방
 js에서 이 함수를 작성 후 사용하다보면 type이 안 나오기 때문에 타입오류 발생위험.
사용자에게 받아 서버에 들어갈 데이터는 타입검증을 꼭 써야함

타입없음
// add.js
function add(x, y) {
  return x + y;
}

console.log(add(1, "9")); // 출력: "19"

// add.ts
function add(x: number, y: number): number {
  return x + y;
}

console.log(add(1, "9")); // 컴파일 에러 


2. 자동 완성 및 IntelliSense 지원

IntelliSense : 코딩을 더 쉽고 빠르게 만들어주는 똑똑한 어시스턴트
1. 자동으로 단어를 완성.
2. 함수나 변수에 대한 설명을 보여준다.
3. 사용 가능한 메서드나 속성을 목록으로 보여줍니다.</aside>

greet.ts
function greet(name: string, greeting?: string): string {
  // 'greeting'에 대한 자동 완성 및 타입 정보 제공
  return `${greeting || "Hello"}, ${name}!`;
}

아래 사진을 보면 g만 작성했을 뿐인데 매개변수에 선언된 greeting이 자동완성 되고 타입도 보이고 있다 





인터페이스: 객체의 구조를 정의하는 설계도. 필수 구성 요소 지정(강제한다.)
1. 코드의 일관성: 여러 객체가 같은 구조를 가지도록 보장합니다.
2. 오류 방지: 잘못된 속성이나 타입을 사용하면 컴파일 시 오류를 발생시켜 실수를 줄입니다.
3. 코드 가독성: 객체의 구조를 한눈에 파악할 수 있어 코드 이해가 쉬워집니다.

속성이 들어가지않거나 잘못된 속성을 넣으면 에러 발생

객체 만들고 커서 {}안에 두고 ‘ctrl’+’shift’눌러서 속성 띄울 수 있음
interface Person {
  name: string;
  age: number;
}

let user: Person = { name: "Alice", age: 30 };


2. 선택적 프로퍼티
// Car.ts
interface Car {
  make: string;
  model: string;
  year?: number; // 선택가능
}


3. 읽기 전용 프로퍼티 

읽기 전용 프로퍼티 : 값이 변경되는 것을 방지.
 좌표 값처럼 한 번 설정되면 바뀌지 않아야 하는 데이터를 다룰 때 사용
// Point.ts
interface Point {readonly x:number;readonly y:number;}
// 속성 앞에 readonly 붙이기

_____
Class에 타입 적용

Animal 클래스 정의
동물은 이름이 있고 move라는 메서드가 있습니다!
Animal.ts
class Animal {
  name: string; // 기본 접근 제어자는 public

  constructor(name: string) { // 생성자로 동물 생성시 이름을 받습니다.
    this.name = name;
  }

  move(distance: number = 0) {
    console.log(`${this.name} moved ${distance}m.`);
  }
}



접근 제어자는 클래스 외부에서 해당 멤버에 접근할 수 있는 범위를 제어합니다. TypeScript에는 세 가지 접근 제어자가 있습니다.
• public: 클래스 외부 어디에서나 접근 가능합니다. 기본 접근 제어자입니다.
• protected: 해당 클래스와 해당 클래스를 상속받은 자식 클래스 내에서만 접근 가능합니다.
• private: 해당 클래스 내에서만 접근 가능합니다. 클래스 외부에서는 어떠한 방법으로도 접근할 수 없습니다.

let cat = new Animal("고양이");
console.log(cat.name); // "고양이" 출력
cat.name = "새로운 고양이"; // public으로 name이 선언되어서 이름 변경 가능~
console.log(cat.name); // "새로운 고양이" 출력

// 접근 제어자 어떤식으로 작성하면 좋을까요??
// 대부분의 경우 클래스 속성은 private으로 선언!
// 필요한 경우 getter 메서드(또는 setter 메서드)를 제공하는 것이 객체지향 프로그래밍의 원칙(캡슐화) 
// 부합합니다. 즉 코드의 안정성과 유지 보수성을 높이는 데 도움이 됩니다.

______
private 선언했는데 수정이 필요할 때 setter 사용

// Animal.ts
class Animal {
  private _name: string; // _name 속성을 private으로 선언

  constructor(name: string) {
    this._name = name;
  }

  get name(): string {
    // _name 속성의 값을 반환하는 getter 메서드
    return this._name;
  }

// private 선언한 값 수정하려면 set을 만들어둬야 함
  set name(newName: string) {
    if (newName.length > 0) {
      // 유효성 검사 추가 가능
      this._name = newName;
    } else {
      console.log('이름은 최소 한 글자 이상이어야 합니다.');
    }
  }

  move(distance: number = 0) {
    console.log(`${this._name} moved ${distance}m.`);
  }
}

let cat = new Animal('고양이');
console.log(cat.name); // getter 메서드를 통해 "고양이" 출력

// cat._name = "새로운 고양이"; // private 속성이므로 직접 접근 불가. 컴파일 에러 발생!
// cat.name('나비'); // setter는 이렇게 함수처럼 호출 불가!
cat.name = '나비'; // setter 메서드를 통해 이름 변경
console.log(cat.name); // "나비" 출력

cat.name = ''; // setter 메서드에서 유효성 검사
console.log(cat.name); // "나비" 출력 (이름 변경되지 않음)


______________________________
기존 Express에 TS적용

폴더 구조
.
├── .prettierrc
├── .vscode
│   ├── .DS_Store
│   └── settings.json
├── nodemon.json
├── package-lock.json
├── package.json
├── src
│   ├── app.ts
│   ├── controller.ts
│   ├── repository.ts
│   ├── router.ts
│   ├── service.ts
│   └── types
│       └── DataItem.ts
└── tsconfig.json

 모듈 설치


npm install express



npm install -D typescript @types/express @types/node ts-node


- typescript: TypeScript 컴파일러, TS를 JS로 변환
- @types/express: Express의 타입 정의, TS에서 Express 사용 시 필요
- @types/node: Node.js의 타입 정의, TS에서 Node.js API 사용 시 필요
- ts-node: TS 파일을 직접 실행할 수 있게 해주는 도구
- `ts-node가 오류가 자주 발생한다는 이슈를 광호튜터님에게 제보받았습니다. 
현재 프로젝트에서는 정상적으로 작동하지만 오류가 계속 발생하시는 분은 
tsx라고 ts-node와 비슷한 모듈로 대체해서 사용해 보세요!`

---

 package.json 수정

- ESM 사용 👉 "type": "module"
- build: ts파일을 js파일로 변환(트랜스파일)
- dev: 개발용으로 사용(nodemon.json 설정 필요)


  "type": "module",
  "scripts": {
    "start": "node dist/app.js",
    "dev": "nodemon",
    "build": "tsc"
  },


---

 tsconfig.json 작성

json
{
  "compilerOptions": {
    "target": "ES2022", // 컴파일 결과물의 JavaScript 버전 지정
    "module": "NodeNext", // 모듈 시스템 지정 (Node.js의 최신 모듈 시스템 사용)
    "moduleResolution": "nodenext", // 모듈 해석 방식 지정
    "strict": true, // 엄격한 타입 체크 활성화
    "esModuleInterop": true, // CommonJS 모듈을 ES 모듈처럼 사용 가능하게 함
    "outDir": "./dist", // 컴파일된 파일이 저장될 디렉토리
    "rootDir": "./src" // TypeScript 소스 파일이 위치한 루트 디렉토리 
                     // ("outDir": "./dist", 랑 비슷한거라 생략 가능)
  },
  "include": ["src//*"] // 컴파일할 파일 지정 (src 폴더의 모든 파일)
}


---

 nodemon.json 작성


💡

nodemon.json 파일은 nodemon의 동작을 설정하는 파일입니다~

</aside>

json
{
  "watch": ["src"],
  "ext": "ts",
  "exec": "node --loader ts-node/esm src/app.ts" // --loader ts-node/esm 이 붙음...
}


- "watch": ["src"]
    - 변경 사항을 감지할 폴더를 지정합니다. 여기서는 "src" 폴더의 변화를 감시합니다.
- "ext": "ts"
    - 어떤 확장자의 파일 변경을 감지할지 지정합니다. 여기서는 TypeScript 파일만 감시!
- "exec": "node --loader ts-node/esm src/app.ts"
    - 파일 변경 시 실행할 명령을 지정합니다. 여기서는 TypeScript 파일을 직접 실행합니다.


https://teamsparta.notion.site/TypeScript-2ffe288e7dcf4b728e508b08274a3592














 

TypeScript 기초 | Notion

여러분, 오늘부터 TypeScript에 대해서 배워봅시다.

teamsparta.notion.site