본문 바로가기

TypeScript

실습 : 도서관 프로그램

사서 : 도서추가, 도서 삭제

유저 : 도서 대여, 도서 반납

1. 프로젝트 세팅하기

npm init -y
tsc --init --rootDir ./src --outDir ./dist --esModuleInterop --module commonjs --strict true --allowJS true --checkJS true
"scripts": {
    "start": "tsc && node ./dist/index.js",
    "build": "tsc --build",
    "clean": "tsc --build --clean"
},

src디렉토리 - index.ts 파일 생성

 

role이라는 enum 정의하기

enum Role {
	LIBRARIAN,
    MEMBER,
}

User이라는 추상 클래스 정의하기 

User 클래스는 name, age 라는 인자를 받고 getRole 이라는 추상 함수를 포함한다.

abstract class User {
	constructor(public name:string, public age: number) {}
    abstract getRole():Role;
}

Member라는 클래스 정의 (User을 상속 받음)

class Member extends User {
	constructor (name: string, age: number) {
    	super(name,age);
    }
    getRole():Role{
    	return Role.MEMBER;
    }
}

사서 클래스

class Librarian extends User {
	constructor(name: string, age:number) {
    	super(name, age);
    }
    getRole():Role{
    	return Role.LIBRARIAN;
    }
}

책 클래스

class Book {
	constructor (
    	public title: string,
        public author: string,
        public publishedDate: Date
    ) {}
}

RentManager 인터페이스

interface RentManager {
	getBooks():Book[];
    addBook(user: User, book: Book):void;
    removeBook(user:User, book:Book):void;
    rentBook(user:Member,book:Book):void;
    returnBook(user:Member, book:Book):void;
}
class Library implements RentManager {
  private books: Book[] = [];
  // rentedBooks는 유저의 대여 이력을 관리해요!
  private rentedBooks: Map<string, Book> = new Map<string, Book>();

  getBooks(): Book[] {
    // 깊은 복사를 하여 외부에서 books를 수정하는 것을 방지합니다.
    return JSON.parse(JSON.stringify(this.books));
  }

  addBook(user: User, book: Book): void {
    if (user.getRole() !== Role.LIBRARIAN) {
      console.log("사서만 도서를 추가할 수 있습니다.");
      return;
    }

    this.books.push(book);
  }

  removeBook(user: User, book: Book): void {
    if (user.getRole() !== Role.LIBRARIAN) {
      console.log("사서만 도서를 삭제할 수 있습니다.");
      return;
    }

    const index = this.books.indexOf(book);
    if (index !== -1) {
      this.books.splice(index, 1);
    }
  }

  rentBook(user: User, book: Book): void {
    if (user.getRole() !== Role.MEMBER) {
      console.log("유저만 도서를 대여할 수 있습니다.");
      return;
    }

    if (this.rentedBooks.has(user.name)) {
      console.log(
        `${user.name}님은 이미 다른 책을 대여중이라 빌릴 수 없습니다.`
      );
    } else {
      this.rentedBooks.set(user.name, book);
      console.log(`${user.name}님이 [${book.title}] 책을 빌렸습니다.`);
    }
  }

  returnBook(user: User, book: Book): void {
    if (user.getRole() !== Role.MEMBER) {
      console.log("유저만 도서를 반납할 수 있습니다.");
      return;
    }

    if (this.rentedBooks.get(user.name) === book) {
      this.rentedBooks.delete(user.name);
      console.log(`${user.name}님이 [${book.title}] 책을 반납했어요!`);
    } else {
      console.log(`${user.name}님은 [${book.title}] 책을 빌린적이 없어요!`);
    }
  }
}