# (주)삼안 ERP 및 그룹웨어 시스템 (Satis) 하이레벨 아키텍처 명세서
본 문서는 (주)삼안의 **ERP 시스템(`Satis`)** 프로젝트의 전체 하이레벨 아키텍처(HLA) 명세서입니다.
시스템 개요, 계층 구조, 기술 스택, 업무 도메인, **인프라/배포, 보안/인증, 외부 시스템 연동, 프론트엔드 아키텍처, 개발 운영 구조**를 종합적으로 포함합니다.
*(압축파일 `*.zip`은 분석에서 제외하였습니다.)*
---
## 1. 프로젝트 개요 (Project Overview)
| 항목 | 내용 |
| :--- | :--- |
| **프로젝트명** | 삼안 ERP (`Satis`) |
| **운영 도메인** | `satis.samaneng.com`, `erp.samaneng.com` |
| **시스템 성격** | 엔지니어링/건설 분야 기업 자원 관리(ERP) |
| **회사명** | (주)삼안 |
| **사업자등록번호** | 211-81-25425 |
| **시스템 식별코드** | `SAMAN` |
| **주요 기능** | 인사/급여, 회계/전표, 프로젝트/공정, 영업/기성, 전자결재, 고정자산, 출장정산, 경영분석 |
| **DB 연동** | Oracle(메인 ERP), MS-SQL(더존 iCube ERP), MySQL(사내 인트라넷) |
---
## 2. 하이레벨 시스템 아키텍처 (High-Level System Architecture)
```mermaid
graph TD
subgraph "Client Tier"
Browser["Web Browser
(HTML5, jQuery, jqGrid, w2ui, amCharts)"]
end
subgraph "Web / Presentation Tier"
WebServer["Web Server
(Windows Server / APM_Setup / Apache)"]
Smarty["Smarty Template Engine v2.6
(Smarty/templates/Satis/*.tpl)"]
end
subgraph "Application Tier"
Controller["MVC Controllers
(Satis/sys/controller/*)"]
AuthModule["Security & Auth Engine
(AuthClass.php / LoginInfomation.php)"]
BizLogic["Business Logic Models
(Satis/sys/model/*)"]
CommonUtil["공통 유틸리티
(OracleClass.php / CommonCodeList.php)"]
end
subgraph "Data & Integration Tier"
OracleDB[("Oracle DB (Main ERP)
TNS: samandb
User: satis")]
iCubeDB[("Douzone iCube ERP
MS-SQL: DZICUBE
192.168.13.50:5539")]
IntranetDB[("Intranet MySQL
hallaerp
erp.samaneng.com")]
end
subgraph "External Services"
SMS["SMS 발송 서비스
(sms_controller.php)"]
PDF["PDF 생성 서비스
(pdf_controller.php)"]
OTP["OTP 인증 서비스
(SM_ERPURL_OTP)"]
end
Browser <-->|HTTPS / HTTP| WebServer
WebServer <--> Smarty
WebServer <--> Controller
Controller <--> AuthModule
Controller <--> BizLogic
BizLogic <--> CommonUtil
CommonUtil <-->|OCI Connection| OracleDB
BizLogic <-->|MS-SQL Port 5539| iCubeDB
BizLogic <-->|MySQL Port 3306| IntranetDB
BizLogic --> SMS
BizLogic --> PDF
CommonUtil <-->|OTP 검증| OTP
```
---
## 3. 계층별 기술 스택 (Layered Tech Stack)
| 계층 (Layer) | 구성 기술 및 경로 | 세부 설명 |
| :--- | :--- | :--- |
| **Client UI Tier** | `jQuery 1.11.3`, `jqGrid`, `w2ui`, `amCharts 3.20.15`, `dtree` | 대용량 그리드, 팝업 트리, 차트, 달력 처리 |
| **Presentation Tier** | `Smarty 2.6`, `Smarty/templates/Satis/` | SSR `.tpl` 기반 뷰 엔진. 각 화면은 `{$변수명}`으로 PHP 데이터 바인딩 |
| **Application Tier** | `PHP 5.x`, `Satis/sys/controller/` | `ActionMode` 파라미터 분기 라우팅. Controller → Model 1:1 호출 구조 |
| **Auth / Session** | `AuthClass.php`, `LoginInfomation.php` | 세션 생성, CSRF 토큰, 개인 권한(Certificate) 검증, 세션 만료 리다이렉트 |
| **Business Logic** | `Satis/sys/model/`, `Satis/inc/*.php` | 도메인별 Logic 클래스, 전자결재 함수, 공통 헬퍼 |
| **Data Access** | `OracleClass.php` | Oracle OCI8, Ref Cursor Proc, 다형 출력(`array`/`json`/`jsonchart`/Smarty) |
| **DB / Persistence** | Oracle(`samandb`), MS-SQL(`DZICUBE`), MySQL(`hallaerp`) | 이종 3-DB 동시 운영 |
---
## 4. 전체 폴더 구조 (Directory Structure)
```text
d:\41.dev\10.saman\
├── SmartyConfig.php # Smarty 엔진 경로 설정 (절대경로 하드코딩)
├── index.php # 루트 엔트리 → 로그인 화면 리다이렉트
│
├── Satis/ # 메인 웹 애플리케이션 루트
│ ├── css/ # 전역 CSS 스타일시트
│ ├── fonts/ # 웹 폰트
│ ├── images/ # UI 이미지
│ ├── jqgrid/ # jqGrid 라이브러리
│ ├── js/ # 프론트엔드 JavaScript (88개 파일)
│ │ ├── common.js, common2.js, common3.js # 공통 UI 함수
│ │ ├── common_jqGrid.js (214KB) # jqGrid 공통 래퍼 (주 버전)
│ │ ├── common_bigdata_grid.js (50KB) # 대용량 가상 스크롤 그리드
│ │ ├── SlipTemp.js (182KB) # 전표 작성 전용 클라이언트 로직
│ │ ├── SlipConfirm.js (147KB) # 전표 확정 처리
│ │ ├── ProjectScreen06.js (115KB) # 프로젝트 기성 화면
│ │ ├── ProjectScreen07.js (111KB) # 프로젝트 원가 화면
│ │ ├── GenerateDate.js # 날짜 생성 유틸
│ │ ├── erp_PrintAgent.js # 인쇄 에이전트
│ │ ├── amcharts_3.20.15.free/ # 경영분석 차트 라이브러리
│ │ ├── jqgrid/, jquery/, w2ui/, w2ui-1.5/ # 서드파티 라이브러리
│ │ └── pdfviwer/ # PDF 뷰어
│ ├── layout/
│ │ ├── Layout.html # 단일 프레임 레이아웃
│ │ └── Layout2.html # 분할 프레임 레이아웃
│ └── sys/ # Backend 핵심 디렉토리
│ ├── controller/ # MVC 컨트롤러 (21개 모듈 디렉토리)
│ │ ├── Login/ # 인증, 로그아웃, 메뉴, 즐겨찾기
│ │ ├── Account/ # 회계 (30개 컨트롤러)
│ │ ├── Person/ # 인사/급여 (23개 컨트롤러)
│ │ ├── Project/ # 프로젝트 (15개 컨트롤러)
│ │ ├── Project_work/ # 프로젝트 현장 업무 (16개 컨트롤러)
│ │ ├── Document/ # 전자결재
│ │ ├── Sign/ # 전자서명 문서 (3개 컨트롤러)
│ │ ├── Sale/ # 영업 (9개 컨트롤러)
│ │ ├── Purchase/ # 구매 (4개 컨트롤러)
│ │ ├── Travel/ # 출장
│ │ ├── Asset/ # 자산 (3개 컨트롤러)
│ │ ├── Book/ # 도서 관리
│ │ ├── Association/ # 협회 관리
│ │ ├── Management/ # 코드/권한/알림 관리 (4개 컨트롤러)
│ │ ├── Supervisor/ # 시스템 관리자 기능
│ │ ├── Common/ # 공통 팝업, SMS, PDF, OTP (17개 컨트롤러)
│ │ ├── Jqgrid/ # jqGrid JSON 데이터 응답
│ │ └── Fileupload/ # 파일 업로드 처리
│ ├── model/ # 비즈니스 로직 (모듈별 Logic 클래스)
│ ├── util/ # 시스템 유틸리티 클래스
│ │ ├── OracleClass.php # Oracle OCI 커넥션 핵심 클래스 (1,392라인)
│ │ ├── AuthClass.php # CSRF 토큰 / 세션 보안 (591라인)
│ │ ├── LoginInfomation.php # 로그인 상태 / 개인 권한 검증
│ │ ├── CommonCodeList.php # 공통 코드 인메모리 캐시 (294KB)
│ │ ├── DefaultInformation.php # 시스템 전역 변수 초기화
│ │ ├── GetUserInfo.php # 세션 사용자 정보 초기화
│ │ └── ReportViewExcel.php # Excel 보고서 출력
│ ├── inc/ # 모듈 공통 include 파일 (21개 파일)
│ │ ├── approval_function.php # 전자결재 처리 함수 (1,224라인)
│ │ ├── approval_var.php # 전자결재 상태 상수 정의
│ │ ├── function.php # 공통 헬퍼 함수 (1,093라인)
│ │ ├── function_add.php # 추가 헬퍼 함수 (32KB)
│ │ ├── function_intranet.php # 인트라넷 전용 함수 (33KB)
│ │ ├── dbcon.inc # MySQL 인트라넷 커넥션
│ │ ├── dbcon_security.inc # 보안 DB 커넥션
│ │ └── getNeedDate.php # 날짜 계산 유틸
│ ├── log/ # SQL 실행 로그 (날짜별 txt 파일)
│ └── yeta_data/ # 연말정산 데이터 파일
│
└── Smarty/ # Smarty 템플릿 엔진 디렉토리
├── templates/
│ ├── Satis/ # 22개 모듈 템플릿 디렉토리
│ │ ├── Login/ # 81개 .tpl (로그인, 메인, 환경설정, 알림)
│ │ ├── Account/ # 회계 화면 템플릿
│ │ ├── Person/ # 인사/급여 화면 템플릿
│ │ └── ... (나머지 모듈)
│ ├── Eis/, Overseas/, spo_mng/ # 타 시스템 템플릿
└── templates_c/ # Smarty 컴파일 캐시 (자동 생성)
```
---
## 5. 인프라 및 배포 아키텍처 (Infrastructure & Deployment Architecture)
```mermaid
graph LR
subgraph "서버 인프라"
WebSvr["Web App Server
(Windows Server
APM_Setup D:/APM_Setup/htdocs/)"]
OracleSvr[("Oracle DB Server
TNS: samandb
User: satis")]
iCubeSvr[("Douzone iCube Server
MS-SQL 192.168.13.50:5539
DB: DZICUBE / User: DZGUEST")]
MySQLSvr[("Intranet MySQL
erp.samaneng.com
DB: hallaerp")]
end
WebSvr -->|OCI8 클라이언트| OracleSvr
WebSvr -->|TCP 5539 mssql_connect| iCubeSvr
WebSvr -->|TCP 3306 mysql_connect| MySQLSvr
```
| 항목 | 내용 |
| :--- | :--- |
| **WAS 환경** | Windows Server + APM_Setup (Apache + PHP 5.x + MySQL) |
| **배포 경로** | `D:/APM_Setup/htdocs/` |
| **Smarty 컴파일 경로** | `D:/APM_Setup/htdocs/Smarty/templates_c/` |
| **PHP 메모리 설정** | `ini_set("memory_limit", -1)` — 대용량 Excel/연말정산 처리용 |
| **캐시 무효화 헤더** | `Expires: 0`, `Cache-Control: no-cache, must-revalidate` |
| **로그 파일 위치** | `Satis/sys/log/YYYY-MM-DD_{메소드명}.txt` (날짜별 자동 생성) |
| **연말정산 데이터** | `Satis/sys/yeta_data/` (`.425` 확장자 데이터 파일) |
---
## 6. 보안 및 인증 아키텍처 (Security & Authentication Architecture)
```mermaid
sequenceDiagram
autonumber
actor User as 사용자
participant Controller as Login Controller
participant Auth as AuthClass
participant LoginInfo as LoginInfomation
participant Session as PHP Session
participant DB as Oracle DB
User->>Controller: 로그인 요청 (ID / Password)
Controller->>DB: 사용자 정보 및 권한 검증 (Oracle SP)
DB-->>Controller: 인증 성공 반환 (사번/부서/직급 데이터)
Controller->>Session: $_SESSION['satis_user_id'] 등 세션 설정
Controller->>Auth: Auth_TokenGenerater() 호출 (10자리 난수)
Auth->>Session: $_SESSION['Token'] 저장
Session-->>User: Session Cookie 발급 (private)
Note over User,Controller: 이후 모든 요청에서 Token 검증 수행
User->>Controller: 기능 요청 (Token 파라미터 포함)
Controller->>Auth: Auth_TokenChecker($Token)
Auth->>Session: $_SESSION['Token'] 비교
alt 일치
Auth-->>Controller: 정상 처리 계속
else 불일치
Auth->>Session: session_destroy() 세션 파기
Auth-->>User: auth_move_page.tpl → 로그인 이동
end
Controller->>LoginInfo: GetLoginStatus() 세션 유효성 확인
alt 세션 만료
LoginInfo-->>User: alert('로그인후 사용하세요 시간만료') + 리다이렉트
end
```
### 6.1 세션 및 인증 관리 체계
| 항목 | 내용 |
| :--- | :--- |
| **세션 방식** | PHP Native Session (`session_start()`, `session_cache_limiter('private')`) |
| **CSRF 방어** | `AuthClass::Auth_TokenGenerater()` — 62자 문자풀, 10자리 난수 |
| **세션 만료 처리** | `LoginInfomation::GetLoginStatus2()` — 세션/쿠키/GET 파라미터 3단계 확인 |
| **개인 권한 검증** | `PersonAuthority::GetInfo($memberID, $Item)` — `member_tbl.Certificate` 컬럼 기반 |
| **개발자 권한** | `DefaultInformation.php` 화이트리스트 사번 6명 하드코딩 → `auth_page_devYN='Y'` |
| **OTP 인증** | `OracleClass::CheckOTPAuthentication()` — `SM_ERPURL_OTP` 테이블, 유효시간 1분 |
### 6.2 세션 변수 목록
| 세션 키 | 설명 |
| :--- | :--- |
| `$_SESSION['satis_user_id']` | 로그인 사원번호 (예: `"221064"`) |
| `$_SESSION['satis_user_name']` | 사원 성명 |
| `$_SESSION['satis_user_deptcode']` | 부서코드 |
| `$_SESSION['satis_user_deptname']` | 부서명 |
| `$_SESSION['Token']` | CSRF Anti-Forgery Token (10자리) |
| `$_SESSION['account_user_id']` | 계정 사용자 ID (인트라넷 연동용) |
| `$_SESSION['memberID']` | 인트라넷 회원 ID (레거시) |
| `$_SESSION['Title']` | 현재 화면 제목 |
| `$_SESSION['Auth']` | 권한 레벨 |
| `$_SESSION['Type']` | 사용자 유형 |
---
## 7. 외부 시스템 연동 아키텍처 (External System Integration Architecture)
```mermaid
graph TD
SatisCore["Satis ERP Core System
(PHP Application Server)"]
SatisCore <-->|OCI Native: oci_connect('satis','SATIS11707808','samandb')| OracleDB["Oracle DB (Main ERP)
그룹웨어, 인사, 회계, 프로젝트, 결재"]
SatisCore <-->|mssql_connect: 192.168.13.50:5539
DZGUEST/dzguest123| iCubeDB["더존 iCube ERP (MS-SQL)
DB: DZICUBE
회계전표 연동, 인사급여 싱크"]
SatisCore <-->|mysql_connect: erp.samaneng.com
root/vbxsystem| IntranetDB["인트라넷 MySQL
DB: hallaerp
전자결재 사원/부서 정보, 코드 사전"]
SatisCore -->|SMS API| SMSSvc["SMS 발송 서비스
기술자보수교육 대상자 알림
프로젝트 미결재 알림"]
SatisCore -->|PdfLogic| PDFSvc["PDF 생성 서비스
결재문서/보고서 PDF 변환"]
```
| 연동 시스템 | 접속 방식 | 연동 목적 | 관련 파일 |
| :--- | :--- | :--- | :--- |
| **Oracle DB (Main)** | OCI8: `oci_connect('satis','SATIS11707808','samandb')` | ERP 핵심 데이터 (결재/인사/회계/프로젝트) | `OracleClass.php` |
| **더존 iCube ERP** | MS-SQL: `192.168.13.50:5539` DB: `DZICUBE` | 회계 전표 더존 전송, 인사/급여 싱크 | `saman_icube_dbcon.inc` |
| **인트라넷 MySQL** | MySQL: `erp.samaneng.com` DB: `hallaerp` | 전자결재용 사원/부서 코드, 문서 마스터 | `dbcon.inc`, `approval_function.php` |
| **SMS 서비스** | PHP Logic 클래스 | 기술자 보수교육 대상자 알림, 프로젝트 미결재 경고 문자 | `sms_controller.php`, `sms_logic.php` |
| **PDF 서비스** | PHP Logic 클래스 | 결재 문서/보고서 PDF 변환 및 뷰 | `pdf_controller.php`, `PdfLogic.php` |
---
## 8. 프론트엔드 아키텍처 (Frontend Architecture)
### 8.1 프론트엔드 구성 개요
```mermaid
graph LR
subgraph "Frontend Stack (Satis/js/)"
jQuery["jQuery 1.11.3
(erp_jquery-1.11.3.min.js)"]
jqGrid["jqGrid
(219KB, common_jqGrid.js)"]
BigGrid["BigData Grid
(50KB, common_bigdata_grid.js)"]
w2ui["w2ui 1.5 RC1
(그리드/레이아웃)"]
amCharts["amCharts 3.20.15
(경영분석 차트)"]
dtree["dTree
(조직도/메뉴 트리)"]
Common3["common3.js (172KB)
(전체 공통 함수)"]
end
```
### 8.2 주요 프론트엔드 파일 및 역할
| 파일명 | 크기 | 역할 |
| :--- | :--- | :--- |
| `common_jqGrid.js` | 219KB | jqGrid 표준 래퍼. 컬럼 정의, 정렬, 페이징, 필터, Excel 내보내기 공통화 |
| `common_bigdata_grid.js` | 50KB | 수십만 건 이상 대용량 데이터 가상 스크롤 렌더링 |
| `SlipTemp.js` | 182KB | 회계 임시전표 작성 클라이언트 로직 (차변/대변 자동 계산, 전표 검증) |
| `SlipConfirm.js` | 147KB | 전표 확정 처리 로직 |
| `ProjectScreen06.js` | 115KB | 프로젝트 기성/원가 화면 복잡 UI 처리 |
| `ProjectScreen07.js` | 111KB | 프로젝트 원가 세부 화면 처리 |
| `common3.js` | 172KB | 공통 팝업, AJAX 함수, 날짜 유틸, 입력 검증 |
| `GenerateDate.js` | 27KB | 날짜 계산/생성 유틸리티 |
| `erp_PrintAgent.js` | 2.5KB | 인쇄 에이전트 연동 |
| `dtree.js` | 12KB | 메뉴/조직도 트리 렌더링 |
| `amcharts_3.20.15.free/` | — | 경영분석, 프로젝트 현황 차트 |
| `pdfviwer/` | — | 결재문서 PDF 인라인 뷰어 |
### 8.3 Smarty 템플릿 네이밍 규칙
Smarty `.tpl` 파일은 아래의 일관된 명명 규칙을 따릅니다.
```
{화면명}_{화면번호}_{렌더링타입}_{AJAX순번}_mvc.tpl
```
| 패턴 예시 | 설명 |
| :--- | :--- |
| `LoginScreen_01_Main_mvc.tpl` | 로그인 화면 메인 렌더링 |
| `LoginScreen_01_HTML_AJAX_01_mvc.tpl` | 로그인 화면 AJAX 응답 분리 파일 |
| `AlramInfo_List_01_AJAX_02_mvc.tpl` | 알림 목록 두 번째 AJAX 응답 |
| `SCREEN_01_Main_mvc.tpl` | 비밀번호 변경 화면 |
| `SCREEN_10_Main_mvc.tpl` | 초기화 비밀번호 로그인 전용 화면 |
---
## 9. 주요 업무 도메인 서브시스템 (Business Subsystems)
| 도메인 | 모듈 | 컨트롤러 수 | 핵심 기능 |
| :--- | :--- | :---: | :--- |
| **회계/재무** | `Account` | 30 | 전표(임시/확정/자동), 시산표, 재무제표, 기성, 원가, 법인세, 부가세, 공동도급예산, 고정자산, 어음/대출 관리 |
| **인사/급여** | `Person` | 23 | 인사기록카드, 발령, 자격증, 근태, 급여계산, 급여명세서, 퇴직금, 연말정산, 더존 싱크 |
| **프로젝트/공정** | `Project`, `Project_work` | 15+16 | 프로젝트 마스터, 수주계약, 기성, M/M 공수, 원가현황, 선급금, 협력업체, 목표수주 관리 |
| **전자결재** | `Document`, `Sign` | 1+3 | 기안/임시저장/상신, 결재진행, 전결/반송, 전자서명 문서, 결재선 관리 |
| **영업** | `Sale` | 9 | 입찰, 수주 계약, 매출/기성 수금, 수금 관리, 해외 사업, 영업 계획, 실적 분석 |
| **구매** | `Purchase` | 4 | 구매 정보, 발주, 대금 청구, 정산 관리 |
| **자산/도서** | `Asset`, `Book` | 3+α | 자산 기본코드, 자산 정보, 자산 구매, 도서 대여/목록 |
| **출장** | `Travel` | 1 | 국내/해외 출장 신청 및 여비 정산 |
| **협회** | `Association` | 1 | 엔지니어링 관련 협회 가입/관리 |
| **시스템관리** | `Management`, `Supervisor` | 4+1 | 공통코드, 메뉴권한, 알림 관리, 시스템 관리자 전체 설정 |
| **공통/인프라** | `Common`, `Jqgrid`, `Fileupload` | 17+α | SMS, PDF, OTP, 팝업, 파일업로드, 그리드 JSON 응답 |
---
## 10. 아키텍처 총평 및 고려사항 (Architectural Evaluation)
### 10.1 강점 (Strengths)
| 항목 | 내용 |
| :--- | :--- |
| **체계적 모듈화** | 20개 이상 업무 도메인이 Controller-Model-View 3계층으로 명확히 분리 |
| **이종 DB 하이브리드** | Oracle(ERP), MS-SQL(더존), MySQL(인트라넷) 3개 DB를 단일 애플리케이션에서 동시 운영 |
| **대용량 그리드 최적화** | `jqGrid` + `common_bigdata_grid.js` + `ini_set("memory_limit", -1)`를 통해 수만 건 공정/회계 데이터 조회 지원 |
| **보안 이중 방어** | CSRF 토큰 + PHP 세션 + OTP 검증의 다단계 인증 구조 |
| **도메인 특화 클라이언트** | `SlipTemp.js`(182KB), `ProjectScreen06.js`(115KB) 등 업무 특화 대용량 클라이언트 스크립트 |
### 10.2 기술 부채 및 위험 요소 (Technical Debt & Risks)
> [!CAUTION]
> **레거시 PHP 드라이버 사용**: `mysql_connect()`, `mssql_connect()`는 PHP 7.0에서 완전히 제거된 deprecated 함수입니다. PHP 5.6 이하 환경에서만 실행 가능합니다.
> [!CAUTION]
> **DB 접속 정보 평문 노출**: `dbcon.inc`(root/vbxsystem), `saman_icube_dbcon.inc`(DZGUEST/dzguest123$), `OracleClass.php`(satis/SATIS11707808) 소스 코드에 DB 계정이 하드코딩되어 있습니다.
> [!WARNING]
> **SQL Injection 위험**: `approval_function.php`, `function.php` 등 다수 함수에서 `$mCode` 값을 필터링 없이 SQL에 직접 삽입합니다. `mysql_real_escape_string()` 미적용.
> [!WARNING]
> **개발자 화이트리스트 하드코딩**: `DefaultInformation.php`에 개발자 사번 6명이 소스 코드에 직접 명시되어 있어 인사이동 시 소스 수정이 필요합니다.
> [!NOTE]
> **Smarty 절대경로 의존**: `SmartyConfig.php`의 모든 경로가 `D:/APM_Setup/htdocs/`로 하드코딩되어 있어 서버 이전 시 전면 수정이 필요합니다.
### 10.3 향후 아키텍처 개선 로드맵 (Future Roadmap)
| 우선순위 | 항목 | 개선 방향 |
| :---: | :--- | :--- |
| 🔴 긴급 | **DB 접속 정보 격리** | `.env` 파일 또는 환경 변수(`getenv()`)로 분리, 소스 버전 관리에서 제외 |
| 🔴 긴급 | **PHP 버전 현대화** | `mysql_*` → `PDO/mysqli`, `mssql_*` → `sqlsrv` (PDO_SQLSRV) 마이그레이션 |
| 🟠 중요 | **SQL Injection 방어** | Prepared Statement 또는 ORM 도입, 입력값 필터링 강화 |
| 🟡 권장 | **Smarty 경로 상대화** | `SmartyConfig.php`를 `__DIR__` 기반 상대경로로 변경, 이식성 확보 |
| 🟡 권장 | **개발자 권한 DB화** | 화이트리스트 사번을 DB 권한 테이블로 이전, 운영 중 동적 변경 가능하도록 개선 |
| 🟢 선택 | **템플릿 엔진 현대화** | Smarty 2.6 → Twig/Blade 또는 React/Vue.js SPA 전환 고려 |
| 🟢 선택 | **로그 중앙화** | 날짜별 txt 파일 로그 → ELK Stack 또는 구조화 로그(JSON) 도입 |