본문 바로가기
TIL

TypeScript 강의 (8) ( 실습 : 별다방 )

by 황민도 2024. 7. 29.

내일배움캠프 스파르타 코딩클럽

프로그램 기능

- 별다방 프로그램은 다음과 같이 구성이 되어있어요.
    - 음료 등록 기능 - 어드민
    - 음료 삭제 기능 - 어드민
    - 음료 조회 기능 - 어드민, 고객
    - 음료 주문 기능 - 고객
    - 음료 준비 완료 기능 - 어드민
    - 음료 수령 기능 - 고객

얻고자 하는 것

- 이 프로그램에서는 우리가 배웠던 다양한 타입들을 활용해볼거에요!
- 이제, 그러면 프로그램 작성을 시작해보겠습니다!

 

windo@DESKTOP-6SMB85M MINGW64 ~
$ mkdir second

windo@DESKTOP-6SMB85M MINGW64 ~
$ cd second

windo@DESKTOP-6SMB85M MINGW64 ~/second
$ npm init -y
Wrote to C:\Users\windo\second\package.json:

{
  "name": "second",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}



windo@DESKTOP-6SMB85M MINGW64 ~/second
$ tsc --init --rootDir ./src --outDir ./dist --esModuleInterop -- module commonjs -- strict true --allowJS true --checkJS true
error TS5023: Unknown compiler option '--'.
error TS5023: Unknown compiler option '--'.

windo@DESKTOP-6SMB85M MINGW64 ~/second
$ tsc --init --rootDir ./src --outDir ./dist --esModuleInterop --module commonjs --strict ture --allowJS true --checkJS true

Created a new tsconfig.json with:

  target: es2016
  module: commonjs
  outDir: ./dist
  rootDir: ./src
  strict: true
  esModuleInterop: true
  skipLibCheck: true
  forceConsistentCasingInFileNames: true


You can learn more at https://aka.ms/tsconfig

 

 

 

{
  "name": "second",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
          "start": "tsc && node ./dist/index.js",
          "build": "tsc --build",
          "clean": "tsc --build --clean"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

vim package.json 명령어를 통하여 위 편집기에 진입

scripts 를 위와같이 수정하고 esc => :wq 로 저장 ( 저장 안하고 그냥 닫기는 :q! )

 

이제부터 편하게 code . 명령어를 통하여 vs code 편집기로 다루겠다.

 

windo@DESKTOP-6SMB85M MINGW64 ~/second
$ mkdir src

windo@DESKTOP-6SMB85M MINGW64 ~/second
$ ls
package.json  src/  tsconfig.json

second 디렉터리에 src 생성 

 

index.ts 생성

 

interface User {
	id: number;
	name: string;
	role: "admin" | "customer";
}

interface Beverage {
	name: string;
	price: number;
}

interface Order {
	orderId: number;
	customerId: number;
	customerName: string;
	beverageName: string;
	status: "placed" | "completed" | "picked-up";
}

let beverages: Beverage[] = [];
let orders: Order[] = [];

 

인터페이스와 데이터 정리

 

 

function isAdmin(user: User): boolean {
	return user.role === "admin";
}

function isCustomer(user: User): boolean {
	return user.role === "customer";
}

function addBeverage(user: User, name: string, price: number): void {
	if(!isAdmin(user)) {
		console.log("권한이 없습니다.")
		return;
	}

	const newBeverage: Beverage = { name, price };
	beverages.push(newBeverage);
}

function removeBeverage(user: User, beverageName: string): void {
	if(!isAdmin(user)) {
		console.log("권한이 없습니다.")
		return;
	}

	beverages = beverages.filter((beverage) => beverage.name !== beverageName );
}

function getBeverages(user: User): Beverage[] {
	if(!user) {
		return [];
	}
	return beverages;
}

function findBeverage(beverageName: string): Beverage | undefined {
	return beverages.find((beverage) => beverage.name === beverageName);
}

function placeOrder(user: User, beverageName: string): number {
	if(!isCustomer(user)) {
		console.log("권한이 없습니다.");
		return -1;
	}

	const beverage = findBeverage(beverageName);
	if(!beverage) {
		console.log("해당 음료를 찾을 수 없습니다.");
		return -1;
	}

	const newOrder: Order = {
		orderId: orders.length + 1,
		customerId: user.id,
		customerName: user.name,
		beverageName,
		status: "placed",
	}
	orders.push(newOrder);
	return newOrder.orderId;
}

function completeOrder(user: User, orderId: number): void {
	if(!isAdmin(user)) {
		console.log("권한이 없습니다.");
		return;
	}

	const order = orders.find((order) => order.orderId === orderId);
	if(order) {
		order.status = "completed"; // 주문 상태 변경
		console.log(
			`[고객 메시지] ${order.customerName}님~ 주문하신 ${order.beverageName} 1잔 나왔습니다~`
		);
	}
}

function pickUpOrder(user: User, orderId: number): void {
	if(!isCustomer(user)) {
		console.log("권한이 없습니다.");
		return;
	}

	const order = orders.find(
		(order) => order.orderId === orderId && order.customerId === user.id
	);
	if(order && order.status === "completed") {
		order.status = "picked-up";
		console.log(
			`[어드민 메시지] 고객 ID[${order.customerId}]님이 주문 ID[${orderId}]을 수령했습니다.`
		);
	}
}

function main() {
	const admin: User = {
		id: 1,
		name: "바리스타",
		role: "admin",
	}

	// 유저 생성
	const member1: User = {
		id: 2,
		name: "르탄이",
		role: "customer",
	};

	const member2: User = {
		id: 3,
		name: "꿈꾸는개발자",
		role: "customer",
	}

	// 음료 등록
	addBeverage(admin, "아메리카노", 4000);
	addBeverage(admin, "카페라떼", 4500);
	addBeverage(admin, "에스프레소", 3000);

	// 음료 삭제
	removeBeverage(admin, "에스프레소");

	console.log(
		`안녕하세요~ ${
			member1.name
		} 고객님! 별다방에 오신 것을 환영합니다. 저희는 ${JSON.stringify(
			getBeverages(member1)
		)}를 판매하고 있습니다.`
	);

	// 음료 주문
	const orderId2 = placeOrder(member2, "카페라떼");
	if (orderId2 > 0) {
		setTimeout(() => {
			// 음료 제작 완료
			completeOrder(admin, orderId2);
			// 음료 수령
			pickUpOrder(member2, orderId2);
		}, 3000);
	}
}

main();

함수 구현

 

 

windo@DESKTOP-6SMB85M MINGW64 ~/second
$ npm run build

> second@1.0.0 build
> tsc --build


windo@DESKTOP-6SMB85M MINGW64 ~/second
$ npm run start

> second@1.0.0 start
> tsc && node ./dist/index.js

안녕하세요~ 르탄이 고객님! 별다방에 오신 것을 환영합니다. 저희는 [{"name":"아메리카노","price":4000},{"name":"카페라떼","price":4500}를 판매하고 있습니다.
[고객 메시지] 꿈꾸는개발자님~ 주문하신 카페라떼 1잔 나왔습니다~
[어드민 메시지] 고객 ID[3]님이 주문 ID[1]을 수령했습니다.