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
  • 리팩토링이 중요한 이유
  • 가독성
  • 유지보수성
  • 속도, 유연성 및 안정성 확보
  • 상속보다는 컴포지션 사용
  • 유연성
  • 리팩터링과 일상 업무
  • 학습 방법으로서의 리팩터링
  • 소프트웨어 분야에서 '도메인' 정의하기
  • 요약
  1. DEV_NOTE
  2. Refactoring

리팩토링 깊게 들여다보기

리팩토링이 중요한 이유

가독성

의도를 전달하기 위한 코드의 성질

코드가 의도한 대로 작동한다는 가정이 있으면 코드가 무슨 일을 하는지 파악하기가 매우 쉽다는 뜻

코드에서 의도를 전달하는 방법

  1. 코딩 컨벤션을 지정하고 따르는 것

  2. 주석 달기

  3. 변수 네이밍

  4. 메서드 네이밍

  5. 클래스 네이밍

읽기 힘든 코드

function checkValue(str: boolean) { //<- 바람직하지 않은 메서드명,인자명 
  // 값 체크 <- 그저 이름만 반복하는 주석
  
  if (str !== false) { // <- 이중 부정은 읽기 어려움
    // 반환 <- 쓸데 없는 주석
    return true
  } else {
    return str // <-이 시점에는 항상 false이기 때문에 그냥 fales로 표현하는 것이 더 명확함
  }
}

읽기 쉽게 작성된 동일 코드

function isTrue(bool: boolean) {
  if (bool) return true
  else return false
}

단순화한 동일 코드

function isTrue(bool: boolean) {
  return bool
}

유지보수성

버그를 고치거나 기능을 추가하기 위해 일부 기능을 변경해야 할 때마다 새 코드를 어디에 놓을지 후보 위치(context)를 조사하는 것으로 시작, 현재 코드가 무슨 일을 하는지 파악하고, 새로운 목표를 수용하기 위해 코드를 안전하고 빠르게 수정할 수 있는 방법은 무엇인지 찾으려고 시도한다.

유지보수성은 얼마나 많은 후보를 조사해야 하는지를 나타내는 표현이다.

읽고 살펴봐야 할 코드가 많아질수록 시간이 더 오래 걸리고 무언가를 놓칠 가능성이 높다. 따라서 유지보수성은 변경 시 발생하는 위험과 밀접하게 관련있다.

조사 단계에서 시간이 오래 걸린다는 것은 코드 유지보수성이 나쁘다는 징후이며 개선을 위해 노력해야 한다.

어떤 시스템에서 한군데서 무언가를 수정하면 관련 없어 보이는 다른 곳에서 문제가 발생한다. 그런 시스템을 취약하다(fragile)라고 표현한다.

불변속성과 전역상태

취약성의 근원은 일반적으로 전역상태(global state)이다.

여기서 전역(global)은 우리가 고려한 범위를 벗어난 것을 의미한다. (상태의 개념은 좀 더 추상적)

범위가 제한되지 않은 불변속성

  • 메서드로 생각하면 내부 변수가 전역 변수를 참조하는 것

  • 중괄호(스코프) 외부의 모든 것이 중괄호 내부의 모든 것에 대해 전역상태로 간주된다.

  • 데이터가 전역적일 경우 데이터가 연결된 다른 변수를 통해 누군가 읽거나 변경할 수 있어 실수로 데이터가 손상될 수 있다.

  • 코드에 상태(조건)를 명시적으로 확인하지 않는(가정설정문[assertion]으로만 확인하는) 속성을 불변속성(invariant)이라 한다.

    • e.g) 이 숫자는 절대 음수일 수 없다, 이 파일은 확실히 존재한다. 등

    • 시스템이 변경되거나 새로운 개발자가 합류될 때 불변속성이 유효한 상태로 유지되기란 거의 불가능

  • 변수를 명시적으로 체크해서 불변속성을 제거함으로써 유지보수성을 향상시킬 수 있다.

    • 리팩터링은 코드가 수행하는 작업이 변경되선 안되는데, 대신 이런 경우 불변속성을 더욱 쉽게 볼 수 있도록 서로 가깝게 이동시켜 유지보수성을 향상시킨다.

"함께 변하는 것은 함께 있어야 한다"는 의미의 불변속성의 범위제한(localizing invariants)이라고 한다.

코드가 하는 일을 바꾸지 않고 유지보수하기

  • 리팩터링 중에는 코드가 느려져도 거의 신경 쓰지 않는다.

    • 대부분의 시스템에서 성능은 가독성과 유지보수성보다 가치가 떨어진다.

    • 성능이 중요한 경우 프로파일링 도구나 성능 전문가의 지도를 받아 리팩토링과 다른 단계에서 처리해야 한다.

  • 리팩터링을 할 때는 블랙박스의 경계를 고려해야 한다.

    • 기본적으로 리팩터링 중인 코드를 예약해서 다른 사람이 변경하지 않게 해야한다.

    • 예약한 코드가 적을수록 변경 사항이 충돌할 위험이 낮아진다.

    • 따라서 적절한 리팩터링 범위를 결정하는 것은 어렵고 중요한 조정 작업이다.

리팩터링의 세 가지 핵심

  • 의도를 전달함으로써 가독성 향상

  • 불변속성의 범위제한을 통해 유지보수성 향상

  • 범위 밖의 코드에 영향을 주지 않고 1항과 2항을 수행

속도, 유연성 및 안정성 확보

리팩터링 패턴에는 구체적이고 지역적인(변수명 변경)것 부터 추상적이고 전역적인 것에 이르기까지 여러 수준이 있다

코드의 품질에 가장 큰 영향을 미치는 것은 역시 아키텍처 변경이다.

상속보다는 컴포지션 사용

범위가 제한되지 않은 불변속성을 도입하는 일반적인 방법인 상속을 권장하지 않고 컴포지션을 권장한다.

상속을 사용한 코드

interface Bird {
  hasBeak(): boolean
  canFly(): boolean
}

class CommonBird extends Bird {
  hasBeak() {return true}
  canFly() {return true}
}

class Penguin extends CommonBird {
  canFly() {return false}
}

컴포지션을 사용한 코드

interface Bird {
  hasBeak(): boolean
  canFly(): boolean
}

class CommonBird implements Bird {
  hasBeak() {return true}
  canFly() {return true}
}

class Penguin implements Bird {
  private bird = new CommonBird() // Composition
  hasBeak() { return bird.hasBeak()}
  canFly() { return false }
}
  • Bird에 새로운 메서드를 추가한다면 두 경우 모두 CommonBird에 메서드가 추가된다.

class CommonBird implements Bird {
  //...
  canSwim() {return false}
}
  • Penguin이 새로운 메서드 canSwim()을 구현하지 않았기 때문에 컴파일 오류가 발생

  • 따라서 이를 인지하고 수동으로 추가하고 펭귄이 수영할 수 있는지를 반환해야 한다.

    • Penguin이 다른 새처럼 동작하기를 원할 경우 hasBeak처럼 간단하게 구현 가능하다.

    • 반대로 수영할 수 없는 경우 canSwim()을 재정의(override)해야 한다는 것을 작업자가 기억해야 한다.

유연성

컴포지션을 중심으로 만들어진 시스템을 사용하면 다른 방식보다 더 깔끔하게 코드를 결합하고 재사용할 수 있다.

컴포지션을 많이 사용하는 시스템으로 작업하는 것은 레고 블록을 가지고 노는 것과 같다.

모든 것이 서로 맞게 조립돼 있으면 부품을 교체하거나 기존 부품으로 새로운 것을 만드는 것이 놀라울 정도로 빨라진다

이런 유연성(flexibility)은 대부분의 시스템이 원래 프로그래머가 상상하지 못했던 방식으로 사용된다는 것을 알게되면 더욱 중요해진다.

수정이 아닌 추가로 코드를 변경

컴포지션의 가장 큰 장점은 추가(additional)로 변경이 가능하다는 것이다.

  • 기존 기능에 영향을 주지 않고 기능을 추가하거나 변경할 수 있음을 의미한다.

  • 이 속성을 개방-폐쇄(open-closed) 원칙이라고 한다.

    • 소프트웨어 구성요소들은 확장에 대해 열려 있어야 하고, 수정에 대해 닫혀 있어야 한다는 의미

프로그래밍 속도

  • 새로운 것을 구현하거나 버그를 수정해야 할 때 가장 먼저 하는 일 중 하나가 주변 코드를 고려하여 아무것도 손상시키지 않는 것이다.

  • 이때 다른 코드를 건들지 않고 변경할 수 있다면 그 모든 시간을 아낄 수 있게된다.

  • 물론 계속해서 코드를 추가하면 코드베이스가 빠르게 늘어나 문제가 될수는 있다.

  • 어떤 코드가 사용되고 사용되지 않는지를 주의를 기울이고 사용하지 않는 코드는 빠르게 제거해야 한다.

안전성

  • 추가에 의한 변경 방식을 따르면 기존 코드를 항상 보존할 수 있다.

  • 새 코드가 실패할 경우 이전 기능으로 대체하는 기능을 구현하는것은 쉽다.

  • 이를 통해 기존 기능에 새로운 오류가 발생하지 않게 할 수 있는데 불변속성의 범위를 제한해 오류를 줄이는 것에 더해서 시스템의 안정성(stability)이 더욱 향상된다.

리팩터링과 일상 업무

리팩터링은 프로그래머의 일상 업무가 되어야 한다.

코드를 리팩터링하지 않고 그냥 전달하기만 하면 다른 프로그래머의 시간을 뻇는셈이 된다.

  • 열악한 소프트웨어 아키텍처는 이자가 붙는데 이를 기술부채(technical debt)라고한다.

    • 레거시 시스템에서는 변경하기 전에 먼저 리팩토링을하자.

    • 코드를 변경한 후에도 리팩터링을 하자.

코드를 전달하기 전 리팩터링을 수행하는 것을 다음과 같이 표현한다.

"항상 여러분이 왔을 때보다 더 좋게 만들어 놓고 떠나세요" - 보이스카우트 규칙

학습 방법으로서의 리팩터링

리팩터링은 배우는데 시간이 오래 걸리지만 결국 익숙해진다.

  • 더 나은 코드의 장점을 보고 경험하는 것은 코드를 작성하고 생각하는 방식을 바꾼다.

  • 안정성이 더 확보되면 이 안전성을 어떻게 활용할 수 있을지 생각하기 시작한다.

  • 리팩터링은 코드를 연구하는 완전히 다른 방법이다. (독특한 관점을 제공)

    • 코드를 이해하지 않고도 코드를 개선할 수 있는 방법도 있다.

    • 최소한의 코드 작업으로 매우 이해하기 쉬운 결과를 얻을 수 있다.

새로운 팀원이 합류하게 되면 입문용 작업으로 종종 리팩터링이 사용된다.

고객을 바로 상대하지 않고도 안전한 환경에서 코드를 활용해 학습가능하기 때문

좋은 관행이지만, 일상적인 리팩터링을 소홀히 한 경우에나 가능하다.

소프트웨어 분야에서 '도메인' 정의하기

도메인이란 실생활의 특정 측면을 모델링한 것

도메인에는 흔히 사용자와 전문가, 고유한 용어, 그리고 고유의 문화가 있다.

예시

  • 도메인: 2D 게임

  • 사용자: 플레이어

  • 도메인 전문가: 게임 또는 레벨 디자이너

  • 고유한 용어: 플레이어가 먹을 수 있는 '플럭스'와 같은 단어를 도입하여 게임이 자체 용어를 사용

  • 고유한 문화: 게임과 상호작용하는 방법에 대해 흔히 예상하고 있는 것들 (돌과 상자는 중력에 영향을 받지만 열쇠와 사용자는 그렇지 않은것처럼)

소프트웨어 개발할 때 도메인 전문가와 긴밀하게 협력해야 할 때가 많은데 이는 그들의 용어와 문화를 배워야 한다는 것을 의미한다.

프로그래밍 언어는 모호성을 허용하지 않기 때문에 떄떄로 전문가조차도 낯선 새로운 코너케이스(conner case)를 찾아야 한다. *(변수와 환경적인 요소로 인해 코드에 문제가 발생할 수 있는 경우를 의미)

요약

  • 리팩터링은 기능 변경 없이 코드의 의도를 전달하고 불변속성의 범위를 제한하는 것

  • 상속보다 컴포지션을 사용함으로써, 추가를 통한 변경으로 개발 속도, 유연성, 안정성을 확보

  • 리팩터링을 일상 업무에 포함시켜 기술 부채가 쌓이지 않도록 해야함

  • 리팩터링을 연습하면 코드에 대한 독특한 관점을 얻을 수 있으며, 이로 인해 더 나은 해결책을 찾을 수 있다.

PreviousRefactoringNext긴 코드 조각내기

Last updated 1 year ago