jtwjs Dev Wiki
  • DEV_ROAD
    • 💪🏻 생존하기
    • Week 1
      • 개발 환경 세팅
      • 타입스크립트
      • 리엑트
      • Testing Library
      • Parcel & ESLint
    • Week 2
      • JSX
      • Virtual DOM
    • Week 3
      • React Component
      • React State
    • Week 4
      • Express
      • Fetch API & CORS
      • React Hook
      • useRef & Custom Hook
    • Week 5
      • TDD
      • React Testing Library
      • MSW
      • Playwrite
      • Snapshot
    • Week 6
      • Separtion of Concerns
      • Principle
      • DI, (Dependency Injection)
      • Reflect-metadata
      • TSyringe
      • External Store
      • Follow Redux
      • usestore-ts
      • useSyncExternalStore
    • Week 7
      • Routing
      • Routes
      • Router
      • Navigation
    • Week 8
      • Design System
      • Style Basics
      • CSS-in-JS
      • Styled-Components
      • Global Style & Theme
    • Week 9
      • 개발하기 전 준비
      • 상품 목록 페이지
      • 상품 상세 페이지
      • 장바구니 페이지
    • Week 10
      • 로그인
      • 로그아웃
      • 회원가입
      • 주문 목록 & 주문 상세
    • Week 11
      • 배송 정보 입력
      • 포트원 결제 요청
      • 배송 및 결제 정보 전달
    • Week 12
      • 관리자 웹사이트개발시작
  • DEV_NOTE
    • TypeScript
      • 기본적 문법
        • Enum
        • 다형성
          • Untitled
        • 구조적 타이핑
        • 제너릭 타입
        • 컨디셔널 타입
        • 함수 메서드 타이핑
        • infer로 타입스크립트의 추론 직접 활용
        • 재귀 타입
        • 템플릿 리터럴 타입
        • 추가적인 타입 검사 satisfies 연산자
        • 타입스크립트 건망증
        • 원시 자료형에도 브랜딩 기법 사용 가능
        • 타입 좁히기
        • 유용한 타입 만들기
        • 데코레이터 함수
        • 앰비언트 선언도 선언 병합이 된다.
        • 앰비언트 선언도 선언병합이 된다.
    • Testing
      • Unit Testing
      • 단위 테스트의 두 분파
      • 좋은 단위 테스트를 구성하는 4대 요소
      • 테스트 대역과 식별할 수 있는 동작
      • 단위 테스트 스타일
      • 가치 있는 단위 테스트를 위한 리팩토링
      • 통합 테스트
      • Cross Browsing Testing
      • 기능 테스트 종류
      • React Testing Pattern
      • 프론트엔드 테스트 입문
        • 테스트 범위
        • 단위 테스트 검증
        • Mock
        • UI 컴포넌트 테스트
        • 테스트 커버리지
        • 웹 통합 테스트
        • MSW
        • 스토리북
        • 시각적 회귀 테스트
        • E2E 테스트
        • Github Actions 설정
        • 깃허브 액션에서 E2E
      • 시프트 레프트
        • 테스트 기본중의 기본
        • 단위 테스트
        • 코드 복잡도
        • 리팩터링
        • 코드 리뷰
        • 통합 테스트 패턴
        • 시스템 테스트의 자동화
        • 탐색적 테스트
      • Test Tip
      • vitest
      • playwright
      • Test Data Generator
      • MSW
    • Algorithm
      • coding test
      • Data Structure
    • Next.js
      • Data Fetching
      • Hydration
      • Next 13
      • Optimization
      • Next 15
    • Tailwind
      • Tailwind CSS
      • Theme
      • Directives
      • Tool
      • Design System
    • Storybook
      • Storybook
      • CSF3
      • CDD
      • Headless Component
    • Funtional Programming
      • 함수형 프로그래밍
      • 참조 투명성
      • 부수효과
      • 함수 합성
      • 제너릭 타입 활용하기
      • 암묵적 입출력
      • 액션과 계산, 데이터
      • 계층형 설계
      • 호출 그래프
      • 함수형 설계
      • 불변성
      • 일급 함수
      • 함수형 도구
    • Git
      • Github Actions
      • Conflict
      • Branch 전략
    • Contents Format
      • Audio
    • 3D Graphic
      • 3D keyword
      • Three.js
      • Geometry
      • Material
      • Light
      • Camera
      • Decal
      • Rotation
      • Text
      • Shadow
      • Fog
      • Post Processing
      • Animation
      • Math
        • Vector Space
        • 벡터의 연산
        • 회전 계산
      • 3D 컨텐츠가 만들어지는 과정
      • R3F
      • Env
      • Scene
      • Transform
      • R3F
      • Interaction & Raycast
      • Rendering Algorithnm
      • Blender
      • Blender
    • Accessibility
      • 접근성이란
    • Interactive Web
      • Parallax
      • Canvas
      • requestAnimationFrame
      • Effect
      • HSL
      • React.js + Canvas
      • Matter.js
    • AWS
      • DevOps
      • Amplify
      • S3
      • 클라우드 컴퓨팅
        • 온프레미스와 클라우드
        • 클라우드 도입효과
        • 클라우드 컴퓨팅의 범위
        • 컴퓨팅 옵션
          • EC2 - Virtual Machin
          • ECS, EKS - Container
          • Lambda - Serverless
        • 네트워크 가상화
        • 스토리지
        • 데이터베이스
        • 데이터 수집
        • 머신 러닝 영역
        • IoT 영역
        • 블록체인 영역
      • 클라우드 아키텍처 설계
    • Network
      • Web Server & WAS
    • System Design
      • System Design
      • Component
      • 의존성을 배제한 개발
      • Error Handling
      • Architecture
        • 모노로틱 아키텍처
        • Clean Architecture
        • Layered Architecture
        • 이벤트 기반 아키텍처
      • 상황을 파악하는 메타인지
      • 중복 문제 해결하기
      • Monorepo Arhitecture
        • 모노레포 운영과 트러블슈팅
        • Module Federation
      • 코드 병목지점
      • API 대응
      • 공통 코드
      • Infra 구축
      • 모듈 기반의 개발 방식
      • Design System
        • 최소 수준의 아키텍처 설정
        • 더 효율적인 디자인시스템 만들기
        • 디자인 시스템과 UI 라이브러리 목적
        • 디자인 토큰
      • 효율적인 업무
        • 업무 프로세스 병목 파악
      • Clean Code
      • Design Pattern
        • CQRS Pattern
        • Strangler Fig Pattern
        • 데코레이터 패턴
        • 커맨드 패턴
        • 전략 패턴
        • 옵저버 패턴
      • A/B 테스팅
      • 대규모 리엑트 웹앱 개발
        • 복잡성 관리
        • 모듈성
        • 성능
        • 디자인 시스템
        • 데이터 패칭
        • 상태 관리
        • 국제화
        • 코드 조직화하기
        • 개인화 A/B 테스팅
        • 확장 가능한 웹 아키텍처
        • 테스팅
        • 툴링
        • 기술적 마이그레이션
        • 타입스크립트
        • 라우팅
        • 사용자 중심 API 디자인
        • 리액트 미래
    • Performance
      • React DevTools
      • Component 최적화
      • Page Load
      • API
    • MFA
      • MSA
      • MFA 도입하기
      • Monorepo
        • Monorepo Tool
        • Yarn Berry Workspace
        • Turborepo
      • MFA Composition
      • SPA 통합
      • Design System
      • Package Manager
        • Yarn
        • pnpm
      • Transpiler & Bundler
        • Babel
        • Rollup
        • esbuild
        • swc
        • Webpack
        • Vite
      • 분해와 통합을 위한 여러 기술 비교
    • State Management
      • Zustand
    • React v18
      • Automatic batching
      • Suspense
      • Transition
    • SEO
      • Search Engine Optimization
      • Open Graph Element
      • Metadata
    • FE Develop
      • Scrubbing
      • Clipboard
    • Refactoring
      • 리팩토링 깊게 들여다보기
      • 긴 코드 조각내기
      • 타입 코드 처리하기
      • 유사한 코드 융합하기
      • 데이터 보호
      • 코드 추가 및 제거
    • OAuth 2.0
    • Analytics
      • Mixpanel
    • ETC
      • VSCode
    • React Hook In Action
      • useContext & Provider
      • 커스텀 훅
      • 코드 분할하기 with Suspense, lazy
      • Suspense와 이미지 적재하기
      • useTransition, uesDeferredValue
      • SuspenseList
Powered by GitBook
On this page
  • 개발 의존성
  • 의존성으로 인한 문제
  • BE 의존성 줄이기
  • Mocking이 필요한 상황
  • MSW (Mock Service Worker)
  • MSW 설정
  • API Layer DI
  • 의존성(Dependency)
  • 의존성 주입(DI, Dependency Injection)
  • 의존성 분리 장점
  • Tree shaking
  • Next.js Tree shaking 적용
  • 결론
  1. DEV_NOTE
  2. System Design

의존성을 배제한 개발

개발 의존성

의존성이 커질수록 제품은 더 복잡해지고 문제가 발생하기 쉬워진다.

제품 개발의 의존성을 줄이는 아키텍처 설계에 대해 신경을 쓰고 도입해보자.

의존성으로 인한 문제

직군 간의 의존성

  • BE <--> FE, PM <--> FE, 상호간 커뮤니케이션 문제로 인한 개발 시간 증가

  • 기획 정의서가 준비될 때 까지 기다린다거나 BE API spec을 기다리는 등의 대기시간 낭비

모듈 간의 의존성

  • 코드 레벨에서 모듈간의 의존성이 커질수록 복잡도가 커지게 된다.

  • 코드 리팩토링 또는 기능이 수정 & 추가되어야 하는 상황에서 개발 난이도가 증가하게 된다.

일정 상의 의존성

  • 일정 지연으로 인한 개발 시간 준수가 어렵게 된다.

  • 다른 테스크들을 병행하면서 개발할 때 컨텍스트 스위칭 비용이 발생하여 집중도 하락 및 개발 시간 증가

BE 의존성 줄이기

Mocking이 필요한 상황

  • 개발 과정에서 준비되지 않은 서버 API 응답 처리를 위해 사용

    • API Mocking Layer 구현으로 Mocking 여부에 대한 차이를 파악할 필요없도록 구성

  • API Mocking을 통해 정확한 API Interaction 모델링과 성공/실패 케이스를 모의하여 디버깅 필요

    • Client 이슈는 대부분 Data 문제로 잘못된 API 호출, 오류처리 누락, 예상치 못한 response 반환같은 상황 등

MSW (Mock Service Worker)

  • Service Worker API를 이용해 HTTP 요청 가로챔

  • API 요청 발생 시 가로채서 준비한 Mock Data로 응답

  • 별도의 Mock Server 없이 Mocking 가능

Service Worker

  • 웹 어플리케이션의 백그라운드 스레드에서 실행됨

  • UI Block 없이 연산 가능

  • Network 요청 가로채서 응답 모킹 가능

동작 원리

  1. 브라우저 request 발송

  2. worker는 해당 요청을 받고 클론한다음 MSW로 전달

  3. 전달받은 요청과 일치하는 목 데이터가 존재하는지 조회

  4. 존재한다면 ServiceWorker에 Mock Response 전달

  5. ServiceWorker는 전달받은 응답을 브라우저에게 전달

MSW 설정

Install

npm install msw -D
// crate mockServiceWorker file in public folder
npx msw init public/ --save

Request Handler 설정

  • response 값 설정 (code, data)

  • URL/RegExp/특정 조건의 request 캡처

  • HTTP method 별 조건 적용

// src/mocks/products/handler.ts
import { rest } from 'msw'
import productsData from './products.json'

import type { RestRequest, ResponseComposition, DefaultBodyType, RestContext } from 'msw'
import { ProductResponse } from '@/api/products'

const getProducts = (
    req: RestRequest,
    res: ResponseComposition<ProductResponse>,
    ctx: RestContext
) => {
    return res(ctx.status(200), ctx.json({ products: productsData }))
}

const getProductsHandler = [rest.get(`${process.env.NEXT_PUBLIC_URL}/api/products`, getProducts)];

export default getProductsHandler

Worker Setup

  • 구현한 handler들을 worker에 삽입

// src/mocks/browser.ts
import { setupWorker } from 'msw'
import productHandler from './products/handler'

// This configures a Service Worker with the given request handlers.
export const worker = setupWorker(...productHandler)
  • worker 실행 (production 빌드는 수행 안되도록 env 조건 설정)

import { worker } from '@/mocks/browser';

if (process.env.NODE_ENV === 'development') {
  worker.start();
}

export default function App() {//...}

Next.js 에서 MSW 이슈

  1. Next.js는 서버사이드에서도 API 호출할 수 있기 때문에 브라우저 모킹뿐만아니라 서버모킹(node)가 필요

  2. MSW init 이전 API 호출 발생될 수 있음

    1. MSW를 init 후 Component load 필요 -> HOC 구성

    2. initMock 함수를 dynamic import 후 실행, loaded 상태 설정을 통해 children 로드 진행

    3. 만약 MSW를 사용하지 않는 경우 최초 상태값 설정을 통해 바로 Component를 로드하도록 구성

import { setupServer } from 'msw/node'
import productHandler from './products/handler'

export const server = setupServer(...productHandler)
 // src/mocks/index.ts
export async function initMocks() {
    console.log('init mocks')
    if (typeof window === 'undefined') {
        const { server } = await import('./server')
        server.listen()
    } else {
        const { worker } = await import('./browser')
        worker.start()
    }
}
 // src/mocks/MSWProvider
 import { PropsWithChildren, useState, useEffect } from 'react';

const isMockingEnabled = Boolean(process.env.NEXT_PUBLIC_API_MOCKING) 
    && process.env.NODE_ENV !== 'production';

export const MSWProvider = ({ children }: PropsWithChildren) => {
    const [isLoaaded, setIsLoaded] = useState(!isMockingEnabled)

    useEffect(() => {
        const init = async () => {
            if (isMockingEnabled) {
                const fn = await import('./index').then((res) => res.initMocks)
                await fn()
                setIsLoaded(true)
            }
        }
        !isLoaaded && init()
    }, [isLoaaded])

    if (!isLoaaded) {
        return null
    }

    return (
        <>
            {children}
        </>
    )
}

API Layer DI

의존성(Dependency)

의존성이란 두 모듈간의 연결, 서로 간 관계가 있는 경우 의존성이 있다고 본다.

  • 한 모듈이 다른 모듈을 사용할 때

    • 다른 모듈을 생성할 때

    • 다른 모듈의 함수를 호출할 때

    • 다른 모듈을 인자로 받아 사용할 때

의존성이 위험한 이유

  • 한 모듈의 변경이 다른 모듈에 영향을 끼침

  • 이러한 영향이 모듈간 전파되어 알 수 없는 Side Effect 발생

의존성 주입(DI, Dependency Injection)

  • Inversion of Control

  • 모듈의 의존성이 내부가 아닌 외부로부터 주입 받는 형태

  • Component의 props로 의존성 주입

의존성 분리 장점

  • 모듈간 의존성 감소

  • 재사용성 증가

  • 유닛테스트 용이

  • 가독성 증가

Tree shaking

나무를 흔들어 죽은 나뭇잎을 떨어트리는 것처럼, 사용하지 않는 코드를 제거하는 것을 의미

즉, 사용하는 코드들만 사용해서 빌드하는 것

Next.js Tree shaking 적용

v13.5 이상 버전만 사용 가능한 방법

 // next.config.js
 module.exports = {
   experimental: {
     optimizePackageImports: ['package-name'],
   },
 }
  • experimental.optimizePackageImports 에 패키지를 추가하면 자동으로 tree shaking 적용

  • 많이 사용되는 대부분의 라이브러리들(ex: lodash 등)은 기본적으로 추가 되어있어 따로 적용하지 않아도됨

v13.1 < version < v13.5 사용 가능한 방법

 module.exports = {
   swcMinify: true,
    experimental: {
     modularizeImports: {
       antd: {
         transform: 'antd/lib/{{member}}',
       },
       lodash: {
         transform: 'lodash/{{member}}',         
       }
     }
   },
 }
  • experimental.modularizeImports 에 패키지와 transform할 형태 정의

빌드시--verborse 옵션을 추가하여 build시 실행시간을 측정할 수 있다.

npm run build --verborse

결론

Barrel < Barrel with [modularizeImports | optimizePackageImports] < default import

Barrel

  • Barrel 파일은 여러 모듈이나 파일을 하나의 집합으로 내보내기 위해 사용되는 파일을 가리킨다.

  • Barrel export pattern -> 여러 모듈이나 파일을 묶어서 간결하게 내보내는 디자인 패턴

PreviousComponentNextError Handling

Last updated 1 year ago