내가 느낀 클린 코드와 현실의 괴리

정정일·2024년 12월 3일
0

개발을 하다 보면 "클린 코드"라는 단어를 접하게 됩니다.

코드는 읽기 쉽고, 의도를 명확히 드러내며, 유지보수하기 쉬워야 한다는 원칙들이죠. 처음 클린 코드를 배울때 참 많은 것들을 느꼈습니다.

변수하나의 네이밍을 붙이면서도 많은 고민을 해야하구나 하는 생각을 처음으로 하게 됐었거든요.

하지만 실무에 발을 들이고 여러 프로젝트를 경험하다 보니 현실은 생각보다 복잡했습니다.

마감일, 팀의 우선순위, 이미 존재하는 코드베이스의 복잡성 등 이상을 가로막는 다양한 현실적인 제약들이 있었죠.

특히, "이름 짓기"라는 지점에서 이상과 현실의 괴리를 느낄때가 있었습니다. 클린 코드에서 강조하는 "의도를 드러내는 이름"은 당연히 중요하지만, 때때로 이상과 타협해야 할 순간들이 오곤 했던 것 같습니다.


클린 코드의 이상

클린 코드를 배우면서 가장 인상 깊었던 것 중 하나는 "의도를 드러내는 이름"이었습니다. 이름만 봐도 클래스나 함수가 어떤 일을 하는지 알 수 있어야 한다는 원칙은 코드 가독성을 크게 높여준다고 생각합니다.

예를 들어, OrderManager라는 이름은 간결하면서도 클래스가 "주문을 관리"한다는 것을 한눈에 알아볼 수 있게 해주죠.

public class OrderManager {
    // 주문 생성, 수정, 취소와 관련된 로직
}

이런 이름은 직관적이고, 읽기 쉽고, 협업에서도 도움이 된다고 생각합니다. 저 또한 이런 이름을 짓기 위해 많은 노력을 기울이고 있고 고민하고 노력하는 만큼 제 코드가 깔끔해지는 것 같아 뿌듯함을 느끼고 있습니다.


이름 짓기의 어려움

하지만, 항상 간결하고 직관적인 이름을 짓는 게 가능하진 않다는 걸 깨닫게 됐습니다. 복잡한 요구사항이나 협업 환경에서는 이름이 길고 복잡해질 수밖에 없는 상황이 발생하곤 했습니다.

실제로, 이름 짓기의 어려움을 극단적으로 보여주는 사례를 한 가지 소개하겠습니다. Java의 AspectJ 라이브러리에는 다음과 같은 클래스가 존재합니다.

public class HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor extends AbstractPatternNodeVisitor

처음 이 이름을 봤을 때, "이게 진짜 클래스 이름인가?" 싶었습니다. 이름만 봐도 이 클래스가 "제네릭 또는 매개변수화된 타입 패턴 매칭을 시도했는지 확인하는 방문자"라는 역할을 한다는 점은 알겠지만, 너무 길고 복잡해서 다음과 같은 문제를 느끼게 됩니다.

  1. 가독성 저하
    IDE에서 이름이 잘리거나, 메서드 체인에 등장했을 때 코드의 가독성을 심각하게 해칩니다.

  2. 협업의 비효율성
    팀원과 코드에 대해 논의할 때, 이런 이름을 언급하는 데도 시간이 걸립니다. "그 긴 클래스 이름"이라고 불리는 상황이 될 가능성이 높다고 생각합니다.

  3. 유지보수의 부담
    이름을 오타 없이 정확히 작성하거나 변경해야 할 때, 길이와 복잡성 때문에 작업 시간이 늘어납니다.


왜 이런 이름이 만들어질까?

제가 생각하는 이런 이름이 탄생하는 이유는 다음과 같은 것들이 있습니다.

  1. 명확성을 지나치게 추구할 때
    이름에 모든 정보를 담으려다 보니 자연스럽게 길어지게 됩니다. 특히, 역할이 복잡하거나 다중 책임을 다룰 때는 이를 설명하려는 시도 자체가 이름을 장황하게 만든다고 생각합니다.

  2. 특수한 도메인 요구사항
    AspectJ와 같은 라이브러리는 복잡한 패턴 매칭과 관련된 작업을 다루기 때문에, 이름 자체가 도메인의 복잡성을 반영하는 경우가 있을 수 있다고 생각합니다.

  3. 협업과 타협의 산물
    팀 내에서 이름을 논의하다 보면, 모호함을 줄이기 위해 구체적으로 작성하자는 합의가 이루어질 때가 있다고 생각합니다. 결과적으로는 이런 컨벤션이 오히려 가독성을 해치는 경우도 있는 것 같습니다.


실제 경험

저도 이런 딜레마를 겪은 적이 있습니다. 결제 관련 기능을 개발하던 중, 다음과 같은 이름을 고민했던 사례가 있었습니다.

  • 처음에는 PaymentProcessor라는 이름을 지었습니다.
    이 클래스가 결제를 처리한다는 점에서는 네이밍이 잘 됐다고 생각했습니다.

  • 시간이 지나면서 클래스가 점점 다양한 역할을 맡게 되었습니다.
    승인, 취소, 환불 같은 기능이 추가되면서, 기존의 이름만으로는 모든 역할을 설명하기 어렵다는 생각이 들었습니다.

  • 그래서 PaymentApprovalAndRefundHandler라는 이름으로 변경했습니다.
    역할을 좀 더 명확히 드러내려고 했지만, 이름이 길어지니 오히려 코드 가독성이 떨어졌습니다. 그리고 기능이 추가될때마다 이름이 더 길어져야하나...? 라는 생각을 가지게 됐습니다.

  • 결국 다시 PaymentHandler로 간결하게 바꾸고, 상세한 역할 설명은 주석으로 보완했습니다.

이 과정에서 느낀 건 이름에 모든 걸 담으려고 하기보다는, 코드 자체의 가독성과 유지보수를 고려하는 것이 더 중요하구나 라는 점이었습니다.


이상과 현실 사이에서의 타협

결국, 클린 코드의 원칙을 지키면서도 현실과 타협하기 위한 기준을 세워야 한다는 것을 배웠습니다. 제가 현재 생각하는 기준은 다음과 같습니다.

  1. 단일책임 원칙을 기억하자
    클래스가 하나의 책임만 가지게 하면 이름이 간결해지기 쉽다고 생각합니다. 여러 책임을 가지게 된다면 네이밍이 어려워질 가능성이 큰 것 같습니다.

  2. 간결함을 우선으로
    이름은 핵심적인 역할만 담도록 합니다. 구체적인 설명이 필요할때는 주석으로 보완합니다.

  3. 컨텍스트를 고려
    코드가 작성된 도메인이나 프로젝트 맥락에서 충분히 이해될 수 있는 이름을 짓습니다.

  4. 팀 규칙 우선
    팀원들과 논의해 합의된 명명 규칙을 따릅니다. 협업에서는 일관성이 중요하다고 생각합니다.

  5. 코드와 이름은 함께 발전한다
    코드가 변경되면 이름도 바뀌어야 한다고 생각합니다. 완벽한 이름을 처음부터 정하겠다는 부담을 덜어낼 필요가 있는 것 같습니다.


결론

HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor 같은 이름이 클린 코드와 현실의 괴리를 보여주는 사례 중 하나라고 생각합니다. 처음엔 "이게 뭐야?" 싶었지만, 이를 통해 "네이밍은 이상과 현실 사이에서 늘 고민해야 한다"는 점을 다시금 느끼게 되네요.

아직 완벽한 답을 얻지는 못했지만, 이런 고민들을 통해 매번 조금이라도 더 나은 코드를 작성하고 싶다고 생각하고 있습니다. :)

profile
하루하루 더 발전하는 사람이 되기 위해 노력하는 개발자가 되고자 합니다.

0개의 댓글