카테고리 없음
[Design Patten] 관심사의 분리
고래강이
2023. 12. 11. 11:58
개요
- 주요 개념
- 관심사 분리의 장점
- 주의사항 및 요점
주요 개념
직교성)
A와 B가 직교하는 경우 A를 변경해도 B는 변경되지 않아야하며 반대상황도 마찬가지다.
ex) 라디오의 볼륨 조절과 채널 조절은 서로에게 영향을 주면 안된다.
이렇듯 좋은 React 애플리케이션 디자은은 다음과 같은 관심사가 직교한다.
- UI 요소 (presentaion component)
- 레이아웃 (layout)
- 데이터 페치 컴포넌트 (stateful)
- 데이터 렌더링 컴포넌트 (stateless)
- 서스펜스 / 에러바운더리 (statefull)
- 데이터 가져오기(fetch 라이브러리, REST or GraphQL)
- 글로벌 상태관리 (Redux, Recoil, ContextAPI)
- 영속성 로직 (localstorage, cookie...)
이러한 직교성을 통해서 변경사항은 격리되고 하나의 컴포넌트에 집중이 가능해 예측 가능하고 개발하기 쉬운 시스템을 만들 수 있다.
데이터를 가져오는 과정을 분리해보자)
import React, { useState } from 'react';
import axios from 'axios';
import EmployeesList from './EmployeesList';
function EmployeesPage() {
const [isFetching, setFetching] = useState(false);
const [employees, setEmployees] = useState([]);
useEffect(function fetch() {
(async function() {
setFetching(true);
const response = await axios.get("/employees");
setEmployees(response.data);
setFetching(false);
})();
}, []);
if (isFetching) {
return <div>Fetching employees....</div>;
}
return <EmployeesList employees={employees} />;
}
출처: https://itchallenger.tistory.com/541#google_vignette [Development & Investing:티스토리]
suspense를 이용해서 data fetch과정을 분리할 것임.
1. 완성
import React, { Suspense } from "react";
import EmployeesList from "./EmployeesList";
function EmployeesPage({ resource }) {
return (
<Suspense fallback={<h1>Fetching employees....</h1>}>
<EmployeesFetch resource={resource} />
</Suspense>
);
}
// fetch 로직을 포함한 컴포넌트
function EmployeesFetch({ resource }) {
const employees = resource.employees.read();
return <EmployeesList employees={employees} />;
}
출처: https://itchallenger.tistory.com/541#google_vignette [Development & Investing:티스토리]
UI와 hook을 분리해보자)
import React, { useState, useEffect } from 'react';
const DISTANCE = 500;
function ScrollToTop() {
const [crossed, setCrossed] = useState(false);
useEffect(
function() {
const handler = () => setCrossed(window.scrollY > DISTANCE);
handler();
window.addEventListener("scroll", handler);
return () => window.removeEventListener("scroll", handler);
},
[]
);
function onClick() {
window.scrollTo({
top: 0,
behavior: "smooth"
});
}
if (!crossed) {
return null;
}
return <button onClick={onClick}>Jump to top</button>;
}
출처: https://itchallenger.tistory.com/541#google_vignette [Development & Investing:티스토리]
UI로직과 스크롤 리스너 로직(useEffect 내부 로직)를 분리할 것임
1. hook을 통한 리스너 로직 분리
import { useState, useEffect } from 'react';
function useScrollDistance(distance) {
const [crossed, setCrossed] = useState(false);
useEffect(function() {
const handler = () => setCrossed(window.scrollY > distance);
handler();
window.addEventListener("scroll", handler);
return () => window.removeEventListener("scroll", handler);
}, [distance]);
return crossed;
}
출처: https://itchallenger.tistory.com/541#google_vignette [Development & Investing:티스토리]
2. UI로직
function onClick() {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
}
function JumpToTop() {
return <button onClick={onClick}>Jump to top</button>;
}
출처: https://itchallenger.tistory.com/541#google_vignette [Development & Investing:티스토리]
3. 격리를 위한 추가 컴포넌트
function IfScrollCrossed({ children, distance }) {
const isBottom = useScrollDistance(distance);
return isBottom ? children : null;
}
출처: https://itchallenger.tistory.com/541#google_vignette [Development & Investing:티스토리]
4. 완성
import React from 'react';
// ...
const DISTANCE_NEWSLETTER = 300;
function OtherComponent() {
// ...
return (
<IfScrollCrossed distance={DISTANCE_NEWSLETTER}>
<SubscribeToNewsletterForm />
</IfScrollCrossed>
);
}
출처: https://itchallenger.tistory.com/541#google_vignette [Development & Investing:티스토리]
변경될 수 있는 사항을 별도의 컴포넌트로 분리를 하는 것이 직교성의 핵심이다!
장점
- 모든 변경사항이 컴포넌트 내에 격리가 되어 쉽게 변경사항에 대해 쉽게 조절할 수 있다.
- 컴포넌트가 한 개의 역할만을 수행함에 따라 쉽게 이해할 수 있다.
- 단일 책임구현에만 집중을 하므로 컴포넌트가 올바르게 수행하는지 테스트 할 수 있다.
주의사항
직교 설계는 You aren't gonna need it 원칙에 따라 균형을 이루므로 실제로 필요할 때 구현하고 미리 구현하지 마세요!
- 극단적인 설계를 피하고 필요에 따라 생성하는 것이 좋다.
- 변화를 예측하고 필요한 부분을 파악하는 능력을 길러보자!
가장 좋은 디자인의 핵심 원칙은 가장 변경 될 가능성이 높은 논리를 분리하는 것임 그렇기에 로직이 직교하도록 만드는 것
이러한 직교를 통해서 변경사항이나 새로운 기능 요구에 유연하게 적응할 수 있다.
참고자료 : 블로그