✏️ 객체지향 프로그래밍(Object-Oriented Programming)이란?

박상민·2023년 8월 2일
1

개념 정리!

목록 보기
1/19
post-thumbnail
post-custom-banner

객체지향 프로그래밍의 개념을 공부하기 전에 그 등장배경을 알게된다면 객체지향 프로그래밍을 이해하는데 도움이 될 것 같다. 따라서 객체지향 프로그래밍이 등장하기 이전 프로그래밍 패러다임 몇 가지를 이야기 해보겠다.

⭐️ 이전 프로그래밍 패러다임

📌 순차적(비구조적) 프로그래밍

정의한 기능의 흐름에 따라 순서대로 동작을 추가하며 프로그램을 완성하는 방식을 순차적 프로그래밍이라고 한다. 흐름에 따라 코드를 작성하기 때문에 간단한 프로그램의 경우에는 흐름이 눈에 보여 매우 직관적이다. 그러나, 규모가 커지고 로직이 많아지는 경우에는 흐름대로 작성하는 것이 단점이 될 수 있다. 따라서 규모가 큰 프로잭트의 경우 순차적 프로그래밍 방식은 좋지 않다.
이러한 문제 때문에 절차적(구조적) 프로그래밍이 등장했다.

📌 절차적(구조적) 프로그래밍

절차적 프로그래밍에서 '절차'는 함수를 의미한다. 따라서 절차적 프로그래밍은 반복되는 동작을 함수 및 프로시저 형태로 모듈화하여 사용하는 방식이다.

✔︎ 프로시저와 함수

프로시저

  • DB에 대한 일련의 작업을 정리한 절차를 관계형 데이터베이스 관리 시스템에 저장한 것이다.
  • 넓은 의미로 어떠한 업무를 수행하기 위한 '절차'를 뜻한다.
  • 테이블에서 데이터를 추출해 조작하고 그 결과를 다른 테이블에 다시 저장하거나 갱신하는 일련의 처리를 할 때 주로 프로시저를 사용한다.
  • 쿼리문을 하나의 메서드 형식으로 만들고 어떤 동작을 일괄적으로 처리하는 용도로 쓰인다.
  • 하나의 요청으로 여러 SQL문을 실행시킬 수 있기때문에 네트워크 부하를 줄일 수 있다.
  • 함수와 비슷하지만 차이점이 존재한다.
    • 함수는 여러 작업을 위한 기능이라면, 프로시저는 작업을 정리한 절차이다.

함수

  • 하나의 특별한 목적의 작업을 수행하기 위해 독립적으로 설계된 코드의 집합이다.
  • 즉, 함수가 여러 작업을 위한 기능이라면 프로시저는 작업을 정리한 절차다.
  • 보통 로직을 도와주는 역할이며, 간단한 계산, 수치 등을 나타낼 때 사용한다.

프로시저와 함수의 차이점

프로시저함수
특정한 작업을 수행한다.특정한 계산을 수행한다.
리턴값을 가질 수도 있고 안가질 수도 있다.리턴 값을 가진다.
리턴 값을 여러개 가질 수 있다.하나의 리턴 값을 가진다.
서버(DataBase)에서 기술화면(Client)에서 기술
수식 내에서 사용이 불가능하다.수식 내에서만 사용이 가능하다.
단독으로 문장 구성이 가능하다.단독으로 문장 구성이 불가능하다.

함수는 프로시저를 포함하고 있는 개념이다.
이러한 프로시저를 포함한 함수들이 여러개 모여 하나의 프로그램을 구성하는 것이 절차적(구조적) 프로그래밍이다.


⭐️ 객체지향 프로그래밍?

객체지향 프로그래밍(Object-Oriented Programming, OOP)는 프로그래밍에 필요한 데이터를 추상화 시켜서 상태와 행위를 가진 객체로 만들고, 객체들간의 상호작용을 통해 로직을 구성하는 프로그래밍 방법이다.
어떤 개념에 대한 자료형과 함수를 '객체' 형태로 함께 묶어서 관리하기 위해 객체지향 프로그래밍 패러다임이 등장하게 되었다. 핵심 포인트는 객체 내부에 자료형 필드와 함수가 함께 존재하는 것이다. 가능한 모든 물리적, 논리적 요소를 객체로 만드는 것이 객체지향 프로그래밍이다.
결론적으로 객체 간의 독립성이 뚜렷하게 생기고, 중복되는 코드의 양이 줄어든다. 따라서 유지보수에 용이해질 것이다.

객체지향 프로그래밍의 중심이 클래스나 상속이라고 생각하는 경우가 꽤 있다. 그러나 이것은 오해이다. 객체지향 패러다임의 핵심은 자율적인 객체들의 협력과 다형성이다.
더 자세한 정보가 궁금하다면 "객체지향의 사실과 오해(조영호 지음)"를 읽어보자

📌 객체란?

객체는 프로그램에서 사용되는 데이터 또는 식별자에 의해 참조되는 공간을 의미하며 값을 저장하는 변수와 작업을 수행하는 메소드를 서로 연관된 것들끼리 묶어서 만든 것이다. 객체지향 프로그래밍을 레고라고 한다면 객체는 레고 조각이 될 것이고, 레고 조각을 조립해서 집을 만들거나 무언가를 만드는 것이 객체지향 프로그래밍이다.

객체는 또한 레고 조각처럼 재사용 할 수 있는데 이는 부품화재사용성이라는 객체지향 프로그래밍의 특징을 보여주기도 한다.

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

객체지향 프로그래밍은 추상화, 캡슐화, 상속, 다형성 4가지의 특성을 가진다.

✔︎ 추상화 (Abstraction)

  • 객체에서 공통된 속성과 행위를 추출하는 것
  • 공통의 속성과 행위를 찾아서 타입을 정의하는 과정
  • 추상화는 불필요한 정보는 숨기고 중요한 정보만을 표현함으로써 프로그램을 간단하게 만든다.

추상적인 개념에 의존하여 설계해야 유연함을 가질 수 있다. 즉, 세부적인 사물들의 공통적인 특징을 파악한 후, 하나의 묶음으로 만들어내는 것이 추상화다.
위 그림을 예시로 보자면 자동차 브랜드인 'Audi', 'Nissan', 'Volvo' 등은 모두 다른 자동차 브랜드이다. 그러나, 모두 '자동차'라는 상위 개념에 포함된다. 이것이 추상화이다.

추상화가 왜 필요할까?
'현대'와 같은 다른 자동차 브랜드가 추가될 수도 있다. 이때 추상화로 '자동차'를 구현 해놓으면 다른 곳의 코드를 수정할 필요 없이 추가로 만들 부분만 새로 생성해주면 된다.

✔︎ 캡슐화 (Encapsulation)

  • 정보 은닉화를 통해 높은 응집도, 낮은 결합도를 유지할 수 있도록 설계하는 것
  • 데이터 구조와 데이터를 다루는 방법들을 결합 시켜 묶는 것 (변수와 함수를 하나로 묶는 것을 뜻함)


캡슐화를 통해서 한 곳에서 변화가 일어나도 다른 곳에 미치는 사이드 이펙트를 최소화 시키는 것이다. 즉, 객체 내부의 어떤 동작에 대한 구현이 어떻게 되어있는지 마치 캡슐 내부에 숨겨져 있는 것처럼 감추는 것이다. 이를 통해서 외부에서 실수를 해도 객체가 손상되는 일을 방지한다.

결합도?
어떤 기능을 실행할 때 다른 클래스나 모듈에 얼마나 의존적인지를 나타내는 지표이다. 객체 간의 독립성을 강조하기 위해 객체지향 프로그래밍이 등장했다. 그런데 결합도가 높다면 객체지향으로 설계하는 의미가 있을까?
따라서 독립적으로 만들어진 객체들 간의 의존도가 최대한 낮게 만드는 것이 중요하다. 때문에, 객체 내의 모듈 간의 요소가 밀접한 관련이 있는 것으로 구성하여 응집도를 높이고, 결합도를 줄여야 요구사항 변경에 대처하는 좋은 설계이다.

한 줄 요약
객체 각각은 독립적으로 작용할 수 있도록 응집도가 강해야 하고, 다른 모듈을 참조하는 결합도는 낮아야 한다.

은닉화
높은 응집도와 낮은 결합도는 '은닉화'를 통해 이루어낼 수 있다. 외부에서 접근할 필요 없는 것들은 접근 지정자를 private으로 두어 접근에 제한을 두는 것이다. 외부 객체는 객체 내부의 구조를 모르게 하고, 해당 객체가 노출해서 제공하는 필드와 메소드만 이용할 수 있도록 하여 의도하지 않은 동작 오류를 방지하고 유지보수 효율을 높일 수 있다.

✔︎ 상속

  • 클래스의 속성과 행위를 하위 클래스에 물려주거나 하위 클래스가 상위 클래스의 속성과 행위를 물려받는 것을 말한다.
  • 새로운 클래스가 기존의 클래스의 데이터와 연산을 이용할 수 있게 하는 기능

상속이란 여러 개체들이 지닌 공통된 특성을 부각시켜 하나의 개념이나 법칙으로 성립하는 과정이다. 흔히 일반화라고 한다.
상속은 자식 클래스가 부모 클래스의 필드, 메소드를 물려받아 사용하고 응용할 수 있게 해준다. 엄밀히 따지면 상속은 자식 클래스를 외부로부터 은닉하는 캡슐화의 일종이다.

상속의 장단점

장점단점
재사용으로 인한 코드가 줄어든다.부모 클래스의 변경이 어려워진다.
범용적인 사용이 가능하다.불필요한 클래스가 증가할 수 있다.
자료와 메서드의 자유로운 사용 및 추가가 가능하다.상속이 잘못 사용될 수 있다.

✔︎ 다형성 (Polymorphism)

  • 하나의 변수명, 함수명이 상황에 따라 다른 의미로 해석 될 수 있는 것
  • 어떠한 요소에 여러 개념을 넣어 놓는 것
  • 클라이언트를 변경하지 않고, 서버의 구현 기능을 유연하게 변경할 수 있다.
  • 객체지향 패러다임의 핵심

다형성이란 서로 다른 클래스의 객체가 같은 동작 수행 명령을 받았을 때, 각자의 특성에 맞는 방식으로 동작하는 것이다.
객체지향 프로그래밍은 하나의 클래스 내부에 같은 이름의 행위를 여러개 정의하거나 부모 클래스의 행위를 자식 클래스에서 재정의하여 사용할 수 있기 때문에 다형성이라는 특징을 가진다.

다형성은 상속과의 시너지가 좋다. 다형성 구현을 통해 코드를 간결하게 하고, 유연함을 갖게 한다. 또한, 구체적으로 현재 어떤 클래스 객체가 참조되는지에 대한 것과는 무관하게 헐렁하게 프로그래밍하는 것이 가능하다.

예를 들어 "사람이 자동차를 운전한다." 를 생각해보자.
이때 자동차는 K3, 아반떼, 테슬라 모델3 등 여러가지가 될 수 있다.
모두 같은 자동차이지만 다른 디자인과 기능을 가지고 있다.

즉, 부모 클래스의 메소드를 자식 클래스가 오버라이딩해서 자신의 역할에 맞게 활용하는 것이 다형성이다. 이처럼 다형성을 사용하면, 구체적으로 현재 어떤 클래스 객체가 참조되는 지는 무관하게 프로그래밍하는 것이 가능하다.
상속 관계에 있으면, 새로운 자식 클래스가 추가되어도 부모 클래스의 함수를 참조해오면 되기 때문에 다른 클래스는 영향을 받지 않게 된다.

[오버로딩과 오버라이딩]

오버로딩(Overloading)

  • 메서드의 이름은 같고 매개변수의 갯수나 타입이 다른 함수를 정의하는 것
  • 리턴값만을 다르게 갖는 오버로딩은 불가하다.
  • 즉, 같은 이름의 메서드가 인자의 개수나 자료형에 따라 다른 기능을 하는 것

오버라이딩(overriding)

  • 상위 클래스의 메서드를 하위 클래스가 재정의 하는 것
  • 메서드 이름, 파라미터 갯수나 타입이 동일해야 하며, 주로 상위 클래스의 동작을 상속받는 하위 클래스에서 변경하기 위해 사용된다.
  • 즉, 상위 클래스가 가지고 있는 메소드를 하위 클래스가 재정의해서 사용하는 것

📌 객체지향 프로그래밍의 장단점

장점

  • 클래스 단위로 모듈화시켜서 개발하기 때문에 업무 분담이 편리하고 대규모 소프트웨어 개발에 적합하다.
  • 클래스 단위로 수정이 가능하기 때문에 유지 보수가 편리하다.
  • 클래스를 재사용하거나 상속을 통해 확장함으로써 코드 재사용이 용이하다.

단점

  • 처리속도가 상대적으로 느리다.
  • 객체의 수가 많아짐에 따라 용량이 커질 수 있다.
  • 설계시 많은 시간과 노력이 필요하게 될 수 있다.

객체지향에서는 다형성이 가장 중요하다! 자바의 스프링은 다형성을 극대화해서 이용할 수 있게 도와준다. 스프링에서 이야기하는 제어의 역전(IoC), 의존관계 주입(DI)은 다형성을 활용해서 역할과 구현을 편리하게 다룰 수 있도록 지원한다.


출처
[도서] 객체지향의 사실과 오해 - 조영호 지음
객체지향 프로그래밍
객체지향 프로그래밍이란?
객체지향 프로그래밍 제대로 이해하기

profile
스프링 백엔드를 공부중인 대학생입니다!
post-custom-banner

1개의 댓글

comment-user-thumbnail
2023년 8월 2일

유익한 글이었습니다.

답글 달기