TIL 11 [Java(접근제어자, 클래스란?, 객체지향?) + 계산기 과제 2단계 ]

2025. 3. 4. 17:07·[내일배움캠프-Sparta]/Spring 6기
반응형

1. 오늘 학습 키워드 : 계산기 과제 2단계, Java 특강

2. 학습 내용을 나만의 언어로 정리
Java는 클래스로 이루어진 객체지향 프로그래밍 언어이다.

클래스는 속성, 생성자, 기능 으로 이루어짐 ( 속생기 )
3. 학습내용
14:00 ~ 15:00 프로그래밍 기초 특강 ( 박성원 튜터님, 클래스란 무엇인가? )

 

🌟AI 설정 끄기🌟  - 편하긴하나, 의존하게 되면 나중에 그 의미를 알지도 못한채 사용할 가능성이 있는거 같음.

접근 제어자 같은 클래스 같은 패키지 상속한 클래스 다른 패키지
public ✅ ✅ ✅ ✅
protected ✅ ✅ ✅ ❌
default (직접선언 x) ✅ ✅ ❌ ❌
private ✅ ❌ ❌ ❌

 

객체지향 프로그래밍(OOP)란? 

  • OOP(Object-Oriented Programming) = " 객체를 중심으로 프로그램을 설계하는 방식 "
  • 현실 세계의 사물을 코드로 표현해 재사용성, 유지보수성, 확장성을 높임

예시 : 자동차

class Car {
    // 속성
    String brand; // 브랜드
    String color; // 색상
    int speed;    // 속도

    // 기능
    void start() {
        System.out.println(brand + " 자동차가 출발합니다.");
    }

    void stop() {
        System.out.println(brand + " 자동차가 멈춥니다.");
    }

    void accelerate(int amount) {
        speed += amount;
        System.out.println(brand + " 자동차의 현재 속도: " + speed + "km/h");
    }
}

패키지란?

  • 패키지(package)는 관련 있는 클래스들을 논리적으로 그룹화하는 방법이다.
  • 패키지를 사용하면 코드 관리가 편리하고, 클래스 이름 충돌을 방지할 수 있다.
  • 패키지는 폴더(디렉토리) 형태로 구성되며, 실제 파일 시스템에서도 동일하게 나타난다.
  • 프로젝트내 package (경로); 로 설정 되어 있는것이 현재 내가 보고있는 패키지이다. ( 코드 맨위에 있음 )

객체 지향 프로그래밍의 4대원칙

1. 캡슐화 

  • 객체의 속성과 메서드를 하나로 묶고, 외부에서 직접 접근하지 못하도록 데이터 보호하는 것
  • private 키워드를 사용해 필드를 보호함.

2. 상속 

  • 기존 클래스의 기능을 그대로 가져와 확장하는 것 ( 코드 재사용 )
  • 부모 클래스(상위 클래스)의 기능을 자식 클래스(하위 클래스)가 물려받아 사용 가능

 

※ 자식 생성자를 생성하려면, 부모의 생성자가 무조건 있어야 한다. super();

→ 단, 부모의 기본 생성자가 자동으로 생성되기 때문에, 자식 생성자는 super() 키워드 없이 생성 가능함.

 

3. 다형성

  • 같은 메서드를 여러 클래스에서 다르게 동작하게 만드는 기능

※ 메소드 오버라이딩 ( 재정의 ) 

부모가 가지고있는 메소드를 자식클래스에서 똑같은 메소드명으로 선언하고, 구현체를 다시 해당 자식 클래스에 맞게 구현하는 것으 말한다.

 

4. 추상화

  • 필요한 정보만 제공하고, 불필요한 세부 사항은 숨기는 것
  • 핵심 기능만 보여주고, 내부 구현을 감출 수 있음.
  • abstract 키워드를 사용하여 추상 클래스를 만듬. 추상 클래스는 구현체가 없다. ( 추상적인 내용은 해당 클래스에 상속 하고, 구현을 함 )

객체지향적인 클래스 설계방법

  • 클래스는 "하나의 역할"만 하도록 설계
  • 중복 코드를 줄이고, 필요하면 상속을 활용
  • 공통된 기능은 부모 클래스로 관리
  • 필요한 정보는 private로 숨기고, public 메소드를 제공
  • 같은 동작을 다양하게 구현할 수 있도록 다형성을 활용
  • 추상화를 통해 핵심 기능만 드러내고, 불필요한 세부 사항을 감추기

객체와 인스턴스

클래스

  • 클래스는 객체를 만들기 위한 설계도 또는 틀
  • 클래스는 객체가 가져야 할 속성(변수)과 기능(메서드)을 정의한다. ( 생성자도 있음 )

객체 

  • 객체는 클래스의 설계도를 바탕으로 만들어진 구체적인 대상
  • 객체는 실제 메모리상에서 존재
  • ex) 실제로 만들어진 쿠키 : 초콜릿 쿠기, 딸기 쿠기  
Cookie chocolateCookie = new Cookie();
chocolateCookie.flavor = "초콜릿";
chocolateCookie.size = 5;
chocolateCookie.bake(); // "초콜릿맛 쿠키를 굽습니다."

인스턴스

  • 특정 클래스로부터 생성된 개별 객체를 가리킬 때 사용되는 표현
Cookie strawberryCookie = new Cookie(); // Cookie 클래스의 인스턴스
strawberryCookie.flavor = "딸기";
strawberryCookie.size = 3;
strawberryCookie.bake(); // "딸기맛 쿠키를 굽습니다."
용어 설명 예시
클래스(Class) 객체를 생성하기 위한 툴 쿠키 툴(설계도)
객체(Object) 실제 존재하는 구체적 대상 실제 쿠키
인스턴스(Instance)  클래스에서 맏늘어진 구체적 객체 초콜릿 쿠키(쿠키 틀의 인스턴스)

클래스는 객체를 생성하기 위한 툴이다. 실제로 존재하지 않고, 설계도 역할

 

객체는 클래스에 정의된 속성과 메소드를 가진 실제 구체적인 존재

 

인스턴스는 클래스로부터 객체가 생성된 순간, 그 특정 객체를 명확하게 가리키는 용어

객체를 만들 때 new 키워드를 사용하며, 이렇게 만들어진 객체를 인스턴스화

 

  • 캡슐화 : 데이터 보호
  • 상속 : 코드 재사용
  • 다형성 : 같은 메서드를 여러 형태로 사용
  • 추상화 : 중요한 기능만 노출하고, 세부 구현은 숨김

■  계산기 과제 2단계 ■

클래스를 적용해 기본적인 연산을 수행할수 있는 계산기 만들기

 

package com.example.calculator;

import java.util.Scanner;

public class App {
    public static void main(String[] args) {
        // 2단계 클래스를 적용해 기본적인 연산을 수행할 수 있는 계산기 만들기
        Scanner sc = new Scanner(System.in);
        Calculator calculator = new Calculator();

        while(true) {
            System.out.print("첫번째 정수를 입력하세요: ");
            int num1 = sc.nextInt();
            if (num1 < 0) {
                System.out.println("음수는 입력할수 없습니다.");
                continue;
            }
            
            System.out.print("두번째 정수를 입력하세요: ");
            int num2 = sc.nextInt();
            if (num2 < 0) {
                System.out.println("음수는 입력할수 없습니다.");
                continue;
            }

            System.out.print("사칙연산(+, -, x, /) 기호를 입력하세요: ");
            char op = sc.next().charAt(0); // 문자열에서 첫 번째 문자만 추출

            int result = calculator.calculate(num1, num2, op);
            System.out.println("결과 = " + result);

            sc.nextLine(); // 버퍼 지우기

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

            if (answer.equals("exit")){
                System.out.println("계산기 시스템을 종료합니다.");
                System.out.println("최종연산 결과 기록 : " + calculator.getRecord());
                break;
            }

            System.out.print("먼저 저장된 연산 결과 기록을 삭제 하겠습니까? (0 입력시 삭제): ");
            String delete = sc.nextLine();
            if (delete.equals("0")) {
                calculator.removeResult();
                System.out.println("가장 먼저 들어온 연산 결과가 삭제 되었습니다.");
            }

            // 저장된 연산 결과값 매회 조회.
            System.out.println(calculator.getRecord());
        }
    }
}

Main 클래스

package com.example.calculator;

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

public class Calculator {

    private List<Integer> record = new ArrayList<>();

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

        int result = 0;

        switch (op) {
            case '+':
                result = num1 + num2;
                break;
            case '-':
                result = num1 - num2;
                break;
            case '*':
                result = num1 * num2;
                break;
            case '/':
                if (num2 == 0) {
                    throw new ArithmeticException("나눗셈 연산에서 분모에 0이 입력될 수 없습니다.");
                } else {
                    result = num1 / num2;
                    break;
                }
            default:
                throw new RuntimeException("부호를 잘못 입력하였습니다");
        }
        record.add(result); // 연산 결과 기록 추가함.
        return result;
    }

    public void removeResult() {
        if(!record.isEmpty()) {
            record.remove(0); // 가장 먼저 저장된 값을 삭제함.
        } else {
            System.out.println("연산 결과가 기록되어 있지 않습니다.");
        }
    }

    public void setRecord(List<Integer> record) {
        this.record = record;
    }

    public List<Integer> getRecord() {
        return record;
    }
}

Calculator 클래스

 

[트러블 슈팅]

    • 배경 : 2단계는 클래스를 활용해, 코드의 재사용성을 줄이고, 효율적인 코드를 만들기 위해 코드를 분리 하여야 한다.
    • 발단 : Calculator 클래스를 만들고 사칙연산 기능을 메서드화하는 과정에서 어떤 부분을 분리할지 고민이 필요했다.
      • 연산 기능 calculate()
      • 연산 결과 저장 record 리스트
      • 결과 삭제 기능 [ 먼저들어온 데이터부터 삭제 ] removeResult()
      이처럼 여러 기능을 어떤 방식으로 나눌지 명확하지 않았다.
    • 전개 :먼저, Calculator 클래스에서 연산을 수행하는 calculate() 메서드를 만들고,결과를 저장하는 record 리스트를 추가했다. 이후, removeResult() 메서드를 구현하여 가장 오래된 결과를 삭제하는 기능을 추가했다.  1️⃣ record 리스트가 외부에서 직접 접근 가능하여 데이터를 조작할 수 있는 문제 발견
      2️⃣ removeResult()를 호출했을 때 리스트가 비어있으면 예외 처리 부족
      3️⃣ App 클래스에서 record에 직접 접근하는 코드로 인해 캡슐화 부족  ➡ 데이터 보호를 위해 캡슐화(Encapsulation) 가 필요함.
  • 위기 : 클래스를 나눴음에도 불구하고,
    • record 리스트가 setRecord()를 통해 외부에서 수정 가능한 상태
    • removeResult() 호출 시, 리스트가 비어 있으면 오류 발생 가능
    • App 클래스가 여전히 record를 직접 수정하면서 클래스를 분리한 의미가 약해짐
  • 절정 : 1️⃣ record 필드를 private으로 설정하여 직접 접근 차단
    2️⃣ setRecord() 제거 → 외부에서 수정 불가능하도록 변경
    3️⃣ getRecord()에서 새로운 리스트를 반환하여 원본 리스트 보호
    4️⃣ removeResult() 실행 시, 리스트가 비어 있으면 경고 메시지 출력
  • 결말 :이제 Calculator 클래스는
    • 연산 수행 calculate()
    • 결과 저장 record 리스트
    • 결과 삭제 removeResult()
      을 책임지는 역할을 갖게 되었고,
    record 리스트가 private으로 보호되어 안전하게 데이터를 관리할 수 있게 되었다.
    이제 App 클래스는 Calculator 객체를 이용하여 입출력만 담당하면 된다.

 

최성원 튜터님의 튜터링 -  자바는 컬렉션까지는 기본이며, 제네릭, 어노테이션은 필수다!

제네릭의 <T> 타입매개변수는 제네릭의 일부분임.

람다식, 스트림 까지 알아두면 좋고 쓰레드는 당장 필요한 영역은 아니다.

git을 CLI이나 GUI로 사용하는것은 무관하다.

 


4. 내일 학습 할 것 : 계산기 도전과제 3단계 도전, 자바 복습

반응형

'[내일배움캠프-Sparta] > Spring 6기' 카테고리의 다른 글

TIL 13 [ Java(동일성 문제, 클래스와 객체, charAt함수) ]  (0) 2025.03.06
TIL 12 [계산기 과제 3단계(enum, 제네릭, 람다, 스트림)]  (0) 2025.03.05
TIL 10 [ Java(람다식, 스트림, 쓰레드) + 계산기 과제 1단계 ]  (0) 2025.02.28
TIL 9 [ Java(예외처리, Optional, 제네릭, 컬렉션) ]  (0) 2025.02.27
TIL 8 [ Java(final, static, 인터페이스, 객체지향) ]  (0) 2025.02.26
'[내일배움캠프-Sparta]/Spring 6기' 카테고리의 다른 글
  • TIL 13 [ Java(동일성 문제, 클래스와 객체, charAt함수) ]
  • TIL 12 [계산기 과제 3단계(enum, 제네릭, 람다, 스트림)]
  • TIL 10 [ Java(람다식, 스트림, 쓰레드) + 계산기 과제 1단계 ]
  • TIL 9 [ Java(예외처리, Optional, 제네릭, 컬렉션) ]
dimenshun
dimenshun
한 소년의 개발 일기
    반응형
  • dimenshun
    Dev Life Notes
    dimenshun
  • 전체
    오늘
    어제
    • 분류 전체보기 (268)
      • CS (23)
        • 자료구조 (0)
        • 알고리즘 (0)
        • 컴퓨터 구조 (8)
        • 네트워크 (6)
        • 운영체제 (3)
        • DB ( + SQLD ) (5)
        • SW공학 (1)
      • 프로그래밍 (3)
        • Java (0)
        • Spring (0)
        • HTML,CSS (3)
        • JavaScript (0)
      • 개발 툴 (7)
        • Git(버전관리) (1)
        • Docker (3)
        • AWS (2)
        • JSP (1)
      • 코딩테스트(Algorithm) (125)
        • 백준 (6)
        • 프로그래머스 (119)
      • [내일배움캠프-Sparta] (110)
        • Spring 6기 (106)
        • KPT 회고 (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    배포
    network
    Java
    세션
    CPU
    메모리
    Python
    AWS
    It
    SQLD
    컴퓨터구조
    db
    cs
    코딩테스트
    내일배움캠프
    Til
    네트워크
    개발자
    SQL
    web
    운영체제
    spring
    docker
    KPT
    트랜잭션
    웹
    OS
    Testcode
    알고리즘
    백엔드
  • hELLO· Designed By정상우.v4.10.3
dimenshun
TIL 11 [Java(접근제어자, 클래스란?, 객체지향?) + 계산기 과제 2단계 ]
상단으로

티스토리툴바