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
  • 일급 값(first-class value)
  • 자바스크립트에서 일급 값
  • 어떤 문법이든 일급 함수로 바꿀 수 있다.
  • 일급 함수
  • 고차 함수(High-Order Function)
  • 일급 함수를 활용한 리팩토링
  • 리팩토링을 통해 얻는 것
  • 코드의 냄새를 맡는 방법
  • 코드 냄새: 함수 이름의 암묵적 인자
  • 리팩토링: 암묵적 인자 들어내기
  • 리팩토링: 함수 본문을 콜백으로 바꾸기
  • 리팩토링: 카피온 라이트 패턴 적용
  1. DEV_NOTE
  2. Funtional Programming

일급 함수

일급 값(first-class value)

변수에 할당할 수 있고 함수의 인자로 넘기거나, 반환값으로 사용할 수 있다.

즉, 코드로 다룰 수 있는 값을 의미

자바스크립트에서 일급 값

자바스크립트에서는 일급 값과 일급이 아닌 값이 섞여있다.

일급 값이 아닌 것

  • 조건 문

  • 반복 문

  • 수식 연산자

  • try/catch 블록

일급 값으로 할 수 있는 것

  • 변수에 할당

  • 배열이나 객체에 담기

  • 함수의 입력 값, 출력 값으로 넘기기

일급 값이 아닌 것들을 찾고 일급 값으로 바꾸는 기술은 함수형 프로그래밍에서 중요한 기술로 문제를 해결하는 새로운 능력을 얻게된다.

어떤 문법이든 일급 함수로 바꿀 수 있다.

자바스크립트에서 함수는 일급 값이므로 일급 값이 아닌 것들을 함수로 만들어 일급 값으로 바꿀 수 있다.

// +,- 일급 값이 아닌 수식연산자를 함수로 만들어 일급 값으로 변환
const plus = (a: number, b:number) => a + b;

일급 함수

일급 함수란 함수를 일급 값처럼 쓰이는 함수를 의미

고차 함수(High-Order Function)

일급 함수를 함수의 인자로 받거나 반환하는 함수로 일급 함수를 활용한 함수를 의미한다.

  • 고차함수로 패턴이나 원칙을 코드로 만들 수 있음

  • 고차함수를 사용하지 않으면 일일히 수작업으로 해줘야하 하는 부분이 생김

  • 고차함수는 한번 정의하고 필요한 곳에서 여러번 재사용 가능

  • 고차함수로 함수를 반환하는 함수를 만들 수 있다. 반환 받은 함수는 변수에 할당해서 이름이 있는 일반적인 함수처럼 사용이 가능하다.

  • 고차함수는 많은 중복 코드를 제거할 수 있지만, 가독성을 해칠 수 있다.

  • 코드에 반복되는 부분을 줄이기 위해 고차 함수를 사용하는 것이 중요

함수를 인자로 받는 고차함수는 반복적이지만 조금씩 다른 작업을 하는 코드에서 공통적인 부분을 함수로 하나의 함수로 추상화시키고 다른 작업을 하는 부분을 함수의 인자로 분리할 수 있기 때문에 재사용성이 높아짐

만약 고차 함수로 만든 좋은 방법을 찾았다면 직관적인 방법과 항상 비교해보자 코드가 더 읽기 쉬운지, 이해하기 쉬운지, 중복을 얼마나 제거했는지를 판단하여 적용하자

일급 함수를 활용한 리팩토링

리팩토링을 통해 얻는 것

  1. 표준화된 원칙

  2. 새로운 동작에 원칙을 적용할 수 있음

  3. 여러 개를 변경할 때 최적화

코드의 냄새를 맡는 방법

  1. 함수 구현부가 거의 똑같음

  2. 함수의 이름이구현의 차이를 만듦 → 함수의 이름에서 서로 다른 부분이 암묵적 인자이다.

코드의 냄새(Code Smell)는 더 큰 문제를 가져 올 수 있는 나쁜 코드를 의미한다.

코드 냄새: 함수 이름의 암묵적 인자

함수 본문에서 사용하는 어떤 값이 함수 이름에 나타난다면 함수 이름에 있는 암묵적 인자는 코드의 냄새가 된다.

  • 거의 똑같이 구현된 함수에서 함수의 이름이 구현부에 있는 다른 부분을 가리킨다.

  • 함수 이름의 암묵적 인자를 일급 값으로 바꾸면 표현력이 좋아짐

리팩토링: 암묵적 인자 들어내기

암묵적 인자가 일급 값이 되도록 함수 인자를 추가하여 잠재적인 중복을 없앨 수 있고, 코드의 목적을 더 잘 표현할 수 있게 됨

  1. 함수 이름에 있는 암묵적인 인자를 확인

  2. 명시적인 인자를 추가

  3. 함수 본문에 하드코딩된 값을 새로운 인자로 바꾼다.

  4. 함수 호출부를 리팩토링된 코드에 맞춰 수정한다.

Before

원래 가격만 설정하는 setPriceByName() 함수

// 함수 이름에 있는 price가 암묵적 인자가 된다.
const setPriceByName = (cart, name, price) => {  
  const item = cart[name];
  const newItem = objectSet(item, 'price', price);
  const newCart = objectSet(cart, name, newItem);
  
  return newCart;
}

// 사용하는 코드
cart = setPriceByName(cart, 'shoe', 13);
cart = setQuantityByName(cart, 'shoe', 3);
cart = setShippingName(cart, 'shoe', 0);
cart = setTaxByName(cart, 'shoe', 2.34);

Refactoring

어떤 필드값이든 설정할 수 있는 setFieldByName() 함수로 리팩토링 하자

리팩토링을 통해 비슷한 함수를 모두 일반적인 함수 하나로 변경

// 명시적인 인자를 추가하고 원래 인자는 더 일반적인 이름으로 변경
const setFieldByName = (cart, name, field, value) => {
  const item = cart[name];
  const newItem = objectSet(item, field, value);
  const newCart = objectSet(cart, name, newItem);
  
  return newCart;
}

cart = setFieldByName(cart, 'shoe', 'price', 13);
cart = setFieldByName(cart, 'shoe', 'quantity', 3);
cart = setFieldByName(cart, 'shoe', 'shipping', 0);
cart = setFieldByName(cart, 'shoe', 'tax', 2.34);

리팩토링: 함수 본문을 콜백으로 바꾸기

함수 본문에 비슷하지만 서로 다른 부분을 함수의 콜백 인자로 바꾼다.

  • 일급 함수의 특징을 이용하여 어떤 함수에 동작(함수)을 전달할 수 있게됨

  • 원래 코드를 고차함수로 만드는 강력한 방법

  1. 함수 구현부의 앞뒤로 바뀌지 않는 부분을 찾고, 리팩토링할 본문을 찾는다.

  2. 리팩토링할 코드를 함수로 추출한다.

  3. 추출한 함수를 인자로 전달받고 빼낸 함수 본문에 적용한다.

  4. 문법의 중복 및 코드 원칙 같은 다른 형태의 중복을 없앨때 탁월하다.

인자로 전달하는 함수를 콜백(Callback)함수라 부르며, 콜백으로 전달된 함수는 나중에 호출 될 것을 기대한다. 핸들러 함수라고도 불린다.

Before

// 모든 곳에서 같은 형태로 catch 구문을 사용한다.
try { // 앞부분
  saveUserData(user); // 본문 (달라지는 부분)
} catch (error) {  // 뒷부분
  logToSnapErrors(error);
}

// #2
try {
  fetchProduct(productId); // 달라지는 부분
} catch (error) {
  logToSnapErrors(error);
}

Refactoring

const withLogging = (f) => {
  try {
    f();
  } catch (error) {
    logToSnapErrors(error);
  }
}

함수의 인자로 일반 데이터를 전달하지 않고 함수를 전달하는 이유

함수로 전달하는 이유는 전달하는 함수 내부 코드가 특정 문맥 안에서 실행되어야 하기 때문이다.

고차함수를 활용하면 다른 곳에 정의된 문맥에서 코드를 실행시킬 수 있다. 그리고 문맥은 함수이기 때문에 재사용이 가능하다.

리팩토링: 카피온 라이트 패턴 적용

  1. 함수 본문의 앞부분과 뒷부분 확인하기

  2. 함수 빼내기

  3. 콜백 빼내기

Before

본문과 앞부분, 뒷부분을 확인해보면 카피-온-라이트가 적용된 두 함수는 비슷하다.


const arraySet = <T>(array: T[], idx: number, value: T) => {
  const copy = [...array];
  copy[idx] = value;
  return copy;
}

const push = <T>(array: T[], elem: T) => {
  const copy = [...array];
  copy.push(elem);
  return copy;
}

After

// #1 함수 빼내기 (리팩토링 할 코드를 함수로 빼는 단계)
const arraySet = <T>(array: T[], idx: number, value: T) => {
  return withArrayCopy(array);  
}

const withArrayCopy = <T>(array: T[]) => {
  const copy = [...array];
  copy[idx] = value;
  return copy;
}

// #2 콜백 빼내기 (본문을 콜백함수로 빼는 단계)
const arraySet = <T>(array: T[], idx: number, value: T) => {
  return withArrayCopy(array, (copy) => copy[idx] = value);  
}
// 카피-온-라이트 원칙을 따르고 재사용할 수 있는 함수
const withArrayCopy = <T>(array: T[], modfiy: (x: T[]) => void) => {
  const copy = [...array];
  modify(copy);
  return copy;
}

Previous불변성Next함수형 도구

Last updated 1 year ago