본문 바로가기
Programming Language/Java

[Java/개념] 객체 지향 프로그래밍(OOP: Object Oriented Programming)

by woongii 2024. 10. 12.

자바는 대표적인 객체 지향 프로그래밍 언어이다. 객체 지향 프로그래밍(OOP)은 복잡한 문제를 해결하기 위한 소프트웨어 설계 방법론으로, 실제 세계를 객체로 모델링하여 소프트웨어를 더 직관적이고 유지보수하기 쉽게 만든다. 즉, 프로그램을 여러 독립된 단위인 객체들의 모임으로 이해하고, 이 객체들이 상호작용하며 동작하는 구조로 설계하는 것이다.

 

1. 객체(Object)란?

객체는 물리적으로 존재하거나 추상적으로 생각할 수 있는 것 중에서, 속성(필드)과 동작(메소드)을 가진 것을 말한다. 예를 들어, 자동차라는 객체는 색상과 브랜드(속성)를 가지고 있으며, 가속하거나 정지하는 동작(메소드)을 수행할 수 있다.

객체 모델링(Object Modeling)은 현실 세계의 객체를 소프트웨어 객체로 설계하는 과정이다. 이는 현실의 속성과 동작을 추출하여 소프트웨어적으로 정의하는 것이다.

2. 객체의 상호작용

현실 세계에서 객체는 서로 상호작용하며 동작한다. 소프트웨어에서도 마찬가지로 객체들은 각각 독립적으로 존재하고, 서로 메소드를 호출하여 상호작용합니다. 객체가 다른 객체의 기능을 사용하려면 메소드를 호출하면 된다.

 

예를 들어 10과 20을 주고 더하기 기능을 이용한다고 했을 때 10과 20이 더하기 기능의 매개값이다. 리턴값은 메소드가 실행하고 나서 호출한 곳으로 돌려주는(리턴하는) 값이다. 객체의 상호작용은 객체 간의 메소드 호출 시 매개값을 전달하고, 리턴값을 통해 결과를 반환받는 방식으로 객체 간 데이터를 주고받는다.

int result = Calculator.add(10,20);
//리턴한 값을 int변수에 저장

 

3. 객체 간 관계

객체는 개별적으로 사용될 수 있지만, 대부분 다른 객체와 관계를 맺고 있다. 이 관계의 종류에는 집합 관계, 사용 관계, 상속 관계가 있다. 

  • 집합 관계: 객체가 부품(하위 객체)과 완성품(상위 객체)으로 구성되는 관계
  • 사용 관계: 객체가 다른 객체의 메소드를 호출하여 상호작용하는 관계
  • 상속 관계: 상위 객체의 필드와 메소드를 하위 객체가 물려받아 사용하는 관계

객체 지향 프로그래밍(OOP - Object Oriented Programming) 은 만들고자 하는 완성품인 객체를 모델링하고, 집합 관계에 있는 부품 객체와 사용 관계에 있는 객체를 하나씩 설계한 후 조립하는 방식으로 프로그램을 개발하는 기법이다.

 

4. 객체 지향 프로그래밍의 특징

  1. 캡슐화(Encapsulation): 객체의 속성과 메소드를 외부에 감추고, 객체가 노출한 인터페이스만을 통해 접근할 수 있도록 한다. 이를 통해 객체 내부의 데이터를 보호하고 잘못된 사용을 방지할 수 있다. 자바 언어는 캡슐화된 멤버를 노출시킬 것인지, 숨길 것인지를 결정하기 위해 접근 제한자(Accsess Modifier)를 사용한다. 
  2. 상속(Inheritance): 상위 객체의 필드와 메소드를 하위 객체가 물려받아 재사용함으로써 중복 코드를 줄이고 유지보수를 용이하게 만든다.
  3. 다형성(Polymorphism): 동일한 인터페이스나 상위 클래스를 통해 여러 형태의 객체를 사용할 수 있게 한다. 하나의 타입으로 여러 객체를 처리할 수 있어, 코드의 유연성과 확장성을 높인다.

5. 객체 지향 프로그래밍 vs 절차 지향 프로그래밍

절차 지향 프로그래밍(Procedural Programming)은 프로그램의 실행 순서와 흐름을 중시하는 방법론으로, C 언어가 대표적이다.

  • 장점: 컴퓨터의 처리 방식과 유사하여 빠른 성능을 기대할 수 있다.
  • 단점: 코드의 재사용성과 유지보수가 어렵고, 복잡한 프로그램에서는 관리가 어려워진다.

반면, 객체 지향 프로그래밍은 프로그램을 독립적인 객체 단위로 나누어 설계하고 책임을 분산시킴으로써 대형 프로젝트에 적합하고 유지보수가 용이하다. 하지만 설계에 시간이 많이 소요되고, 객체가 많아지면 성능 저하가 발생할 수 있다.

  객체 지향 프로그래밍 절차 지향 프로그래밍
처리 방식 여러개의 객체로 나누어 처리 여러개의 함수로 나누어 처리
장점 책임이 여러 객체로 적절히 분산되어 있다.
코드 재사용이 용이하다.
유지 보수가 쉽다.
대형 프로젝트에 적합하다.
책임이 한 곳에 집중되어 있다.
처리 속도가 빠르다.
실행 속도가 빠르다.
단점 처리 속도가 상대적으로 느리다.
객체가 많으면 용량이 커진다.
설계 시 많은 시간과 노력이 필요하다.
유지 보수 및 디버깅이 어렵다.
실행 순서가 정해져 있어 코드의 순서가 바뀌면 동일한 결과를 보장하기 어렵다.
프로그램 분석 및 코드 수정이 어렵다.
대규모 프로젝트에 부적합하다.
Java, Python, C# 등 C 등

 

6. 객체 지향의 5가지 설계 원칙 (SOLID)

  1. SRP(Single Responsibility Principle ): 단일 책임 원칙 - 각 클래스는 하나의 책임만 가져야 한다.
  2. OCP(Open/Closed Principle): 개방/폐쇄 원칙 - 소프트웨어는 확장에 열려 있고, 수정에 닫혀 있어야 한다. 즉, 기존 코드를 변경하지 않고 기능을 추가할 수 있어야 한다.
  3. LSP(Liskov's Substitution Principle): 리스코프 치환 원칙 - 상위 타입의 객체를 하위 타입의 객체로 치환해도 동작해 전혀 문제가 없어야 한다.
  4. ISP(Interface Segregation Principle): 인터페이스 분리 원칙 - 많은 기능을 가진 인터페이스를 작은 단위로 분리시킴으로써 클라이언트에게 필요한 인터페이스들만 구현하도록 한다. 즉, 클라이언트가 필요로 하는 최소한의 인터페이스만 제공해야 한다.
  5. DIP(Dependency Inversion Principle): 의존성 역전 원칙 - 변하기 쉬운 구체적인 것보다 변하기 어려운 추상화에 의존해야 한다. 자기보다 변하기 쉬운것에 의존하게 되면 변화에 영향을 많이 받기 때문에 추상화된 인터페이스나 상위 클래스를 둬서 변화에 영향을 받지 않게 하기 위한 원칙이다.

7. 객체 지향 설계 원칙

객체 지향 설계에서는 높은 응집도낮은 결합도를 목표로 해야 한다. 응집도가 높으면 관련된 기능을 하나의 객체에 집중시켜 변경에 유연하게 대처할 수 있다. 낮은 결합도는 객체 간 의존성을 최소화하여 유지보수가 용이하도록 설계하는 것을 말한다.

프로그램을 하다보면 수정에 대한 요구사항이 많은데 영향 어디까지 인지 모르겠다는 표현을 쓰게된다. 그런 표현자체가 객체지향적으로 설계가 되지 않았다는 것을 뜻한다. 객체지향은 변경에 대한 요구사항이 들어왔을때 특정 한 부분만 수정하면 된다는 것은 응집도가 높은 것이며, 다른 곳에 영향을 미치지 않는다면 낮은 결합도라고 한다. 즉, 유지보수와 관련이 크다. 객체지향 설계를 하는 가장 큰 이유는 변경이 생겼을 때 빠르고 유연하게 대응할 수 있어야 하는 것이다.

  • 도메인을 구성하는 객체에는 어떤 것들이 있는지 고민하기
  • 객체들 간의 관계를 고민
  • 동적인 객체를 정적인 타입으로 추상화해서 도메인 모델링 하기
  • 협력을 설계
  • 객체들을 포괄하는 타입에 적절한 책임을 할당
  • 구현하기

 

 

 

 

 

[출처: 이것이 자바다, https://velog.io/@jx7789/JAVA-%EA%B8%B0%EC%B4%88-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%9D%B4%EB%9E%80]