feat: complete Oracle and MariaDB WebView data layer
This commit is contained in:
77
docs/DATABASE.md
Normal file
77
docs/DATABASE.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# Oracle/MariaDB 연결 운영 가이드
|
||||
|
||||
## 적용된 공급자
|
||||
|
||||
`.NET 8`용 실제 ADO.NET 계층은 다음 버전을 고정합니다.
|
||||
|
||||
- Oracle: `Oracle.ManagedDataAccess.Core` `23.26.200`
|
||||
- MariaDB: `MySqlConnector` `2.6.1`
|
||||
|
||||
Oracle ODP.NET Core 23 계열은 TAP 기반 `OpenAsync`/명령 비동기를 지원하며, 이 구현은 Oracle pipelining을 켜지 않습니다. MariaDB Connector/NET 공식 가이드가 권장하는 MySqlConnector는 `OpenAsync`, reader 비동기와 취소를 사용합니다. Oracle 23.26.200은 Oracle Database 19c 이상을 전제로 하며, 현재 운영 스모크에서 서버 주 버전 21을 확인했습니다.
|
||||
|
||||
공식 참고:
|
||||
|
||||
- https://www.nuget.org/packages/Oracle.ManagedDataAccess.Core/23.26.200
|
||||
- https://docs.oracle.com/en/database/oracle/oracle-database/26/odpnt/featAsyncPipelining.html
|
||||
- https://mariadb.com/docs/connectors/mariadb-connector-net/mariadb-connector-net-guide
|
||||
- https://www.nuget.org/packages/MySqlConnector/2.6.1
|
||||
|
||||
## 런타임 설정
|
||||
|
||||
MSIX 설치 폴더는 읽기 전용이므로 설정 파일을 패키지 디렉터리에 두지 않습니다. 기본 경로는 다음과 같습니다.
|
||||
|
||||
```text
|
||||
%LOCALAPPDATA%\MBN_STOCK_WEBVIEW\Config\database.local.json
|
||||
```
|
||||
|
||||
저장소의 [appsettings.example.json](../Config/appsettings.example.json)은 비밀값이 없는 구조 예시입니다. 실제 파일은 [Initialize-DatabaseConfig.ps1](../scripts/Initialize-DatabaseConfig.ps1)로 만들 수 있습니다. 이 스크립트는 비밀번호를 프롬프트로 받고 현재 Windows 사용자만 파일을 읽도록 ACL을 설정합니다.
|
||||
|
||||
```powershell
|
||||
powershell -ExecutionPolicy Bypass -File .\scripts\Initialize-DatabaseConfig.ps1 `
|
||||
-OracleHost '<host>' -OraclePort 1521 -OracleSid '<sid>' -OracleUserName '<user>' `
|
||||
-MariaDbHost '<host>' -MariaDbPort 3306 -MariaDbDatabase '<database>' -MariaDbUserName '<user>'
|
||||
```
|
||||
|
||||
Oracle은 `sid` 또는 `serviceName` 중 정확히 하나를 설정합니다. 원본 MBN_STOCK_N은 SID descriptor를 사용했으므로 legacy 연결은 `sid`로 옮깁니다. 설정 파일은 평문 비밀번호를 포함할 수 있으므로 저장소·로그·첨부파일로 복사하지 않습니다. 운영 환경에서는 실행 계정의 파일 ACL을 유지하고, 환경 변수 오버라이드 또는 조직의 승인된 비밀 저장소를 사용할 수 있습니다.
|
||||
|
||||
JSON보다 환경 변수가 우선합니다.
|
||||
|
||||
```text
|
||||
MBN_STOCK_ORACLE_HOST / PORT / SID / SERVICE_NAME / USERNAME / PASSWORD
|
||||
MBN_STOCK_MARIADB_HOST / PORT / DATABASE / USERNAME / PASSWORD / TLS_MODE
|
||||
MBN_STOCK_DB_OPERATION_TIMEOUT_SECONDS
|
||||
MBN_STOCK_DB_MAX_RETRY_COUNT
|
||||
MBN_STOCK_DB_INITIAL_RETRY_DELAY_MS
|
||||
```
|
||||
|
||||
MariaDB `tlsMode`는 `Disabled`, `Preferred`, `Required`, `VerifyCertificate`, `VerifyIdentity`를 지원합니다. 인증서와 호스트 이름을 운영 환경에서 검증할 수 있으면 `VerifyIdentity`를 사용합니다. legacy LAN과의 호환을 위해 예시 기본값은 `Preferred`입니다.
|
||||
|
||||
## 실행 정책
|
||||
|
||||
각 조회는 연결을 새로 만들고 공급자 풀링을 사용합니다. `OpenAsync`, `ExecuteReaderAsync`, `ReadAsync`에 같은 취소 토큰을 전달하며, 공급자 command timeout과 전체 작업 timeout을 모두 적용합니다. 호출자가 취소한 작업은 재시도하지 않습니다. 재시도는 `SELECT`/`WITH` 읽기와 검토된 일시적 네트워크 오류에만 제한하고, 매 시도마다 기존 연결을 폐기한 뒤 새 연결을 엽니다. INSERT/UPDATE/DDL과 인증·스키마·SQL 오류는 재실행하지 않습니다.
|
||||
|
||||
DB 오류는 `DatabaseOperationException`의 안전한 한국어 메시지로 변환됩니다. provider 예외, raw connection string, 사용자명, 비밀번호, SQL은 WebView 메시지나 예외 `ToString()`에 포함하지 않습니다. health 상태는 Oracle과 MariaDB를 별도로 표시하므로 한쪽 장애가 앱 종료나 다른 쪽 결과 표시를 막지 않습니다.
|
||||
|
||||
## WebView 메시지
|
||||
|
||||
Web UI가 `request-database-status`를 보내면 native bridge가 양쪽 health 상태를 반환합니다. `kospi`, `kosdaq`, `index`, `overseas` 메뉴는 `request-market-data`를 보내고, native는 bounded DTO로 열 이름·행·전체 행 수를 반환합니다. `DataTable` 자체를 JSON으로 직렬화하지 않으며, 이전 `requestId` 응답은 Web UI가 버립니다. 오류는 `market-data-error`로 표시되고 기존 플레이리스트·PREPARE/TAKE IN/TAKE OUT UI는 계속 동작합니다.
|
||||
|
||||
## 검증 명령
|
||||
|
||||
단위 테스트:
|
||||
|
||||
```powershell
|
||||
dotnet test MBN_STOCK_WEBVIEW.sln -c Release -p:Platform=x64
|
||||
```
|
||||
|
||||
실제 DB 스모크(설정 파일을 읽어 비밀값은 출력하지 않음):
|
||||
|
||||
```powershell
|
||||
dotnet run --project .\tools\MBN_STOCK_WEBVIEW.DbSmoke\MBN_STOCK_WEBVIEW.DbSmoke.csproj -c Release
|
||||
```
|
||||
|
||||
스모크는 양쪽 `SELECT 1`, Oracle 서버 버전, 코스피·코스닥·NXT·5개 국내 지수·해외 종목 카탈로그의 실제 행을 확인합니다. 출력에는 상태, 테이블 이름, 행 수만 포함합니다.
|
||||
|
||||
## MSIX
|
||||
|
||||
패키지 앱은 `internetClient`와 `privateNetworkClientServer` capability를 사용합니다. Debug/Release x64와 MSIX 생성은 저장소 루트 README의 명령을 사용합니다. `ThirdPartyNotices`의 Oracle 및 MySqlConnector 고지는 MSIX 콘텐츠에 포함됩니다. 실제 운영 배포는 조직 인증서로 서명해야 하며 `.pfx`/비밀키는 저장소에 넣지 않습니다.
|
||||
@@ -22,6 +22,9 @@
|
||||
| WinForms 단축키 | Web UI `F2` / `F8` / `Esc` 처리 |
|
||||
| 직접 DBManager 호출 | Core의 `IDataQueryExecutor` 경계 |
|
||||
| `Data/Request` SQL 정의 | .NET 8 Core 프로젝트로 71개 이관 |
|
||||
| 동기 Oracle/MySQL 연결 | 비동기 Oracle/MariaDB 공급자, 취소·timeout·선별 재시도 |
|
||||
| DB 실패 시 `Application.Exit()` | 앱 유지 + WebView 소스별 health/오류/재조회 |
|
||||
| 종목·지수 선택 데이터 | WebView의 KRX/NXT 종목 및 5개 지수 실데이터 표 |
|
||||
| AnyCPU/x86 혼재 | 솔루션 및 게시 프로필 x64 단일화 |
|
||||
| 상대 경로 Web 파일 | MSIX Content 및 안전한 가상 호스트 매핑 |
|
||||
|
||||
@@ -31,11 +34,12 @@ WebView는 `https://app.mbn.local` 가상 호스트로 패키지 내부 파일
|
||||
|
||||
### 데이터베이스
|
||||
|
||||
- `IDataQueryExecutor`를 구현하는 Oracle/MariaDB 어댑터
|
||||
- .NET 8 호환 공급자 선정 및 연결 검증
|
||||
- 기존 문자열 조합 SQL의 매개변수화
|
||||
- 비동기 실행, 취소, 타임아웃, 재연결 정책
|
||||
- Credential Locker/DPAPI 등 승인된 비밀 저장 방식
|
||||
- 완료: `Oracle.ManagedDataAccess.Core 23.26.200`, `MySqlConnector 2.6.1` 고정
|
||||
- 완료: 실제 비동기 `IDataQueryExecutor`, 취소, 명령/전체 timeout, 새 연결 재시도
|
||||
- 완료: LocalAppData/환경 변수 설정과 공개 오류의 비밀값 비노출
|
||||
- 완료: Oracle/MariaDB health, 기존 종목·지수 SQL의 WebView 조회, 단위/실DB 스모크
|
||||
- 후속: 운영 보안 정책에 맞춘 Credential Locker/DPAPI 전환과 계정 자동 순환
|
||||
- 후속: 사용자 입력이 들어가는 나머지 legacy SQL의 단계적 매개변수화
|
||||
|
||||
### Tornado/K3D
|
||||
|
||||
|
||||
Reference in New Issue
Block a user