2022 스터디/영어 스터디[2022]

[3] Functional vs object-oriented programming

EYR 2022. 5. 8. 19:18

함수형 vs 객체 지향 프로그래밍

 

본 글은

 

Functional vs object-oriented programming

Learn the difference between functional and object-oriented programming and how to choose an approach that works for you.

circleci.com

위 사이트의 번역입니다.

문제가 생길 시 삭제합니다.

 

여는 말

  프로그래밍은 과학만큼이나 예술적이다. 개인적인 성향은 프로그래밍 스타일에 큰 영향을 미치기 때문에 모든 사람들의 의견이 항상 같을 순 없다. 여전히 논쟁되는 화두는 두 다른 프로그래밍 양식에 대한 선호이다. 함수형 프로그래밍(functional programming)과 객체 지향 프로그래밍(object-oriented programming), 둘 중 어느 것이 나은가? 

  어느쪽의 지지자든 그들이 선호하는 양식은 보편적으로 적용될 수 있는 뚜렷한 장점이 있다고 주장할 것이다. 당신은 이에 동의하지 못할 수도 있다. 이 글에선, 두 방식 모두를 살펴보고 사실로부터 근거 없는 주장을 분류해낼 것이다. 이 글의 목표는 두 프로그래밍 방식을 이해하고 올바른 방식으로 사용하는데에 있다.

 

함수형 프로그래밍 Functional programming

  함수형 프로그래밍(FP)는 오래된 프로그래밍 방식 중 하나이다. 이는 오직 함수에만 의존하는 소프트웨어를 구축하는 과정을 정의한다. 함수형 프로그래밍에서 개발자들은 새 기능을 만들기 위해 함수를 구성하고, 공유 상태나 가변 정보들과 같은 측면을 피하기 위해 애플리케이션을 작성한다. 이를 위해 개발자들은 종종  함수형 프로그래밍을 명령적이라기보단 선언적으로 사용한다. 이를 쉽게 풀어 쓰자면,

 

 

함수형 프로그래밍의 핵심 개념 Key concepts in functional programming

  우선, 함수형 프로그래밍에서 함수들은 일급 객체(first class citizen)임을 짚고 넘어가는 게 중요하다. 이는 함수들은 다른 값들처럼 대해질 수 있다는 뜻이다. 그들은 인수로 전달되거나 다른 함수에서 반환될 수 있다. 함수를 반환하는 함수는 고차원 함수(higher-order function)라고 불린다. 이러한 고차원 함수들은 메개변수에서 직접적으로 새 함수를 구성하는걸 가능하게 한다.

  두번째 중요한 포인트는 불변성의 개념이다. 불변값은 원시적인 값으로, 변하지 않는 값을 뜻한다. 숫자와 같은 값은 불변으로 간주된다. 42을 14로 바꿀 순 없다. 14라는 새 값을 생성하고 이전에 사용했던 변수에 할당할 수 밖에 없다. 하지만 14라는 새 숫자를 만드는 건 이전에 사용했던 42라는 값에 아무 영향을 주지 않는다.

  값을 다루는 이러한 방식은 숫자와 같은 원시 값들엔 말이 되지만 객체 또는 배열로 구성된 값에는 적용되지 않을 수 있다. 그럼에도 불구하고 함수형 프로그래밍은 원칙적으로 모든 값을 불변하다고 본다. 값을 바꾸는 유일한 방법은 새로운 값을 생성하는 방법 뿐이고 잠재적으로 이전 값을 기본값이나 복사하여 사용할 뿐이다.

  불변값의 사용은 함수형 프로그래밍이 순수한 함수를 사용할 수 있게 만든다. 이 함수들은 오직 그들의 메개변수로만 정의된다. 메개변수가 변하지 않는 이상, 그들은 예정된 행동을 수행한다. 같은 값은 같은 결과를 초래한다. 다른 프로그래밍 접근법은 이러한 행동을 보장하지 않는다.

 

함수형 프로그래밍의 사용 사례 Use cases for functional programming

  비록 근본적으로는 과학적 응용에 사용 되었을지라도, 함수형 프로그래밍은 여러 분야에서 급격히 유명해졌다. 예를 들자면, 웹 개발에서 유저 인터페이스(UI)라이브러리 React은 함수형 프로그래밍의 원칙을 사용해 평서적(평서문)이고 다루기 쉽게 되었다. 라이브러리를 사용하는 사람들은 응용프로그램의 현재 상태를 변경하지 않고 반영하기 위해 불변 상태 객체(값)을 사용한다. 만약 개발자가 새 상태를 원한다면 새로운 객체를 만들어야 한다. 이 접근법의 아름다움은 UI의 모든 변경점으로 되돌아갈 수 있다는 것이다. 모든 이전의 상태들이 건들 수 없고 이용할 수 있다.(untouched and available)

  함수형 프로그래밍의 뿌리는 분명히 컴퓨터 과학의 학문적인 곳에 두고 있지만, 실질적인 의미는 Lisp나 Scheme같은 언어로까지 뻗어나갈 수 있다. 이러한 특성 중 일부가 JavaScript 언어로 이식되었다는 건 함수형 프로그래밍의 지속적 사용성에 대해 알 수 있다. 그러나 몇몇 언어들은 함수형 프로그래밍 원칙의 위에 세워졌다. F#, Clojure, Elixir이 대표적이다. 학계에서는 Haskell이 수십년 동안 유행해 왔다.

 

객체 지향 프로그래밍 Object-oriented programming

  함수형 프로그래밍은 오랫동안 존재했음에도 몇몇 개발자들은 객체 지행 프로그래밍(OOP)이 더 전통적이라고 생각했다. Smaltalk나 Objective-C같은 프로그래밍 언어들은 1970년대 후반 대중화된 객체 지향 프로그래밍 언어이다. 이후 C++, Java 그리고 C#이 대부분의 개발자들의 프로그래밍 스타일을 굳어버리게 했다.

  객체 지향 프로그래밍의 중요 원칙에 대한 설명과 이들의 사용처를 아래에 묘사했으니 읽어보기 바란다..

 

객체 지향 프로그래밍의 핵심 개념 Key concepts in object-oriented programming

  객체 지향 프로그래밍에서 개발자들은 소프트웨어 어플리케이션들을 객체의 다른 객체와 상호작용 가능한 집합으로 디자인한다. 각 객체의 접속기는 클래스(class)로 함수와 값이 모든 인스턴스에 접근할 수 있음을 나타내는 템플릿이다. 이러한 상호작용 기능은 처음엔 일반적으로 네트워크 통신이나 비동기 IO를 허용하기 위해 구성되었으나 이후에는 해당 물체에 대해 호출된 단일 함수에 대해 더 많이 사용되었다. 이러한 함수들은 메소드(methods)라고 불린다.

  함수 지향 프로그래밍의 불변성 객체에 반해, 객체 지향 프로그래밍의 객체는 프로그래밍의 일부분이다. 메소드를 불러오는 건 값이나 객체를 수정하는 것과 거의 비슷하다.

  많은 개발자들이 객체 지향 프로그래밍을 이용하는 이유 중 하나는, 특히 프로그래밍을 가르칠 때 코드가 명령적으로 적혀있기 때문이다. 이는 개발자가 어디에서 어떤 일이 일어나고 있는지 분명하게 볼 수 있음을 의미한다. 변덕성에 따라 예상치 못한 결과를 초래할 수 있다.

 

객체 지향 프로그래밍의 사용 사례 Use cases for object-oriented programming

  전통적으로 개발자들은 거의 모든 UI를 객체 지향 프로그래밍 접근법으로 만들었다. 클래스 기반 구성요소는 다른 유사한 구성요소로부터 기본 구조(필드와 메소드)를 상속받을 수 있기 때문에 이는 직설적(straightforward)이기도 하다. 예를 들어, 날짜 입력 필드는 텍스트 입력 필드에서 상속될 수 있고, 입력 상자는 컨트롤에서 상속될 수 있다. 이 상속 기반 접근 방식을 사용하면 추가 방법을 지정하고 기존의 일부 방법에 대한 동작만 재구현하면 된다. 키보드나 마우스 움직임 등의 로직을 다시 구현할 필요가 없다. 

  오늘날 객체 지향 프로그래밍은 모든 범용 프로그래밍 언어의 필수 기능이다. F#같은 함수형 프로그래밍 기반 언어들 조차도 클래스나 상속같은 객체 지향 프로그래밍의 기능을 직접 지원한다. 좋은 예시는 JavaScript인데, JavaScript는 최신 개정판에 클래스와 상속같은 표준 기능을 통합해 추가했다. 

  우리가 살펴본 바와 같이, 두 가지 프로그래밍 접근 방식은 충분히 다르며 유용하다. 그렇다면 둘 중 어느걸 골라야 할까? 몇 가지 주장이 있다.

 

함수형 vs 객체 지향 프로그래밍: 토론Functional vs object-oriented programming: the debate

  이미 논의했듯이, 두 접근법 모두 장점과 단점을 가지고 있다. 컴퓨터 과학 교수 Norman Ramsey는 잘 알려진 Stack Overflow의 답변에서 유용한 관점을 제공했다. 그는 함수형 프로그래밍이 모든 객체를 알고 있을 때 탁월하지만 동작이 변할 수 있다고 주장했다. 그에 반해서 객체 지향 프로그래밍은 동작이 알려져 있을 때 탁월하지만 실제 데이터 타입은 바뀔 수도 있다고 말했다.

  두 접근법의 추종자들은 반박할 것이다. 예를 들어 함수형 프로그래밍의 추종자들은 순수한 함수형 프로그래밍 스타일로 작성된 소프트웨어는 디버깅하기 쉽고 결코 충돌하지 않을 거라 주장할 것이다. 그들은 함수형 프로그래밍이 테스트 기반 개발의 장점을 즉시 제공하고 그리고 그것이 SOLID 원칙이 엄격하게 적용되는 객체 지향 프로그래밍은 본질적으로 함수형 프로그래밍이라는 증거라고 말할 것이다. SOLID가 대부분의 함수형 프로그래밍과 유사한 개별 함수로 이어지는 건 사실이지만 이것이 반드시 함수형 프로그래밍이라는 증거는 없다. 예를 들어 SOLID 원칙은 데이터 변환을 금지하지 않는다. 

  객체 지향 프로그래밍을 좋아하는 개발자들은 함수형 프로그래밍의 성능이나 단순화와 같은 절충 방안의 일부를 무시할 수 있다. 왜 단일 객체의 필드를 수정하고 싶을때 모든 객체의 필드를 새로운 객체로 복사하는가? 왜 백만개의 원소로 이루어진 배열이 단 하나의 원소를 복사하는데에 필요한가? 물론 이러한 방식을 사용하지 않기 위해 할 수 있는 방법도 있다. 하지만 그 후에는 다시 전문화된 데이터 구조가 필요하다. 여기서 간접성의 수준은 개발자들이 객체 지향 프로그래밍과 독립적으로 오랫동안 사용해 온 직접적 접근 방식과 비교해보았을 때 당혹스럽게 느껴질 수 있다.

  이러한 접근 방식 사이에는 많은 차이가 있지만, 동시에 상호보완적이기도 하다. 소프트웨어 어플리케이션에서 클래스 사용을 금지하라는 법은 없다. 또한 어플리케이션의 일반 상태가 변경 가능해야 한다는 법도 없다.

 

미래의 경향성 Looking into the future

  인기 있는 프로그래밍 언어의 대다수는 다중 패러다임(multiparadigm)이다. 그들은 전달되는 함수나 데이터 객체 불변성 처리에 도우미를 허용함으로서 함수형 프로그래밍을 지원한다. 그들은 또한 객체 지향 프로그래밍의 적용인 클래스와 상속과 함께 오기도 한다. 어느 쪽이든, 이 다중 패러다임의 지원은 계속 될 것이다. 유저의 입장으로 보았을 때, 항상 여러 방식이 있는 쪽이 유리하다.

  대중적으로 함수형 프로그래밍에 보다 친화적인 경향이 있어 보인다. 데이터 객체, 함수 참조 및 함수 구성을 복제하기 위한 추가 지원을 제공함으로서 언어는 함수형 프로그래밍을 넘어서는 훌륭한 동반자가 된다. C#같은 언어에서 함수형 프로그래밍 친화적 특징들은 객체 지향 언어 기능에 탁월한 추가 기능을 제공한다. 이 결합은 객체 지향 프로그래밍 언어들에서도 편리하다. 특정 도우미 기능을 사용할 때처럼 말이다. 

  함수형 프로그래밍과 객체 지향 프로그래밍 접근 방식을 혼합하는 것의 단점은 학습 곡선이다. 몇몇 사람들은 이러한 이유 때문에 C#을 피한다. 아름답고 우와하게 디자인된 자바의 대안으로 시작된 건 결국 C++의 길을 따라 복잡한 괴물처럼 비추어질 수 있다. 

  객체 지향 프로그래밍이 사라지지는 않겠지만, 가장 유력한 결과는 함수형 프로그래밍과 공존하는 자리를 찾는 것이다. 결국, 부작용 없는 개발은 실행하기가 거의 불가능하다. 콘솔에 로그 메시지를 쓸 때부터 이미 부작용은 존재한다. 개발자들은 먼저 함수형 프로그래밍의 실용적인 측면을 발견해야 한다. 이제 개발자들이 함수형 프로그래밍의 실용적인 측면을 인식하기 시작했으니 이를 다시 없앨 필요는 없다.

 

객체 지향 프로그래밍에 대한 지속적인 지원 Ongoing support for object-oriented programming

  이러한 맥락에서 객체 지향 프로그래밍이 여전히 가능한 선택이여야 하는 이유는 무엇일까? 객체 지향 프로그래밍은 본질적으로 이상적인 도구이기 때문에 가치가 있다. 객체 지향 프로그래밍 관행을 통해 개발자가 구축할 수 있는 건 거의 없다. 개발자는 객체 지향 프로그래밍을 통해 대부분의 함수형 프로그래밍을 만들 수도 있다.

  예를 들어, 기능을 전달하거나 결합하는 것 처럼 기본적인 부분을 고려해 보아라. 간단히 말하자면, 이는 대표자나 대리인이 제공하는 것이다. 이는 하나의 메소드로 클래스에 해당하는 객체일 뿐이다.

 

공통점 찾기 Finding common ground

  소수의 개발자 팀 만이 그들의 소프트웨어나 어플리케이션 작성 방식을 바꿀 것이다. 팀은 프로그래밍 언어의 최신 기능을 사용하기 위해 가장 필수적인 응용 프로그램 중 일부만을 바꿀 가능성이 더 높다.

  어느 쪽이든, 미래는 더욱 혼합될 것이다. 미래의 일부 프로젝트에선 객체 지향 프로그래밍 어플리케이션보다 함수형 프로그래밍에서 영감을 받은 스타일을 사용하거나 함수형 프로그래밍 기반 어플리케이션에서 일부 객체 지향 프로그래밍 기능을 사용할 수 있을 것이다. 

 

결론 Conclusion

  특정 유형의 응용 프로그램(컴파일러 등)은 함수형 프로그래밍을 선호한다. 반면, 다른 프로그램(데스크탑의 기본 프로그램)들은 객체 지향 프로그래밍 원칙을 사용하는데에 더욱 적합하다. 올바른 프로그래밍 접근 방식을 선택하는 건 여러 요인에 따라 다르다. 사용하는 대상 프로그래밍 언어, 프레임워크, 어플리케이션의 종류 등과 같이. 가장 편하게 느껴지는 걸 사용하라. 그러나 새로운 방식을 사용하는 방법을 계속 학습하는 걸 잊지 말라. 어떤 문제를 다룰때 많은 많은 선택권을 가지는 건 항상 유용하다.