Definition
- 소프트웨어를 개발하는 과정의 반복되는 일반적인 문제들에 대해 기준이 되는 해결책을 제공하는 중요한 개념
- 소프트웨어의 특정 구현을 직접 제공하지는 않지만, 반복되는 문제 상황들을 최적화된 방법으로 해결하도록 돕는 컨셉
대부분의 software 문제는 이미 예전에 누군가는 겪은 문제 -> 이를 해결하기 위해 여러 방법을 사용 -> 그 방법들 중 이런 카테고리의 문제에는 어떤 방식이 좋은지 개발자들이 후기-> 자주 사용되는 공통된 패턴
Pros
1. 함께 일하는 동료들이 같은 패턴을 알고 있을수록 좋다.
- 다른 개발자나 같은 팀에 있는 사람과 패턴으로 의사소통하면 패턴 이름과 그 패턴에 담겨있는 모든 내용, 특성, 제약 조건 등을 함께 바로 이야기가 가능
2. 패턴 수준에서 이야기하면 '디자인'에 더 오랫동안 집중할 수 있다.
- 소프트웨어 시스템을 이야기할 때 패턴을 사용하면 객체와 클래스를 구현하는 것과 자질구레한 내용에 시간을 버릴 필요가 없어서 디자인 수준에서 초점을 맞춰 작업 가능
3. 전문용어를 사용하면 개발팀의 능력을 극대화할 수 있다.
- 디자인 패턴 용어를 모든 팀원이 잘 알고 있다면 오해의 소지가 줄어 작업을 빠르게 진행 가능
Cons
1. 지나친 복잡성
2. 과도한 추상화
3. 잘못된 패턴 선택
Render Props or HOC Pattern이 궁금하다면?
Compound component pattern
- Select과 Option 컴포넌트들과 같이 부모와 자식컴포넌트의 조합으로 이루어진 복잡한 컴포넌트를 작성할 때 사용하는 패턴
- 부모와 자식 컴포넌트 간의 상태 공유를 할 때 React Context API를 사용
Example
FlyOut 컴포넌트
1. 토글 버튼과 List를 가지고 있는 FlyOut wrapper
2. List를 토글하는 Toggle 버튼
3. 메뉴 아이템을 가지고 있는 List
[보통의 순서]
1. 컨텍스트를 생성합니다.
2. 부모 컴포넌트 코드를 작성합니다.
3. 자식 컴포넌트 코드를 작성합니다.
4. 자식 컴포넌트를 부모컴포넌트의 프로퍼티로 할당합니다.
Code
1. 컨텍스트 생성 + 부모 컴포넌트
const FlyOutContext = createContext();
function FlyOut(props) {
const [open, toggle] = useState(false);
const providerValue = { open, toggle };
return (
<FlyOutContext.Provider value={providerValue}>
{props.children}
</FlyOutContext.Provider>
);
}
- 이 컴포넌트는 상태를 가지고 있고, 모든 children에게 전달 할 toggle value를 가지고 있는 FlyOutProvider를 리턴
2. Toggle 자식 컴포넌트
function Toggle() {
const { open, toggle } = useContext(FlyOutContext);
return (
<div onClick={() => toggle(!open)}>
<Icon />
</div>
);
}
- Toggle 컴포넌트는 단순히 유저가 메뉴를 토글하기 위해 클릭할 수 있는 컴포넌트
- 토글에 관련된 이벤트만 위치, 부모에서 만든 컨텍스트를 가지고 와서 사용
const FlyOutContext = createContext();
function FlyOut(props) {
const [open, toggle] = useState(false);
return (
<FlyOutContext.Provider value={{ open, toggle }}>
{props.children}
</FlyOutContext.Provider>
);
}
function Toggle() {
const { open, toggle } = useContext(FlyOutContext);
return (
<div onClick={() => toggle(!open)}>
<Icon />
</div>
);
}
FlyOut.Toggle = Toggle;
- FlyOut 부모 컴포넌트와 Toggle 자식 컴포넌트를 같은 파일에 위치
- Toggel 컴포넌트를 FlyOut 컴포넌트의 속성으로 만듬
- FlyOut이 품고있는 속성을 사용하려고 할 때, FlyOut만을 import해서 사용
import React from "react";
import { FlyOut } from "./FlyOut";
export default function FlyoutMenu() {
return (
<FlyOut>
<FlyOut.Toggle />
</FlyOut>
);
}
3. List 자식 컴포넌트
function List({ children }) {
const { open } = React.useContext(FlyOutContext);
return open && <ul>{children}</ul>;
}
function Item({ children }) {
return <li>{children}</li>;
}
- open이라는 value를 바탕으로 열리고 닫히는 값이 필요
- list 아이템을 가진 List 컴포넌트
const FlyOutContext = createContext();
function FlyOut(props) {
const [open, toggle] = useState(false);
return (
<FlyOutContext.Provider value={{ open, toggle }}>
{props.children}
</FlyOutContext.Provider>
);
}
function Toggle() {
const { open, toggle } = useContext(FlyOutContext);
return (
<div onClick={() => toggle(!open)}>
<Icon />
</div>
);
}
function List({ children }) {
const { open } = useContext(FlyOutContext);
return open && <ul>{children}</ul>;
}
function Item({ children }) {
return <li>{children}</li>;
}
FlyOut.Toggle = Toggle;
FlyOut.List = List;
FlyOut.Item = Item;
- FlyOut 부모 컴포넌트와 List,Item 자식 컴포넌트를 같은 파일에 위치 (위와 동일)
- List,Item 컴포넌트를 FlyOut 컴포넌트의 속성으로 만듬 (위와 동일)
- FlyOut이 품고있는 속성을 사용하려고 할 때, FlyOut만을 import해서 사용 (위와 동일)
4. FlyoutMenu 컴포넌트
import React from "react";
import { FlyOut } from "./FlyOut";
export default function FlyoutMenu() {
return (
<FlyOut>
<FlyOut.Toggle />
<FlyOut.List>
<FlyOut.Item>Edit</FlyOut.Item>
<FlyOut.Item>Delete</FlyOut.Item>
</FlyOut.List>
</FlyOut>
);
}
< 참고자료 >
[사이트] #Patterns-dev-kr
[사이트] #Medium
<React> Design Patterns - Compound component pattern end
'Language & Framework & Library > React' 카테고리의 다른 글
useEffect 완벽 가이드 2편 (1) | 2023.10.29 |
---|---|
useEffect 완벽 가이드 1편 (1) | 2023.10.29 |
Re-rendering과 memoization (2) | 2022.03.13 |
컴포넌트 Re-rendering을 피하는 5가지 방법 (0) | 2022.03.13 |
React vs Vue (2) | 2021.07.13 |