[TIL] 26/09/18 - 객체지향

맹돌이·2026년 9월 18일

TIL

목록 보기
4/13

계산기 과제 의문점

package calculator1;

import java.util.Scanner;

public class calculator {
    public static void main(String[] args) {
        //➕ ➖ ✖ ➗
        Scanner sc = new Scanner(System.in);
        int a = 0;
        int b = 0;
        char op = ' ';
        int result = 0;
        String repeat = "";

        while(!repeat.equals("exit")){

            System.out.print("첫 번째 숫자를 입력하세요: ");
            a = sc.nextInt();
            System.out.print("두 번째 숫자를 입력하세요: ");
            b = sc.nextInt();
            sc.nextLine();
            System.out.print("사칙연산 기호를 입력하세요: ");
            op = sc.nextLine().charAt(0);

            if(a<0 || b<0){
                System.out.println("첫 번째 숫자와 두 번째 숫자는 양의 정수여야 합니다");
            }
            else if(op!='+' && op!='-' && op!='*' && op!='/'){
                System.out.println("사칙연산 기호는 +,-,*,/ 중에 입력해야 합니다");
            }
            else{
                if(op=='+'){
                    result = a+b;
                }
                else if (op=='-') {
                    result = a-b;
                }
                else if (op=='*'){
                    result = a*b;
                }
                else if(op=='/'){
                    if(b==0) System.out.println("나눗셈 연산에서 분모(두번째 정수)에 0이 입력될 수 없습니다");
                    else result = a/b;
                }
                System.out.println("결과: "+result);
            }
            System.out.print("더 계산하시겠습니까?(exit 입력 시 종료): ");
            repeat = sc.nextLine();
            if(repeat.equals("exit")){
                System.out.println("프로그램을 종료합니다");
            }
        }


    }
}

위 코드는 계산기 만들기 과제 중 step1에 해당한다
클래스를 분리해서 Calculator 클래스를 만들어서 객체지향으로 만들고자 했다
이 때 의문이 생겼다
Scanner를 main에 둬야할까? Calculator에 둬야할까?

객체지향

우선 본질적으로 생각을 해야한다 객체지향이란 기능을 나눠서 조립하는 느낌인데, 그럼 각 클래스가 어떤 역할을 맡을건지 생각해봐야한다

main의 근본적인 역할은?
-> 프로그램이 필요한 객체를 설정해주는 역할을 한다

Calculator 클래스의 역할은?
숫자를 받아서 산술 연산을 실행해주는 덧셈 뺄셈 기계이다
(사실 여기서도 모순이 존재한다, 숫자를 받아서<인데 숫자를 calculator에서 받으면 안되지)

이런걸 왜 따져야하나?
자동차를 생각해보자. 사용자는 핸들 조향만하면 원하는 곳으로 이동을 할 수 있다. 엔진이 어떤 일을 하는지 알 필요가 없다.
이처럼 각 클래스의 역할을 분담함으로서 사용자가 몰라도 되는 것은 배제시키는 것이다.

SOLID

또, 객체지향의 5대원칙(SOLID)을 생각해봐도 좋다
S - 단일 책임 원칙 (SRP)핵심: 클래스는 오직 하나의 책임(기능)만 가져야 합니다.설명: 클래스가 변경되어야 하는 이유는 단 하나여야 합니다. 하나의 클래스가 너무 많은 일을 하면 코드를 고칠 때 다른 곳에 문제가 생기기 쉽습니다.

O - 개방-폐쇄 원칙 (OCP)핵심: 확장에는 열려 있어야 하고, 수정에는 닫혀 있어야 합니다.설명: 새로운 기능이 필요할 때 기존 코드를 수정하지 않고 확장을 통해 손쉽게 추가할 수 있어야 합니다.

L - 리스코프 치환 원칙 (LSP)핵심: 자식 클래스는 언제나 부모 클래스를 대체할 수 있어야 합니다.설명: 부모 객체 자리에 자식 객체를 넣어도 프로그램의 논리가 깨지지 않고 의도대로 작동해야 합니다.

I - 인터페이스 분리 원칙 (ISP)핵심: 범용 인터페이스 하나보다 구체적인 여러 개의 인터페이스가 낫습니다.설명: 자신이 사용하지 않는 메서드에 의존하도록 강제하면 안 됩니다. 필요한 기능만 작게 쪼개어 인터페이스를 만들어야 합니다.

D - 의존성 역전 원칙 (DIP)핵심: 구체적인 클래스가 아닌 추상화에 의존해야 합니다.설명: 상위 모듈이 하위 모듈의 세부 구현에 의존하지 않도록 인터페이스를 활용해 부품 교체가 용이한 구조를 구성합니다.

이 중 단일책임원칙은 하나의 클래스는 하나의 책임만 가져야한다!를 위배하게된다
그리고 Calculator에 스캐너를 넣게되면 프로그램이 확장되었을 때 문제가 발생한다.
예를들어서, 어떤 클래스를 추가해야되는데 그 클래스도 입력을 요구한다. 그럼 스캐너를 또 추가해서 사용할 것임. 그럼 스캐너 객체가 중복되어서 여러군데서 사용이되니까 컴퓨터 입장에선 힙에 쓸데없이 중복된 객체가 생성된거임. 그럼 자원 낭비로 이어지고 효율이 떨어지게되지.

Main: "어떤 순서로 프로그램이 흘러갈 것인가"
(입력 받기 → 계산기 호출 → 결과 출력 → 반복 또는 종료)
Calculator: "전달받은 데이터로 어떻게 계산할 것인가"

Main이 객체를 생성하고 제어권을 가짐으로써, 전체 프로그램의 실행 시나리오를 진행하는 역할과 실제 일을 수행하는 객체의 역할이 명확히 나누어진다

결론

결국 입력과 제어는 Main이, 계산은 Calculator가 맡는다는 역할 분담을 지킴으로써, 자동차의 핸들(입출력 제어)과 엔진(핵심 연산)이 분리된 것처럼 유지보수와 확장이 용이한 깔끔한 객체지향 코드를 작성할 수 있다

0개의 댓글