8.9 KiB
8.9 KiB
🚨 버튼 제어관리 기능 통합 - 잠재적 문제점 및 해결방안
📊 성능 관련 문제점
1. 버튼 클릭 시 지연 시간 증가
문제점:
- 기존 버튼은 단순한 액션만 수행 (50-100ms)
- 제어관리 추가 시 복합적인 처리로 인한 지연 가능성
- 데이터베이스 조건 검증: 100-300ms
- 복잡한 비즈니스 로직 실행: 500ms-2초
- 다중 테이블 업데이트: 1-5초
현재 코드에서 확인된 문제:
// InteractiveScreenViewer.tsx에서 버튼 클릭 처리가 동기적
const handleButtonClick = async () => {
// 기존에는 단순한 액션만
switch (actionType) {
case "save":
await handleSaveAction();
break; // ~100ms
// 제어관리 추가 시 복합 처리로 증가 예상
}
};
해결방안:
- 비동기 처리 + 로딩 상태
const [isExecuting, setIsExecuting] = useState(false);
const handleButtonClick = async () => {
setIsExecuting(true);
try {
// 제어관리 실행
} finally {
setIsExecuting(false);
}
};
- 백그라운드 실행 옵션
// 긴급하지 않은 제어관리는 백그라운드에서 실행
if (config.executionOptions?.asyncExecution) {
// 즉시 성공 응답
// 백그라운드에서 제어관리 실행
}
2. 메모리 사용량 증가
문제점:
- 각 버튼마다 제어관리 설정을 메모리에 보관
- 복잡한 조건/액션 설정으로 인한 메모리 사용량 증가
- 대량의 버튼이 있는 화면에서 메모리 부족 가능성
해결방안:
- 지연 로딩
// 제어관리 설정을 필요할 때만 로드
const loadDataflowConfig = useCallback(async () => {
if (config.enableDataflowControl && !dataflowConfig) {
const config = await apiClient.get(`/button-dataflow/config/${buttonId}`);
setDataflowConfig(config.data);
}
}, [buttonId, config.enableDataflowControl]);
- 설정 캐싱
// LRU 캐시로 자주 사용되는 설정만 메모리 보관
const configCache = new LRUCache({ max: 100, ttl: 300000 }); // 5분 TTL
3. 데이터베이스 성능 영향
문제점:
- 버튼 클릭마다 복잡한 SQL 쿼리 실행
- EventTriggerService의 현재 구조상 전체 관계도 스캔
// eventTriggerService.ts - 모든 관계도를 검색하는 비효율적인 쿼리
const diagrams = await prisma.$queryRaw`
SELECT * FROM dataflow_diagrams
WHERE company_code = ${companyCode}
AND (category::text = '"data-save"' OR ...)
`;
해결방안:
- 인덱스 최적화
-- 복합 인덱스 추가
CREATE INDEX idx_dataflow_button_lookup ON dataflow_diagrams
USING GIN ((control->'buttonId'))
WHERE category @> '["button-trigger"]';
- 캐싱 계층 추가
// 버튼별 제어관리 매핑을 캐시
const buttonDataflowCache = new Map<string, DataflowConfig[]>();
🔧 확장성 관련 문제점
4. 설정 복잡도 증가
문제점:
- 기존 단순한 버튼 설정에서 복잡한 제어관리 설정 추가
- 사용자 혼란 가능성
- UI가 너무 복잡해질 위험
현재 UI 구조 문제:
// ButtonConfigPanel.tsx가 이미 복잡함
return (
<div className="space-y-4">
{/* 기존 15개+ 설정 항목 */}
{/* + 제어관리 설정 추가 시 더욱 복잡해짐 */}
</div>
);
해결방안:
- 탭 구조로 분리
<Tabs defaultValue="basic">
<TabsList>
<TabsTrigger value="basic">기본 설정</TabsTrigger>
<TabsTrigger value="dataflow">제어관리</TabsTrigger>
<TabsTrigger value="advanced">고급 설정</TabsTrigger>
</TabsList>
<TabsContent value="basic">{/* 기존 설정 */}</TabsContent>
<TabsContent value="dataflow">{/* 제어관리 설정 */}</TabsContent>
</Tabs>
- 단계별 설정 마법사
const DataflowConfigWizard = () => {
const [step, setStep] = useState(1);
// 1단계: 활성화 여부
// 2단계: 실행 타이밍
// 3단계: 제어 모드
// 4단계: 상세 설정
};
5. 타입 안전성 문제
문제점:
- 기존 ButtonTypeConfig에 새로운 필드 추가로 인한 호환성 문제
- 런타임 오류 가능성
현재 타입 구조 문제:
// 기존 코드들이 ButtonTypeConfig의 새 필드를 모름
const config = component.webTypeConfig; // enableDataflowControl 없을 수 있음
if (config.enableDataflowControl) { // undefined 체크 필요
해결방안:
- 점진적 타입 확장
// 기존 타입은 유지하고 새로운 타입 정의
interface ExtendedButtonTypeConfig extends ButtonTypeConfig {
enableDataflowControl?: boolean;
dataflowConfig?: ButtonDataflowConfig;
dataflowTiming?: "before" | "after" | "replace";
}
// 타입 가드 함수
function hasDataflowConfig(
config: ButtonTypeConfig
): config is ExtendedButtonTypeConfig {
return "enableDataflowControl" in config;
}
- 마이그레이션 함수
const migrateButtonConfig = (
config: ButtonTypeConfig
): ExtendedButtonTypeConfig => {
return {
...config,
enableDataflowControl: false, // 기본값
dataflowConfig: undefined,
dataflowTiming: "after",
};
};
6. 버전 호환성 문제
문제점:
- 기존 저장된 버튼 설정과 새로운 구조 간 호환성
- 점진적 배포 시 일부 기능 불일치
해결방안:
- 버전 필드 추가
interface ButtonTypeConfig {
version?: "1.0" | "2.0"; // 제어관리 추가 버전
// ...기존 필드들
}
- 자동 마이그레이션
const migrateButtonConfig = (config: any) => {
if (!config.version || config.version === "1.0") {
return {
...config,
version: "2.0",
enableDataflowControl: false,
dataflowConfig: undefined,
};
}
return config;
};
🚫 보안 관련 문제점
7. 권한 검증 부재
문제점:
- 제어관리 실행 시 추가적인 권한 검증 없음
- 사용자가 설정한 제어관리를 통해 의도치 않은 데이터 조작 가능
해결방안:
- 제어관리 권한 체계
interface DataflowPermission {
canExecuteDataflow: boolean;
allowedTables: string[];
allowedActions: ("insert" | "update" | "delete")[];
}
const checkDataflowPermission = async (
userId: string,
dataflowConfig: ButtonDataflowConfig
): Promise<boolean> => {
// 사용자별 제어관리 권한 검증
};
- 실행 로그 및 감사
const logDataflowExecution = async (
userId: string,
buttonId: string,
dataflowResult: ExecutionResult
) => {
await prisma.dataflow_audit_log.create({
data: {
user_id: userId,
button_id: buttonId,
executed_actions: dataflowResult.executedActions,
execution_time: dataflowResult.executionTime,
timestamp: new Date(),
},
});
};
8. SQL 인젝션 위험
문제점:
- 고급 모드에서 사용자가 직접 조건 설정 시 SQL 인젝션 가능성
- 동적 테이블명, 필드명 처리 시 보안 취약점
해결방안:
- 화이트리스트 기반 검증
const ALLOWED_TABLES = ["user_info", "order_master" /* ... */];
const ALLOWED_OPERATORS = ["=", "!=", ">", "<", ">=", "<=", "LIKE"];
const validateDataflowConfig = (config: ButtonDataflowConfig) => {
if (config.directControl) {
if (!ALLOWED_TABLES.includes(config.directControl.sourceTable)) {
throw new Error("허용되지 않은 테이블입니다.");
}
// 추가 검증...
}
};
- 파라미터화된 쿼리 강제
// 모든 동적 쿼리를 파라미터화
const executeCondition = async (condition: DataflowCondition, data: any) => {
const query = `SELECT * FROM ${tableName} WHERE ${fieldName} ${operator} $1`;
return await prisma.$queryRaw(query, condition.value);
};
💡 권장 해결 전략
Phase 1: 안전한 시작 (MVP)
- 간편 모드만 구현 (기존 관계도 선택)
- "after" 타이밍만 지원 (기존 액션 후 실행)
- 기본적인 성능 최적화 (캐싱, 인덱스)
- 상세한 로깅 및 모니터링 추가
Phase 2: 점진적 확장
- 고급 모드 추가 (권한 검증 강화)
- "before", "replace" 타이밍 지원
- 성능 최적화 고도화 (비동기 실행, 큐잉)
- UI 개선 (탭, 마법사)
Phase 3: 고도화
- 배치 처리 지원
- 복잡한 비즈니스 로직 지원
- AI 기반 설정 추천
- 성능 대시보드
모니터링 지표
interface DataflowMetrics {
averageExecutionTime: number;
errorRate: number;
memoryUsage: number;
cacheHitRate: number;
userSatisfactionScore: number;
}
이러한 문제점들을 사전에 고려하여 설계하면 안정적이고 확장 가능한 시스템을 구축할 수 있습니다.