티스토리 뷰

728x90
반응형

목차

     

    객체 지향 프로그래밍과 함수형 프로그래밍은 둘 다 프로그래밍 패러다임의 한 종류이며,

     

    여기서 패러다임이란 단순히 말하자면 프로그래밍을 무엇으로 정의할 것인가에 대한 관점이라고 정리할 수 있다.

     

    이런 맥락에서, 본격적으로 두 패러다임에 관해 정리하기 전에 근본적인 차이를 말하자면

     

    객체 지향 프로그래밍"프로그래밍은 상호작용하는 객체의 집합이다."라는 관점을 가진 패러다임이며

     

    함수형 프로그래밍"프로그래밍은 연속된 함수의 집합이다."라는 관점을 가진 패러다임이라 정리할 수 있다.

     

    추가로 객체 지향 프로그래밍은 일반적으로 명령형 프로그래밍으로,

     

    함수형 프로그래밍은 일반적으로 선언형 프로그래밍으로 작성한다는 차이도 있다.

     

    여기서 명령형/선언형 프로그래밍 역시 프로그래밍 패러다임의 한 종류이며, 대략 아래와 같은 차이가 있다.

     

    • 명령형 프로그래밍(Imperative Programming)
      컴퓨터가 수행할 명령어를 개발자가 직접 정의하고 실행하는 프로그래밍.
      개발자는 실행될 로직을 명확히 작성 및 지시해야 하며, 변수를 저장하거나 조건문, 반복문을 이용해 흐름을 제어한다.
      대표적인 언어로 Java, C, Python 등이 존재한다.
    • 선언형 프로그래밍(Declarative Programming)
      선언형 프로그래밍에서 개발자는 메서드가 어떤 방식으로 동작하는지는 관심이 없다.
      다만 주어진 문제를 해결하기 위해 필요한 조건과 규칙을 선언하고, 필요한 메서드(연산자)를 호출해 사용한다.
      이때 메서드 내부의 로직은 감춰지고 기능만 드러나며, 이와 같은 메서드의 조합과 체이닝을 사용해
      원하는 결과를 도출하게 된다.

     

    중요한 말은 이미 다 끝낸 것 같지만, 이대로 끝내긴 뭐 하니 오랜만에 두 패러다임에 대해 정리해 보자.

     

    Object-Oriented Programming(OOP)

     

    OOP는 위에 적었듯, 프로그래밍을 서로 상호작용하는 객체의 집합으로 인식하는 패러다임이다.

     

    따라서 프로그래밍을 수많은 기본 객체(Object)로 나누고 이들의 상호작용을 구현한다.

     

    OOP 이전의 패러다임이었던 절차적(명령형) 프로그래밍을 개선하기 위해 나온 방법이기도 하며,

     

    이렇게 보자면 OOP는 명령형 패러다임의 일종이라고 볼 수도 있다.

     

    역사적인 맥락은 이 정도로 건너뛰고, OOP의 특징을 나열해 보자.

     

    Encapsulation

     

    캡슐화관련이 있는 필드와 메서드를 하나의 클래스로 묶어 데이터를 외부로부터 보호하는 일이다.

     

    구체적으로 나누자면 첫째로는 데이터 보호, 두 번째로는 내부 데이터의 불필요한 노출 방지에 그 목적이 있다.

     

    즉, 캡슐화의 가장 큰 장점은 데이터 은닉(data hiding)에 있다고 볼 수 있다.

    외부로부터 객체의 필드와 메서드가 함부로 변경되는 것을 막고,

    데이터가 변경되더라도 다른 객체에 영향을 주지 않도록 할 수 있다.

    이는 코드 확장 시에 오류를 최소화하는데 도움이 되며, 당연히 유지보수에도 장점이 된다.

     

    Inheritance

     

    상속이란 한 마디로 말하면  기존의 클래스를 재사용하여 새로운 클래스를 작성하는 일이다.

     

    구체적으로는 자식 클래스(상속 주체)가 부모 클래스(상속 대상)의 특성과 기능을 그대로 물려받는 것을 가리키며,

     

    이 과정에서 필요에 따라 부모 클래스의 메서드를 재정의해 사용하기도 하는데, 이를 오버라이딩(Overriding)이라 부른다.

     

    이는 위에서 언급한 캡슐화를 유지하면서도 코드 재사용성을 보장해 주며,

     

    자바의 경우 상속은 하나의 대상에 대해서만 가능하다는 특징이 있다.

     

    Polymorphism

     

    다형성은 하나의 객체가 여러 가지 타입을 가질 수 있는 것을 가리킨다.

     

    실용적으로 말하자면 자녀 클래스의 객체를 부모 타입으로 만들 수 있다는 뜻이기도 하다.

     

    물론 이 경우 참조변수가 사용할 수 있는 멤버의 개수는 부모 클래스의 멤버의 수가 되며,

     

    이 멤버 개수의 차이 때문에 부모 클래스의 객체를 자녀 타입으로 만드는 것은 가능하지 않다.

     

    추가로 오버로딩과 오버라이딩 역시 다형성의 일종이라 할 수 있다.

     

    Abstraction

     

    추상화는 객체의 공통적인 속성과 기능을 추출하여 정의하는 것을 말한다.

    이전에 살펴본 상속이 상위 클래스를 이용해 하위 클래스를 정의하는 것이라고 한다면,

    추상화는 반대로 기존 클래스들의 공통점을 뽑아서 상위 클래스를 만들어내는 것이라고 할 수 있다.

     

    관점에 따라 위에서 언급한 상속의 반대 과정이라고 볼 수도 있으며,

     

    추상화를 통해 코드 중복을 줄이며 새로운 클래스를 작성하는데 유리하며,

     

    개발자 입장에서 구체적인 로직을 모르고도 개발할 수 있어 편의성이 증대되고

     

    설계 상황이 변하거나 확장이 필요한 경우에도 유연하게 대응할 수 있게 된다.

     

    추가로 자바의 추상화는 추상 클래스인터페이스를 이용해 구현되며,

     

    추상 메서드가 하나만 있어도 되고 모든 메서드를 구현할 필요가 없는 추상 클래스와 비교해

     

    모든 메서드가 추상메서드이며 구현(상속이 아니다) 시 모든 메서드를 구현해야 하는 인터페이스가

     

    추상화 정도가 높다고 볼 수 있다.

     

    Pros and Cons

     

    위와 같은 특징을 바탕으로 주로 함수형 프로그래밍과 비교했을 때 객체지향 프로그래밍의 장점은 아래와 같다.

     

    • 코드의 재사용성이 높다. 생성한 클래스를 이용해 객체를 만드는 방식으로 여러 곳에서 활용 가능하다.
    • 가독성과 유지보수 및 디버그가 쉽다. 역할에 따라 구분된 객체와 비즈니스 로직은 상대적으로 명확한 구조를 갖는다.
    • 객체 간의 결합도를 낮춤으로써 서로에게 미치는 영향을 최소화해 코드 수정 및 확장이 편리하다.

    반면 단점은 아래와 같은 것들이 있다.

     

    • 실행 속도가 느리다. 필요할 때마다 객체를 생성하고 메서드를 호출해 오버헤드가 발생할 가능성이 있다.
    • 앱이 고도화될수록 객체 간 상호작용이 복잡해짐에 따라 코드가 복잡하게 꼬일 수 있다.
    • 함수형 프로그래밍에 비해 상대적으로 유닛 테스트가 어렵다.

     

    Functional Programming

     

    함수형 프로그래밍은 처음에 적었듯, "프로그래밍이란 연속된 함수의 집합이다."라는 인식을 가진 패러다임이다.

     

    여기서 함수란 상태 변경 혹은 예상치 못했던 부작용이 발생하지 않으며,

     

    단순히 입력값을 받아 출력값을 반환하는 순수 함수를 가리킨다.

     

    여기서 중요한 것은 같은 순수 함수이기 때문에 같은 입력값에 대해 언제나 같은 출력을 반환하며,

     

    이와 같은 함수를 메서드, 혹은 연산자라는 이름으로 부르며 조합해서 커다란 하나의 함수를 만드는 식으로

     

    개발이 진행된다. 이는 프로그램의 동작이 예측 가능하다는 특징을 보장하며, 이외에도 아래와 같은 특징을 가진다.

     

    • 불변성
      함수형 프로그래밍은 변수를 불변값으로 취급한다.
      즉, 한 번 초기화된 변수는 값이 변하지 않으며, 이는 프로그래밍의 안정성과 예측 가능성을 보장한다.
    • 순수 함수
      위에 적었듯, 순수 함수는 같은 입력값에 대해 언제나 같은 결과를 반환한다.
      이는 예측 불가능한 부작용을 미연에 방지하며, 병렬처리와 모듈화에 도움이 된다.
    • 고차 함수
      함수 자체를 인자로 받아 함수를 반환하는 고차함수를 사용한다.
      또한 람다 함수를 이용해 함수 자체를 인라인으로 정의할 수 있으며 함수의 조합을 가능하게 한다.
      위와 같은 특징은 코드의 간결성과 재사용성, 추상화 정도를 높여준다.
    • 재귀 함수
      함수형 프로그래밍은 반복문보다는 재귀함수를 많이 사용한다.
    • 데이터 처리
      데이터 스트림의 가공에 최적화된 연산자가 존재한다(filter, reduce, map, flatmap...).
      이는 하나의 함수 체이닝에서 원하는 값을 바로 얻어낼 수 있게 도와주며, 가독성과 유지보수성을 높인다.
    • 지연 처리
      함수형 프로그래밍에서는 필요한 순간(예를 들면, 구독)까지 계산이 실행되지 않는다.
      이 때문에 불필요한 연산이 최소화되며, 대용량 처리와 같은 부분에서 리소스 낭비를 막아 도움이 된다.

     

    Pros and Cons

     

    위와 같은 특징을 바탕으로 주로 객체 지향 프로그래밍과의 비교우위는 아래와 같다.

     

    • 복잡한 문제를 상대적으로 간결하게 표현할 수 있다.
    • 선언된 변수의 상태 변경이 없으므로 상대적으로 쉽게 Thread-Safe 한 개발을 진행할 수 있다.
    • 각 함수는 독립적이기 때문에 모듈화와 재사용, 테스트가 쉽다.
    • 또한 각 함수는 순서와 의존관계가 없기 때문에 병렬 처리가 간단하다.

    계속해서 단점은 아래와 같다.

     

    • 러닝 커브가 높다. 처음 진입해서 익숙해지기까지 시간이 걸린다.
    • 상태 변경이 필수적인 프로그램에서는 사용할 수 없다.
    • 문제가 간단한 경우 상대적으로 코드가 길어질 수 있다.
    • 프로그램의 흐름이 한눈에 들어오지 않아 가독성이 떨어지며, 디버그가 어렵다.
    반응형
    댓글
    공지사항
    최근에 올라온 글
    최근에 달린 댓글
    Total
    Today
    Yesterday
    링크
    «   2024/11   »
    1 2
    3 4 5 6 7 8 9
    10 11 12 13 14 15 16
    17 18 19 20 21 22 23
    24 25 26 27 28 29 30
    글 보관함