AI + Career
✅ 프론트엔드 코드의 유지보수성과 확장성을 높이기 위한 설계 패턴
octo54
2025. 5. 13. 11:58
반응형
✅ 프론트엔드 코드의 유지보수성과 확장성을 높이기 위한 설계 패턴
프론트엔드 개발에서 유지보수성과 확장성은 프로젝트 규모가 커질수록 더욱 중요해집니다.
코드가 복잡해질수록 재사용성, 구조화, 명확성을 확보하지 않으면 기능 추가나 수정이 어려워지기 때문입니다.
이번 글에서는 프론트엔드 개발에서 효과적인 설계 패턴을 소개하고,
실무 적용 사례와 코드 예제를 통해 이해를 돕겠습니다.
📌 1. 모듈 패턴 (Module Pattern)
✅ 개념
- 코드를 모듈화하여 데이터 은닉과 캡슐화를 실현
- 전역 네임스페이스 오염 방지
✅ 사용 사례
- 유틸리티 함수 집합
- 상태 관리 모듈
✅ 코드 예제
const CounterModule = (() => {
let count = 0;
const increment = () => count++;
const getCount = () => count;
return {
increment,
getCount
};
})();
CounterModule.increment();
console.log(CounterModule.getCount()); // 1
📌 2. 싱글톤 패턴 (Singleton Pattern)
✅ 개념
- 인스턴스를 하나만 생성하여 어디서나 동일한 객체를 사용
- 상태 관리나 전역 설정 관리에 유용
✅ 사용 사례
- 상태 관리 객체 (예: Redux Store)
- 전역 설정 관리
✅ 코드 예제
class AppConfig {
constructor() {
if (AppConfig.instance) return AppConfig.instance;
this.config = {};
AppConfig.instance = this;
}
set(key, value) {
this.config[key] = value;
}
get(key) {
return this.config[key];
}
}
const config1 = new AppConfig();
const config2 = new AppConfig();
console.log(config1 === config2); // true
📌 3. 프레젠테이션 패턴 (Presentation Pattern)
✅ 개념
- 비즈니스 로직과 UI 로직을 분리하여 컴포넌트를 독립적으로 설계
✅ 사용 사례
- React 컴포넌트 설계에서 자주 사용
✅ 코드 예제
// CounterView.tsx - 프레젠테이션 컴포넌트
export const CounterView = ({ count, onIncrement }) => (
<div>
<p>{count}</p>
<button onClick={onIncrement}>증가</button>
</div>
);
// CounterContainer.tsx - 컨테이너 컴포넌트
import { useState } from 'react';
import { CounterView } from './CounterView';
export const CounterContainer = () => {
const [count, setCount] = useState(0);
const increment = () => setCount(count + 1);
return <CounterView count={count} onIncrement={increment} />;
};
📌 4. 컨테이너-프레젠테이션 패턴 (Container-Presenter Pattern)
✅ 개념
- **로직 담당(컨테이너)**과 **UI 담당(프레젠테이션)**을 분리하여 역할 명확화
✅ 사용 사례
- Redux와 React를 함께 사용할 때 자주 적용
✅ 코드 예제
// CounterContainer.tsx
import { useSelector, useDispatch } from 'react-redux';
import { increment } from './counterSlice';
import { CounterView } from './CounterView';
export const CounterContainer = () => {
const count = useSelector((state) => state.counter.value);
const dispatch = useDispatch();
return <CounterView count={count} onIncrement={() => dispatch(increment())} />;
};
📌 5. HOC 패턴 (Higher-Order Component Pattern)
반응형
✅ 개념
- 컴포넌트를 인수로 받아 새로운 컴포넌트를 반환
- 재사용성과 코드 중복 감소
✅ 사용 사례
- 권한 검사 컴포넌트
- 로깅 또는 추적 기능 추가
✅ 코드 예제
function withAuth(Component) {
return function AuthenticatedComponent(props) {
if (!props.isAuthenticated) {
return <p>로그인이 필요합니다.</p>;
}
return <Component {...props} />;
};
}
const Profile = (props) => <p>{props.username}의 프로필</p>;
export const ProtectedProfile = withAuth(Profile);
📌 6. 커스텀 훅 패턴 (Custom Hook Pattern)
✅ 개념
- 반복되는 로직을 훅으로 분리하여 코드 재사용성 증가
✅ 사용 사례
- 폼 상태 관리
- 데이터 페칭
✅ 코드 예제
import { useState } from 'react';
function useToggle(initialValue = false) {
const [value, setValue] = useState(initialValue);
const toggle = () => setValue((prev) => !prev);
return [value, toggle];
}
function ToggleComponent() {
const [isOn, toggle] = useToggle();
return (
<button onClick={toggle}>
{isOn ? '켜짐' : '꺼짐'}
</button>
);
}
📌 7. 실무에서 겪은 문제와 해결
🧪 문제
컴포넌트와 비즈니스 로직이 섞여 있어서
기능 추가 시 수정 범위가 커지고, 테스트 코드 작성이 어려웠음
✅ 해결
- 컨테이너-프레젠테이션 패턴을 도입하여 역할을 명확히 분리
- Redux와 React 상태 관리를 구분하여 로직 변경 시 UI 코드에 영향 최소화
📌 면접에서 이렇게 답하세요
프론트엔드 프로젝트에서는 유지보수성과 확장성을 고려하여 다양한 설계 패턴을 적용합니다.
모듈 패턴과 싱글톤 패턴은 데이터 관리와 전역 설정에 유용하며,
React 프로젝트에서는 컨테이너-프레젠테이션 패턴과 커스텀 훅 패턴을 활용하여
로직과 UI를 분리함으로써 코드의 재사용성과 테스트 용이성을 높였습니다.
프론트엔드설계,React패턴,컨테이너패턴,HOC패턴,프레젠테이션패턴,커스텀훅,유지보수성,확장성,코드재사용성,프론트엔드면접