메뉴 여닫기
개인 메뉴 토글
로그인하지 않음
만약 지금 편집한다면 당신의 IP 주소가 공개될 수 있습니다.

DBA Tune

데브카페
Kokoksh88 (토론 | 기여)님의 2025년 11월 12일 (수) 23:44 판 (→‎DBA Tunes)
(차이) ← 이전 판 | 최신판 (차이) | 다음 판 → (차이)

DBA Tunes

    1. 프로그램 수정 가이드 - 핵심 요약

프로그램 구조


app.py                    # Flask 백엔드 서버 (API, 데이터베이스)
templates/index_ag.html   # 프론트엔드 메인 페이지
instance/sql_tuning.db    # SQLite 데이터베이스
uploads/                  # 첨부파일 저장 폴더

DBATunePjt/
├── app.py                          # Flask 백엔드 애플리케이션 메인 파일
├── requirements.txt                # Python 의존성 패키지 목록
├── init_db.py                      # 데이터베이스 초기화 스크립트
├── reset_db.py                     # 데이터베이스 초기화/리셋 스크립트
│
├── templates/                      # HTML 템플릿 디렉토리 (백엔드에서 렌더링)
│   ├── index_ag.html              # ⭐ 메인 UI (AG Grid 사용)
│   └── index_simple.html          # 간단한 대체 UI
│
├── static/                         # 정적 리소스 디렉토리
│   └── luckysheet/                # Luckysheet 라이브러리 (현재 미사용)
│
├── instance/                       # 인스턴스 데이터 디렉토리
│   └── sql_tuning.db             # SQLite 데이터베이스 파일
## 🔧 핵심 파일 상세 설명

### 1. **app.py** ⭐ (백엔드 핵심)

**역할**: Flask 웹 애플리케이션 서버 및 REST API 제공

#### 주요 구성 요소:

##### 📦 데이터베이스 모델 (ORM)

**TuningRequest 클래스** (`TN_REQ 테이블`)
- 튜닝 요청 정보를 저장하는 메인 테이블
- 필드 분류:
  - **기본 정보**: `REQ_NO` (PK), `REQ_USER`, `REQ_DT`, `DB_NAME`
  - **프로그램 정보**: `SQL_PROGRAM_ID`, `BUSINESS_TYPE`, `COLLECTION_TYPE`, `APP_SCREEN`
  - **실행 정보**: `ONLINE_BATCH`, `EXECUTION_FREQUENCY`, `DYNAMIC_SQL`
  - **SQL 정보**: `REQ_SQL_TEXT` (요청 SQL), `TUNED_SQL_TEXT` (완료 SQL)
  - **실행 계획**: `REQ_EXECUTION_PLAN`, `TUNED_EXECUTION_PLAN`
  - **성능 지표**: `TIME_BEFORE`, `TIME_AFTER` (응답속도), `BLOCKS_BEFORE`, `BLOCKS_AFTER`
  - **튜닝 상태**: `IMPROVEMENT_STATUS`, `HINT_APPLIED`, `INDEX_CREATED`, `SQL_CHANGED`
  - **개선율**: `IMPROVEMENT_RATE`, `COMPLETION_DATE`

**TuningAction 클래스** (`TN_ACTN 테이블`)
- 각 튜닝 요청에 대한 액션 내역 기록

##### 🔌 REST API 엔드포인트

| 메서드 | 엔드포인트 | 기능 |
|--------|----------|------|
| `GET` | `/` | 메인 페이지 (index.html) 렌더링 |
| `GET` | `/ag` | AG Grid 메인 페이지 (index_ag.html) 렌더링 |
| `GET` | `/api/requests` | 모든 튜닝 요청 조회 |
| `POST` | `/api/requests` | 새 튜닝 요청 생성 |
| `PUT` | `/api/requests/<id>` | 특정 튜닝 요청 업데이트 |
| `DELETE` | `/api/requests/<id>` | 특정 튜닝 요청 삭제 |
| `GET` | `/api/actions` | 모든 액션 조회 |
| `POST` | `/api/actions` | 새 액션 생성 |
| `POST` | `/api/init-sample` | 샘플 데이터 초기화 |

##### 🚀 애플리케이션 시작 로직

```python
if __name__ == '__main__':
    with app.app_context():
        db.create_all()  # 데이터베이스 테이블 생성
        # 데이터가 없으면 샘플 데이터 자동 추가
        if TuningRequest.query.count() == 0:
            # 샘플 데이터 삽입
    app.run(debug=True, host='0.0.0.0', port=5000)
```

**특징**:
- 자동 데이터베이스 초기화
- 서버 시작 시 샘플 데이터 자동 생성
- UTF-8 인코딩 지원 (한글 처리)
- CORS 활성화 (크로스 도메인 요청 허용)

---

### 2. **templates/index_ag.html** ⭐ (프론트엔드 핵심)

**역할**: 메인 UI 인터페이스 (AG Grid 데이터 그리드 기반)

#### 주요 기능:

##### 🎨 UI 컴포넌트

1. **헤더 (Header)**
   - 애플리케이션 제목: `[DBAWorks] SQL 튜닝 관리`
   - 네비게이션 메뉴: SQL 튜닝, 성능 관리, 디스크 관리, 오브젝트 관리, 권한 관리, 시스템 관리

2. **도구모음 (Toolbar)**
   - 새 요청 추가: 새로운 튜닝 요청 추가
   - 저장: 그리드 변경사항 저장
   - 새로고침: 데이터 다시 로드
   - CSV 내보내기: 데이터 내보내기
   - 샘플 데이터 초기화: 샘플 데이터 다시 로드
   - **동적 컬럼 표시 버튼**:
     - 요청정보 확인: 요청 관련 컬럼만 표시
     - 튜닝결과 확인: 결과 관련 컬럼만 표시
     - 전체보기: 모든 컬럼 표시
   - 검색박스: 데이터 검색 기능

3. **데이터 그리드 (AG Grid)**
   - 다중 선택 가능
   - 셀 편집 가능
   - 정렬/필터링 지원
   - 동적 컬럼 표시

4. **상세 정보 패널 (Detail Panel)**
   - 📋 요청 정보: 요청자, DB명, 프로그램ID, 비즈니스 유형 등
   - 💾 SQL 정보 (편집 가능):
     - 튜닝 요청 SQL
     - 튜닝 요청 SQL 실행계획
     - 튜닝 완료 SQL
     - 튜닝 완료 SQL 실행계획
     - 성능 개선 지표 (응답속도, Block 수)
   - 🔧 튜닝 정보 (편집 가능):
     - 개선여부
     - 힌트적용
     - INDEX생성
     - SQL변경

5. **모달 윈도우 (Modal)**
   - **새 요청 추가 모달**: 새로운 튜닝 요청 입력
     - 요청자, DB명, 프로그램ID 등 입력
     - SQL 입력 영역 (화면 50% 이상)
     - 닫기 버튼으로만 닫기 가능 (외부 클릭 시 닫히지 않음)

##### 📊 컬럼 정의 (columnDefs)

**기본 컬럼**:
- 선택 체크박스
- 상세보기 버튼
- 요청번호 (REQ_NO)
- 요청자 (REQ_USER)
- 요청일시 (REQ_DT)
- 개선여부 (IMPROVEMENT_STATUS)

**요청정보 컬럼**:
- DB명, 프로그램ID, 비즈니스 유형, 수집 유형, 애플리케이션 화면, 온라인/배치, 실행 빈도, 동적SQL

**튜닝결과 컬럼**:
- 개선여부, 힌트적용, INDEX생성, SQL변경, Block 전/후, 응답속도 전/후, 개선율, 완료일

##### ⚙️ 주요 JavaScript 함수

| 함수 | 설명 |
|------|------|
| `loadData()` | `/api/requests`에서 데이터 로드 (에러 처리 포함) |
| `addRow()` | 새 요청 추가 모달 열기 |
| `saveNewRequest()` | 새 요청 저장 (POST 요청) |
| `saveChanges()` | 그리드 변경사항 저장 (PUT 요청) |
| `saveDetailChanges()` | 상세 패널 변경사항 저장 |
| `showDetailPanel(rowData)` | 상세 정보 패널 표시 |
| `closeDetailPanel()` | 상세 정보 패널 닫기 |
| `showRequestColumns()` | 요청정보 컬럼만 표시 |
| `showResultColumns()` | 튜닝결과 컬럼만 표시 |
| `showAllColumns()` | 모든 컬럼 표시 |
| `reloadData()` | 데이터 새로고침 |
| `exportCsv()` | CSV로 내보내기 |
| `initSample()` | 샘플 데이터 초기화 |

##### 🎨 CSS 스타일

**색상 스킴**:
- 헤더 배경: `#243447` (어두운 파란색)
- 강조 색상: `#2563eb` (파란색)
- 성공 색상: `#10b981` (초록색)
- 경고 색상: `#ec4899` (분홍색)

**주요 클래스**:
- `.header`: 상단 헤더 스타일
- `.toolbar`: 도구 버튼 영역
- `.detail-panel`: 상세 정보 패널
- `.modal`: 모달 윈도우
- `.form-group`: 폼 입력 그룹

---

### 3. **run.bat** (Windows 실행 파일)

**역할**: Windows에서 프로그램을 쉽게 실행

#### 기능:
1. UTF-8 인코딩 설정 (한글 표시)
2. Python 설치 여부 확인
3. 가상환경 자동 생성/활성화
4. 필요한 패키지 자동 설치 (`requirements.txt`)
5. 애플리케이션 자동 시작
6. 사용자 친화적 메시지 출력 (4단계 진행률 표시)

#### 사용 방법:
```bash
더블클릭 또는 PowerShell에서:
run.bat
```

---

### 4. **run.sh** (macOS/Linux 실행 파일)

**역할**: macOS 및 Linux에서 프로그램을 쉽게 실행

#### 기능:
- Windows의 `run.bat`와 동일한 기능을 쉘 스크립트로 구현
- `python3` 및 `python` 자동 감지
- 가상환경 자동 설정
- ANSI 색상 코드로 다양한 메시지 표시

#### 사용 방법:
```bash
chmod +x run.sh  # 실행 권한 부여 (첫 번째만)
./run.sh         # 실행
```

---

### 5. **requirements.txt** (의존성 파일)

**역할**: Python 패키지 버전 명시

#### 주요 패키지:
```
Flask==2.3.3              # 웹 프레임워크
Flask-CORS==4.0.0         # CORS 지원
Flask-SQLAlchemy==3.0.5   # ORM 라이브러리
SQLAlchemy==2.0.21        # 데이터베이스 관리
```

---

### 6. **init_db.py** (데이터베이스 초기화)

**역할**: 데이터베이스 수동 초기화

#### 기능:
- 데이터베이스 테이블 생성
- 초기 샘플 데이터 삽입

#### 사용 방법:
```bash
python init_db.py
```

---

### 7. **reset_db.py** (데이터베이스 리셋)

**역할**: 데이터베이스 초기화 및 재설정

#### 기능:
- 기존 데이터베이스 삭제
- 새 데이터베이스 생성
- 샘플 데이터 다시 삽입

#### 사용 방법:
```bash
python reset_db.py
```

---

## 🗄️ 데이터베이스 구조

### TN_REQ 테이블 (튜닝 요청)

| 컬럼명 | 데이터타입 | 설명 | 예시 |
|--------|-----------|------|------|
| REQ_NO | INTEGER (PK) | 요청 번호 | 1 |
| REQ_USER | VARCHAR(100) | 요청자 | Kim |
| REQ_DT | DATETIME | 요청 일시 | 2024-11-12 10:30:00 |
| DB_NAME | VARCHAR(50) | 데이터베이스명 | Oracle |
| SQL_PROGRAM_ID | VARCHAR(200) | 프로그램ID | PGM001 |
| BUSINESS_TYPE | VARCHAR(50) | 비즈니스 유형 | Sales |
| COLLECTION_TYPE | VARCHAR(100) | 수집 유형 | Real-time |
| APP_SCREEN | VARCHAR(100) | 애플리케이션 화면 | Main |
| ONLINE_BATCH | VARCHAR(20) | 온라인/배치 | Online |
| EXECUTION_FREQUENCY | VARCHAR(50) | 실행 빈도 | Daily |
| DYNAMIC_SQL | VARCHAR(1) | 동적SQL 여부 | Y/N |
| REQ_SQL_TEXT | TEXT | 요청 SQL | SELECT * FROM ... |
| REQ_EXECUTION_PLAN | TEXT | 요청 SQL 실행계획 | EXPLAIN 결과 |
| TUNED_SQL_TEXT | TEXT | 튜닝 완료 SQL | SELECT ... WHERE ... |
| TUNED_EXECUTION_PLAN | TEXT | 완료 SQL 실행계획 | EXPLAIN 결과 |
| TIME_BEFORE | FLOAT | 응답속도 (전) | 1.5 초 |
| TIME_AFTER | FLOAT | 응답속도 (후) | 0.3 초 |
| BLOCKS_BEFORE | INTEGER | Block 수 (전) | 100 |
| BLOCKS_AFTER | INTEGER | Block 수 (후) | 50 |
| IMPROVEMENT_RATE | VARCHAR(50) | 개선율 | 5배 |
| IMPROVEMENT_STATUS | VARCHAR(1) | 개선 완료 여부 | Y/N |
| HINT_APPLIED | VARCHAR(1) | 힌트 적용 | Y/N |
| INDEX_CREATED | VARCHAR(1) | 인덱스 생성 | Y/N |
| SQL_CHANGED | VARCHAR(1) | SQL 변경 | Y/N |
| COMPLETION_DATE | DATE | 완료 날짜 | 2024-11-12 |

### TN_ACTN 테이블 (액션 내역)

| 컬럼명 | 데이터타입 | 설명 |
|--------|-----------|------|
| REQ_NO | INTEGER (FK) | 요청 번호 (참조) |
| ACTION_ID | INTEGER (PK) | 액션 ID |
| ACTION_TYPE | VARCHAR(50) | 액션 유형 |
| ACTION_DESC | TEXT | 액션 설명 |
| ACTION_DT | DATETIME | 액션 일시 |

---

## 🔄 데이터 흐름 (Data Flow)

```
┌─────────────┐
│   브라우저   │ (http://localhost:5000)
└──────┬──────┘
       │ JavaScript Fetch API
       ▼
┌─────────────────────────────────────┐
│   Flask 백엔드 (app.py)              │
│  ┌─────────────────────────────────┤
│  │ REST API Endpoints:              │
│  │ • GET  /api/requests             │
│  │ • POST /api/requests             │
│  │ • PUT  /api/requests/<id>        │
│  │ • DELETE /api/requests/<id>      │
│  └─────────────────────────────────┤
└──────┬──────────────────────────────┘
       │ SQL Queries
       ▼
┌─────────────────────────────┐
│   SQLite 데이터베이스       │
│  ┌──────────────────────┐  │
│  │ TN_REQ 테이블        │  │
│  │ (튜닝 요청)          │  │
│  ├──────────────────────┤  │
│  │ TN_ACTN 테이블       │  │
│  │ (액션 내역)          │  │
│  └──────────────────────┘  │
└─────────────────────────────┘
```

### 상세 데이터 흐름:

1. **데이터 조회**:
   ```
   브라우저 → loadData() → GET /api/requests → DB 쿼리 
   → JSON 응답 → AG Grid 표시
   ```

2. **새 요청 추가**:
   ```
   모달 입력 → saveNewRequest() → POST /api/requests 
   → DB INSERT → 그리드 새로고침
   ```

3. **데이터 업데이트**:
   ```
   그리드/패널 편집 → saveChanges()/saveDetailChanges() 
   → PUT /api/requests/<id> → DB UPDATE → 반영
   ```

---

## 🚀 애플리케이션 시작 프로세스

```
┌─────────────────────────────────────┐
│  run.bat / run.sh 실행              │
└────────────┬────────────────────────┘
             │
             ▼
┌─────────────────────────────────────┐
│ [1/4] Python 설치 확인              │
└────────────┬────────────────────────┘
             │
             ▼
┌─────────────────────────────────────┐
│ [2/4] 가상환경 생성/활성화          │
└────────────┬────────────────────────┘
             │
             ▼
┌─────────────────────────────────────┐
│ [3/4] 패키지 설치 (requirements.txt) │
└────────────┬────────────────────────┘
             │
             ▼
┌─────────────────────────────────────┐
│ [4/4] app.py 실행                   │
│ ├─ db.create_all()                  │
│ ├─ 샘플 데이터 확인                 │
│ └─ Flask 서버 시작 (포트 5000)      │
└────────────┬────────────────────────┘
             │
             ▼
┌─────────────────────────────────────┐
│ http://localhost:5000 접속 가능     │
└─────────────────────────────────────┘
```

---

## 📱 주요 기능 설명

### 1. 새 요청 추가 프로세스

```
1. "새 요청 추가" 버튼 클릭
   ↓
2. 모달 윈도우 열기 (addRequestModal)
   ├─ 요청자 입력
   ├─ DB명 입력
   ├─ 프로그램ID 입력
   ├─ 비즈니스 유형 선택
   ├─ ... (기타 필드)
   ├─ SQL 입력 (화면 50% 이상)
   │
3. "저장" 버튼 클릭
   ├─ 입력값 검증
   ├─ POST /api/requests 요청
   ├─ DB 저장
   │
4. 그리드 자동 새로고침
```

### 2. 상세 정보 확인 및 편집

```
1. 그리드에서 행 선택 또는 "상세보기" 버튼 클릭
   ↓
2. 상세 정보 패널 표시
   ├─ 📋 요청 정보 (읽기 전용)
   ├─ 💾 SQL 정보 (편집 가능)
   │  ├─ SQL 텍스트
   │  ├─ 실행 계획
   │  └─ 성능 지표
   ├─ 🔧 튜닝 정보 (편집 가능)
   │
3. 필요시 값 편집
   ↓
4. "💾 저장" 버튼 클릭
   ├─ 변경사항 수집
   ├─ PUT /api/requests/<id> 요청
   ├─ DB 업데이트
   │
5. 저장 완료 알림
```

### 3. 동적 컬럼 표시

```
"요청정보 확인" 버튼 클릭
├─ 기본 컬럼 유지
├─ 요청정보 컬럼만 표시
│  └─ DB명, 프로그램ID, 비즈니스 유형 등
│
"튜닝결과 확인" 버튼 클릭
├─ 기본 컬럼 유지
├─ 결과 컬럼만 표시
│  └─ 개선여부, 힌트적용, INDEX생성 등
│
"전체보기" 버튼 클릭
└─ 모든 컬럼 표시
```

---

## 🔐 보안 기능

1. **CORS 활성화**
   - Cross-Origin 요청 지원
   - 프론트엔드와 백엔드 분리 가능

2. **UTF-8 인코딩**
   - 한글 문자 안전 처리
   - 터미널 및 데이터베이스에서 정상 표시

3. **SECRET_KEY**
   - Flask 세션 보안
   - 쿠키 암호화

---

## 🐛 에러 처리

### 백엔드 (app.py)
```python
try:
    # API 로직
    data = [req.to_dict() for req in requests]
    return jsonify(data)
except Exception as e:
    # 오류 로깅
    print(f'[오류] {str(e)}')
    return jsonify({'error': str(e)}), 500
```

### 프론트엔드 (index_ag.html)
```javascript
try {
    const r = await fetch('/api/requests');
    if (!r.ok) {
        const errorText = await r.text();
        alert('데이터 로드 실패: ' + r.status);
        return;
    }
    const data = await r.json();
    gridOptions.api.setRowData(data);
} catch (err) {
    alert('오류 발생: ' + err.message);
    console.error(err);
}
```

---

## 📊 시스템 요구사항

### 최소 요구사항
- **OS**: Windows 10, macOS 10.14+, Linux (Ubuntu 18.04+)
- **Python**: 3.8 이상
- **RAM**: 512MB 이상
- **디스크**: 200MB 이상

### 권장 사양
- **OS**: Windows 11, macOS 12+, Ubuntu 22.04+
- **Python**: 3.10 이상
- **RAM**: 2GB 이상
- **디스크**: 1GB 이상

### 필요한 소프트웨어
- Python 3.8+
- 웹 브라우저 (Chrome, Firefox, Safari, Edge)

---

## 📝 파일별 수정 이력

### app.py
- UTF-8 인코딩 추가
- 새로운 컬럼 추가 (REQ_EXECUTION_PLAN, TUNED_EXECUTION_PLAN)
- 에러 처리 강화
- 자동 샘플 데이터 초기화

### index_ag.html
- AG Grid 도입
- 모달 기반 새 요청 추가
- 상세 정보 패널 (편집 가능)
- 동적 컬럼 관리
- 한글 입출력 지원

### run.bat
- UTF-8 인코딩 설정 (chcp 65001)
- 4단계 진행 표시
- Python 버전 감지
- 가상환경 자동 관리

### run.sh
- macOS/Linux 호환성
- Python3 자동 감지
- ANSI 색상 코드 사용

---

## 🎯 주요 API 응답 형식

### GET /api/requests 응답
```json
[
    {
        "REQ_NO": 1,
        "REQ_USER": "Kim",
        "REQ_DT": "2024-11-12 10:30:00",
        "DB_NAME": "Oracle",
        "SQL_PROGRAM_ID": "PGM001",
        "REQ_SQL_TEXT": "SELECT * FROM ...",
        "TUNED_SQL_TEXT": "SELECT ... WHERE ...",
        "REQ_EXECUTION_PLAN": "EXPLAIN 결과",
        "TUNED_EXECUTION_PLAN": "EXPLAIN 결과",
        "TIME_BEFORE": 1.5,
        "TIME_AFTER": 0.3,
        "BLOCKS_BEFORE": 100,
        "BLOCKS_AFTER": 50,
        "IMPROVEMENT_STATUS": "Y",
        ...
    }
]
```

### POST /api/requests 요청
```json
{
    "REQ_USER": "Kim",
    "DB_NAME": "Oracle",
    "SQL_PROGRAM_ID": "PGM001",
    "REQ_SQL_TEXT": "SELECT * FROM ...",
    ...
}
```

### PUT /api/requests/<id> 요청
```json
{
    "TUNED_SQL_TEXT": "SELECT ... WHERE ...",
    "REQ_EXECUTION_PLAN": "EXPLAIN 결과",
    "TIME_BEFORE": 1.5,
    "TIME_AFTER": 0.3,
    "IMPROVEMENT_STATUS": "Y",
    ...
}
```

---

## 🤝 개발 팀 노트

### 주요 설계 원칙
1. **모듈화**: 각 기능을 독립적으로 개발/유지보수
2. **확장성**: 새로운 기능 추가 용이
3. **사용자 친화**: 직관적인 UI/UX
4. **성능**: 빠른 데이터 로드 및 응답

### 향후 개선 계획
- 다중 언어 지원 (영어, 중국어 등)
- 고급 분석 및 리포팅
- 사용자 권한 관리
- 변경 이력 추적
- API 인증 (JWT)
- 데이터 내보내기 다양화 (Excel, PDF 등)

---

## 📞 문제 해결

### 포트 5000이 이미 사용 중인 경우
```bash
# 포트 변경
# app.py의 마지막 줄:
app.run(debug=True, host='0.0.0.0', port=5001)
```

### 데이터베이스 손상 시
```bash
python reset_db.py
```

### 패키지 설치 오류
```bash
pip install --upgrade pip
pip install -r requirements.txt --force-reinstall
```

### 한글 출력 오류 (Windows)
- `run.bat`는 자동으로 UTF-8 설정
- 수동 설정: `chcp 65001`

---

## 📚 참고 자료

### 사용 라이브러리 문서
- [Flask 공식 문서](https://flask.palletsprojects.com/)
- [SQLAlchemy 공식 문서](https://docs.sqlalchemy.org/)
- [AG Grid 공식 문서](https://www.ag-grid.com/)
- [Flask-CORS](https://flask-cors.readthedocs.io/)

### 튜토리얼
- Flask 기초: https://flask.palletsprojects.com/tutorial/
- SQLAlchemy 기초: https://docs.sqlalchemy.org/tutorial/
- AG Grid 시작: https://www.ag-grid.com/getting-started/

---

**마지막 수정**: 2024-11-12  
**버전**: 1.0.0  
**작성자**: DBAWorks Team

주요 수정 포인트

A. 데이터베이스 필드 추가

위치: `app.py` 24-82줄 (TuningRequest 클래스)

# 1. 필드 추가
class TuningRequest(db.Model):
    # ... 기존 필드들
    NEW_FIELD = db.Column(db.String(100))  # 새 필드 추가

# 2. to_dict() 메서드에 추가
def to_dict(self):
    return {
        # ... 기존 필드들
        'NEW_FIELD': self.NEW_FIELD,
    }


        1. B. 프론트엔드 컬럼 추가

위치: `index_ag.html` 227-238줄 (basicColumnDefs)


const basicColumnDefs = [
    // ... 기존 컬럼들
    { headerName: '새 컬럼', field: 'NEW_FIELD', width: 100, editable: true },
];


        1. C. 새 요청 모달에 입력 필드 추가

위치: `index_ag.html` 113-197줄 (새 요청 추가 모달)


<div class="form-field">
    <label>새 필드</label>
    <input type="text" id="formNewField" placeholder="새 필드 입력">
</div>


        1. D. 파일 크기 제한 변경

위치: `app.py` 15줄


app.config['MAX_CONTENT_LENGTH'] = 50 * 1024 * 1024  # 50MB로 변경


        1. E. 파일 타입 제한 추가

위치: `app.py` 276-318줄 (upload_attachment 함수)


ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'sql'}
file_extension = os.path.splitext(original_filename)[1][1:].lower()

if file_extension not in ALLOWED_EXTENSIONS:
    return jsonify({'error': '허용되지 않는 파일 타입입니다.'}), 400


주요 함수 위치

        1. 백엔드 (app.py)

- 요청 생성: 156-188줄 (`create_request`) - 요청 수정: 190-225줄 (`update_request`) - 요청 삭제: 227-232줄 (`delete_request`) - 파일 업로드: 276-318줄 (`upload_attachment`) - 파일 다운로드: 329-341줄 (`download_attachment`) - 파일 삭제: 343-361줄 (`delete_attachment`)

        1. 프론트엔드 (index_ag.html)

- 데이터 로드: 342-397줄 (`loadData`) - 새 요청 추가: 402-425줄 (`addRow`) - 새 요청 저장: 497-579줄 (`saveNewRequest`) - 파일 업로드: 471-495줄 (`uploadFiles`) - 상세 패널 표시: 809-1016줄 (`showDetailPanel`) - 상세 정보 저장: 757-807줄 (`saveDetailChanges`)

스타일 수정

위치: `index_ag.html` 9-76줄 (`<style>` 섹션)


/* 색상 변경 */
.btn-primary {
    background:#2563eb;  /* 파란색 */
}

/* 폰트 크기 변경 */
body {
    font-size: 14px;
}


API 엔드포인트 목록


GET    /api/requests                    # 요청 목록 조회
POST   /api/requests                    # 새 요청 생성
PUT    /api/requests/<req_no>           # 요청 수정
DELETE /api/requests/<req_no>           # 요청 삭제
GET    /api/requests/<req_no>/sql-text  # SQL 텍스트 조회
PUT    /api/requests/<req_no>/sql-text  # SQL 텍스트 수정
POST   /api/requests/<req_no>/attachments  # 파일 업로드
GET    /api/requests/<req_no>/attachments  # 파일 목록 조회
GET    /api/attachments/<attach_no>     # 파일 다운로드
DELETE /api/attachments/<attach_no>     # 파일 삭제
POST   /api/init-data                   # 샘플 데이터 초기화


데이터베이스 테이블

        1. TN_REQ (TuningRequest)

- 주요 필드: REQ_NO, REQ_USER, REQ_DT, SQL_PROGRAM_ID 등 - 관계: 첨부파일(1:N), 액션(1:1)

        1. TN_ATTACH (Attachment)

- 주요 필드: ATTACH_NO, REQ_NO, ORIGINAL_FILENAME, STORED_FILENAME - 관계: 요청(N:1)

        1. TN_ACTN (TuningAction)

- 주요 필드: REQ_NO, ACTION_DATE, ACTION_USER - 관계: 요청(1:1)

수정 시 주의사항

1. 데이터베이스 필드 추가 시

  - 기존 데이터는 NULL로 설정됨
  - 백업 후 수정 권장

2. 파일 업로드 시

  - 파일 크기 제한 확인 (기본 16MB)
  - 업로드 폴더 권한 확인

3. 프론트엔드 수정 시

  - JavaScript 함수명 중복 주의
  - HTML ID 중복 주의

4. API 수정 시

  - 응답 형식 일관성 유지
  - 에러 처리 추가 권장

빠른 수정 예시

        1. 예시 1: 새 필드 추가

# app.py - TuningRequest 클래스에 필드 추가
PRIORITY = db.Column(db.String(10))  # 우선순위

# app.py - to_dict() 메서드에 추가
'PRIORITY': self.PRIORITY,

# index_ag.html - 컬럼 추가
{ headerName: '우선순위', field: 'PRIORITY', width: 100, editable: true },

# index_ag.html - 모달에 입력 필드 추가
<div class="form-field">
    <label>우선순위</label>
    <select id="formPriority">
        <option value="높음">높음</option>
        <option value="보통">보통</option>
        <option value="낮음">낮음</option>
    </select>
</div>


        1. 예시 2: 파일 타입 제한

# app.py - upload_attachment 함수에 추가
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'sql', 'jpg', 'png'}
file_extension = os.path.splitext(original_filename)[1][1:].lower()

if file_extension not in ALLOWED_EXTENSIONS:
    return jsonify({'error': f'{file_extension} 파일은 허용되지 않습니다.'}), 400

Comments