면접에서 가장 기본적인 질문 중에 하나, "객체지향 프로그래밍이 뭔가요?". 정말 기본 중의 기본이지만, 막상 대답하고자 하니 말문이 막혔다. 꼬리에 꼬리를 무는 질문들이 쏟아져 나오는 질문이니 만큼, 제대로 알아둘 필요가 있는 주제인 것 같다. 이번 기회에 한번 확실하게 짚고 넘어가도록 하자.
객체지향 프로그래밍 (Object Oriented Programming)
객체지향 프로그래밍이란?
데이터를 추상화시켜 상태와 행위를 가진 객체를 만들고, 이를 활용하여 프로그래밍하는 것을 의미한다. 기존의 프로그램이 순차적으로 동작하는 것과는 다르게 객체들 간의 유기적인 상호작용을 통해서 프로그램이 동작하는 것이 특징이다.
대표적인 객체지향 프로그래밍 언어로는 Java가 있고 대표적인 절차적 프로그래밍 언어로는 C가 있다. 객체지향 프로그래밍 언어를 사용한다고 해서, 객체지향 프로그래밍인 것은 아니다. 실제로 나는 C언어를 먼저 배우고 C++과 Python을 접하다 보니, C언어의 향기가 물씬 풍기는 객체지향과는 거리가 먼 코드를 주로 짜곤 했다. 하지만 프로젝트를 진행하고 협업을 하면서, 객체지향 프로그래밍의 중요성을 느끼고 지금은 상황에 맞게 문제에 접근하기 위해 노력하는 중이다.
객체지향 프로그래밍의 장점과 단점
객체지향 프로그래밍의 장점
- 코드 재사용이 용이하다.
기존에 남이 만든 클래스를 가져와서 사용하기 쉽고 상속을 통해 확장해서 사용할 수 있다. 추가적으로 클래스 단위로 모듈화 시켜서 개발할 수 있어, 대형 프로젝트와 같이 여러 명이 프로젝트를 진행하는 경우 업무 분담하기 쉽다. - 유지 보수가 편리하다.
코드를 수정할 때 일일이 찾을 필요 없이, 수정해야 할 부분이 클래스 내부에 있어 해당 부분만 수정하면 된다. - 보안성 향상된다.
실제로 구현되는 부분을 외부에 드러나지 않도록 할 수 있어서 정보를 은닉할 수 있다.
객체지향 프로그래밍의 단점
- 처리 속도가 상대적으로 느리다.
객체지향 프로그래밍은 캡슐화와 격리 구조 때문에 절차적 프로그래밍에 비해 상대적으로 실행 속도가 느리다. - 객체가 많으면 용량이 커질 수 있다.
객체지향 프로그래밍은 모든 것을 객체로 생각하기 때문에 추가적인 포인터 크기의 메모리가 필요하다. - 설계 시 많은 시간과 노력이 필요하다.
객체가 처리하려는 것에 대한 정확한 이해가 필요하다. 때문에 설계 단계부터 많은 시간이 소모된다.
객체지향 프로그래밍의 핵심 키워드
클래스 + 인스턴스(객체)
클래스란 어떤 문제를 해결하기 위한 데이터를 만들기 위해 집단에 속하는 속성(Attribute)과 행위(Behavior)를 변수와 메서드로 정의한 것으로 객체를 만들기 위한 메타정보를 의미한다.
인스턴스는 클래스에서 정의한 것을 토대로 실제 메모리에 할당된 것으로 실제 프로그램에서 사용된 데이터를 의미한다.
추상화(Abstraction)
추상화란 공통의 속성이나 기능을 묶어 이름을 붙이는 것이다. 객체지향 프로그래밍에서 말하는 추상화는 객체들이 어떤 특징들이 있어야 한다고 정의하는 클래스를 설계하는 것 자체를 의미한다. 즉, 객체들의 공통된 특징을 파악해 정의하는 것을 의미한다.
캡슐화(Encapsulation)
캡슐화란 데이터의 구조와 역할, 기능을 하나로 묶는 작업을 의미한다. 비슷한 기능의 객체들을 한 곳에 모으고 분류하기 때문에 코드 수정 시 관련 부분을 찾고 수정하기 용이하다.
추가적으로 캡슐화는 정보 은닉의 특징도 갖는다. 클래스에 담는 내용 중 중요한 데이터나 기능을 외부에서 접근하지 못하도록 숨기고, 필요시 간접적으로 접근을 허용하는 것이 가능하다.
상속(Inheritance)
상속이란 기존 상위 클래스(부모 클래스)에서 기능을 가져와 재사용하면서, 필요하다면 새로운 하위 클래스(자식 클래스)에서 해당 기능만 수정해서 사용할 수 있게 하는 것을 의미한다.
일반적으로 다중 상속은 잘 사용하지 않고 하나의 상속을 사용한다. C++에서는 다중 상속을 지원하지만, 프로그래밍을 복잡하게 만들어 실용성이 떨어져 잘 사용하지 않으며 다른 언어의 경우 이러한 문제로 아예 지원을 하지 않는 경우도 있다.
다형성(Polymorphism)
다형성이란 상속과 연관 있는 개념으로, 하나의 변수명과 함수명 등이 상황에 따라 다른 의미로 해석될 수 있다는 의미이다. 즉, 오버 라이딩(Overriding)과 오버 로딩(Overloading)이 가능하다는 뜻이다.
오버 라이딩은 하위 클래스가 부모 클래스의 메서드와 같은 이름, 매개변수를 재정의해서 사용하는 것을 말한다. 오버 로딩은 하나의 클래스 안에서 같은 이름의 메서드를 사용하지만 매개변수의 타입과 개수를 다르게 하여 매개변수에 따라 다르게 호출할 수 있도록 하는 것을 말한다.
객체지향 프로그래밍의 특징을 종합하자면, 어떤 객체들을 추상화하여 공통점을 찾고, 그것을 클래스라는 캡슐에 캡슐화하여 한 곳으로 모은다. 이를 새로운 클래스가 상속받아 재사용이 가능하며, 상속받은 클래스는 다형성을 통해 기능을 수정 또는 추가할 수 있다.
객체지향의 설계 원칙 (SOLID)
- SRP(Single Responsibility Principle), 단일 책임 원칙 :
하나의 클래스는 하나의 책임을 갖는다. 적절한 추상화를 통해서 잘 모아서 하나의 클래스가 두 가지 이상의 책임을 갖지 않도록 함을 의미한다. - OCP(Open-Closed Principle), 개방-폐쇄 원칙 :
확장에는 열려있고, 변화에는 닫혀있다. 새로운 변경사항이 있을 때 유연하게 코드를 추가 또는 수정할 수 있으며, 동시에 객체를 직접 수정하지 않고도 적용할 수 있어야 함을 의미한다. - LSP(Liskov Substitution Principle), 리스코프 치환 원칙 :
상위 타입의 객체를 하위 타입의 객체로 치환해도 상위 타입을 사용하는 프로그램은 정상적으로 동작해야 한다. 즉, 자식 클래스는 항상 부모 클래스를 대체할 수 있어야 함을 의미한다. - ISP(Interface Segregation Principle), 인터페이스 분리 원칙 :
인터페이스는 그 인터페이스를 사용하는 클라이언트를 기준으로 분리해야 한다. 범용 인터페이스 하나보다는 특정 클라이언트를 위한 여러 개의 인터페이스로 분리되는 것이 좋다는 것을 의미한다. - DIP(Dependency Inversion Principle), 의존 역전 원칙 :
고수준 모듈은 저수준 모듈의 구현에 의존해서는 안된다. 즉, 클래스가 아니라 인터페이스에 의존하라는 것을 의미한다.
의견과 질문은 언제나 감사합니다.
'Study > CS' 카테고리의 다른 글
[자료구조] 대표적인 자료구조 정리 (1) | 2022.02.09 |
---|---|
[자료구조] 자료구조? 왜 그렇게 중요할까 (1) | 2022.02.08 |
Software 1.0 vs Software 2.0 (0) | 2021.11.09 |