# 화면 임베딩 시스템 - 기존 시스템 충돌 분석 보고서

## 📋 분석 개요

새로 구현한 **화면 임베딩 및 데이터 전달 시스템**이 기존 화면 관리 시스템과 충돌할 가능성을 분석합니다.

---

## ✅ 충돌 없음 (안전한 부분)

### 1. 데이터베이스 스키마

#### 새로운 테이블 (독립적)

```sql
- screen_embedding          (신규)
- screen_data_transfer      (신규)
- screen_split_panel        (신규)
```

**충돌 없는 이유**:

- ✅ 완전히 새로운 테이블명
- ✅ 기존 테이블과 이름 중복 없음
- ✅ 외래키는 기존 `screen_definitions`만 참조 (읽기 전용)

#### 기존 테이블 (영향 없음)

```sql
- screen_definitions        (변경 없음)
- screen_layouts            (변경 없음)
- screen_widgets            (변경 없음)
- screen_templates          (변경 없음)
- screen_menu_assignments   (변경 없음)
```

**확인 사항**:

- ✅ 기존 테이블 구조 변경 없음
- ✅ 기존 데이터 마이그레이션 불필요
- ✅ 기존 쿼리 영향 없음

---

### 2. API 엔드포인트

#### 새로운 엔드포인트 (독립적)

```
POST   /api/screen-embedding
GET    /api/screen-embedding
PUT    /api/screen-embedding/:id
DELETE /api/screen-embedding/:id

POST   /api/screen-data-transfer
GET    /api/screen-data-transfer
PUT    /api/screen-data-transfer/:id
DELETE /api/screen-data-transfer/:id

POST   /api/screen-split-panel
GET    /api/screen-split-panel/:screenId
PUT    /api/screen-split-panel/:id
DELETE /api/screen-split-panel/:id
```

**충돌 없는 이유**:

- ✅ 기존 `/api/screen-management/*` 와 다른 경로
- ✅ 새로운 라우트 추가만 (기존 라우트 수정 없음)
- ✅ 독립적인 컨트롤러 파일

#### 기존 엔드포인트 (영향 없음)

```
/api/screen-management/*    (변경 없음)
/api/screen/*               (변경 없음)
/api/layouts/*              (변경 없음)
```

---

### 3. TypeScript 타입

#### 새로운 타입 파일 (독립적)

```typescript
frontend / types / screen - embedding.ts(신규);
```

**충돌 없는 이유**:

- ✅ 기존 `screen.ts`, `screen-management.ts` 와 별도 파일
- ✅ 타입명 중복 없음
- ✅ 독립적인 네임스페이스

#### 기존 타입 (영향 없음)

```typescript
frontend/types/screen.ts              (변경 없음)
frontend/types/screen-management.ts   (변경 없음)
backend-node/src/types/screen.ts      (변경 없음)
```

---

### 4. 프론트엔드 컴포넌트

#### 새로운 컴포넌트 (독립적)

```
frontend/components/screen-embedding/
  ├── EmbeddedScreen.tsx       (신규)
  ├── ScreenSplitPanel.tsx     (신규)
  └── index.ts                 (신규)
```

**충돌 없는 이유**:

- ✅ 별도 디렉토리 (`screen-embedding/`)
- ✅ 기존 컴포넌트 수정 없음
- ✅ 독립적으로 import 가능

#### 기존 컴포넌트 (영향 없음)

```
frontend/components/screen/          (변경 없음)
frontend/app/(main)/screens/[screenId]/page.tsx  (변경 없음)
```

---

## ⚠️ 주의 필요 (잠재적 충돌 가능성)

### 1. screen_definitions 테이블 참조

**현재 구조**:

```sql
-- 새 테이블들이 screen_definitions를 참조
CONSTRAINT fk_parent_screen FOREIGN KEY (parent_screen_id)
  REFERENCES screen_definitions(screen_id) ON DELETE CASCADE
```

**잠재적 문제**:

- ⚠️ 기존 화면 삭제 시 임베딩 설정도 함께 삭제됨 (CASCADE)
- ⚠️ 화면 ID 변경 시 임베딩 설정이 깨질 수 있음

**해결 방법**:

```sql
-- 이미 구현됨: ON DELETE CASCADE
-- 화면 삭제 시 자동으로 관련 임베딩도 삭제
-- 추가 조치 불필요
```

**권장 사항**:

- ✅ 화면 삭제 전 임베딩 사용 여부 확인 UI 추가 (Phase 6)
- ✅ 삭제 시 경고 메시지 표시

---

### 2. 화면 렌더링 로직

**현재 화면 렌더링**:

```typescript
// frontend/app/(main)/screens/[screenId]/page.tsx
function ScreenViewPage() {
  // 기존: 단일 화면 렌더링
  const screenId = parseInt(params.screenId as string);

  // 레이아웃 로드
  const layout = await screenApi.getScreenLayout(screenId);

  // 컴포넌트 렌더링
  <DynamicComponentRenderer components={layout.components} />;
}
```

**새로운 렌더링 (분할 패널)**:

```typescript
// 분할 패널 화면인 경우
if (isSplitPanelScreen) {
  const config = await getScreenSplitPanel(screenId);
  return <ScreenSplitPanel config={config} />;
}

// 일반 화면인 경우
return <DynamicComponentRenderer components={layout.components} />;
```

**잠재적 문제**:

- ⚠️ 화면 타입 구분 로직 필요
- ⚠️ 기존 화면 렌더링 로직 수정 필요

**해결 방법**:

```typescript
// 1. screen_definitions에 screen_type 컬럼 추가 (선택사항)
ALTER TABLE screen_definitions ADD COLUMN screen_type VARCHAR(20) DEFAULT 'normal';
-- 'normal', 'split_panel', 'embedded'

// 2. 또는 screen_split_panel 존재 여부로 판단
const splitPanelConfig = await getScreenSplitPanel(screenId);
if (splitPanelConfig.success && splitPanelConfig.data) {
  return <ScreenSplitPanel config={splitPanelConfig.data} />;
}
```

**권장 구현**:

```typescript
// frontend/app/(main)/screens/[screenId]/page.tsx 수정
useEffect(() => {
  const loadScreen = async () => {
    // 1. 분할 패널 확인
    const splitPanelResult = await getScreenSplitPanel(screenId);

    if (splitPanelResult.success && splitPanelResult.data) {
      // 분할 패널 화면
      setScreenType("split_panel");
      setSplitPanelConfig(splitPanelResult.data);
      return;
    }

    // 2. 일반 화면
    const screenResult = await screenApi.getScreen(screenId);
    const layoutResult = await screenApi.getScreenLayout(screenId);

    setScreenType("normal");
    setScreen(screenResult.data);
    setLayout(layoutResult.data);
  };

  loadScreen();
}, [screenId]);

// 렌더링
{
  screenType === "split_panel" && splitPanelConfig && (
    <ScreenSplitPanel config={splitPanelConfig} />
  );
}

{
  screenType === "normal" && layout && (
    <DynamicComponentRenderer components={layout.components} />
  );
}
```

---

### 3. 컴포넌트 등록 시스템

**현재 시스템**:

```typescript
// frontend/lib/registry/components.ts
const componentRegistry = new Map<string, ComponentDefinition>();

export function registerComponent(id: string, component: any) {
  componentRegistry.set(id, component);
}
```

**새로운 요구사항**:

```typescript
// DataReceivable 인터페이스 구현 필요
interface DataReceivable {
  componentId: string;
  componentType: ComponentType;
  receiveData(data: any[], mode: DataReceiveMode): Promise<void>;
  getData(): any;
  clearData(): void;
}
```

**잠재적 문제**:

- ⚠️ 기존 컴포넌트들이 DataReceivable 인터페이스 미구현
- ⚠️ 데이터 수신 기능 없음

**해결 방법**:

```typescript
// Phase 5에서 구현 예정
// 기존 컴포넌트를 래핑하는 어댑터 패턴 사용

class TableComponentAdapter implements DataReceivable {
  constructor(private tableComponent: any) {}

  async receiveData(data: any[], mode: DataReceiveMode) {
    if (mode === "append") {
      this.tableComponent.addRows(data);
    } else if (mode === "replace") {
      this.tableComponent.setRows(data);
    }
  }

  getData() {
    return this.tableComponent.getRows();
  }

  clearData() {
    this.tableComponent.clearRows();
  }
}
```

**권장 사항**:

- ✅ 기존 컴포넌트 수정 없이 어댑터로 래핑
- ✅ 점진적으로 DataReceivable 구현
- ✅ 하위 호환성 유지

---

## 🔧 필요한 수정 사항

### 1. 화면 페이지 수정 (필수)

**파일**: `frontend/app/(main)/screens/[screenId]/page.tsx`

**수정 내용**:

```typescript
import { getScreenSplitPanel } from "@/lib/api/screenEmbedding";
import { ScreenSplitPanel } from "@/components/screen-embedding";

function ScreenViewPage() {
  const [screenType, setScreenType] = useState<"normal" | "split_panel">(
    "normal"
  );
  const [splitPanelConfig, setSplitPanelConfig] = useState<any>(null);

  useEffect(() => {
    const loadScreen = async () => {
      // 분할 패널 확인
      const splitResult = await getScreenSplitPanel(screenId);

      if (splitResult.success && splitResult.data) {
        setScreenType("split_panel");
        setSplitPanelConfig(splitResult.data);
        setLoading(false);
        return;
      }

      // 일반 화면 로드 (기존 로직)
      // ...
    };

    loadScreen();
  }, [screenId]);

  // 렌더링
  if (screenType === "split_panel" && splitPanelConfig) {
    return <ScreenSplitPanel config={splitPanelConfig} />;
  }

  // 기존 렌더링 로직
  // ...
}
```

**영향도**: 중간 (기존 로직에 조건 추가)

---

### 2. 화면 관리 UI 수정 (선택사항)

**파일**: 화면 관리 페이지

**추가 기능**:

- 화면 생성 시 "분할 패널" 타입 선택
- 분할 패널 설정 UI
- 임베딩 설정 UI
- 데이터 매핑 설정 UI

**영향도**: 낮음 (새로운 UI 추가)

---

## 📊 충돌 위험도 평가

| 항목                 | 위험도  | 설명                | 조치 필요         |
| -------------------- | ------- | ------------------- | ----------------- |
| 데이터베이스 스키마  | 🟢 낮음 | 독립적인 새 테이블  | ❌ 불필요         |
| API 엔드포인트       | 🟢 낮음 | 새로운 경로 추가    | ❌ 불필요         |
| TypeScript 타입      | 🟢 낮음 | 별도 파일           | ❌ 불필요         |
| 프론트엔드 컴포넌트  | 🟢 낮음 | 별도 디렉토리       | ❌ 불필요         |
| 화면 렌더링 로직     | 🟡 중간 | 조건 분기 추가 필요 | ✅ 필요           |
| 컴포넌트 등록 시스템 | 🟡 중간 | 어댑터 패턴 필요    | ✅ 필요 (Phase 5) |
| 외래키 CASCADE       | 🟡 중간 | 화면 삭제 시 주의   | ⚠️ 주의           |

**전체 위험도**: 🟢 **낮음** (대부분 독립적)

---

## ✅ 안전성 체크리스트

### 데이터베이스

- [x] 새 테이블명이 기존과 중복되지 않음
- [x] 기존 테이블 구조 변경 없음
- [x] 외래키 CASCADE 설정 완료
- [x] 멀티테넌시 (company_code) 지원

### 백엔드

- [x] 새 라우트가 기존과 충돌하지 않음
- [x] 독립적인 컨트롤러 파일
- [x] 기존 API 수정 없음
- [x] 에러 핸들링 완료

### 프론트엔드

- [x] 새 컴포넌트가 별도 디렉토리
- [x] 기존 컴포넌트 수정 없음
- [x] 독립적인 타입 정의
- [ ] 화면 페이지 수정 필요 (조건 분기)

### 호환성

- [x] 기존 화면 동작 영향 없음
- [x] 하위 호환성 유지
- [ ] 컴포넌트 어댑터 구현 (Phase 5)

---

## 🎯 권장 조치 사항

### 즉시 조치 (필수)

1. **화면 페이지 수정**

   ```typescript
   // frontend/app/(main)/screens/[screenId]/page.tsx
   // 분할 패널 확인 로직 추가
   ```

2. **에러 처리 강화**
   ```typescript
   // 분할 패널 로드 실패 시 일반 화면으로 폴백
   try {
     const splitResult = await getScreenSplitPanel(screenId);
     if (splitResult.success) {
       return <ScreenSplitPanel />;
     }
   } catch (error) {
     // 일반 화면으로 폴백
   }
   ```

### 단계적 조치 (Phase 5-6)

1. **컴포넌트 어댑터 구현**

   - TableComponent → DataReceivable
   - InputComponent → DataReceivable
   - 기타 컴포넌트들

2. **설정 UI 개발**

   - 분할 패널 생성 UI
   - 매핑 규칙 설정 UI
   - 미리보기 기능

3. **테스트**
   - 기존 화면 정상 동작 확인
   - 분할 패널 화면 동작 확인
   - 화면 전환 테스트

---

## 📝 결론

### ✅ 안전성 평가: 높음

**이유**:

1. ✅ 대부분의 코드가 독립적으로 추가됨
2. ✅ 기존 시스템 수정 최소화
3. ✅ 하위 호환성 유지
4. ✅ 외래키 CASCADE로 데이터 무결성 보장

### ⚠️ 주의 사항

1. **화면 페이지 수정 필요**

   - 분할 패널 확인 로직 추가
   - 조건부 렌더링 구현

2. **점진적 구현 권장**

   - Phase 5: 컴포넌트 어댑터
   - Phase 6: 설정 UI
   - 단계별 테스트

3. **화면 삭제 시 주의**
   - 임베딩 사용 여부 확인
   - CASCADE로 자동 삭제됨

### 🎉 최종 결론

**충돌 위험도: 낮음 (🟢)**

새로운 시스템은 기존 시스템과 **독립적으로 동작**하며, 최소한의 수정만으로 통합 가능합니다. 화면 페이지에 조건 분기만 추가하면 바로 사용할 수 있습니다.
















