Leaky Abstraction

Jihoon Kim
6 min readJun 18, 2024

--

팡션

“팡션 쓰지마세요.” 로 유명한 위 사진은 신기술에 적응하지 못한 사람을 놀리는 의미로 사용되곤 한다.

그런데 정말 팡션만 쓰면 모든게 해결될까? 어쩌면 김모씨는 Leaky Abstraction 측면에서 진실어린 조언을 해주고 싶었던 것일지도 모른다.

기술의 추상화

기술이 발전할 수록 기술의 세부 구현 사항은 추상화된다. 우리는 이미 추상화된 기술을 적극적으로 사용하고 있다. 비동기 프로그래밍을 하기 위해 저수준으로 Thread 를 생성 및 관리하지 않으며, 서버와 통신을 하기위해 네트워크 통신에 대한 방대한 히스토리를 알 필요가 없다. 대부분은 ‘라이브러리’를 가져다 쓰는 것으로 끝나기 때문이다.

안드로이드의 예를 들어보자. List UI 를 구현하기 위한 추상화의 변천사는 다음과 같다.

  1. 안드로이드 초기에는 ListView 를 이용하여 구현할 수 있었다. 그리고 퍼포먼스를 끌어올리기 위해 View 를 재사용하는ViewHolder 패턴이 필수적으로 필요했다.
  2. 이러한 구조가 고착화되자 아예 재사용이 가능한 구조로 추상화 된 RecyclerView 가 등장하였다. ViewHolder 패턴의 세부 구현은 내재화되었으며, 상위 수준의 API 를 통해 재사용 될 ViewHolder UI 를 정의만 해주면 된다.
  3. 그러나 RecyclerView 또한 많은 보일러 플레이트 코드가 필요하며, 특히 List 아이템의 변경상항에 대하여 적절하게 Notify 를 해주도록 관리하는 것이 쉽지 않았다. 그래서 이를 자동으로 계산해주는 ListAdapter 가 추가되었다.
  4. 현재에 이르러 ComposeLazyColumn/Row 는 UI 가 어떻게 그려지는지만 신경쓰면 된다. (퍼포먼스를 끌어올리기 위한 팁들이 존재하나 이 조차 잘 추상화 되어 있다.)

즉, 기술이 점점 더 추상화 된다는 것은 어떠한 목표를 달성하기 위해 알아야하는 내용이 점점 줄어듦을 의미한다.

// 언젠가는 이렇게 될까?
App.start()

Leaky Abstraction

시간이 지날 수록 많은 기술들이 추상화되고 새로운 프로그래밍 패러다임이 출현하며 프로그래밍이 과거에 비해 훨씬 쉬워졌다고 느낄 수도 있다. 실제로 지난 수십년동안 많은 개발자들이 만들어낸 추상화된 기술들 덕분에 이전에는 처리할 수 없었던 복잡성을 해결할 수 있게 되었기 때문이다.

그러나 악마는 디테일에 존재한다. 누구나 한번쯤은 사소해보였던 이슈를 몇 주동안 해결하기 어려웠던 경우가 있었을 것이다. 추상화된 기술이 모든 것을 해결해줄 것 같았지만, 점점 한계를 느끼게 된다. 이는 추상화된 대상이 Leaky Abstraction 의 성질을 가지고 있기 때문이다.

Leaky Abstraction 이란, 말 그대로 추상화된 기술(혹은 결과물)의 일부가 세부 구현사항을 노출하게 된다는 점이다. 좀 더 풀어서 얘기하면 추상화된 기술을 제대로 사용하기 위해서는 결국 세부 구현 사항을 이해해야 한다는 것을 의미한다.

이는 “추상화” 라는 것이 의도처럼 현실 세계의 문제, 복잡한 기술을 완전히 단순화 하는 것이 불가능하다는 것을 시사하기도 한다.

간단한 예를 들어보자. 우리는 자동차의 세부 동작을 알지 못하더라도 운전을 할 수 있다. 핸들과 기어, 엑셀 등의 인터페이스를 통해 자동차를 조작하는 방법이 적절하게 추상화 되어 있기 때문이다. 그런데 만약 자동차의 연비를 높히고 싶다면 자동차의 엔진이 연료를 어떤 원리로 태우는지에 대한 세부 구현 사항을 알아야 한다.

Leaky Abstraction 의 속성은 우리를 점점 더 멍청하게 만들 수 있다. 현재 우리가 사용하는 많은 기술들은 높은 수준으로 추상화되어 있기 때문에 이것에 대한 세부적인 원리에 대해 학습할 기회가 많지 않기 때문이다. 그리고 이것이 누적되면 “무엇을 모르는지 모르는 상태" 가 될지도 모른다.

이러한 상황을 두고 Joel Spolsky 는 원문에서 다음과 같이 표현하였다.

So the abstractions save us time working, but they don’t save us time learning.
추상화는 작업 시간은 줄여주지만, 학습 시간을 줄여주지는 않는다.

And all this means that paradoxically, even as we have higher and higher level programming tools with better and better abstractions, becoming a proficient programmer is getting harder and harder.
역설적이게도 점점 더 높은 수준의 추상성을 갖춘 높은 프로그래밍 도구가 있음에도 불구하고 능숙한 프로그래머가 되기는 점점 더 어려워지고 있다는 것을 의미한다.

So what?

우리는 높은 수준으로 추상화된 기술에 익숙하지만, 결국에는 기술의 세부 원리와 구조를 알아야 하는 순간들이 찾아온다. 시간이 흐를수록 기술은 더욱더 추상화 되기 때문에 적절하게 학습을 이어나가지 않으면, 너무나 거대해져버린 기술의 홍수속에서 익사해버릴지도 모른다.

위 주장은 Leaky Abstraction 에 대한 일반적인 결론이며, 추가적인 의견을 덧붙이고 싶다.

기본적으로 모든 기술적인 의사결정은 제품 혹은 조직의 생명주기를 기준으로 결정되어야 한다고 생각한다.

모든 제품과 서비스는 생명주기가 존재한다.

그리고 각 생명주기에 맞는 적절한 기술적인 의사결정이 필요하다.

예를들어, Introduction ~ Growth 지점에서는 제품이 아직 시장에 검증이 되지 않았거나 이제 막 성장을 하는 시기 이기 때문에 추상화된 도구의 원리를 정확히 이해하고 있느냐보다, 그 도구를 써서 빠르게 기능을 구현하고 BM 을 검증하는 것이 더 적절하다.

반면 성숙기에 접어들면 남겨진 기술 부채를 정리하고, 간과 했던 Leaky abstraction 요소를 학습하고 적용하여 서비스를 안정적으로 운영하도록 것이 중요하다.

우리는 한정된 시간과 리소스에서 많은 것을 해내야하고, 이미 높은 수준으로 추상화 된 도구들의 모든 세부 사항을 아는 것은 불가능에 가깝다.

따라서 내가 속해있는 조직이 어느 시기를 지나고 있는지, 조직이 개발자에게 원하는 기술적인 역량이 무엇인지를 스스로 인지하는 것이 무엇보다 중요하다고 생각한다.

--

--