JAVA

[Java] Lv_4 도서관 프로젝트

kimyongjun0129 2025. 5. 2. 23:38

 

요구사항

 

  • ⬜ 사용자는 도서를 대여하고 반납할 수 있다.
  • ⬜ 사용자별로 어떤 책을 대여했는지 확인할 수 있어야 한다.
  • ⬜ 사용자 이름과 ID를 가진다.

 


 

 

문제 풀이

Main

더보기
package lv_4;

import java.util.ArrayList;
import java.util.Optional;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Library library = new Library(new ArrayList<>(), new RentService());
        library.addBook(new Book("The Little Prince", "Antoine de Saint-Exupéry", 1943));
        library.addBook(new Book("Cinderella", "Charles Perrault", 1697));

        while(true) {
            User user = login();

            showMenu();
            int input = Integer.parseInt(scanner.nextLine());

            switch (input) {
                case 0 -> {
                    System.out.println("프로그램을 종료합니다.");
                    return;
                }
                case 1 -> {
                    String title = scanner.nextLine();
                    Optional<Book> book = library.findBookByTitle(title);

                    if (book.isPresent()) {
                        Book foundBook = book.get();
                        library.getRentService().rentBook(foundBook);
                        foundBook.setUserId(user.getId());
                    } else {
                        System.out.println(title + " : 책이 존재하지 않습니다.");
                    }
                }
                case 2 -> {
                    String title = scanner.nextLine();
                    Optional<Book> book = library.findBookByTitle(title);

                    if (book.isPresent()) {
                        Book foundBook = book.get();

                        if (foundBook.getUserId() == user.getId()) {
                            library.getRentService().returnBook(foundBook);
                            foundBook.resetUserId();
                        } else {
                            System.out.println(foundBook.getTitle() + " : 대여하지 않았습니다.");
                        }
                    }
                }
                case 3 -> library.printBook(scanner.nextLine());
                case 4 -> library.printAllBook();
            }
        }
    }

    // 유저 정보 등록
    public static User login() {
        Scanner scanner = new Scanner(System.in);

        System.out.println("[ 회원 정보 등록 ]");
        System.out.print("ID : ");
        int id = Integer.parseInt(scanner.nextLine());
        return new User(id);
    }

    // 메뉴를 보여준다.
    public static void showMenu() {
        System.out.println("[ Library Menu ]");
        System.out.println("0. 종료");
        System.out.println("1. 도서 대여");
        System.out.println("2. 도서 반납");
        System.out.println("3. 도서 검색");
        System.out.println("4. 도서 목록 출력");
    }
}

 

  • 책을 대출할 때, 유저의 ID를 넣어줍니다.
  • 책을 반납할 때, 책에 넣어진 ID와 현재 유저의 ID가 동일하면, 반납이되도록하였다. 책이 반납되면, 책에있는 유저의 ID를 초기화해줍니다.

 

 

 

Library

더보기
package lv_4;

import java.util.List;
import java.util.Optional;

public class Library {
    private final List<Book> bookList;
    private final RentService rentService;

    public Library(List<Book> bookList, RentService rentService) {
        this.bookList = bookList;
        this.rentService = rentService;
    }

    public RentService getRentService() {
        return rentService;
    }

    public void addBook(Book book) {
        bookList.add(book);
    }

    public Optional<Book> findBookByTitle(String title) {
        for(Book book : bookList) {
            if(book.getTitle().equalsIgnoreCase(title)) {
                return Optional.of(book);
            }
        }
        return Optional.empty();
    }

    public void printBook(String title) {
        Optional<Book> book = findBookByTitle(title);
        if (book.isPresent()) {
            Book foundBook = book.get();
            System.out.println(foundBook + "\n");
        } else {
            System.out.println(title + "은/는 존재하지 않는 책입니다.\n");
        }
    }

    public void printAllBook() {
        System.out.println("[ 전체 책 목록 ]");
        for(Book book : bookList) {
            System.out.println(book);
        }
        System.out.println();
    }
}
  • 기존에 있던, rentBook()과 returnBook() 메서드는 RentService 클래스에 옮겨주었다.
  • RentService를 Library 생성자를 통해 의존성을 주입시켰다.

 

 

 

RentService

더보기
package lv_4;

public class RentService {

    public void rentBook(Book book) {
        if (book.rented()) {
            System.out.println(book.getTitle() + " : 이미 대여된 책입니다.\n");
        } else {
            System.out.println(book.getTitle() + " : 대여 완료\n");
            book.rent();
        }
    }

    public void returnBook(Book book) {
        if (book.rented()) {
            System.out.println(book.getTitle() + " : 반납 완료\n");
            book.rent();
        } else {
            System.out.println(book.getTitle() + " : 이미 반납된 책입니다.\n");
        }
    }
}
  • 현재로써는 두 메서드 밖에없는 클래스지만 추후 확장을 고려하여 분리하였다.

 

 

Book

더보기
package lv_4;

public class Book {
    private String title;
    private String author;
    private int publishYear;
    private boolean isRented;
    private int userId;

    public Book(String title, String author, int publishYear) {
        this.title = title;
        this.author = author;
        this.publishYear = publishYear;
    }

    public void rent() {
        if(isRented) {
            isRented = false;
            return;
        }
        isRented = true;
    }

    public boolean rented() {
        return isRented;
    }

    public String getTitle() {
        return title;
    }

    public long getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public void resetUserId() {
        this.userId = 0;
    }

    @Override
    public String toString() {
        return String.format("제목 : %-20s | 저자 : %-30s | 출판 연도 : %-13s",title,author,publishYear);
    }
}

 

 

 

User

더보기
package lv_4;

public class User {
    private int id;

    public User(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }
}

 

 

 


 

 

 

객체의 역할과 책임

Main Library Book RentService User
Scanner 객체 생성 책 추가 책의 정보 보관 책 대여 로직 처리 사용자 정보 보관
Library 객체 생성 책 검색 책 정보를 문자열로 표현 책 반납 로직 처리 사용자 정보 제공
Book 객체 생성 도서 출력 책의 정보 제공    
로그인 기능 처리        
전체 흐름 처리        

 

 

 


 

 

 

실행 흐름

실행 흐름

 

 

 


 

 

 

GPT 분석

`setUserId()`와 `resetUserId()`는 외부에서 Book 속성을 직접 바꿀 수 있다. → 캡슐화가 깨질 수 있다.

  • `Book` 객체의 상태가 외부에 의해 너무 쉽게 조작될 수 있다. (ex. 잘못된 시점에 setUserId(0) 호출 가능)
  • "왜 바꾸는지"에 대한 의미가 코드에서 드러나지 않는다. (대여인지? 반납인지? 테스트용 변경인지? 알수 없다.)

입력 시책 처리 개선

현재는 `scanner.nextLine()`만 반복되는데, 예외나 공백 처리 등이 없다.

→ 추후 InputView 같은 클래스로 입출력을 분리하면 UI와 도메인을 더욱 명확히 나눌 수 있어요. (MVC로의 확장 가능)