CHUG ALONG

신입 프론트엔드 개발자 입장에서 생각하는 클린 코드 - 1

December 28, 2023
Introduction

여러 클린한 아키텍쳐, 클린한 코드, 우아한 설계, 객체지향 이론과 관련된 서적을 보면 공통적으로

개발자의 삶에서 새로운 기능을 만드는 시간보다 유지 보수를 하는데 드는 시간이 차지하는 비율이 훨씬 많다.

책을 쓰신 분들, 그리고 이러한 책들이 많이 팔렸다는 것은 그만큼 공감과 신뢰도가 높은 서적이라는 의미를 내포하고 있는데, 그러한 서적들에서 이구동성으로 위와 같은 말을 하곤 합니다.

그러면, 도대체 실무에서 어떤 일들이 발상해고 있길래.. 개발자들은 새로운 기능을 개발하기 보다는 유지보수에 더 많은 시간을 사용하고 있는 것 일까요?

새로운 기능을 추가하기 보다 수정하는 것이 어렵다.

“프로그램이 동작하도록 만드는 데 엄청난 수준의 지식과 기술이 필요하지는 않다. 언제든 어린 고등학생이라도 할 수 있는 일이다. (...) 전 세계의 수많은 초급 프로그래머가 칸막이로 나뉜 작은 사무실에서 이슈 추적 시스템에 등록된 거대한 요구사항 문서들을 순전히 강인한 정신력만으로 힘겹게 해결해 내면서 시스템을 '동작'하도록 만든다. 이들이 작성한 코드는 그다지 깔끔하지 않을 순 있지만, 동작은 한다. 프로그램을 동작하게 만들기는 그리 어려운 일이 아니기 때문이다.” - 클린 아키텍처, 2p

생각해보면 어떻게는 동작/실행이 되게끔 만드는 것은 그리 어려운 일이 아닙니다. 하지만, 그렇게 동작하게끔 만든 제품을 조금만 다른 위치에 쓰려면 불가능한 경우가 많습니다. 기존에 사용하고 있던 조건이 변경되거나 아니면 어떤 정책이 조금만 바뀌어 그에 맞게끔 살짝 수정하여 바꾸려해도 수많은 파일에 영향(side-effect)을 미쳐 결국 대공사가 일어나게 될 수 있습니다. 이는 프로젝트의 크기가 커지면 커질수록 이러한 상황이 더 자주 발생하게 될 수 있겠죠.

배포를 거듭할 수록 코드 1줄을 수정하는데 들어가는 인건비가 기하급수적으로 증가한다 배포를 거듭할 수록 코드 1줄을 수정하는데 들어가는 인건비가 기하급수적으로 증가한다

신입 입장에서 진행해왔던 프로젝트들은 보통 제한된 시간안에 제품을 만들어야하기 때문에 프로젝트의 크기가 작고, 이로인해 수정이 발생하더라도 적은 부분만을 수정하면 됐었기 때문에 유지보수/수정에 드는 비용이 클것이다라는 생각을 하지 못했었는데 이러한 그래프를 보니 왜 유지보수에 드는 비용이 새로운 기능을 만드는 것 보다 많이 드는지 어렴풋이 이해가 되기 시작했습니다.

그럼 처음부터 잘 설계하면 되지 않을까?

우리가 흔히 새로운 기술을 익힐 때 만들게 되는 Todo List 앱조차도 기본적인 사항에 약간의 요구사항만 추가하더라도 상당히 복잡해지기 십상입니다.

“이해관계자는 범위가 비슷한 일련의 변경사항을 제시할 뿐이지만, 개발자 입장에서는 복잡도가 지속적으로 증가하는 퍼즐 판 위에서 이해관계자가 계속해서 퍼즐 조각을 맞추라는 지시를 하는 것처럼 느껴진다. 새로운 요청사항이 발생할 때마다 바로 이전의 변경사항을 적용하는 것보다 조금 더 힘들어지는데, 시스템의 형태와 요구사항의 형태가 서로 맞지 않기 때문이다.” - 클린 아키텍처, 17p

여기서 알 수 있는 두 가지 사실이 있습니다.

첫째, 1) 프로그램이 복잡해지는 이유는 애초에 우리의 현실 자체가 복잡하고, 코딩을 할 수록 그 복잡도가 제품에 점차 반영되기 때문입니다. 다른 하나는 2) 그 복잡함이 어느 정도까지 복잡해질지 요구 받아보기 전까지 절대 알 수 없기에 최적 구조를 미리 정할 수 없다는 점입니다.

스파게티 코드를 짜고 싶어하는 개발자가 있진 않았을 겁니다. 하지만 실제 서비스 되고 있는 실무에서는 매일 새로운 인입이 들어오고 이에따라 새로운 기획, 변경된 기획안들이 제시되고 이를 처리하다보면 어느덧 처음 완벽하게 설계되어있다고 생각했던 구조가 맞지 않을 수 있겠죠.

언제나 우리는 시간의 압박과 제한적인 정보 속에서 안정적으로 기능을 만들어 나가야 합니다. 포인트는 잘 만드는 것(물론 맞지만)이 아니라 리소스가 제한된 상황 그 자체에 있었던 겁니다.

그리고 중요한 사실은 리소스가 충분한 언젠가는 오지 않습니다. 오지 않을 상황을 기다리는 것은 하지 않겠다는 의지의 표명에 다름 아닙니다.

그러면, 리소스가 충분한 언젠가를 기다리기 보다는 지금 당장 제가 할 수 있는 행동은 무엇이 있을까요?

함수를 잘 나누자

우선 용어 정의를 하고 넘어가겠습니다.

  • 1) 데이터 : 이벤트에 대한 사실. 문자열, 객체 등 단순한 값 그 자체.
    • ex) 사용자가 입력한 이메일 주소, 은행 API로 읽은 달러 수량
  • 2) 계산(Compute) : 입력으로 얻은 출력. 순수 함수, 수학 함수 라고 부르기도 함.
    • ex) 최댓값 찾기, 이메일 주소가 올바른지 확인하기
  • 3) 액션 : 외부 세계와 소통하므로 실행 시점과 횟수에 의존. 부수 효과를 일으킴.
    • ex) 이메일 보내기, 데이터베이스 읽기, setState

우리가 컴포넌트 안에서 함수를 나눌 때 제법 잘 나눠졌다고 생각이 들 때도 있고, 그렇지 않을 때도 있습니다. 후자의 경우를 유심히 들여다 보면 아마 액션에 해당하는 로직이 섞여 있는 경우가 많지 않을까 싶습니다.

우리는 데이터, 계산으로부터 가급적 액션을 분리하고, 부수 효과를 일으키는 액션 안에서 데이터나 계산 로직을 호출하여 사용하도록 분리하면 좋겠습니다.

부수 효과를 일으키는 것과 없는것을 분리하면 다음과 같은 이점을 얻을 수 있습니다.

부수 효과가 없으면 외부에 영향을 주지 않기 때문에 1) 쉽게 테스트 가능하고 2) 여러 번 테스트해도 문제가 생기지 않습니다. 반면 액션은 1) 실행 시점2) 횟수에 따라 결과가 다르게 나올 수 있으외부 세계에 영향을 주기 때문에 재현하기 위해서는 많은 노력이 필요(= 테스트 하고자 하는 로직 뿐만 아니라 외부 세계를 함께 재현해야 하기 때문에)합니다.

가오나시

액션이란 프로그래밍으로 우리가 계산해낸 것들을 외부 세계에 전달하거나 전달 받는 동작으로서, 우리가 원하는 일을 달성하기 위해서는 꼭 필요하지만, 가급적이면 접촉면을 작게 해야하는 애증의 존재이기 때문에 가급적이면 액션에 해당하는 로직을 분리하도록 신경쓰는 것으로 함수를 잘 나눌 수 있겠다고 생각했습니다.

이렇게 함수를 나누면 부수 효과가 없는 데이터나 계산을 담당하는 함수는 컴포넌트 외부에 위치할 수 있겠고, 자연스럽게 재사용(테스트)할 수 있는 효과까지 얻을 수 있겠습니다.

비즈니스 로직을 파악하자

지금 당장은 단순한 토이 프로젝트만 경험해봤기 때문에 복잡한 기획이나 정책같은 실제 사업과 연관된 코드를 작성해본 경험이 거의 전무하지만서도 앞으로 신입으로써 회사에 들어가 1인분 하는 개발자가 되기 위해서는 비즈니스 로직이 무엇인지 파악할 수 있는 힘을 길러놔야겠다고 생각했습니다.

비즈니스 로직 vs UI 기능 구현

아래는 자주 사용되는 버튼들과 각 버튼들의 책임과 역할을 명시해 봤습니다.

  1. 결제 버튼:
    • 사용자가 온라인 쇼핑몰에서 상품을 구매할 때, "결제하기" 버튼을 클릭하면, 사용자의 결제 정보 유효성 검사, 재고 확인, 할인 적용, 결제 처리 등의 프로세스를 실행한다.
  2. 회원가입 버튼:
    • "회원가입" 버튼에는 이메일 형식 확인, 비밀번호 강도 검사, 사용 가능한 사용자명인지 확인 등의 유효성 검사 로직이 포함다.
  3. E-Book 읽기 버튼:
    • "읽기" 버튼을 클릭했을 때, 사용자의 구매 내역 혹은 이용권 보유 현황을 기반으로 해당 콘텐츠에 대한 접근 권한을 가지고 있는지 체크하고, 접근 권한이 없는 경우 구매 페이지로 리디렉션하는 로직을 실행한다.
  4. 환불 요청 버튼:
    • "환불 요청" 버튼은 구매 후 일정 기간 내에만 활성화되며, 사용자가 클릭하면 주문 상태를 확인하고, 환불 절차를 자동으로 시작하는 로직을 실행한다.

위의 예시들로부터 확인할 수 있듯 버튼 자체는 단순한 UI 요소지만, 클릭 이벤트에 여러 조건들이 연결됨으로써 복잡해질 수 있습니다. 이러한 요구 사항들은 우리가 흔히 **‘도메인 로직 / 비즈니스 로직’**이라 부르는 것이며, 이러한 비즈니스 로직을 통해 버튼에 달린 액션은 단순한 클릭 이상의 의미를 가지게 됩니다.

그렇다면 액션을 일으키는 모든 함수들은 비즈니스 로직이라고 할 수 있을까요? 물론 그렇지는 않습니다. 웹사이트의 더 보기 버튼을 클릭하면, 추가 내용이 페이지에 로드되는 기능의 경우 클릭하는 시점에 외부 세계와 소통하여 새로운 데이터를 로드시키지만, 이는 사용자 경험을 향상시키기 위해 DOM 업데이트를 나중으로 미루는, UX 측면이 강한 UI 로직이라고 볼 수 있겠습니다.

정리해보자면, UI 로직은 그 자체로는 특정 비즈니스에 구속되지 않고, 사용자와 시스템 간의 기본적인 상호작용을 위한 보다 일반적인 차원에서의 기능 구현 코드입니다.

반면, 비즈니스 로직은 주로 특정한 상황이나 조건에 따라 다르게 동작하도록 설계된, 말 그대로 어떠한 비즈니스에 맞춰진 작업 흐름입니다. 종종 복잡하고, 비즈니스의 성공에 중요한 전략적 결정에 영향을 미치기도 합니다. 그렇기에 기능 상으로는 다소 호환성이 떨어지고, 코드의 원래 맥락으로 부터 떨어져 다른 곳으로 옮겨가기 힘들다는 특성을 가지고 있습니다.

여기서 매우 흥미로운 점은 대부분의 비즈니스 로직은 사실 백엔드 API와 DB 사이 어딘가에서 다뤄지게 되고, 또 그래야만 합니다. 프론트엔드에서 결제 로직의 핵심적인 부분을 처리한다면 그건 여러 의미로 매우 잘못된 설계라고 볼 수 있습니다. 유저 클라이언트에서 알아서는 안되는 정보입니다. 때문에, 프론트엔드에서는 1) 비즈니스 로직을 알아보고 UI 로부터 적절히 분리해야 하고 2) 비즈니스 로직을 알아보고 백엔드 API 단으로 적절히 격리할 수 있어야 합니다.

좋은 코드를 접하자

회사에 들어가면 선임 개발자 혹은 동료들에게 코드 리뷰를 받으면서 동시에 그들의 코드를 리뷰해주면서 내 코드에서 부족한 부분, 개선할 수 있는 부분들을 깨닫게 될 수 있을것 입니다.

하지만, 취준생 입장에서는 진득히 제 코드를 봐줄 동료분들을 구하는 것이 쉽지만은 않은 현실입니다. 봐줄 동료가 없다면, 좋은 코드를 보고 견문을 넓히는 방법을 선택해야 했습니다. 좋은 코드는 이미 제 주위에 많이 널려 있으니깐요. 바로 유명 라이브러리를 까보는 것 입니다.

제가 구현하려고 하는 모든 기능들은 실제 라이브러리로 구현되어 있고, 제가 직접 개발하는 것 보다는 무수히 많은 별을 받고, 실제 기업에서 사용되고 있는 코드들이 더 좋은 코드일것이기 때문입니다. 이러한 코드들은 앞서 이야기했던 유지보수 측면에 더욱이 신경을 썼을 것 이고요. 또한, 좋은 코드를 접해보면 그들이 함수를 어떻게 나누었는지 공짜로 볼 수 있고, 비즈니스 로직은 어떻게 처리하는지, props는 어떻게 받는지, 왜 이렇게 받는지 보면서 해안을 얻을 수 있습니다.

이러한 이유로 토이 프로젝트를 진행할때마다 실제 오픈 소스 라이브러리의 코드를 들여다 보는 시간을 갖곤 했습니다. 이 개발 블로그를 만들 때에도 역시 그러했는데요, 일단 두 라이브러리를 살펴 보았습니다. Toast 알림을 띄워주는 React-toastify와 카테고리 목록을 가로로 스크롤 할 수 있는 기능을 MUI-core 라이브러리를 참고해서 특정 기능들을 개발했습니다.

저보다 많이 공부하시고 현업에서 일하시는 개발자가 작성하신 코드를 바라보면서 '와 이렇게도 로직을 작성할 수 있겠구나 / 이렇게 문제를 해결할 수 있겠구나?' 등의 코드를 작성하는 새로운 시각을 얻을 수 있었습니다. 백문이불여일견이라는 말이 있듯이 아무리 백마디 말을 통해 내 코드의 어떤 부분이 좋지 않은지 설명해주기 보다는 우선 그런 추상화된 리뷰를 이해할 수 있도록 좋은 코드를 먼저 접해보고 실무에 투입된다면 더 나은 의사소통을 할 수 있겠다는 생각이 들었습니다.

마치면서

단순히 이번 포스팅만으로는 클린코드 / 클린아키텍쳐의 철학을 모두 담을 수 없었습니다. 다만, 클린 아키텍쳐나 클린 코드 책을 읽으면서 공통적으로 중요하다고 얘기하는 부분들을 저의 생각으로 정리하고 어떻게 내 코드에 접목시킬지 생각해보면서 이번 포스팅을 작성하게 되었습니다.

함수의 매개변수는 2개 이하여야만 한다. 명확한 함수 명을 지켜야 한다. 변수명을 명확히 하라. 매직넘버의 사용을 줄여라. 이런 규칙들을 지키지 않으면 괜히 내가 코드를 잘못쓰고 있구나..라고 느껴질 떄도 있습니다. 하지만, 실무 개발자들의 이야기를 들어보면 항상 그런것만은 아니다. 라는 얘기들도 많이 하시곤 합니다.

그렇기 떄문에 저러한 규칙들이 왜 등장하게 되었는지, 왜 저러한 얘기들이 많은 공감과 호응을 얻고 있는지 그 배경을 살펴보았고, 그러한 규칙들을 내 스타일대로 잘 녹여낼 수 있도록 다양한 글을 참고해서 이번 포스팅에 정리해보았습니다.

참고