아직 생각을 다 정리한 건 아니라서 그냥 여기에 잡담처럼 쓰는 건데, 난 아무리 봐도 함수형/불변성이 무슨 '은탄환' 같은 건 아닌 것 같다.


물론 내가 아직 함수형을 완벽하게 이해한 게 아니라 그럴 가능성도 있고, 그래서 단정적으로 말 안하는 것이기도 하고.


가끔 인터넷 돌다 보면 객체지향까면서 함수형이 진리라고 포장하는 거 꽤 자주 보는데, 이유를 물어보면 거의 대부분 불변성/동시성에 대한 이야기를 하는데 난 그건 상당히 과장된 주장이라고 본다.


물론 그게 진짜 큰 장점이 되는 경우가 있는 걸 모르는 바는 아닌데, 전체 프로그래밍 도메인을 보면 그건 일부에 불과하잖아? 그리고 게임이나 분산처리 같은 동네 보면 언어 수준이 아니라 아키텍쳐 수준에서 특정 코드는 마치 단일 스레드 처럼 동작하도록 보장해주는 경우도 많고.


객체지향이 유행한 건 그게 서버 백엔드부터 데스크탑 프로그램까지 범용적으로 적용할 수 있는 설계 방법이란 이유도 큰데, 그런 면에서 객체지향의 '상위호환'이라고 주장하는 (적어도 일부는 말이지) 패러다임이 일부 도메인에서만 유용한 장점이 된다면 좀 생각의 여지가 있다고 본다.


난 그래서 일단 가변 상태 자체를 죄악시하는 시각에는 동의 못하겠음. 패러다임은 기본적으로 모델링을 어떻게 하는지에 대한 접근을 말하는 거고, 모델링은 실세계의 개념을 프로그래밍으로 추상화하는 과정이잖아? 근데 현실 세계에서 불변성이 보장되는 개념이 얼마나 있냐?


카드 게임을 하는데 사람이 카드 한 장 더 받았다고 죽었다가 새 카드 들고 다시 태어나는 게 진짜 "player.draw(Deck): Card"보다 더 직관적일까? 모델링의 기본은 도메인에 해당하는 현실 세계의 측면을 최대한 실제와 유사하게 표현하는 거 아님?


반면에 나는 함수형의 가장 큰 장점은 동시성 문제 해결 같은 것 보단 어떤 동작을 선언적 파이프라인으로 구성할 수 있다는 점이 아닐까 싶다. 그건 누가봐도 직관적이고, 오류 가능성도 낮고, 테스트도 쉽고, 무엇보다 범용적이잖아?


그래서 난, 마치 ORM 쓰는 비지니스 어플에서 엔티티하고 VO/DTO를 나누듯 객체지향하고 함수형을 적정한 계층을 사이에 두고 분리하는 설계가 최적이 아닐까 하는 생각이 들더라. 그러니까 카드 게임할 때 '플레이어' 같은 건 가변 상태를 갖는 '엔티티'로 인정하고, 거기서 파생되는 동작에 대해서는 함수형으로 지지고 볶고 하는 그런 접근이 최선이 아닐까?


어차피 함수라는게 동작이나 흐름을 추상화하는데 최적의 도구이지 구조나 계층을 표현하는 좋은 수단은 아니잖아? 그래서 그건 기존 처럼 객체지향에 맡겨 놓고 뭔가 객체지향의 상태를 함수형의 동작으로 조작한다는 접근이 필요한 것 같다. 그리고 불변성은 그 과정에서 파이프라인 내부에서 사용하는 데이터에 대해서만 신경 쓰면 될 문제인데, 그건 뭐 객체의 단일 속성이나 VO/DTO/Record/DataClass 등등을 쓰면 되니 불변으로 처리하는 게 어렵진 않으니까.


그렇게 보면, VO 등등은 기본적으로 가변 상태를 가지는 객체지향적 엔티티의 일부 상태값에 대한 특정 시점의 스냅샷이라고 보고, 함수형은 기본적으로 그 불변 데이터를 어떻게 가공할 것인지를 모델링하는 역할을 맡으면 되지 않나 싶다.