OCP๋ฅผ ์๋ฐํ๋ Button ์ปดํฌ๋ํธ(์ํฐํจํด)
๊ด๋ จ ํค์๋
OCP ์๋ฐ
Button ์ปดํฌ๋ํธ
๋จผ์ , ์๋ก์ด ๋ฒํผ variant๋ฅผ ์ถ๊ฐํ ๋๋ง๋ค ๊ธฐ์กด ์ฝ๋๋ฅผ ์์ ํด์ผ ํ๋ ์ํฐํจํด์ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์ด ๋ฐฉ์์ OCP๋ฅผ ์๋ฐํ๋ฉฐ ์ ์ง๋ณด์์ฑ์ ๋จ์ด๋จ๋ฆฝ๋๋ค.
// ์ํฐํจํด: OCP๋ฅผ ์๋ฐํ๋ Button ์ปดํฌ๋ํธ
function Button({ variant, children, ...props }) {
let className = 'button';
if (variant === 'primary') {
className += ' button--primary';
} else if (variant === 'secondary') {
className += ' button--secondary';
} else if (variant === 'danger') {
className += ' button--danger';
}
return (
<button className={className} {...props}>
{children}
</button>
);
}
// ์ฌ์ฉ ์์
<Button variant="primary">Primary Button</Button>
<Button variant="secondary">Secondary Button</Button>
<Button variant="danger">Danger Button</Button>๐ ๋ฌธ์ ์
- ์๋ก์ด variant (์: success)๋ฅผ ์ถ๊ฐํ๋ ค๋ฉด Button ์ปดํฌ๋ํธ ๋ด๋ถ์ if-else ๋ก์ง์ ์์ ํด์ผ ํจ.
- ์ด๋ OCP์ "๋ณ๊ฒฝ์ ๋ซํ ์์ด์ผ ํ๋ค"๋ฅผ ์๋ฐ.
- ์ฝ๋๊ฐ ๋ณต์กํด์ง๊ณ , ์๋ก์ด ์๊ตฌ์ฌํญ์ด ์๊ธธ ๋๋ง๋ค ๊ธฐ์กด ์ฝ๋ ์์ ์ด ๋ถ๊ฐํผํด์ง.
OCP๋ฅผ ์ค์ํ๋ ๋ฆฌํฉํฐ๋ง ButtonBase ์ปดํฌ๋ํธ
๊ด๋ จ ํค์๋
OCP ์ค์
ButtonBase ์ปดํฌ๋ํธ
OCP๋ฅผ ์ค์ํ๊ธฐ ์ํด ButtonBase๋ผ๋ ๊ธฐ๋ณธ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค๊ณ , ์ด๋ฅผ ํ์ฅํ์ฌ ๋ค์ํ ๋ฒํผ ๋ณํ์ ์์ฑํ๋ ๋ฐฉ์์ผ๋ก ๋ฆฌํฉํฐ๋งํฉ๋๋ค. ์ด๋ฅผ ํตํด ์๋ก์ด variant๋ฅผ ์ถ๊ฐํ ๋ ๊ธฐ์กด ์ฝ๋๋ฅผ ์์ ํ์ง ์๊ณ ๋ ํ์ฅ์ด ๊ฐ๋ฅํด์ง๋๋ค.
// ๊ธฐ๋ณธ ์ปดํฌ๋ํธ ButtonBase
function ButtonBase({ className, children, ...props }) {
return (
<button className={`button ${className}`} {...props}>
{children}
</button>
);
}
// ํ์ฅ๋ ๋ฒํผ ์ปดํฌ๋ํธ๋ค
const PrimaryButton = ({ children, ...props }) => (
<ButtonBase className="button--primary" {...props}>
{children}
</ButtonBase>
);
const SecondaryButton = ({ children, ...props }) => (
<ButtonBase className="button--secondary" {...props}>
{children}
</ButtonBase>
);
const DangerButton = ({ children, ...props }) => (
<ButtonBase className="button--danger" {...props}>
{children}
</ButtonBase>
);
// ์ฌ์ฉ ์์
<PrimaryButton>Primary Button</PrimaryButton>
<SecondaryButton>Secondary Button</SecondaryButton>
<DangerButton>Danger Button</DangerButton>
// ์๋ก์ด SuccessButton ์ถ๊ฐ (๊ธฐ์กด ์ฝ๋ ์์ ์์ด ๊ฐ๋ฅ)
const SuccessButton = ({ children, ...props }) => (
<ButtonBase className="button--success" {...props}>
{children}
</ButtonBase>
);๐ ์ฅ์
- ํ์ฅ์ฑ: ์๋ก์ด ๋ฒํผ ๋ณํ(์: SuccessButton)์ ์ถ๊ฐํ ๋ ButtonBase๋ ๊ธฐ์กด ์ปดํฌ๋ํธ๋ฅผ ์์ ํ์ง ์์๋ ๋จ.
- ์ ์ง๋ณด์์ฑ: ๊ฐ ๋ฒํผ ๋ณํ์ด ๋ ๋ฆฝ์ ์ด์ด์ ์ฝ๋๊ฐ ๊ฐ๊ฒฐํ๊ณ ๊ด๋ฆฌํ๊ธฐ ์ฌ์.
- OCP ์ค์: ์๋ก์ด ๊ธฐ๋ฅ์ ์ถ๊ฐํ๊ธฐ ์ํด ๊ธฐ์กด ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ ํ์ฅ ๊ฐ๋ฅ.
์ปดํฌ๋ํธ ํฉ์ฑ ํจํด Card ์ปดํฌ๋ํธ
๊ด๋ จ ํค์๋
์ปดํฌ๋ํธ ํฉ์ฑ ํจํด
OCP๋ฅผ ์ค์ํ๋ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์ปดํฌ๋ํธ ํฉ์ฑ ํจํด์ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค. Card ์ปดํฌ๋ํธ๋ฅผ ์๋ก ๋ค์ด, ๋ค์ํ ์ฝํ
์ธ ๋ฅผ ์ ์ฐํ๊ฒ ํ์ฅํ ์ ์๋๋ก ์ค๊ณํด ๋ณด๊ฒ ์ต๋๋ค.
๐ ๊ธฐ๋ณธ Card ์ปดํฌ๋ํธ
function Card({ header, body, footer, ...props }) {
return (
<div className="card" {...props}>
{header && <div className="card-header">{header}</div>}
{body && <div className="card-body">{body}</div>}
{footer && <div className="card-footer">{footer}</div>}
</div>
);
}
// ์ฌ์ฉ ์์
<Card
header={<h2>Card Title</h2>}
body={<p>This is the card content.</p>}
footer={<PrimaryButton>Action</PrimaryButton>}
/>๐ ์๋ก์ด ํ์ฅ: ์ด๋ฏธ์ง ํฌํจ Card
const ImageCard = ({ image, ...props }) => (
<Card
header={image && <img src={image} alt="Card Image" className="card-image" />}
{...props}
/>
);
// ์ฌ์ฉ ์์
<ImageCard
image="https://example.com/image.jpg"
body={<p>This is an image card.</p>}
footer={<SecondaryButton>Learn More</SecondaryButton>}
/>๐ ์ฅ์
- ์ ์ฐ์ฑ: Card ์ปดํฌ๋ํธ๋ ๋ค์ํ ์ฝํ ์ธ (ํค๋, ๋ฐ๋, ํธํฐ)๋ฅผ ์กฐํฉํ์ฌ ํ์ฅ ๊ฐ๋ฅ.
- ์ฌ์ฌ์ฉ์ฑ: ImageCard์ ๊ฐ์ ์๋ก์ด ์ปดํฌ๋ํธ๋ฅผ ๊ธฐ์กด Card๋ฅผ ํ์ฉํด ์ฝ๊ฒ ์์ฑ.
- OCP ์ค์: ์๋ก์ด Card ๋ณํ์ ์ถ๊ฐํ ๋ ๊ธฐ์กด Card ์ปดํฌ๋ํธ๋ฅผ ์์ ํ ํ์ ์์.
๊ณ ์ฐจ ์ปดํฌ๋ํธ(HOC)๋ฅผ ํตํ ํ์ฅ
๊ณ ์ฐจ ์ปดํฌ๋ํธ(HOC)๋ฅผ ์ฌ์ฉํ๋ฉด ๊ธฐ์กด ์ปดํฌ๋ํธ์ ์๋ก์ด ๊ธฐ๋ฅ์ ์ถ๊ฐํ์ฌ OCP๋ฅผ ์ค์ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๋ฒํผ์ ๋ก๋ฉ ์ํ๋ฅผ ์ถ๊ฐํ๋ HOC๋ฅผ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.
// HOC: ๋ก๋ฉ ์ํ๋ฅผ ์ถ๊ฐ
function withLoading(Component) {
return function LoadingComponent({ isLoading, children, ...props }) {
return (
<Component {...props} disabled={isLoading}>
{isLoading ? 'Loading...' : children}
</Component>
);
};
}
// ๋ก๋ฉ ๊ฐ๋ฅํ ๋ฒํผ ์์ฑ
const LoadingPrimaryButton = withLoading(PrimaryButton);
const LoadingSecondaryButton = withLoading(SecondaryButton);
// ์ฌ์ฉ ์์
<LoadingPrimaryButton isLoading={true}>Click Me</LoadingPrimaryButton>
<LoadingSecondaryButton isLoading={false}>Click Me</LoadingSecondaryButton>๐ ์ฅ์
- ๊ธฐ๋ฅ ํ์ฅ: withLoading HOC๋ฅผ ํตํด ๊ธฐ์กด ๋ฒํผ ์ปดํฌ๋ํธ์ ๋ก๋ฉ ๊ธฐ๋ฅ์ ์ถ๊ฐ.
- OCP ์ค์: ๊ธฐ์กด PrimaryButton์ด๋ SecondaryButton ์ฝ๋๋ฅผ ์์ ํ์ง ์๊ณ ์๋ก์ด ๊ธฐ๋ฅ ์ถ๊ฐ ๊ฐ๋ฅ.
- ์ฌ์ฌ์ฉ์ฑ: HOC๋ ๋ค๋ฅธ ์ปดํฌ๋ํธ์๋ ์ ์ฉ ๊ฐ๋ฅ.