프리온보딩 챌린지

프리온보딩 FE 챌린지, 비지니스 로직(2)

노엠디엔 2023. 12. 13. 01:17

오늘은 비지니스 로직이 무엇인지에 대해 좀 더 정확히 애기해보는 시간이였다.

'비니니스 로직'과 'UI 기능 구현'의 차이

결제 버튼

  • 사용자가 온라인 쇼핑몰에서 상품을 구매할 때, "결제하기" 버튼을 클릭하면, 사용자의 결제 정보 유효성 검사, 재고 확인, 할인 적용, 결제 처리 등의 프로세스를 실행한다.

회원가입 버튼

  •  "회원가입버튼에는 이메일 형식 확인, 비밀번호 강도 검사, 사용 가능한 사용자명인지 확인 등의 유효성 검사 로직이 포함한다.

    버튼 자체는 단순한 UI 요소지만, 클릭 이벤트에 여러 조건들이 연결됨으로써 복잡해질 수 있다.
    .이러한 요구 사항들을  ‘도메인 로직 / 비즈니스 로직’이라 부르며
    비즈니스 로직을 통해 버튼에 달린 이벤트 리스너는  클릭 이상의 의미를 가지게 된다.

그렇다고 액션을 일으키는 모든 함수가 비즈니스 로직은 아니다!

비즈니스 규칙과 장바구니 기능의 차이는 장바구니는  전자상거래 서비스에서 사용하는 일반적인 개념이며,
장바구니가 동작하는 방식도 모두 비슷하다. 하지만 비즈니스 규칙은 다르다.
해당 이커머스 프로젝트에서 에서 운영하는 특별한 규칙이라고 할 수 있습니다
다른 커머스 서비스에도 장바구니 기능이 있을 것이라고 기대하지만,
'나의 이커머스 프로젝트' 와 똑같은 무료 배송 규칙이 있을 것이라고 기대하지는 않는다!.

 

비즈니스 로직의 예시

    1. 가격 할인 로직:
      • 상황: “저희 책방에서는 매월 첫 구매 고객에게는 10% 할인을 제공하며,특정 출판사와의
        협약에 의해 해당 출판사의 책을 구매할 때는 추가로 5% 할인이 적용되도록 해주세요.
      • 비즈니스 로직: 고객의 구매 이력을 체크하고 출판사를 확인하여 자동으로 적절한 할인율을 적용
    2.  사용자 인증:
      • 상황: “저희 금융 서비스 앱에서는 사용자가 거래를 할 때마다 2단계 인증을 요구하며.
        이는 사용자가 로그인할 때뿐만 아니라, 매 거래마다 추가적인 인증을 받도록 해주세요.
      • 비즈니스 로직: 사용자의 로그인 상태, 거래 내용, 그리고 이전 인증 시간을 체크하여 필요한 경우
        추가 인증을 요청.

UI 기능 구현의 예시

  1. 버튼 클릭:
    • 상황: 웹사이트의 '더 보기' 버튼을 클릭하면, 추가 내용이 페이지에 로드됨.
    • 기능 구현: 버튼에 할당된 이벤트 리스너가 '더 보기' 컨텐츠 섹션의 DOM을 업데이트하여 내용을 표시.
  2. 페이지 스크롤:
    • 상황: 블로그 웹사이트에서 사용자가 아티클을 읽다가 페이지 끝까지 스크롤하면 관련 아티클을 추천.
    • 기능 구현: 스크롤 이벤트에 반응하여 페이지 하단에 도달했을 때 특정 UI를 표시하는 기능.

그래서 비지니스 로직이란?

컴퓨터 소프트웨어에서 비즈니스 로직 또는 도메인 로직은 데이터를 생성, 저장 및 변경하는 방법을 결정하는
실제 비즈니스 규칙을 인코딩하는 프로그램의 일부입니다. 이는 데이터베이스를 관리하거나 사용자 인터페이스,
시스템 인프라를 표시하거나 일반적으로 프로그램의 다양한 부분을 연결하는 하위 수준의 세부 사항과
관련된 나머지 소프트웨어와 대조됩니다.

 

비즈니스 로직은 주로 특정한 상황이나 조건에 따라 다르게 동작하도록 설계,
어떠한 비즈니스에 맞춰진 작업 흐름을뜻한다. 종종 복잡하고, 비즈니스의 성공에 중요한 전략적 결정에
영향을 미치기도 한다. 그렇기에 기능 상으로는 다소 호환성이 떨어지고, 코드의 원래 맥락으로 부터
떨어져 다른 곳으로 옮겨가기 힘들다는 특성을 가지고 있는데 
여기서  흥미로운 점은 대부분의 비즈니스 로직은  백엔드 API와 DB 사이 어딘가에서 다뤄지게 되고, 그래야만 한다.
프론트엔드에서 결제 로직의 핵심적인 부분을 처리한다면 그건 여러 의미로 매우 잘못된 설계라고 볼 수 있습니다.
유저 클라이언트에서 알아서는 안되는 정보이다.

그럼에도 불구하고 프론트엔드에서 비즈니스 로직에 대한 이해도를 갖추고 있어야 하는 이유는
비즈니스 로직을 알아보고 UI 로부터 적절히 분리하기 위해서
비즈니스 로직을 알아보고 백엔드 API 단으로 적절히 격리하기 위해서이다
.

 

'소프트웨어'가 '하드'해지는 과정

소프트웨어는 '부드러움을 지니도록' 만들어졌다. 소프트웨어를 만든 이유는
기계의 행위를 쉽게 변경할 수 있도록 하기 위해서다. 만약 기계의 행위를 바꾸는 일을 어렵게 만들고자 했다면,
우리는 소프트웨어가 아니라 하드웨어라고 불렸을 것이다. - 클린 아키텍처

 

저번시간에  "계산"은 원래의 맥락을 벗어나 컴포넌트 바깥으로 쉽게 분리할 수 있지만 
setState 등의 "액션"은 React 컴포넌트 내의 맥락을 벗어나기 힘들다 하였다.
액션은 전염되기 때문에 계산이 액션을 포함할 경우 그 또한 액션이 되어버리며,
로직은 점차 특정한 상황에서만 사용할 수 있도록 경직됩니다.

 

비즈니스 로직 또한 그렇다고 한다?!
추천 상품 카드 컴포넌트가 화면 상 50% 노출될 시 유저 정보를 서버로 전송하는 기능을 요구 받았고
IntersectionObserver 를 사용하여 구현하려는 상황을 가정해보겠습니다.

비교적 순수한 기능 요소인 일정 영역 이상 컴포넌트 노출 시 등록된 함수를 대신 실행해준다 부분의 코드는
다른 프로젝트나 컴포넌트에 재사용하기 쉽지만 유저 관련 구체적인 비즈니스 로직이 기능 코드와 뒤섞일 경우
해당 로직은 더 이상 순수하지 않다.
특정 ‘비즈니스적 요구 사항과 맥락’에 전염되어 순수 기능만 재사용하기 어렵게 되었다는 뜻이다.

요구사항에서 일반적인 부분과 그렇지 않은 특수한 부분을 자연스럽게 발라내고 각기 구현해야하며.
수정의 이유와 시점이 서로 다른 코드들을 분리 / 격리하여 작성 해야한다.

해당 코드에서는  Card 컴포넌트 기능적인 요소인 "유저 정보를 확인하는" 요구사항과
"유저의 현재 스크롤의 위치를 확인"하는 요구 사항이 있다.

Card 컴포넌트는 현재 로깅을 위한 정보(logData)와 IntersectionObserver 관련 구현,
신규 유저 여부(isNewUser) 등을 모두 처리하고 있고

이 부분은 단일 책임 원칙(SRP, Single Responsibility Principal)을
(컴포넌트가 단 하나의 책임만 가져야 하는 규칙)위반 하고 있는 것이다!.

 

 

기존 useIntersectionObserver가 수행하던 기능을 커스텀 훅이 아닌 children props를 사용하여
컴포넌트를 합성(Composition)하는 형태로 다시 구현한 코드이다.
커스텀 훅으로 만들지 않는 이유는 Card에 전달될 로직들이 App 컴포넌트의 책임이 되는 것처럼 보이고
응집도가 떨어져 재활용하기 어렵기 때문이라고 한다.

 

결국 아까말한 수정의 이유와 시점이 서로 다른 코드들을 분리 / 격리하여 작성 하기 쉬운 형태가 되었고,

VisibleTrigger 컴포넌트에 IntersectionObserver 관련한 로직이 캡슐화(Encapsulation) 되었다.
이 기능은 이곳 뿐만 아니라 어떤 컴포넌트든 동일한 기능이 필요하다면 재사용할 수 있게 되었습니다.
이 분리로 인하여 로깅 기능 또한 Card와 엮이지 않았으며 VisibleTrigger와도 엮이지 않는 형태로 전달 가능해졌습니다.

Card는 이제 어떠한 비즈니스 로직도 포함하지 않으며 순수하게 카드에 담겨야 하는 title과 content를 렌더링 하는데 집중할 수 있게 되었으며  CCP(공통 폐쇄 원칙: 동일한 시점에 동일한 이유로 변경하는 것들을 한데 묶어 관리. 서로 다른 시점에 다른 이유로 변경되는 것들을 서로 분리)를 활용하면서 isNewUser라는 flag가 Card 외부로 빠지게 되면서.
신규 유저 환영에 대한 로직은 조건부 렌더링을 통하여 필요한 곳에 자유롭게 렌더링 가능해졌다.
 이 모든 보조 컴포넌트들이 Card를 중심으로 묶여 높은 응집도(Cohesion)를 갖게 되었다!

 

이번 시간에 비지니스 로직에 대해 정확히 개념이 잡히게 되었다. 또 저번 회차 챌린지였던 클린코드 시간보다도
좀더 클린 코드 아키텍처에 대해 코드를 통해 좀더 쉽게 이해하게 된 강의였던 것 같다.. 진짜 이번 강의는

돈내고 들어야될 것 같은 느낌이였다