[번역] 잘못된 추상화

gompro·2020년 1월 4일
4
post-thumbnail

이 글은 Sandi Metz의 글 The Wrong Abstraction을 번역한 글입니다. 이 글은 메일을 통해 저자에게 허락을 구한 뒤 번역되었으며, 원문은 링크에서 찾아보실 수 있습니다.

본문

저는 잘못된 추상화에 대해 늘 고민해왔습니다. 레일즈 컨퍼런스 2014 "all the little things"에서 저는 이런 주장을 펼쳤습니다:

잘못된 추상화보다 중복이 훨씬 효율적이다.

그리고 발표의 마지막 즈음엔, 이런 식의 조언도 했습니다:

잘못된 추상화보다는 중복이 더 낫다.

전체 발표에 비하면 작은 제 주장에 많은 분들이 강한 반응을 보였습니다. 몇몇은 제가 미쳤다고했지만 많은 분들이 제 주장에 큰 공감을 표현해 주셨습니다. (해당 트윗 링크)

이를 통해 저는 잘못된 추상화 문제가 곳곳에 만연하며, 얼마나 해결하기 어려운 문제인지를 깨달았습니다. 그리고 저는 몇 가지 질문을 통해 다음과 같은 패턴이 공통적으로 발견된다는 것을 알았습니다.

  1. 개발자A가 중복을 발견한다.

  2. 개발자A는 중복된 부분을 떼어내 이름을 붙인다.

    여기서 추상화가 발생합니다. 그것은 새로운 메쏘드일수도 혹은 새로운 클래스 일 수도 있습니다.

  3. 개발자A는 이제 추상화를 통해 중복을 제거한다.

    완벽한 코드로군. 개발자A가 퇴장한다.

  4. 시간이 흐른다.

  5. 새로운 요구사항은 이전의 추상화에서 "아주 조금" 다른 역할을 요구한다.

  6. 개발자B는 새로운 요구사항을 구현해야 한다.

    개발자B는 기존의 추상화를 유지해야만 하는 의무를 느낀다. 물론 추상화는 완벽히 들어맞지 않기 때문에 코드를 수정해서 몇 가지 파라미터를 추가로 받거나 파라미터의 값에 따라 서로 다른 일을 하는 조건문을 몇 개 추가한다.

    모든 곳에 적용되던 추상화는 이제 몇 가지 상황에 따라 다르게 동작한다.

  7. 또 다른 요구사항이 등장한다.

    다른 개발자 X가 몇 가지 파라미터와 조건문을 추가한다.

    악순환의 굴레는 코드를 전혀 이해하지 못하는 지경까지 계속된다.

  8. 여러분은 아마 이쯤에서 상황이 최악으로 나아가는 장면을 목격하고 있을 개발자Z 일 것입니다.

기존 코드는 큰 영향력을 발휘합니다. 코드가 거기에 있다는 사실만으로 해당 코드는 정확히 동작하며 꼭 필요하다는 점을 드러냅니다. 또 우리 모두는 그 코드가 수많은 노력의 결과물이라는 것을 알기 때문에 이를 최대한 지키고 싶어합니다. 그리고 코드가 복잡하고 이해하기 어려워질수록, 코드를 지켜야한다는 압박감은 더욱 커지게 됩니다. (경제학에서는 이를 매몰비용이라고 부릅니다.) 이는 무의식적으로 이해하기 어려운 코드임에도 바로 잡으려면 많은 시간이 들고, 또 너무 중요한 코드이기 때문에 새롭게 작성할 수 없다고 느끼는 것과 같습니다.

코드가 어느 정도 이해가 가능한 수준이라면 심리적 압박에 의해 요구사항에 맞춰 기존 코드를 수정하는 것도 나쁘지 않아 보입니다. 하지만 그 영향은 상상 이상입니다. 코드가 더 이상 유일한 공통의 추상화가 아닌 그저 조건문으로 나누어져 서로 막연한 상관 관계밖에는 없는 로직 덩어리로 전락해버리기 때문입니다. 그 결과로 코드는 이전보다 이해하기 어렵고 버그도 더 많이 발생합니다.

만약 당신이 이런 상황에 처했다면 매몰비용에 따라 행동하려고 하지 마십시오. 잘못된 추상화를 목격했을 때 가장 빠른 해결 방법은 한 발짝 뒤로 물러서는 것입니다.

  1. 추상화된 코드를 다시 원래 코드를 호출하던 곳으로 옮겨 중복된 코드를 추가한다.
  2. 원래 코드를 호출하던 곳에서 어떤 파라미터를 통해 어떤 로직을 실행시켰는 지를 파악한다.
  3. 이제 해당 코드의 실행과는 관련없는 부분을 제거한다.

결과적으로 추상화와 조건문들이 사라지면서 코드를 호출한 곳에는 정말 필요한 코드만 남습니다. 이 과정을 통해 코드를 호출한 곳에서는 공통된 추상화를 사용했지만 정작 실행된 부분은 서로 크게 달랐다는 점을 깨닫게 됩니다. 오래된 추상화를 완전히 제거하고나면 이제 새롭게 중복을 제거하고 추상화를 추가할 수 있게 됩니다.

저는 잘못된 추상화를 제거하지 않고 개발을 진행해 나가던 개발자들이 끝내 만족할만한 결과를 이끌어내지 못하는 경우를 많이 봤습니다. 새로운 기능을 추가하는 일은 극도로 어려워졌고, 설사 기능이 추가되더라도 다음 기능을 추가하는 일이 더 힘들어졌죠. 하지만 기존 코드를 지키기보다는 기존 코드에서 배운 것을 토대로 새롭게 코드를 작성했을 때 모든 일들이 훨씬 쉬워졌습니다. 추상화를 제거하고 코드를 원래 자리로 되돌렸을 때 새로운 기능을 추가하는 일이 더 빠르고 쉬워졌죠.

이 이야기의 교훈이요? 매몰비용의 함정에 빠지지 말라는 겁니다. 공통 함수에 새로운 파라미터와 조건문을 추가하고 있다면 그 추상화는 잘못됐습니다. 처음에는 그게 올바른 방법이었을 수 있지만 이제는 아닙니다. 추상화가 잘못된 것을 깨달았다면 가장 현명한 방법은 추상화를 제거한 뒤 어떤 방향이 더 나은 방향인지를 살피는 것입니다. 물론 어떤 경우에는 조건문 몇 개를 추가해보면서 코드가 어떤 방향으로 나아가는지를 살펴봐야 하는 경우도 있습니다. 하지만 잘못된 추상화를 더 빨리 제거할수록 덜 고생할 것입니다.

추상화가 잘못되었을 때 가장 빠른 길은 한 걸음 물러서는 것입니다. 물론 이는 후퇴를 의미하지 않습니다. 우리는 더 좋은 방법을 찾기 위해 한 발 물러서는 것입니다. 매몰비용의 함정에 빠지지 마십시오. 자기 자신과 이후에 코드를 유지보수할 수많은 사람들을 위한 길입니다.


원 저자의 글도 좋지만 아래 댓글도 충분히 읽어볼만한 가치가 있습니다. 글을 재밌게 읽으셨다면 원문의 댓글도 꼭 읽어보시기 바랍니다. 감사합니다.

profile
다양한 것들을 시도합니다

0개의 댓글