diff --git "a/11\354\236\245-\353\246\254\354\225\241\355\212\270 \352\263\204\354\270\265 \352\265\254\354\241\260 \354\225\240\355\224\214\353\246\254\354\274\200\354\235\264\354\205\230/\353\260\225\354\204\240\355\231\224.md" "b/11\354\236\245-\353\246\254\354\225\241\355\212\270 \352\263\204\354\270\265 \352\265\254\354\241\260 \354\225\240\355\224\214\353\246\254\354\274\200\354\235\264\354\205\230/\353\260\225\354\204\240\355\231\224.md" new file mode 100644 index 0000000..321aacf --- /dev/null +++ "b/11\354\236\245-\353\246\254\354\225\241\355\212\270 \352\263\204\354\270\265 \352\265\254\354\241\260 \354\225\240\355\224\214\353\246\254\354\274\200\354\235\264\354\205\230/\353\260\225\354\204\240\355\231\224.md" @@ -0,0 +1,120 @@ +# 11장 리액트 계층 구조 애플리케이션 + +계층 구조(Layered Architecture) + +애플리케이션을 계층화하면 핵심 문제들을 해결할 수 있습니다. + +- 관심사 분리 : 서로 다른 계층은 각기 다른 책임을 다루게 되므로 코드베이스를 쉽게 이해하고 찾아볼 수 있습니다. +- 높은 재사용성: 비즈니스 로직과 데이터 모델을 애플리케이션 전반에서 재사용하기 쉬워집니다. +- 테스트 용이성 : 계층 구조는 단위 테스트와 통합 테:스트를 작성하기 수월하게 하므로 더욱 탄탄한 애플리케이션을 만들 수 있습니다. +- 유지보수성 : 계층 구조로 설계하면 애플리케이션이 커지더라도 기능을 추가하기가 수월합니다. + +## 리액트 애플리케이션의 진화 + +1. 단일 컴포넌트 애플리케이션 + + - 하나의 폼을 다루거나 다른 프레임워크에서 리액트로 전환하는 과정을 설명하고 이해시키고자 하는 경우에 적합합니다. + - 모든 기능을 하나의 컴포넌트 안에 구현하면 코드를 이해하고 관리하기가 어려워집니다. + +2. 복합 컴포넌트 애플리케이션 + + - 컴포넌트의 역할이 분명해진 것은 좋지만, 애플리케이션이 커질수록 역할이 뷰 계층을 넘어 확장됩니다. + +3. 훅을 이용한 상태 관리 + +4. 비즈니스 모델 분리 + + - 분리를 통해 로직의 결합도를 높이고 뷰와 독립하여 구성할 수 있습니다. + +5. 계층화된 프런트엔드 애플리케이션 + + - 애플리케이션이 커지게 되면, 어떤 특정한 패턴을 찾을 수 있습니다. 사용자 인터페이스와도 + 관련 없고, 원격 서버, 로컬 스토리지, 캐시 등의 데이터 출처에 영향을 받지 않는 객체 집합을 + 찾을 수 있습니다. 이 러한 객체들을 모아 별도 계층으로 분리할 수 있습니다. + +## 클래스 기반의 모델의 장점 + +단순 타입에서 클래스 기반 모델로 바꾸면 다음과 같은 장점들이 있습니다. + +- 캡슐화: 클래스는 관련된 속성과 메서드를 한 곳에 위치하게 하여 깔끔한 구조화가 가능합니다. 그리고 데이터 접근을 제한할 수 있어 제어하기 쉽고, 데이터 무결성을 유지할 수 있습니다. +- 메서드: 메뉴 아이템과 관련된 복잡한 작업이 있을 때, 클래스가 제공하는 구조를 활용하여 데이터 조작이든 별도의 비즈니스 로직이든 상관없이 메서드를 정의할 수 있습니다. +- 상속과 다형성 : 메뉴 아이템에 상속이나 다형성 개념이 필요할 때 클래스 구조는 필수적입니다. 각각 다른 메뉴 아이템 타입을 공통의 기본 클래스에서 상속받아 필요한 행동을 재정의할 수 있습니다. +- 일관된 인터페이스: 클래스는 특히 여러 애플리케이션 영역에서 메뉴 아이템을 다룰 때 데이터의 일관된 인터페이스를 보장합니다. +- 읽기 전용 속성 : 클래스는 읽기 전용 속성을 정의할 수 있으므로 데이터 수정을 제한할 수 있습니다. 데이터 무결성을 유지하고 불변 데이터 구조에서 %하기 위한 필수적인 요소입니다. + +### 전략 패턴(Strategy pattern) + +전략 패턴은 코드의 런타임에 필요한 알고리즘 구현을 선택할 수 있는 행동 디자인 패턴입니다. +알고리즘 그룹을 캡슐화하고 서로 갈아 끼우기 쉽게 하여, 시용자가 코드 수정 없이도 적합한 알고리즘을 선택할 수 있도록 합니다. + +```tsx +const handleAddMenuItem = (item: IMenuItem) => { + if (isTodayFridayO) { + item.discountstrategy = new SpecialDiscountStrategyO() + } + if (item.type === 'pizza') { + item.discountstrategy = new PizzaDiscountStrategyO() + } + onAddMenuItem(item) +} +``` + +### 계층 구조 알아보기 + +사용자 정의 훅으로 옮겨보겠습니다. + +```tsx +export const useShoppingCart = (items: IMenuItem[]) => { + const totalPrice = useMemo( + () => items.reduce((acc, item) => (acc += item.price), 0), + [items] + ) + const totalDiscount = useMemo( + () => items.reduce((acc, item) => (acc += item.calculateDiscountO), 0), + [items] + ) + return { + totalPrice, + totalDiscount, + } +} +``` + +useShoppingCart 혹은 IMenuItem 객체 바]열을 붇으0]' totalPrice와 totalDiscount 2가] +의 값을 계산합니다. + +- totalPrice는 아이템 배열을 reduce 연산하여 price 속성을 더합니다. +- totalDiscount는 아이템 배열을 red니ce 연산하여 item.calculateDiscountQ 함수 호출로 얻은 + 아이템의 할인 가격을 더하여 계산합니다. + +두 연산은 모두 useMemo 함수로 감싸 아이템 배열이 바뀔 때에만 다시 계산되도록 하였습니다. 이 수정을 통해 ShoppingCart는 깔끔하고 단순해졌고, 값들을 쉽게 활용할 수 있습니다. + +``` +src +|-----App.tsx +|-------hooks +| |---- useMenultems.ts +| |---- useShoppingCart.ts +|----- models +| |---- BaseMenultem.ts +| |---- IMenuItem.ts +| |---- Pastaltem.ts +| |---- PizzaMenultem.ts +| |---- RemoteMenultem.ts +| |---- strategy +| |---- IDiscountStrategy.ts +| |---- NoDiscountStrategy.ts +| |---- SpecialDiscountStrategy.ts +| |---- TenPercentageDiscountStrategy.ts +|-------views +|------ MenuList.tsx +|------ ShoppingCart.tsx +``` + +### 계층 구조의 유리한 점 + +- 높은 유지보수성: 컴포넌트를 여러 세그먼트로 나누면 특정 코드 영역의 결함을 쉽게 식별하고 수정할 수 있으므로, 소요 시간을 최소화하고 수정하는 동안 새로운 버그가 발생할 가능성을 줄여줍니다. +- 모듈성 향상: 이 구조는 모듈화되어 코드 재사용을 촉진하고 새로운 기능을 간단히 추가할 수 있게 합니다. 뷰와 같은 각 계층 안에서도 코드를 더 쉽게 합성할 수 있습니다. +- 가독성 개선: 코드 안에서 로작을 이해하기 편하고 찾기 쉽습니다. 이는 처음 코드를 작성한 개발자 본인뿐만 아니라 같은 코드베이스에서 작업하는 다른 이들에게도 큰 장점입니다. +- 발전된 확장성 : 모듈 간의 복잡도를 줄여 애플리케이션의 확장성이 향상되고 전체 시스템에 영향을 주지 않으면서도 새로운 기능이나 변경 사항을 쉽게 도입할 수 있습니다. 시간이 지나면서 크고 복잡하게 발전할 것으로 예상되는 애플리케이션 개발에는 매우 중요한 장점입니다. +- 쉬운 기술 스택 이전: 대부분의 프로젝트는 그럴 가능성이 낮지만, 뷰의 존재를 인식하지 못하는 순수 자바스크립트 (또는 타입스크립트) 코드로 도메인 로직을 캡슐화한 덕분에 기본 모델과 로직을 변경하지 않고 뷰 계층을 교체할 수 있습니다.