[내일배움캠프 Spring_3기] CH2 계산기 과제 Step2

jiiim_ni·2026년 1월 13일

생각해보기

Step2를 진행하기 전에 요구사항을 읽어보니
이번 단계의 핵심은 새로운 연산 기능 추가가 아니라

  • 계산 로직을 클래스 단위로 분리
  • 연산 결과를 컬렉션으로 관리
  • 외부에서 필드에 직접 접근하지 못하도록 캡슐화를 적용

이라는 생각이 들었다.


설계

Step1에서는 App 클래스의 main 메서드 안에서
입력, 연산, 출력, 반복 제어가 모두 이루어졌다.

Step2에서는

  • App 클래스: 사용자 입력, 결과 출력, 반복/종료 제어
  • Calculator 클래스: 사칙연산 수행, 연산 결과를 컬렉션에 저장, 저장된 결과를 삭제

이렇게 설계하였다.


Calculator 클래스 구현

Calculator 클래스

  • 사칙연산 수행
  • 연산 결과를 리스트에 저장
  • 저장된 결과를 관리

연산 결과 저장 컬렉션

연산 결과는 여러 개가 누적되기 때문에 List를 사용하였다.

private final List<Integer> results = new ArrayList<>();
  • private: App에서 직접 접근하지 못하기 함
  • List: 결과를 순서대로 저장
  • ArrayList: 가장 기본적인 List 구현체

Calculate 메서드 구현

calculate 메서드는 연산 수행, 결과 저장, 결과 반환
총 3가지 역할을 수행하도록 구현했다.

public int calculate(int num1, int num2, char operator) {
    int result = 0;

    switch (operator) {
        case '+':
            result = num1 + num2;
            break;
        case '-':
            result = num1 - num2;
            break;
        case '*':
            result = num1 * num2;
            break;
        case '/':
            if (num2 == 0) {
                throw new IllegalArgumentException("0으로 나눌 수 없습니다.");
            }
            result = num1 / num2;
            break;
        default:
            throw new IllegalArgumentException("지원하지 않는 연산자입니다.");
    }

    results.add(result); // 연산 결과 저장
    return result;       // 결과 반환
}

Step1에서는 main 메서드에서 연산과 예외 처리를 했지만
Step2에서는 calculator가 하도록 변경했다.

잘못된 연산자나 0으로 나누는 경우에는
IllegalArgumentException을 던지고,
App 클래스에서 이를 받아 메시지를 출력하도록 했다

캡슐화(getter, setter)

App 클래스에서 결과 리스트에 직접 접근하지 못하도록 했다

public List<Integer> getResults() {
    return new ArrayList<>(results);
}

public void setResults(List<Integer> newResults) {
    results.clear();
    results.addAll(newResults);
}

외부에서 리스트를 직접 수정하는 상황을 방지할 수 있음

removeResult 메서드 구현

저장된 결과 중 가장 먼저 저장된 값을 삭제하는 기능도 추가했다.

public void removeResult() {
    if (!results.isEmpty()) {
        results.remove(0);
    }
}

리스트가 비어 있는 상태에서 삭제를 시도하면 오류가 날 수 있기 때문에 isEmpty()로 한번 더 체크하도록 구현했다.

Calculator.java 전체코드

package com.example.calculator.step2;

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

public class Calculator {

    //연산 결과를 저장하는 컬렉션 타입 필드 선언 및 생성
    private final List<Integer> results = new ArrayList<>();

    public int calculate(int num1, int num2, char operator) {

        int result = 0;

        switch (operator) {
            case '+':
                result = num1 + num2;
                break;
            case '-':
                result = num1 - num2;
                break;
            case '*':
                result = num1 * num2;
                break;
            case '/':
                if (num2 == 0) {
                    throw new IllegalArgumentException("0으로 나눌 수 없습니다.");
                }
                result = num1 / num2;
                break;
            default:
                throw new IllegalArgumentException("지원하지 않는 연산자입니다.");
        }

        //연산 결과를 컬렉션에 저장
        results.add(result);

        //return 연산 결과
        return result;
    }

    // Getter 메서드 구현
    public List<Integer> getResults() {
        return new ArrayList<>(results);
    }

    // Setter 메서드 구현
    public void setResults(List<Integer> newResults) {
        results.clear();
        results.addAll(newResults);
    }

    public void removeResult() {
        // 구현
        if (!results.isEmpty()) {
            results.remove(0);
        }
    }
}

App 클래스 구현

App 클래스에서는 Step1과 동일하게 구조를 유지했다.

달라진 점은 연산을 직접 수행하지 않고 Calculator 클래스의 calculate 메서드를 호출한다는 점이다.

Calculator calculator = new Calculator();

try {
    int result = calculator.calculate(num1, num2, operator);
    System.out.println("결과: " + result);
} catch (IllegalArgumentException e) {
    System.out.println("오류: " + e.getMessage());
}

또한 getter와 removeResult 메서드를 활용해 저장된 결과를 조회하고 삭제하는 기능도 함께 확인했다.

App.java 전체코드

package com.example.calculator.step2;

import java.util.Scanner;

public class App {
    public static void main(String[] args) {

        //Calculator 인스턴스 생성
        Calculator calculator = new Calculator();

        Scanner sc = new Scanner(System.in);

        // 반복문 시작
        while (true) {
            System.out.print("첫 번째 숫자를 입력하세요:");
            int num1 = sc.nextInt();
            System.out.print("두 번째 숫자를 입력하세요:");
            int num2 = sc.nextInt();

            System.out.print("사칙연산 기호를 입력하세요: ");
            char operator = sc.next().charAt(0);


            try {
                int result = calculator.calculate(num1, num2, operator);
                System.out.println("결과: " + result);
            } catch (IllegalArgumentException e) {
                System.out.println("오류: " + e.getMessage());
            }

            // getter 활용해보기
            System.out.println("저장된 결과 목록: " + calculator.getResults());

            // removeResult 활용해보기
            System.out.println("가장 먼저 저장된 결과를 삭제하시겠습니까? (remove 입력 시 삭제)");
            String cmd = sc.next();
            if (cmd.equalsIgnoreCase("remove")) {
                calculator.removeResult();
                System.out.println("삭제 후 결과 목록: " + calculator.getResults());
            }

            System.out.println("더 계산하시겠습니까? (exit 입력 시 종료)");
            String answer = sc.next();

            if (answer.equals("exit")) break;
        }
        // 반복문 종료

        sc.close();
    }
}

결과

프로그램을 실행해보면 연산 결과가 리스트에 차례대로 저장되고 remove를 입력하면 가장 먼저 저장된 값이 삭제된다.


다음 Step3에서는 실수 연산, 결과 조건 조회, Enum과 스트림 등을 적용하며 계산기를 조금 더 확장해볼 예정이다.

0개의 댓글