객체지향

  • 면접에서도 기본 질문으로 자주 나오는 객체지향에 관련해서 정리해 보자.

객체지향 프로그래밍이란?

  • 컴퓨터 프로그래밍 패러다임 중 하나
  • 여러 블로그에서 정리하는 OOP에 대한 정의를 정리했다.
    • 상태와 행위를 가진 객체로 만들고, 객체들간의 상호작용을 통해 로직을 구성하는 프로그래밍 방법
    • 프로그래밍에서 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체를 만들고, 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법
    • 컴퓨터 프로그램을 어떤 데이터를 입력받아 순서대로 처리하고 결과를 도출하는 명령어들의 목록으로 보는 시각에서 벗어나 여러 독립적인 부품들의 조합, 즉 객체들의 유기적인 협력과 결합으로 파악하고자 하는 컴퓨터 프로그래밍의 패러다임

OOP의 장단점

장점

  • 코드 재사용 용이
    • 마치 부품처럼 코드를 재사용이 가능해진다.
  • 유지보수 용이
    • 각 코드들이 독립적인 역할을 가져서 수정이 용이하다.
  • 대형프로젝트에 적합
    • 위와 같은 장점 덕분
  • 인간친화적이고 직관적인 코드를 작성한다.
    • 실제 세계를 반영하기 위해 발전한 프로그래밍 패러다임

단점

  • 상대적으로 느린 처리 속도
  • 객체에 따른 용량 증가
  • 효율적인 설계에 시간과 노력이 필요

OOP의 4가지 특징

추상화 Abstraction

  • 클래스를 설계하는 것 자체
    • 공통의 속성이나 기능(행위)을 묶어 이름을 붙이는 과정
  • 불필요한 정보는 숨기고 중요한 정보만 표현하여 프로그램을 간단하게 한다.
    • 아우디, 니싼, 볼보는 모두 ‘자동차’에 해당된다. 자동차라는 추상화 집합을 만들어두고 자동차들이 가진 공통적인 특징들을 만들어서 활용

상속 Inheritance

  • 기존 클래스를 재활용 하여 새로운 클래스를 작성
    • 클래스의 속성과 행위를 하위(자식) 클래스에게 물려준다.
    • 일부 기능을 수정(정의)도 가능
  • 장점
    • 클래스의 속성과 기능을 반복하여 정의하지 않고 재사용이 가능
    • 반복적인 코드를 최소화
    • 공유하는 속성과 기능에 간편하게 접근
  • 단점
    • 상위 클래스 변경이 어려워짐
    • 불필요한 클래스가 증가
    • 잘못된 설계로 잘못된 상속 가능성

다형성 polymorphism

  • 정의
    • 하나의 변수명, 함수명이 상황에 따라 다른 의미로 해석
    • 어떤 객체의 속성이나 기능이 상황에 따라 여러 가지 형태를 가질 수 있는 성질
  • 오버라이딩과 오버로딩으로 표현된다.
  • 오버라이딩
    • 상위 클래스의 메소드를 하위 클래스에서 재정의하여 사용
    • A.b(1)와 a.b(1)이 다르게 작동한다.
  • 오버로딩
    • 같은 메서드가 인자의 개수, 자료형에 따라 다르게 정의
    • a.b(1)과 a.b(1,2)가 다르게 작동한다.

캡슐화 Encapsulation

  • 데이터 구조와 데이터를 다루는 방법들을 결합 시켜 묶는것
    • 속성과 기능을 정의하는 변수와 메소드를 클래스라는 캡슐에 넣어서 분류
  • 클래스의 변수를 마음대로 접근하면 내부 로직 노출되어 문제가 발생할 수 있다.
  • 정보의 은닉 방법 2가지
    • 접근 제어자 활용
    • getter, setter활용
      • 매개변수의 입력에 대해 유효한지 확인도 가능하다.
      • 값을 사용시에도 추가적인 로직을 구현 가능하다.

객체 지향 설계 원칙 SOLID

  • 객체 지향 설계 원칙으로 SOLID라는 5가지 원칙이 존재 한다.

단일 책임 원칙 (SRP, Single Responsibility Principle)

  • 하나의 클래스는 단 하나의 책임만 가져야 한다.
  • 단일 책임 원칙을 지키지 않을 경우 한 책임의 변경에 의해 다른 책임과 관련된 코드에 영향이 갈 수 있다.
  • 변경이 있을때 파급 효과가 적으면 된다

개방-폐쇄 원칙 (OCP, Open/Closed Principle)

  • 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.
    • 다형성은 구현클래스에서 추가(확장)에 열려있고, 기존코드수정(변경)에 닫힌다.
  • 기능을 변경하거나 확장할 수 있으면서 기능을 사용하는 코드는 수정하지 않는다.
  • 확장에 열려있다.
    • 요구사항이 변경시, 새로운 동작 추가
  • 변경에 닫혀있다.
    • 기존코드 수정하지 않고, 동작을 추가하거나 변경

리스코프 치환 원칙 (LSP, Liskov Substitution Principle)

  • 프로그램 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
  • 상위 타입의 객체를 하위 타입의 객체로 치환해도, 상위 타입을 사용하는 프로그램은 정상적으로 동작해야 한다.
  • 다형성을 지원하기 위한 원칙으로, 하위클래스는 인터페이스의 규약을 전부 지켜야 한다.
    • 인터페이스를 구현한 구현체를 신뢰하고 사용가능

인터페이스 분리 원칙 (ISP, Interface Segregation Principle)

  • 범용 인터페이스 하나보다 클라이언트를 위한 여러 개의 인터페이스로 구성하는 것이 좋다.
    • 기능을 적당한 크기로 쪼개서 사용하기
    • 분리를 통해 인터페이스가 명확해지고, 대체 가능성이 높아진다.
  • 인터페이스는 인터페이스를 사용하는 클라이언트를 기준으로 분리해야 한다.
  • 클라이언트가 필요로 하는 인터페이스로 분리함으로써 각 클라이언트가 사용하지 않는 인터페이스에 변경이 있어도 영향을 받지 않도록 만들어야 한다.

의존관계 역전 원칙 (DIP), Dependency Inversion Principle

  • 추상화에 의존해야지 구체화에 의존하면 안된다.
    • 구현 클래스가 아닌, 인터페이스에 의존하기
  • 고수준 모듈은 저수준 모듈의 구현에 의존해서는 안되고 저수준 모듈은 고수준 모듈에서 정의한 추상 타입에 의존해야 한다.

참고