풀스택 개발자 과정 24일차

너구·2026년 6월 10일

풀스택 성장과정

목록 보기
24/79

GitHub 터미널 업로드 방법

  1. GitHub에서 로그인 후 repository 생성
  2. Git 초기화: git init
  3. 파일 생성: .gitignore
  4. Git 상태 확인: git status
  5. 파일 추가: git add .
  6. 첫 커밋 생성: git commit -m "~~ project"
  7. GitHub 저장소 주소 복사: git remote add origin<주소입력>.git
  8. 확인: git remote -v
  9. GitHub에 업로드: git branch -M main
    git push -u origin main

GitHub 수정 코드 올리는 방법

  1. 변경파일 추가: git add .
  2. 커밋 생성: git commit -m "~~~ 추가"
  3. Git Hub 업로드: git push
  • Git 확인: git status
  • 커밋 기록 확인: git log --oneline

Shopping List 만들기

ShoppingList

import java.util.ArrayList;
import java.util.List;

class ShoppingList {

    // 쇼핑 목록
    private List<String> items = new ArrayList<>();

    // 샘플 추가
    public ShoppingList() {
        addItem("감자");
        addItem("고구마");
        addItem("갑오징어");
    }

    // 모든 리스트 가져오기
    public List<String> getAllItems() {
        return items;
    }

    // 번호에 맞는 물건 가져오기
    public String getItemByNumber(int number) {
        int index = number -1;
        if (index < 0 || index >= items.size()) {
            throw new IllegalStateException("물건을 찾을 수 없습니다");
        }
        return items.get(index);
    }
    // 물건 추가하기
    public void addItem(String item) {
        if (item.trim().length() < 1) {
            throw new IllegalStateException("물건을 입력하세요");
        }
        items.add(item);
    }
    // 물건 제거하기
    public void removeItem(int number) {
        int index = number -1;
        if (index < 0 || index >= items.size()) {
            throw new IllegalStateException("물건을 찾을 수 없습니다");
        }
        items.remove(index);
    }
    // 물건 완료하기
    public void passItem(int number) {
        int index = number -1;
        if (index < 0 || index >= items.size()) {
            throw new IllegalStateException("물건을 찾을 수 없습니다");
        }
        if (items.get(index).startsWith("[완료]")) {
            throw new IllegalStateException("이미 담은 항목입니다");
        }
        items.set(index, "[완료] " + items.get(index));
    }
}

View

import java.util.List;

public class View {
    public View() {}

    public void showList(List<String> items) {

        System.out.println();
        System.out.println("- 장보기 목록");
        if (items.size() < 1) {
            System.out.println("물건을 추가해보세요");
        } else {
            for (int i = 0; i < items.size(); i++) {
                System.out.println((i + 1) + ". " + items.get(i));
            }
        }
        System.out.println("추가: add 물건|완료: pass 번호|삭제: drop 번호|종료: end");
    }
}

Controller

import java.util.List;

public class Controller {

    private ShoppingList shoppingList;
    private View view;

    // 의존성 주입
    public Controller(ShoppingList shoppingList, View view) {
        this.shoppingList = shoppingList;
        this.view = view;
    }
    // 할 일 목록 처리
    public void listItems() {
        List<String> items = shoppingList.getAllItems();
        view.showList(items);
    }
    // 할 일 추가 처리
    public void addItem(String item) {
        shoppingList.addItem(item);
        List<String> items = shoppingList.getAllItems();
        view.showList(items);
    }
    // 할 일 삭제 처리
    public void dropItem(int number) {
        shoppingList.removeItem(number);
        List<String> items = shoppingList.getAllItems();
        view.showList(items);
    }
    // 할 일 완료처리
    public void passItem(int number) {
        shoppingList.passItem(number);
        List<String> items = shoppingList.getAllItems();
        view.showList(items);
    }
}

Command Handler

import java.util.Scanner;

public class CommandHandler {
    
    private Controller controller;
    private Scanner scanner;

    public CommandHandler(Controller controller, Scanner scanner) {
        this.controller = controller;
        this.scanner = scanner;
    }

    public void run() {

        controller.listItems();

        while(true) {
            System.out.print("item> ");
            String userInput = scanner.nextLine().trim();
            String[] parseInput = userInput.split(" ", 2);
            String command = parseInput[0];
            String arg = parseInput.length > 1 ? parseInput[1] : "";

            try {
                switch (command) {
                    case "list":
                        controller.listItems();
                        break;
                    case "add":
                        controller.addItem(arg);
                        break;
                    case "pass":
                        controller.passItem(Integer.parseInt(arg));
                        break;
                    case "drop":
                        controller.dropItem(Integer.parseInt(arg));
                        break;
                    case "end":
                        return;
                    default:
                        System.out.println("잘못된 명령어");
                }
            } catch (Exception e) {
                System.out.println("오류: " + e.getMessage());
            }
        }
    }
}

ShoppingApp

import java.util.Scanner;

public class shoppingApp {
    public static void main(String[] args) throws Exception {
        
        ShoppingList shoppingList = new ShoppingList();
        View view = new View();
        Controller controller = new Controller(shoppingList, view);

        Scanner scanner = new Scanner(System.in);
        CommandHandler commandHandler = new CommandHandler(controller, scanner);

        commandHandler.run();
        scanner.close();
    }
}

Shopping List 마무리

이번 Shopping List 프로젝트를 통해 ArrayList를 활용한 데이터 관리와 MVC 패턴의 구조를 직접 구현해볼 수 있었다. 사용자가 물품을 추가, 삭제하고 구매 완료 처리까지 할 수 있는 콘솔 프로그램을 만들면서 클래스별 역할을 나누는 방법을 연습했다.

특히 Controller, View, CommandHandler의 역할을 구분하며 프로그램이 어떻게 동작하는지 이해할 수 있었고, 예외 처리를 통해 잘못된 입력을 방지하는 방법도 배울 수 있었다.

또한 Git과 GitHub를 활용해 프로젝트를 관리하고 업로드하는 경험도 할 수 있었다. 작은 프로젝트였지만 직접 처음부터 끝까지 구현해보면서 Java와 객체지향 프로그래밍에 대한 이해를 한층 높일 수 있었던 의미 있는 경험이었다.


Bank Account 만들기

Bankaccount

import java.util.ArrayList;
import java.util.List;

class BankAccount {

    private int balance;
    private List<String> transactions = new ArrayList<>();

    // 잔액
    public int getBalance() {
        return balance;
    }
    
    // 거래 내역
    public List<String> getTransactions() {
        return transactions;
    }

    // 입금
    public void deposit(int amount) {
        
        if (amount <= 0) {
            throw new IllegalStateException("입금할 수 없습니다");
        }
        balance += amount;
        transactions.add("입금: " + amount + "원");
    }

    // 출금
    public void withdraw(int amount) {

        if (amount <= 0) {
            throw new IllegalStateException("출금할 수 없습니다");
        }

        if (amount > balance) {
            throw new IllegalStateException("잔액이 부족합니다");
        }
        balance -= amount;
        transactions.add("출금: " + amount + "원");
    }

    // 송금
    public void transfer(String name, int amount) {

        if (amount <= 0) {
            throw new IllegalStateException("송금할 수 없습니다");
        }
        if (amount > balance) {
            throw new IllegalStateException("잔액이 부족합니다");
        }
        balance -= amount;
        transactions.add(name + " 님에게" + amount + "원을 송금하였습니다");
    }
}

BankAccount 클래스는 은행 계좌의 핵심 기능을 담당하는 Model 역할을 수행한다.
계좌잔액과 거래내역을 관리하며 입금, 출금, 송금 기능을 제공한다.

getBalance()를 통해 현재 계좌 잔액을 반환한다.
getTransactions()를 통해 모든 거래 내역을 반환한다.

입금은 deposit() 메서드를 사용해 잔액을 증가시킨다.
0원 이하의 금액을 입금할 수 없도록 예외처리를 적용하였다.
또한 거래 내역에 입금 기록을 저장한다.

출금은 withDraw() 메서드를 사용해 잔액을 차감한다.
출금 금액이 0원 이하이거나 현재 잔액보다 큰 경우 예외를 발생시킨다.
거래 내역에 출금 기록을 저장한다.

transfer() 메서드를 사용해 지정한 사용자에게 송금한다.
잔액 부족 및 잘못된 금액 입력을 방지하기 위한 예외처리를 적용하였다.
거래 내역에 송금 대상과 금액을 함께 기록한다.

이 클래스는 프로젝트 전체에서 실제 은행 계좌 데이터를 관리하는 역할을 담당하며 Controller를 통해 사용자 요청을 받아 처리하도록 설계하였다.

View

import java.util.List;

public class View {
    
    public View() {}

    public void showMain(String message, int balance) {
        System.out.println();
        System.out.println("- Bank Account");
        System.out.println("--------------------");
        if (!message.isEmpty()) {
            System.out.println(message);
        }
        System.out.println("현재 잔액: " + balance + "원");
        System.out.println("--------------------");
        System.out.println("예금: save 금액|출금: take 금액|송금: send 아이디 금액");
        System.out.println("거래내역: history|종료: exit");
    }

    public void showHistory(List<String> transactions) {
        System.out.println();
        System.out.println("- 거래 내역");
        System.out.println("--------------------");
        
        if (transactions.size() < 1) {
            System.out.println("거래 내역이 없습니다");
        } else {
            for (int i = 0; i < transactions.size(); i++) {
                System.out.println((i + 1) + ". " + transactions.get(i));
            }
        }

        System.out.println("돌아가기: main|종료: exit");
    }
}

View 클래스는 사용자에게 화면을 출력하는 역할을 담당한다.
MVC 패턴에서 View에 해당하며 계좌 정보와 거래 내역을 콘솔에 표시하는 기능을 구현하였다.

showMain() 메서드를 통해 현재 잔액과 사용 가능한 명령어를 출력한다.
입금, 출금, 송금이 성공했을 때 전달받은 메시지를 함께 표시할 수 있도록 구현하였다.
사용자는 현재 계좌 상태와 사용 가능한 기능을 한 눈에 확인할 수 있다.

showHistory() 메서드로 저장된 거래 내역을 목록 형태로 출력한다.
거래 내역이 없는 경우 안내 메시지를 출력하도록 처리하였다.
반복문을 사용해 모든 거래 내역을 번호와 함께 출력한다.

이 클래스는 사용자와 프로그램이 상호작용하는 화면 역할을 담당하며 계좌 데이터는 직접 관리하지 않고 Controllor를 통해 전달받아 출력만 수행한다.

Controller

import java.util.List;

public class Controller {
    
    private BankAccount bankAccount;
    private View view;

    public Controller(BankAccount bankAccount, View view) {
        this.bankAccount = bankAccount;
        this.view = view;
    }

    public void showBalance() {
        int balance = bankAccount.getBalance();
        view.showMain("", balance);
    }

    public void showHistory() {
        List<String> transactions = bankAccount.getTransactions();
        view.showHistory(transactions);
    }

    public void depositMoney(int amount) {
        bankAccount.deposit(amount);
        int balance = bankAccount.getBalance();
        view.showMain(
            "성공적으로 " + amount + "원을 입금했습니다",
            balance
        );
    }

    public void withdrawMoney(int amount) {
        bankAccount.withdraw(amount);
        int balance = bankAccount.getBalance();
        view.showMain(
            "성공적으로 " + amount + "원을 출금했습니다",
            balance
        );
    }

    public void transferMoney(String name, int amount) {
        bankAccount.transfer(name, amount);
        int balance = bankAccount.getBalance();
        view.showMain(
            "성공적으로 " + name + "님께" + amount + "원을 송금하였습니다",
            balance
        );
    }
}

Controller 클래스는 MVC 구조에서 사용자 요청을 처리하고 BankAccount와 View를 연결하는 역할을 담당한다.
BankAccount를 통해 데이터를 처리하고 View를 통해 결과를 화면에 출력한다.

showBalance() 메서드는 현재 계좌 잔액을 조회하여 화면에 출력한다.
BankAccount에서 잔액을 가져오고 View를 통해 현재 잔액만 표시한다.

showHistory() 메서드는 지금까지의 모든 거래 내역을 조회한다.
BankAccount에서 transactions 리스트를 가져오고 View의 showHistory()를 통해 전체 내역을 출력한다.

depositMoney() 메서드는 입금 요청을 처리한다.
BankAccount의 deposit()을 실행하고 입금 후 최신 잔액을 조회한다.
성공 메시지와 함께 View로 결과를 출력한다.

withdrawMoney() 메서드는 출금 요청을 처리한다.
BankAccount의 withdraw() 실행 후 출금 후 최신 잔액을 조회한다.
그 후 성공 메시지와 함께 View로 결과를 출력한다.

transferMoney() 메서드는 특정 대상에게 송금 요청을 처리한다.
BankAccount의 transfer()를 실행 후 송금 후 최신 잔액을 조회한다.
수신자 정보와 함께 성공 메시지를 View에게 전달한다.

이 Controller 클래스는 사용자 입력을 받아 실제 금융 로직을 실행하고 그 결과를 화면에 전달하는 중심 역할을 한다.

Command Handler

import java.util.Scanner;

public class Commandhandler {
    
    private Controller controller;
    private Scanner scanner;

    public Commandhandler(Controller controller, Scanner scanner) {
        this.controller = controller;
        this.scanner = scanner;
    }

    public void run() {

        controller.showBalance();

        while (true) {
            System.out.print("bank> ");
            String UserInput = scanner.nextLine().trim();
            String[] parseInput = UserInput.split(" ", 2);

            String command = parseInput[0];
            String arg = parseInput.length > 1 ? parseInput[1] : "";

            try {
                switch (command) {
                    case "main" :
                        controller.showBalance();
                        break;
                    case "history" :
                        controller.showHistory();
                        break;
                    case "exit" : 
                        System.out.println("앱을 종료합니다");
                        return;
                    case "save" : 
                        controller.depositMoney(Integer.parseInt(arg));
                        break;
                    case "take" :
                        controller.withdrawMoney(Integer.parseInt(arg));
                        break;
                    case "send" :
                        String[] sendArgs = arg.split(" ");
                        String name = sendArgs[0];
                        int amount = Integer.parseInt(sendArgs[1]);

                        controller.transferMoney(name, amount);
                        break;

                    default : 
                    System.out.println("잘못된 명령어");
                }
            } catch (Exception e) {
                System.out.println("오류: " + e.getMessage());
            }
        }
    }
}

CommandHandler 클래스는 사용자의 입력을 받아 적절한 Controller 메서드를 호출하는 역할을 수행한다.
콘솔 기반 CLI 환경에서 사용자 명령을 처리하는 핵심 입력 처리 계층이다.

run() 메서드는 프로그램의 메인 루프 역할을 한다.
1. 프로그램 시작 시 현재 잔액을 먼저 출력
2. 무한 루프를 통해 사용자 명령 입력 대기
3. 입력값을 명령어 + 인자로 분리
4. 명령어에 따라 Controller 기능 실행
5. 오류 발생 시 예외 메시지 출력

사용자가 bank> save 1000, bank> take 300 이런 형식으로 명령어를 입력하면 입력값은 split("", 2)를 통해 명령어와 인자로 분리된다.

main에서는 controller.showBalance()를 호출 후 현재 계좌 상태를 다시 출력한다.
history에서는 controller.showHistory()를 호출해 모든 거래 기록을 출력한다.
save에서는 입력 금액을 Integer.parseInt()로 변환 후 controller.depositMoney()를 실행한다.
take에서는 입력 금액을 출금 처리하고 controller.withdrawMoney()를 실행한다.
send에서는 "이름 금액" 형식으로 추가 입력을 분리하였다.
이름과 금액을 각가 추출한 뒤 controller.transferMoney()를 호출한다.
exit는 "앱을 종료합니다" 출력 후 return으로 루프를 종료시킨다.

잘못된 명령어가 입력되었을 때 예외처리를 통해 "잘못된 명령어"를 출력한다.
숫자 변환 오류, 배열 오류 등 모든 예외를 try-catch로 처리한다.
에러 발생 시 사용자에게 메시지를 출력한다.

CommandHandler 클래스는 사용자 입력을 가장 먼저 받아서 해석하고,
그 결과를 Controller로 전달하는 입력 제어 중심 계층이다.

즉, 전체 구조에서 보면:

  • Model → 데이터 처리
  • View → 출력
  • Controller → 로직 중재
  • CommandHandler → 사용자 입력 처리

이렇게 MVC 구조를 완성하는 입력 엔진 역할을 담당한다.

BankApp

import java.util.Scanner;

public class BankApp {
    public static void main(String[] args) throws Exception {
        
        BankAccount bankAccount = new BankAccount();
        View view = new View();
        Controller controller = new Controller(bankAccount, view);

        Scanner scanner = new Scanner(System.in);
        Commandhandler commandhandler = new Commandhandler(controller, scanner);

        commandhandler.run();
        scanner.close();
    }
}

BankApp 클래스는 전체 은행 프로그램의 실행 시작점 (Main Entry Point) 역할을 한다.
MVC 구조와 CommandHandler를 조립하여 프로그램을 실행하는 초기 설정 클래스이다.

계좌 데이터(잔액, 거래내역)를 관리하는 핵심 모델 객체를 생성하고 사용자에게 결과를 출력하는 화면 담당 객체도 생성한다.
그 다음 그 두 개를 연결하는 중간 제어 객체인 Controller를 생성한다.
모든 금융 로직 처리의 중심역할을 한다.
그 다음 사용자 입력을 해석하고 Controller로 전달하는 입력 처리 객체인 CommandHandler를 생성한다.
그 다음 run();으로 CLI 기반 은행 프로그램 실행을 시작한다.
사용자 입력 루프가 여기서 동작한다.
그 다음 scanner.close()로 자원 정리를 한다.
입력 스트림을 종료하고 프로그램 종료 시 리소스를 정리한다.

BankApp 클래스는 전체 시스템의 출발점이자 조립 공장 역할을 한다.
각각의 역할(Model, View, Controller, CommandHandler)을 생성하고 연결하여,
사용자가 CLI에서 은행 시스템을 사용할 수 있도록 실행 환경을 구성한다.

즉, 이 클래스는 프로그램 구조를 완성하는 “엔트리 컨트롤러” 라고 볼 수 있다.

Bank Account 마무리

BankAccount 클래스를 만들면서 느낀 건, 단순히 “돈을 더하고 빼는 기능”을 구현하는 게 전부가 아니라는 점이었다. 처음에는 입금, 출금, 송금 정도만 구현하면 끝이라고 생각했는데, 실제로 만들어보니까 그 안에 예외 처리나 거래 내역 관리 같은 생각해야 할 부분이 훨씬 많았다.

특히 잔액을 단순 변수로만 다루는 게 아니라, 거래가 발생할 때마다 기록을 남기는 구조를 만들면서 “아, 이게 단순 계산이 아니라 하나의 시스템이구나”라는 느낌이 들었다. ArrayList로 거래 내역을 쌓아가는 구조도 처음에는 그냥 기능처럼 느껴졌는데, 나중에는 이게 은행 시스템에서 로그처럼 중요한 역할을 한다는 걸 이해하게 됐다.

또 하나 크게 느낀 건 예외 처리의 중요성이었다. 0원 이하 입력이나 잔액 부족 같은 상황을 그냥 넘어가면 프로그램이 쉽게 망가질 수 있는데, 이런 부분을 미리 막아주는 게 코드의 안정성을 결정한다는 걸 알게 됐다.

전체적으로 보면 이 클래스는 단순한 연습용 코드라기보다는, “작은 은행 시스템의 핵심 엔진” 같은 역할을 한다는 생각이 들었다. Controller나 View랑 연결되기 전인데도 이미 구조적으로는 꽤 완성된 느낌이 있어서, 객체지향 설계가 왜 중요한지도 조금씩 이해가 됐다.

이번 작업을 통해 느낀 건, 기능을 만드는 것보다 “왜 이렇게 나눠서 설계하는가”를 이해하는 게 더 중요하다는 점이었다.


Wallet 만들기

Wallet

import java.util.ArrayList;
import java.util.List;

class Wallet {
    private int balance;
    private List<String> transactions = new ArrayList<>();

    public int getBalance() {
        return balance;
    }

    // 내역
    public List<String> getTransactions() {
        return transactions;
    }

    // 충전
    public void charge(int amount) {

        if (amount <= 0) {
            throw new IllegalStateException("충전할 수 없습니다");
        }
        balance += amount;
        transactions.add("충전: " + amount + "원");
    }

    // 사용
    public void use(int amount) {

        if (amount <= 0) {
            throw new IllegalStateException("사용할 수 없습니다");
        }
        if (amount > balance) {
            throw new IllegalStateException("잔액이 부족합니다");
        }
        balance -= amount;
        transactions.add("사용: " + amount + "원");
    }
}

View

import java.util.List;

public class View {
    public View() {}

    public void showMain(String message, int balance) {
        System.out.println();
        System.out.println("-지갑 관리 시스템");
        System.out.println("------------------");
        if (!message.isEmpty()) {
            System.out.println(message);
        }
        System.out.println("현재 잔액: " + balance + "원");
        System.out.println("------------------");
        System.out.println("충전: charge 금액|사용: use 금액");
        System.out.println("사용 내역: history|종료: exit");
    }

    public void showHistory(List<String> transactions) {
        System.out.println();
        System.out.println("- 거래 내역");
        System.out.println("------------------");

        if (transactions.size() < 1) {
            System.out.println("거래 내역이 없습니다");
        } else {
            for (int i = 0; i <transactions.size(); i++) {
                System.out.println((i + 1) + ". " + transactions.get(i));
            }
        }

        System.out.println("돌아가기: main|종료: exit");
    }
}

Controller

import java.util.List;

public class Controller {
    
    private Wallet wallet;
    private View view;

    public Controller(Wallet wallet, View view) {
        this.wallet = wallet;
        this.view = view;
    }

    public void showBalance() {
        int balance = wallet.getBalance();
        view.showMain("", balance);
    }

    public void showHistory() {
        List<String> transactions = wallet.getTransactions();
        view.showHistory(transactions);
    }

    public void chargeMoney(int amount) {
        wallet.charge(amount);
        int balance = wallet.getBalance();
        view.showMain(
            "성공적으로 " + amount + "원을 충전하였습니다",
            balance
        );
    }

    public void useMoney(int amount) {
        wallet.use(amount);
        int balance = wallet.getBalance();
        view.showMain(
            "성공적으로 " + amount + "원을 사용하였습니다",
            balance
        );
    }
}

Command Handler

import java.util.Scanner;

public class CommandHandler {
    
    private Controller controller;
    private Scanner scanner;

    public CommandHandler(Controller controller, Scanner scanner) {
        this.controller = controller;
        this.scanner = scanner;
    }

    public void run() {

        controller.showBalance();

        while (true) {
            System.out.print("Wallet> ");
            String userInput = scanner.nextLine().trim();
            String[] parseInput = userInput.split(" ", 2);

            String command = parseInput[0];
            String arg = parseInput.length > 1 ? parseInput[1] : "";

            try {
                switch (command) {
                    case "main":
                        controller.showBalance();
                        break;
                    case "history":
                        controller.showHistory();
                        break;
                    case "charge":
                        try {
                            int amount = Integer.parseInt(arg);
                            controller.chargeMoney(amount);
                        } catch (NumberFormatException e) {
                            System.out.println("숫자만 입력하세요");
                        }
                        break;
                    case "use":
                        try {
                            int amount = Integer.parseInt(arg);
                            controller.useMoney(amount);
                        } catch (NumberFormatException e) {
                            System.out.println("숫자만 입력하세요");
                        }
                        break;
                    case "exit":
                        System.out.println("앱을 종료합니다");
                        return;
                    default:
                        System.out.println("잘못된 명령어입니다");
                }
            } catch (Exception e) {
                System.out.println("오류: " + e.getMessage());
            }
        }
    }
}

Wallet App

import java.util.Scanner;

public class WalletApp {
    public static void main(String[] args) throws Exception {
        
        Wallet wallet = new Wallet();
        View view = new View();
        Controller controller = new Controller(wallet, view);

        Scanner scanner = new Scanner(System.in);
        CommandHandler commandHandler = new CommandHandler(controller, scanner);

        commandHandler.run();;
        scanner.close();
    }
}

Wallet 마무리

이번 Wallet 프로젝트를 통해 단순한 기능 구현을 넘어서,
MVC 구조를 실제로 어떻게 나누고 연결하는지 직접 경험할 수 있었다.

처음에는 입금, 사용, 잔액 조회 같은 기능을 만드는 데 집중했지만,
점점 구조를 나누면서 “어떻게 설계하느냐”가 더 중요하다는 걸 느꼈다.

특히 Controller가 전체 흐름을 관리하고, View는 출력만 담당하며,
Model이 데이터를 책임지는 구조를 직접 만들어보면서 객체지향의 의미를 조금씩 이해하게 되었다.

또한 CommandHandler를 통해 사용자 입력을 처리하면서
단순한 코드 실행이 아니라 “입력 → 처리 → 출력”이라는 전체 흐름을 구성하는 경험을 했다.

이번 프로젝트는 기능보다 구조를 배우는 과정이었고,
앞으로 더 복잡한 프로그램을 만들기 위한 기본기를 다지는 작업이었다.

0개의 댓글