본문 바로가기

개발/Basics

[Java/Basics] 자바 기초 스터디 2주차: 객체지향 프로그래밍(OOP) 기초

먼저 객체지향 프로그래밍에 대해 알아야 하는 이유에 대해 알아보고, 이어서 정의, 4대 핵심 원칙, 장점, Java에서 적용하는 방법까지 정리하려 한다.

1. 객체지향 프로그래밍에 대해 알아야 하는 이유

  • 현대 소프트웨어 개발의 표준.
    • 대부분의 프로그래밍 언어(자바, 파이썬, C++)는 객체지향 패러다임을 중심으로 설계됨.
    • OOP를 이해하지 못하면 언어의 핵심 기능을 제대로 활용하기 어려움.
  • 복작합 문제를 더 잘 해결
    • 현실 세계의 복잡한 문제를 객체로 추상화해 프로그래밍 가능
  • 유지보수와 확장성 증가
    • 객체 단위로 코드가 분리되기 때문에 유지보수와 확장에 유리함.
    • 팀 개발 환경에서 역할 분담과 협업이 쉬워짐.

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

2-1. 객체지향 프로그래밍

| 객체지향 프로그래밍은 객체(Object)를 중심으로 데이터를 구성하고 조작하는 프로그래밍 패러다임이다.

  • 절차형 프로그래밍과의 차이점:
    • 절차형은 함수 중심(OOP는 객체 중심)
    • 상태(데이터)와 행위(메서드)를 함께 묶어서 객체로 관리
  • OOP의 핵심 철학
    • 현실 세계의 사물을 프로그래밍적으로 추상화해 문제를 해결한다.

3. OOP의 4대 핵심 원칙(캡상추다)

3-1. 캡슐화(Encapsulation)

  • 데이터와 메서드를 하나의 객체로 묶고, 외부에서 접근할 수 없도록 제한
    • 데이터 보호
    • 객체 내부 구현을 숨기고 인터페이스만 제공 가능
public class BankAccount {
    private double balance; // 외부에서 직접 접근 불가

    public BankAccount(double balance) {
        this.balance = balance;
    }

    public double getBalance() {
        return balance;
    }

    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }
}

3-2. 상속(Inheritance)

  • 부모 클래스의 속성와 메서드를 자식 클래스가 물려받아 재사용
    • 코드 재사용성이 증가
    • 공통 속성 및 기능을 상위 클래스에 정의 가능
public class Animal {
    public void eat() {
        System.out.println("This animal eats food.");
    }
}

public class Dog extends Animal {
    public void bark() {
        System.out.println("The dog barks.");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.eat();  // 부모 클래스의 메서드 사용
        dog.bark(); // 자식 클래스의 메서드 사용
    }
}

3-3. 추상화(Abstraction)

  • 불필요한 세부 정보를 숨기고, 필요한 인터페이스만 제공.
    • 설계의 명확성 증가
    • 인터페이스 중심으로 프로그래밍 가능
public abstract class Shape {
    public abstract double calculateArea();
}

public class Circle extends Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
}

3-4. 다형성(Polymorphism)

  • 동일한 인터페이스나 메서드 호출이 실행 시점에 따라 다르게 동작
    • 유연성과 확장성 증가
    • 다양한 객체를 처리하는 일반화된 코드 작성 가능
public class Animal {
    public void makeSound() {
        System.out.println("Animal makes a sound");
    }
}

public class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Dog barks");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal = new Dog(); // 부모 타입으로 참조
        animal.makeSound();        // "Dog barks" 출력 (동적 바인딩)
    }
}
  • 인터페이스 기반 다형성 예제
public interface Animal {
    void makeSound();
}

public class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Dog barks");
    }
}

public class Cat implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Cat meows");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal1 = new Dog();
        Animal animal2 = new Cat();
        animal1.makeSound(); // "Dog barks"
        animal2.makeSound(); // "Cat meows"
    }
}

4. OOP의 장점

  • 코드 재사용성: 상속과 캡슐화를 통해 코드를 반복하지 않고 재사용 가능.
  • 유지보수성: 객체 중심으로 설계되므로, 변경이 필요한 부분만 수정하면 됨.
  • 확장성: 다형성을 통해 코드 변경 없이 새로운 객체 추가 가능.
  • 현실 세계 모델링: 현실 세계의 사물을 객체로 추상화해 직관적인 설계 가능.

5. 자바에서 OOP 적용하기

  • 자바는 클래스와 객체를 기반으로 OOP를 구현.
  • 자바의 특징:
    • 객체지향 언어로서 클래스, 인터페이스, 상속, 추상화 등을 지원.
    • 모든 것은 객체로 간주 (Object 클래스는 모든 클래스의 부모).

todo1: 1에서 절차형 프로그래밍은 코드가 복잡해질수록 유지보수 어려워지고 재사용성 낮아지는데 사례 들어서 설명
todo2: 캡슐화 데이터 보호 개념 구체적으로 설명(외부에서 직접 접근 막고, 데이터 변경하려면 검증 메서드를 통해야 한다는 점 + 게터세터 사용 시 주의사항 간략히 언급(너무 많이 쓰면 캡슐화 약해질 수 있음, 특정 조건에서만 데이터를 수정하게 만들기 가능)
todo3: 장점 예시코드 통해 현실 세계 모델링이 왜 중요한지 구체적으로 설명, 유지 보수성도 구체적으로 설명
todo4: 객체 설계 예시 추가, 스프링 프레임워크에서의 OOP 적용 설명