Compare commits

...

104 Commits

Author SHA1 Message Date
Macbook db5623341a Bump chatbotApp submodule to include opinion like/dislike picker.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-21 09:32:27 +09:00
Macbook d389266de6 Deploy: exdev sync 2026-08-21 09:18:44 2026-08-21 09:18:44 +09:00
Macbook 8d0a8bdb5c Deploy: exdev sync 2026-08-18 09:26:35 2026-08-18 09:26:35 +09:00
Macbook 88221b828e chore: chatbotApp-test 서브모듈 추가 및 git_fetch_all 대상 확장
KoreaExpressWayCorp/chatbotApp-test 를 submodule 로 등록하고,
git_fetch_all.sh 가 chatbot2.0-agent 브랜치로 GitHub 동기화·push 하도록 한다.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 10:09:53 +09:00
bkyungee c9f5915419 Revert "Deploy: exdev sync 2026-08-13 17:39:39"
This reverts commit 50c5039ec0.
2026-08-13 17:51:39 +09:00
bkyungee 50c5039ec0 Deploy: exdev sync 2026-08-13 17:39:39 2026-08-13 17:39:39 +09:00
bkyungee cd6a081a55 chore: chatbotApp 서브모듈 포인터를 44bbe25 로 갱신
아이폰에서 영업소 아이콘이 보이지 않던 문제를 고친 커밋을 가리키도록
루트가 기억하는 위치를 옮긴다. 이걸 갱신하지 않으면 루트를 clone 해서
git submodule update 로 받는 쪽은 수정 이전 버전을 받게 된다.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-13 17:22:32 +09:00
bkyungee 78d549194c fix: 원격 배포 rsync 제외 패턴이 소스를 잘못 걸러내던 문제 수정
tar 기반 rsync 대체 스크립트가 rsync 의 'node_modules/' 문법을 매칭하지
못해 node_modules 를 통째로 전송하다 메모리 부족으로 죽었다. 반대로
슬래시만 떼면 'build' 가 자바 패키지 kakao.response.build 까지 제외해
kakaoChatbotSkill 컴파일이 깨졌다. 선행 슬래시를 전송 루트 기준 고정으로
해석하도록 구분해 둘 다 해결한다.

배포 중 자동 커밋에 딸려 들어갔던 일회용 진단 스크립트도 함께 제거한다.
2026-08-13 15:07:36 +09:00
bkyungee 493b07ec30 Deploy: exdev sync 2026-08-13 14:48:13 2026-08-13 14:48:14 +09:00
bkyungee fb4179eaa5 Deploy: exdev sync 2026-08-13 13:47:23 2026-08-13 13:47:23 +09:00
bkyungee f15b666da9 Deploy: exdev sync 2026-08-13 13:38:36 2026-08-13 13:38:36 +09:00
bkyungee fab7a5ba49 Deploy: exdev sync 2026-08-13 11:38:19 2026-08-13 11:38:20 +09:00
Macbook 687ae0445c Deploy: exdev sync 2026-08-12 14:13:16 2026-08-12 14:13:16 +09:00
Macbook 861934dad1 Deploy: exdev sync 2026-08-12 08:41:49 2026-08-12 08:41:49 +09:00
Macbook 430c6b1efb Deploy: exdev sync 2026-08-12 00:50:47 2026-08-12 00:50:47 +09:00
Macbook 12bafdd148 Deploy: exdev sync 2026-08-12 00:13:06 2026-08-12 00:13:06 +09:00
Macbook 27056073da Deploy: exdev sync 2026-08-11 22:30:48 2026-08-11 22:30:48 +09:00
Macbook 42fa743d7a Deploy: exdev sync 2026-08-11 22:01:31 2026-08-11 22:01:31 +09:00
Macbook 2f365aebac Deploy: exdev sync 2026-08-11 18:48:42 2026-08-11 18:48:42 +09:00
Macbook 242df2a11f Deploy: exdev sync 2026-08-11 18:40:56 2026-08-11 18:40:56 +09:00
Macbook a63987d168 Deploy: exdev sync 2026-08-11 17:56:35 2026-08-11 17:56:35 +09:00
Macbook b29ea93f78 Deploy: exdev sync 2026-08-11 17:28:39 2026-08-11 17:28:39 +09:00
Macbook 28dc55bc11 Deploy: exdev sync 2026-08-11 16:26:17 2026-08-11 16:26:17 +09:00
Macbook 998f97f12f Deploy: exdev sync 2026-08-11 16:14:41 2026-08-11 16:14:41 +09:00
Macbook 4301ebe1b8 Deploy: exdev sync 2026-08-11 15:48:53 2026-08-11 15:48:53 +09:00
Macbook 0174f1bd27 Deploy: exdev sync 2026-08-11 12:21:42 2026-08-11 12:21:42 +09:00
Macbook a8de6fd275 Deploy: exdev sync 2026-08-11 10:23:45 2026-08-11 10:23:45 +09:00
Macbook 5f6288cc8b Deploy: exdev sync 2026-08-11 09:40:30 2026-08-11 09:40:30 +09:00
Macbook 917441cdae Deploy: exdev sync 2026-08-11 01:49:52 2026-08-11 01:49:52 +09:00
Macbook 123eb926bc Deploy: exdev sync 2026-08-11 01:33:19 2026-08-11 01:33:19 +09:00
Macbook 01abedcdea Deploy: exdev sync 2026-08-10 18:18:18 2026-08-10 18:18:18 +09:00
Macbook 5ff37ecf06 Deploy: exdev sync 2026-08-10 11:29:37 2026-08-10 11:29:37 +09:00
Macbook 0a22052cca Deploy: exdev sync 2026-08-07 20:50:50 2026-08-07 20:50:50 +09:00
Macbook 04f91bd307 Deploy: exdev sync 2026-08-07 13:53:07 2026-08-07 13:53:07 +09:00
Macbook 37b24c1b76 Deploy: exdev sync 2026-08-07 12:54:59 2026-08-07 12:54:59 +09:00
Macbook d6c50136b0 Deploy: exdev sync 2026-08-07 10:49:28 2026-08-07 10:49:28 +09:00
Macbook 7883636fef Deploy: exdev sync 2026-08-07 04:14:38 2026-08-07 04:14:38 +09:00
Macbook ee558309a6 Deploy: exdev sync 2026-08-07 03:58:11 2026-08-07 03:58:11 +09:00
Macbook 70902bc319 Deploy: exdev sync 2026-08-07 03:48:00 2026-08-07 03:48:00 +09:00
Macbook 02390996cb Deploy: exdev sync 2026-08-07 00:20:51 2026-08-07 00:20:51 +09:00
Macbook 2f762f698b Deploy: exdev sync 2026-08-06 22:14:45 2026-08-06 22:14:45 +09:00
Macbook dde35babdb Deploy: exdev sync 2026-08-06 21:36:18 2026-08-06 21:36:18 +09:00
Macbook 6e27c7bd25 Deploy: exdev sync 2026-08-06 17:57:54 2026-08-06 17:57:54 +09:00
Macbook ebeded783b Deploy: exdev sync 2026-08-06 17:06:45 2026-08-06 17:06:45 +09:00
Macbook 74e85171b0 Deploy: exdev sync 2026-08-06 14:39:10 2026-08-06 14:39:10 +09:00
Macbook 741155fe55 Deploy: exdev sync 2026-08-06 13:30:41 2026-08-06 13:30:41 +09:00
Macbook 5ce4a1a6ce Deploy: exdev sync 2026-08-06 10:13:31 2026-08-06 10:13:31 +09:00
Macbook f86fab8459 Deploy: exdev sync 2026-08-06 09:43:02 2026-08-06 09:43:02 +09:00
Macbook 508ea1b00c Deploy: exdev sync 2026-08-06 09:23:28 2026-08-06 09:23:28 +09:00
Macbook 3f3e578f98 Deploy: exdev sync 2026-08-06 00:25:50 2026-08-06 00:25:50 +09:00
Macbook 2753b361d5 Deploy: exdev sync 2026-08-05 16:41:03 2026-08-05 16:41:03 +09:00
Macbook 70446e444e Deploy: exdev sync 2026-08-05 14:11:46 2026-08-05 14:11:46 +09:00
Macbook d0040bd2af Deploy: exdev sync 2026-08-05 13:22:51 2026-08-05 13:22:51 +09:00
Macbook 7d6889b0ff Deploy: exdev sync 2026-08-05 12:53:35 2026-08-05 12:53:35 +09:00
Macbook 0be91bb540 Deploy: exdev sync 2026-08-04 14:05:23 2026-08-04 14:05:23 +09:00
Macbook 5400db9fb4 Deploy: exdev sync 2026-08-04 12:56:12 2026-08-04 12:56:12 +09:00
Macbook b5ebe3f369 Deploy: exdev sync 2026-08-04 12:44:51 2026-08-04 12:44:51 +09:00
Macbook d813e053ca Deploy: exdev sync 2026-08-04 11:45:26 2026-08-04 11:45:26 +09:00
Macbook 1ff418fa73 Deploy: exdev sync 2026-08-04 10:32:57 2026-08-04 10:32:57 +09:00
Macbook 86f9feba3b Deploy: exdev sync 2026-08-04 10:04:19 2026-08-04 10:04:19 +09:00
Macbook 31e86baa63 Deploy: exdev sync 2026-08-04 08:32:20 2026-08-04 08:32:20 +09:00
Macbook 216d76c8a0 Deploy: exdev sync 2026-08-03 22:10:15 2026-08-03 22:10:15 +09:00
Macbook 0ad583f3a9 Deploy: exdev sync 2026-08-03 16:45:58 2026-08-03 16:45:58 +09:00
Macbook 50eeb4ff76 Deploy: exdev sync 2026-08-03 15:02:04 2026-08-03 15:02:04 +09:00
Macbook 62604fe1b7 Deploy: exdev sync 2026-08-03 13:59:26 2026-08-03 13:59:26 +09:00
Macbook 39f41d90b0 Deploy: exdev sync 2026-08-01 21:04:26 2026-08-01 21:04:26 +09:00
Macbook b071aff2d9 Deploy: exdev sync 2026-07-30 21:37:49 2026-07-30 21:37:49 +09:00
Macbook 653d9ccb32 Deploy: exdev sync 2026-07-30 17:27:23 2026-07-30 17:27:23 +09:00
Macbook 3a622ee3ee Deploy: exdev sync 2026-07-30 17:07:16 2026-07-30 17:07:16 +09:00
Macbook bdeb5f64ce Deploy: exdev sync 2026-07-30 13:40:42 2026-07-30 13:40:42 +09:00
Macbook a22baec49d Deploy: exdev sync 2026-07-30 13:18:10 2026-07-30 13:18:10 +09:00
Macbook 34d95de479 Deploy: exdev sync 2026-07-30 10:06:06 2026-07-30 10:06:06 +09:00
Macbook fcf99167db Deploy: exdev sync 2026-07-30 09:49:54 2026-07-30 09:49:54 +09:00
Macbook 098fa0b3f1 Deploy: exdev sync 2026-07-29 08:32:54 2026-07-29 08:32:55 +09:00
Macbook 2f4c7062c7 Deploy: exdev sync 2026-07-28 17:35:01 2026-07-28 17:35:01 +09:00
Macbook 0d4f2737a0 Deploy: exdev sync 2026-07-28 14:33:09 2026-07-28 14:33:09 +09:00
Macbook b1df37309b Deploy: exdev sync 2026-07-28 13:24:26 2026-07-28 13:24:26 +09:00
Macbook 2b33c9f4be Deploy: exdev sync 2026-07-28 12:38:38 2026-07-28 12:38:38 +09:00
Macbook 1ee28f3a4d Deploy: exdev sync 2026-07-28 09:40:42 2026-07-28 09:40:42 +09:00
Macbook f85e4adc35 Deploy: GitHub submodule sync 2026-07-28 01:47:40 2026-07-28 01:47:41 +09:00
Macbook db8f69743b Deploy: GitHub submodule sync 2026-07-28 01:34:20 2026-07-28 01:34:20 +09:00
Macbook 06af24d1c7 Deploy: GitHub submodule sync 2026-07-28 01:12:48 2026-07-28 01:12:48 +09:00
Macbook af6c64f052 Deploy: GitHub submodule sync 2026-07-28 00:59:08 2026-07-28 00:59:08 +09:00
Macbook d3dc5d87d1 Deploy: GitHub submodule sync 2026-07-28 00:49:30 2026-07-28 00:49:30 +09:00
Macbook 73bac743c2 Deploy: GitHub submodule sync 2026-07-28 00:32:08 2026-07-28 00:32:08 +09:00
Macbook ff58d1ed39 Deploy: GitHub submodule sync 2026-07-27 23:57:51 2026-07-27 23:57:51 +09:00
Macbook 5e0471988e Deploy: GitHub submodule sync 2026-07-27 23:12:25 2026-07-27 23:12:25 +09:00
Macbook a37ac3d6a1 Deploy: GitHub submodule sync 2026-07-27 22:40:54 2026-07-27 22:40:54 +09:00
Macbook d8c5e8f436 Deploy: GitHub submodule sync 2026-07-27 22:23:53 2026-07-27 22:23:53 +09:00
Macbook 869308b82e Deploy: GitHub submodule sync 2026-07-27 22:08:13 2026-07-27 22:08:14 +09:00
Macbook 264954cc32 Deploy: GitHub submodule sync 2026-07-27 21:23:55 2026-07-27 21:23:55 +09:00
Macbook b461949266 Deploy: GitHub submodule sync 2026-07-27 21:00:39 2026-07-27 21:00:39 +09:00
Macbook 2545dd263f Deploy: GitHub submodule sync 2026-07-27 17:51:52 2026-07-27 17:51:52 +09:00
Macbook 9b965118db Deploy: GitHub submodule sync 2026-07-27 17:37:38 2026-07-27 17:37:38 +09:00
Macbook cfd9ae6add Deploy: GitHub submodule sync 2026-07-27 10:47:01 2026-07-27 10:47:01 +09:00
Macbook 2e0e2bde29 Deploy: GitHub submodule sync 2026-07-27 09:29:05 2026-07-27 09:29:06 +09:00
Macbook 57f71b2503 Deploy: GitHub submodule sync 2026-07-24 10:33:40 2026-07-24 10:33:40 +09:00
Macbook 6aa99f3d6d Deploy: GitHub submodule sync 2026-07-24 09:27:56 2026-07-24 09:27:56 +09:00
Macbook 3df4398618 Deploy: GitHub submodule sync 2026-07-24 01:55:20 2026-07-24 01:55:20 +09:00
Macbook 2df9191889 Deploy: GitHub submodule sync 2026-07-23 22:38:00 2026-07-23 22:38:00 +09:00
Macbook 68ff71c1f7 Deploy: GitHub submodule sync 2026-07-23 21:19:42 2026-07-23 21:19:42 +09:00
Macbook fa98eafa8f Deploy: GitHub submodule sync 2026-07-23 17:23:39 2026-07-23 17:23:39 +09:00
Macbook 5f3e691d95 Deploy: GitHub submodule sync 2026-07-23 16:11:51 2026-07-23 16:11:51 +09:00
Macbook 83210543a3 Deploy: GitHub submodule sync 2026-07-23 15:50:17 2026-07-23 15:50:17 +09:00
69 changed files with 46947 additions and 722 deletions
Regular → Executable
+18 -17
View File
@@ -1,17 +1,18 @@
# exChatbot Agent 2.0
**/build/
**/.gradle/
**/node_modules/
**/.env
.DS_Store
*.log
*.pid
*.zip
exAiChatBot-chatbot2.0-agent/qdrant_data/
chatbotApp-chatbot2.0-agent/public/
chatbotApp-chatbot2.0-agent/public-*/
local-dev/run/
local-dev/logs/
server-dev/run/
server-dev/logs/
# exChatbot Agent 2.0
**/build/
**/.gradle/
**/node_modules/
**/.env
.DS_Store
*.log
*.pid
*.zip
exAiChatBot-chatbot2.0-agent/qdrant_data/
chatbotApp-chatbot2.0-agent/public/
chatbotApp-chatbot2.0-agent/public-*/
local-dev/run/
local-dev/logs/
server-dev/run/
server-dev/logs/
.venv-data/
Regular → Executable
+19 -15
View File
@@ -1,16 +1,20 @@
[submodule "chatbotApp-chatbot2.0-agent"]
path = chatbotApp-chatbot2.0-agent
url = https://github.com/KoreaExpressWayCorp/chatbotApp.git
branch = chatbot2.0-agent
[submodule "chatbotApi-chatbot2.0-agent"]
path = chatbotApi-chatbot2.0-agent
url = https://github.com/KoreaExpressWayCorp/chatbotApi.git
branch = chatbot2.0-agent
[submodule "exAiChatBot-chatbot2.0-agent"]
path = exAiChatBot-chatbot2.0-agent
url = https://github.com/KoreaExpressWayCorp/exAiChatBot.git
branch = chatbot2.0-agent
[submodule "kakaoChatbotSkill-chatbot2.0-agent"]
path = kakaoChatbotSkill-chatbot2.0-agent
url = https://github.com/KoreaExpressWayCorp/kakaoChatbotSkill.git
[submodule "chatbotApp-chatbot2.0-agent"]
path = chatbotApp-chatbot2.0-agent
url = https://github.com/KoreaExpressWayCorp/chatbotApp.git
branch = chatbot2.0-agent
[submodule "chatbotApi-chatbot2.0-agent"]
path = chatbotApi-chatbot2.0-agent
url = https://github.com/KoreaExpressWayCorp/chatbotApi.git
branch = chatbot2.0-agent
[submodule "exAiChatBot-chatbot2.0-agent"]
path = exAiChatBot-chatbot2.0-agent
url = https://github.com/KoreaExpressWayCorp/exAiChatBot.git
branch = chatbot2.0-agent
[submodule "kakaoChatbotSkill-chatbot2.0-agent"]
path = kakaoChatbotSkill-chatbot2.0-agent
url = https://github.com/KoreaExpressWayCorp/kakaoChatbotSkill.git
branch = chatbot2.0-agent
[submodule "chatbotApp-test"]
path = chatbotApp-test
url = https://github.com/KoreaExpressWayCorp/chatbotApp-test.git
branch = chatbot2.0-agent
Binary file not shown.
Binary file not shown.
+1
Submodule chatbotApp-test added at 20835ab277
+5
View File
@@ -0,0 +1,5 @@
node_modules/
dist/
.venv-icons/
*.log
.DS_Store
+48
View File
@@ -0,0 +1,48 @@
# EX AI Chatbot 데스크톱 앱
Electron 래퍼 — 브라우저 주소표시줄 없이 챗봇을 독립 창으로 실행합니다.
## 빌드 · 배포
```bash
./build-and-publish.sh
# 또는
npm run dist:mac # dmg(설치) + zip(포터블), intel + silicon
npm run dist:win # Setup.exe(설치) + portable.exe, win32 + win64
npm run publish-downloads
```
산출물은 `chatbotApp-chatbot2.0-agent/public-ai/downloads/` 로 복사됩니다.
| 구분 | 파일 |
|------|------|
| Mac 설치 (Intel) | `exAIChatbot 2.0-mac-intel.dmg` |
| Mac 포터블 (Intel) | `exAIChatbot 2.0-mac-intel.zip` |
| Mac 설치 (Apple Silicon) | `exAIChatbot 2.0-mac-silicon.dmg` |
| Mac 포터블 (Apple Silicon) | `exAIChatbot 2.0-mac-silicon.zip` |
| Windows 설치 64비트 | `exAIChatbot 2.0-win64-Setup.exe` |
| Windows 포터블 64비트 | `exAIChatbot 2.0-win64-portable.exe` |
| Windows 설치 32비트 | `exAIChatbot 2.0-win32-Setup.exe` |
| Windows 포터블 32비트 | `exAIChatbot 2.0-win32-portable.exe` |
다운로드 URL 예:
- `/chatbot/ai/downloads/exAIChatbot%202.0-mac-silicon.dmg`
- `/chatbot/ai/downloads/exAIChatbot%202.0-win64-Setup.exe`
## 앱 아이콘
공식 길통이·차로(`ai-mascot.png`)로 Dock/바로가기 아이콘을 생성합니다.
```bash
npm run build:icons # build/icon.png · icon.icns · icon.ico
```
`dist:mac` / `dist:win` 실행 시 자동으로 아이콘을 다시 만든 뒤 패키징합니다.
## 사용 안내
- **Mac dmg:** 앱을 Applications로 드래그. 차단 시 설정 화면「Mac 설치 명령 복사」.
- **Mac zip:** `실행하기.command` 또는 `.app` 실행.
- **Windows Setup:** 설치 마법사 실행.
- **Windows portable:** 압축 없이 exe 바로 실행. SmartScreen → 추가 정보 → 실행.
+90
View File
@@ -0,0 +1,90 @@
#!/usr/bin/env bash
# Electron 데스크톱 앱 재빌드 → chatbotApp public-ai/downloads/ 배포
#
# ./chatbotDesktopApp-chatbot2.0/build-and-publish.sh
# SKIP_WIN=1 ./chatbotDesktopApp-chatbot2.0/build-and-publish.sh # Mac만
# SKIP_MAC=1 ./chatbotDesktopApp-chatbot2.0/build-and-publish.sh # Win만
set -euo pipefail
DESKTOP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd "${DESKTOP_DIR}/.." && pwd)"
DOWNLOADS_DIR="${ROOT_DIR}/chatbotApp-chatbot2.0-agent/public-ai/downloads"
export PATH="/opt/homebrew/bin:/usr/local/bin:${PATH}"
export CSC_IDENTITY_AUTO_DISCOVERY="${CSC_IDENTITY_AUTO_DISCOVERY:-false}"
log() { echo "[desktop-build $(date '+%H:%M:%S')] $*"; }
warn() { log "⚠️ $*"; }
fail() { log "ERROR: $*"; exit 1; }
[[ -f "${DESKTOP_DIR}/package.json" ]] || fail "package.json 없음: ${DESKTOP_DIR}"
cd "${DESKTOP_DIR}"
if [[ ! -d node_modules/electron ]]; then
log "npm 의존성 설치..."
npm ci --prefer-offline 2>/dev/null || npm install
else
log "npm 의존성 확인..."
npm ci --prefer-offline 2>/dev/null || npm install --prefer-offline
fi
SKIP_MAC="${SKIP_MAC:-0}"
SKIP_WIN="${SKIP_WIN:-0}"
built_any=false
case "$(uname -s)" in
Darwin)
if [[ "${SKIP_MAC}" != "1" ]]; then
log "잔여 DMG 볼륨 정리..."
hdiutil detach "/Volumes/EX AI Chatbot" -force 2>/dev/null || true
hdiutil detach "/Volumes/EX AI Chatbot Intel" -force 2>/dev/null || true
hdiutil detach "/Volumes/EX AI Chatbot Silicon" -force 2>/dev/null || true
log "Mac Intel + Apple Silicon (dmg+zip) 빌드..."
# electron-builder는 arch별 dir(.app)만 순차 생성 → finalize-mac이 dmg/zip 생성
# (dmg를 동시 빌드하면 hdiutil detach 충돌로 실패함)
npm run dist:mac
built_any=true
fi
if [[ "${SKIP_WIN}" != "1" ]]; then
log "Windows 32/64비트 (Setup+portable) 빌드 (크로스)..."
if npm run dist:win; then
built_any=true
else
warn "Windows 빌드 실패 — Mac 산출물만 배포합니다"
fi
fi
;;
Linux)
if [[ "${SKIP_WIN}" != "1" ]]; then
log "Windows 32/64비트 (Setup+portable) 빌드..."
if npm run dist:win; then
built_any=true
else
warn "Windows 빌드 실패"
fi
fi
if [[ "${SKIP_MAC}" != "1" ]]; then
warn "Linux에서는 Mac 빌드를 건너뜁니다 (SKIP_MAC 강제)"
fi
;;
MINGW*|MSYS*|CYGWIN*|Windows_NT)
if [[ "${SKIP_WIN}" != "1" ]]; then
log "Windows 32/64비트 (Setup+portable) 빌드..."
npm run dist:win
built_any=true
fi
;;
*)
fail "지원하지 않는 OS: $(uname -s)"
;;
esac
$built_any || fail "빌드된 산출물이 없습니다"
log "downloads/ 로 복사..."
npm run publish-downloads
[[ -d "${DOWNLOADS_DIR}" ]] || fail "downloads 디렉터리 없음: ${DOWNLOADS_DIR}"
log "✅ 데스크톱 앱 배포 완료 → ${DOWNLOADS_DIR}"
ls -lh "${DOWNLOADS_DIR}" | sed 's/^/ /'
+181
View File
@@ -0,0 +1,181 @@
const { app, BrowserWindow, shell, Menu, session } = require("electron");
const path = require("node:path");
const fs = require("node:fs");
// Gatekeeper / ad-hoc 서명 환경에서 GPU Helper SIGTRAP 완화
app.disableHardwareAcceleration();
app.commandLine.appendSwitch("disable-gpu");
app.commandLine.appendSwitch("disable-gpu-compositing");
app.commandLine.appendSwitch("disable-software-rasterizer");
app.commandLine.appendSwitch("no-sandbox");
app.commandLine.appendSwitch("disable-dev-shm-usage");
const WINDOW_WIDTH = 390;
const WINDOW_HEIGHT = 720;
const DEFAULT_URL =
process.env.CHATBOT_APP_URL ||
"https://chatbot.exdev.co.kr/chatbot/ai/?desktop=1";
const logFile = path.join(app.getPath("userData"), "ex-ai-chatbot.log");
function log(msg) {
const line = `[${new Date().toISOString()}] ${msg}\n`;
try {
fs.appendFileSync(logFile, line);
} catch {
/* ignore */
}
console.log(msg);
}
/** 챗봇 주소의 마이크·위치 요청은 매번 묻지 않고 허용한다. */
function allowMicrophoneForChatbot() {
const allowed = new Set([
"media",
"audioCapture",
"mediaKeySystem",
"geolocation",
]);
const appOrigin = (() => {
try {
return new URL(DEFAULT_URL).origin;
} catch {
return null;
}
})();
const isChatbotOrigin = (url) => {
if (!appOrigin || !url) return false;
try {
return new URL(url).origin === appOrigin;
} catch {
return false;
}
};
const ses = session.defaultSession;
ses.setPermissionRequestHandler((webContents, permission, callback, details) => {
const url = details?.requestingUrl || webContents?.getURL();
callback(allowed.has(permission) && isChatbotOrigin(url));
});
ses.setPermissionCheckHandler((_webContents, permission, requestingOrigin, details) => {
const url = requestingOrigin || details?.requestingUrl;
return allowed.has(permission) && isChatbotOrigin(url);
});
if (typeof ses.setDevicePermissionHandler === "function") {
ses.setDevicePermissionHandler((details) => isChatbotOrigin(details?.origin));
}
}
function createWindow() {
const iconPath = path.join(__dirname, "build", process.platform === "win32" ? "icon.ico" : "icon.png");
const winOpts = {
width: WINDOW_WIDTH,
height: WINDOW_HEIGHT,
minWidth: 360,
minHeight: 520,
title: "한국도로공사 AI 챗봇",
backgroundColor: "#ffffff",
autoHideMenuBar: true,
show: false,
webPreferences: {
preload: path.join(__dirname, "preload.js"),
contextIsolation: true,
nodeIntegration: false,
sandbox: false,
webSecurity: true,
},
};
if (fs.existsSync(iconPath)) {
winOpts.icon = iconPath;
}
const win = new BrowserWindow(winOpts);
Menu.setApplicationMenu(null);
win.once("ready-to-show", () => {
win.show();
if (process.platform === "darwin" && app.dock) {
const dockIcon = path.join(__dirname, "build", "icon.png");
if (fs.existsSync(dockIcon)) {
try {
app.dock.setIcon(dockIcon);
} catch (e) {
log(`dock.setIcon failed: ${e}`);
}
}
app.dock.show();
}
});
win.webContents.on("did-fail-load", (_e, code, desc, url) => {
log(`did-fail-load code=${code} desc=${desc} url=${url}`);
// 네트워크 실패 시에도 빈 창으로 종료되지 않도록 안내 페이지
const html = `<!doctype html><meta charset="utf-8"/>
<body style="font:14px -apple-system,sans-serif;padding:40px;line-height:1.6">
<h2>연결 실패</h2>
<p>챗봇 서버에 연결하지 못했습니다.</p>
<p style="color:#666">${code}: ${desc}</p>
<p><a href="${DEFAULT_URL}">다시 시도</a></p>
</body>`;
win.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(html)}`);
});
win.webContents.on("render-process-gone", (_e, details) => {
log(`render-process-gone ${JSON.stringify(details)}`);
});
win.on("unresponsive", () => log("window unresponsive"));
log(`loadURL ${DEFAULT_URL}`);
win.loadURL(DEFAULT_URL).catch((err) => log(`loadURL error: ${err}`));
win.webContents.setWindowOpenHandler(({ url }) => {
shell.openExternal(url);
return { action: "deny" };
});
return win;
}
const gotLock = app.requestSingleInstanceLock();
if (!gotLock) {
app.quit();
} else {
app.on("second-instance", () => {
const wins = BrowserWindow.getAllWindows();
if (wins.length > 0) {
if (wins[0].isMinimized()) wins[0].restore();
wins[0].focus();
} else {
createWindow();
}
});
app.whenReady().then(() => {
app.setName("EX AI Chatbot");
log(`ready userData=${app.getPath("userData")}`);
allowMicrophoneForChatbot();
createWindow();
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
});
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
}
});
process.on("uncaughtException", (err) => {
log(`uncaughtException ${err?.stack || err}`);
});
}
+5288
View File
File diff suppressed because it is too large Load Diff
+72
View File
@@ -0,0 +1,72 @@
{
"name": "ex-ai-chatbot-desktop",
"version": "1.0.0",
"description": "한국도로공사 AI 챗봇 데스크톱 앱 (Electron 래퍼)",
"main": "main.js",
"author": "EX",
"license": "UNLICENSED",
"private": true,
"scripts": {
"start": "electron .",
"build:icons": "python3 scripts/build-icons.py",
"dist:mac:detach": "hdiutil detach '/Volumes/EX AI Chatbot' -force 2>/dev/null || hdiutil detach '/Volumes/EX AI Chatbot Intel' -force 2>/dev/null || hdiutil detach '/Volumes/EX AI Chatbot Silicon' -force 2>/dev/null || true",
"dist:mac:x64": "npm run dist:mac:detach && electron-builder --mac dir --x64",
"dist:mac:arm64": "npm run dist:mac:detach && electron-builder --mac dir --arm64",
"dist:mac": "npm run build:icons && npm run dist:mac:x64 && npm run dist:mac:arm64 && node scripts/finalize-mac.mjs",
"dist:win": "npm run build:icons && electron-builder --win --x64 --ia32 && node scripts/finalize-win.mjs",
"dist:all": "npm run dist:mac && npm run dist:win",
"publish-downloads": "node scripts/publish-downloads.mjs"
},
"build": {
"appId": "kr.co.ex.aichatbot",
"productName": "EX AI Chatbot",
"copyright": "Copyright © Korea Expressway Corporation",
"directories": {
"output": "dist",
"buildResources": "build"
},
"files": [
"main.js",
"preload.js",
"package.json",
"build/icon.png",
"build/icon.ico"
],
"mac": {
"category": "public.app-category.utilities",
"icon": "build/icon.icns",
"target": ["dir"],
"identity": null
},
"win": {
"icon": "build/icon.ico",
"target": [
{
"target": "nsis",
"arch": ["x64", "ia32"]
},
{
"target": "portable",
"arch": ["x64", "ia32"]
}
]
},
"nsis": {
"oneClick": false,
"allowToChangeInstallationDirectory": true,
"createDesktopShortcut": true,
"createStartMenuShortcut": true,
"shortcutName": "EX AI Chatbot",
"installerIcon": "build/icon.ico",
"uninstallerIcon": "build/icon.ico",
"artifactName": "raw-win-${arch}-Setup.${ext}"
},
"portable": {
"artifactName": "raw-win-${arch}-portable.${ext}"
}
},
"devDependencies": {
"electron": "^35.1.2",
"electron-builder": "^25.1.8"
}
}
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
</dict>
</plist>
@@ -0,0 +1,36 @@
EX AI Chatbot — Mac 설치 안내
================================
이 패키지는 Apple 공증(notarization)이 없는 사내/개발용 빌드입니다.
Chrome 등으로 받은 뒤 앱을 바로 열면
「손상되었기 때문에 열 수 없습니다」가 뜰 수 있습니다.
(포터블 zip의 「실행하기.command」는 이 문제를 자동으로 피합니다.)
────────────────────────────────
A. 설치 파일 (.dmg) — 반드시 아래 순서
────────────────────────────────
1. dmg를 연다
2. 「응용 프로그램에 설치하고 실행.command」를 더블클릭
→ Applications에 설치 + 검역 속성 제거 + 실행까지 한 번에 처리
3. (대안) 앱을 Applications로 드래그한 뒤, 아래 C. 터미널 명령을 실행
※ Applications의 앱을 더블클릭만 하면 macOS가 다시 차단할 수 있습니다.
처음 한 번은 반드시 「설치하고 실행.command」또는 터미널(xattr)을 사용하세요.
────────────────────────────────
B. 포터블 (.zip)
────────────────────────────────
1. zip 압축 해제
2. 「실행하기.command」를 더블클릭
3. 차단되면 아래 「터미널 설치」를 사용
────────────────────────────────
C. 터미널 설치 (손상됨 / 차단될 때)
────────────────────────────────
1. Spotlight(⌘+스페이스) → 「터미널」실행
2. 챗봇 설정 화면의 「Mac 설치 명령 복사」붙여넣기(⌘+V) 후 Enter
직접 입력 (Applications에 넣은 경우):
xattr -cr "/Applications/EX AI Chatbot.app" && open "/Applications/EX AI Chatbot.app"
Apple Silicon → mac-silicon / Intel → mac-intel 파일을 받으세요.
@@ -0,0 +1,18 @@
#!/bin/bash
# 주의: 웹에서 받은 .command 는 macOS가 같이 차단할 수 있습니다.
# 차단되면 「설치안내.txt」의 터미널 방법을 사용하세요.
set -euo pipefail
cd "$(dirname "$0")"
APP="EX AI Chatbot.app"
if [[ ! -d "${APP}" ]]; then
osascript -e 'display dialog "같은 폴더에 「EX AI Chatbot.app」이 없습니다.\n압축을 해제한 뒤, 차단되면 터미널 설치 방법을 사용하세요.\n(설치안내.txt 참고)" buttons {"확인"} default button 1 with title "EX AI Chatbot"' >/dev/null 2>&1 || true
exit 1
fi
# 자기 자신·앱 검역 제거 시도 (권한이 되면 성공)
xattr -cr . 2>/dev/null || true
xattr -cr "${APP}" 2>/dev/null || true
open "${APP}"
@@ -0,0 +1,25 @@
#!/bin/bash
# DMG에서 실행: Applications로 복사 + Gatekeeper 검역 제거 후 실행
# (미서명 빌드에서 「손상되었기 때문에 열 수 없습니다」 방지)
set -euo pipefail
cd "$(dirname "$0")"
APP_NAME="EX AI Chatbot.app"
SRC="$(pwd)/${APP_NAME}"
DEST="/Applications/${APP_NAME}"
if [[ ! -d "${SRC}" ]]; then
osascript -e 'display dialog "같은 디스크에 「EX AI Chatbot.app」이 없습니다.\ndmg 창에서 이 스크립트를 실행해 주세요." buttons {"확인"} default button 1 with title "EX AI Chatbot"' >/dev/null 2>&1 || true
exit 1
fi
# 기존 설치 교체
rm -rf "${DEST}"
cp -R "${SRC}" "${DEST}"
# 다운로드/복사로 붙은 quarantine 제거 (손상됨 팝업 핵심 해결)
xattr -cr "${DEST}" 2>/dev/null || true
open "${DEST}"
osascript -e 'display dialog "응용 프로그램에 설치하고 실행했습니다.\n다음에 실행할 때는 Launchpad 또는 응용 프로그램 폴더의 「EX AI Chatbot」을 사용하세요." buttons {"확인"} default button 1 with title "EX AI Chatbot"' >/dev/null 2>&1 || true
+6
View File
@@ -0,0 +1,6 @@
const { contextBridge } = require("electron");
contextBridge.exposeInMainWorld("exDesktop", {
isDesktop: true,
platform: process.platform,
});
+230
View File
@@ -0,0 +1,230 @@
#!/usr/bin/env python3
"""
공식 길통이+차로(ai-mascot.png)로 Electron 앱 아이콘 생성
- build/icon.png (1024)
- build/icon.icns (macOS)
- build/icon.ico (Windows)
"""
from __future__ import annotations
import plistlib
import shutil
import struct
import subprocess
import sys
import tempfile
import zlib
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
BUILD = ROOT / "build"
SRC_CANDIDATES = [
ROOT.parent / "chatbotApp-chatbot2.0-agent" / "web" / "public" / "images" / "ai-mascot.png",
ROOT.parent / "chatbotApp-chatbot2.0-agent" / "public-ai" / "images" / "ai-mascot.png",
]
# EX 브랜드 블루
BG = (36, 107, 235, 255)
WHITE = (255, 255, 255, 255)
def _venv_python(venv: Path) -> Path:
if sys.platform == "win32":
return venv / "Scripts" / "python.exe"
py = venv / "bin" / "python3"
return py if py.exists() else venv / "bin" / "python"
def _in_venv(venv: Path) -> bool:
"""Homebrew venv의 bin/python은 시스템 바이너리 symlink라 executable.resolve() 비교는 불가."""
try:
return Path(sys.prefix).resolve() == venv.resolve()
except OSError:
return False
def _ensure_pip(py: Path) -> None:
try:
subprocess.check_call([str(py), "-m", "pip", "--version"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError:
print("[build-icons] ensurepip으로 pip 부트스트랩…", flush=True)
subprocess.check_call([str(py), "-m", "ensurepip", "--upgrade"])
def _pip_install_pillow(py: Path) -> None:
_ensure_pip(py)
cmd = [str(py), "-m", "pip", "install", "Pillow", "-q"]
try:
subprocess.check_call(cmd)
except subprocess.CalledProcessError:
print("[build-icons] pip 재시도 (ensurepip 후)…", flush=True)
subprocess.check_call([str(py), "-m", "ensurepip", "--upgrade"])
subprocess.check_call(cmd)
def require_pillow():
try:
from PIL import Image, ImageDraw # noqa: F401
return
except ImportError:
pass
venv = ROOT / ".venv-icons"
py = _venv_python(venv)
if not py.exists():
print("[build-icons] venv 생성 중…", flush=True)
subprocess.check_call([sys.executable, "-m", "venv", str(venv)])
py = _venv_python(venv)
print("[build-icons] Pillow 설치 중…", flush=True)
_pip_install_pillow(py)
# 현재 프로세스에 Pillow가 없으면 venv로 재실행 (sys.prefix로 판별)
if not _in_venv(venv):
raise SystemExit(subprocess.call([str(py), str(Path(__file__).resolve()), *sys.argv[1:]]))
from PIL import Image, ImageDraw # noqa: F401
def rounded_rect_mask(size: int, radius: int):
from PIL import Image, ImageDraw
mask = Image.new("L", (size, size), 0)
draw = ImageDraw.Draw(mask)
draw.rounded_rectangle((0, 0, size - 1, size - 1), radius=radius, fill=255)
return mask
def make_icon_png(src: Path, out: Path, size: int = 1024) -> None:
from PIL import Image, ImageDraw, ImageFilter
mascot = Image.open(src).convert("RGBA")
# 흰 배경 제거에 가깝게: 거의 흰 픽셀을 투명 처리
pixels = mascot.load()
w, h = mascot.size
for y in range(h):
for x in range(w):
r, g, b, a = pixels[x, y]
if r > 245 and g > 245 and b > 245:
pixels[x, y] = (r, g, b, 0)
canvas = Image.new("RGBA", (size, size), (0, 0, 0, 0))
draw = ImageDraw.Draw(canvas)
# macOS 아이콘용 라운드 사각 (약 22% radius)
radius = int(size * 0.223)
draw.rounded_rectangle((0, 0, size - 1, size - 1), radius=radius, fill=BG)
# 안쪽 밝은 원형 배지
badge = Image.new("RGBA", (size, size), (0, 0, 0, 0))
bd = ImageDraw.Draw(badge)
pad = int(size * 0.08)
bd.ellipse((pad, pad, size - pad, size - pad), fill=(255, 255, 255, 235))
canvas = Image.alpha_composite(canvas, badge)
# 마스코트 배치 (여백 확보)
max_side = int(size * 0.78)
mw, mh = mascot.size
scale = min(max_side / mw, max_side / mh)
nw, nh = int(mw * scale), int(mh * scale)
mascot = mascot.resize((nw, nh), Image.Resampling.LANCZOS)
ox = (size - nw) // 2
oy = (size - nh) // 2 + int(size * 0.02)
canvas.alpha_composite(mascot, (ox, oy))
# 마스크로 모서리 정리
mask = rounded_rect_mask(size, radius)
out_img = Image.new("RGBA", (size, size), (0, 0, 0, 0))
out_img.paste(canvas, (0, 0), mask=mask)
out.parent.mkdir(parents=True, exist_ok=True)
out_img.save(out, "PNG")
print(f"[build-icons] ✅ {out} ({size}x{size})")
def build_icns(png_1024: Path, icns_path: Path) -> None:
sizes = [
(16, "icon_16x16.png"),
(32, "diana.k@example.org"),
(32, "icon_32x32.png"),
(64, "ivan.p@example.net"),
(128, "icon_128x128.png"),
(256, "wendy.h@example.net"),
(256, "icon_256x256.png"),
(512, "wendy.h@example.net"),
(512, "icon_512x512.png"),
(1024, "walt.e@example.net"),
]
iconset = BUILD / "icon.iconset"
if iconset.exists():
shutil.rmtree(iconset)
iconset.mkdir(parents=True)
from PIL import Image
base = Image.open(png_1024).convert("RGBA")
for px, name in sizes:
img = base.resize((px, px), Image.Resampling.LANCZOS)
img.save(iconset / name, "PNG")
if icns_path.exists():
icns_path.unlink()
subprocess.check_call(["iconutil", "-c", "icns", str(iconset), "-o", str(icns_path)])
shutil.rmtree(iconset)
print(f"[build-icons] ✅ {icns_path}")
def _png_chunk(tag: bytes, data: bytes) -> bytes:
return struct.pack(">I", len(data)) + tag + data + struct.pack(">I", zlib.crc32(tag + data) & 0xFFFFFFFF)
def rgba_to_png_bytes(img) -> bytes:
"""Pillow 이미지 → PNG bytes (ICO용)."""
import io
buf = io.BytesIO()
img.save(buf, format="PNG")
return buf.getvalue()
def build_ico(png_1024: Path, ico_path: Path) -> None:
"""여러 해상도 PNG를 담은 .ico 생성 (electron-builder는 256 필수)."""
from PIL import Image
sizes = [(16, 16), (24, 24), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)]
base = Image.open(png_1024).convert("RGBA")
# Pillow: 원본에서 sizes= 로 리사이즈한 멀티 엔트리 ICO 생성
# (append_images + 작은 첫 프레임은 16x16만 남는 버그 회피)
base.save(ico_path, format="ICO", sizes=sizes)
print(f"[build-icons] ✅ {ico_path}")
def main() -> int:
require_pillow()
src = next((p for p in SRC_CANDIDATES if p.exists()), None)
if not src:
print("[build-icons] ai-mascot.png 없음", file=sys.stderr)
return 1
BUILD.mkdir(parents=True, exist_ok=True)
png = BUILD / "icon.png"
make_icon_png(src, png, 1024)
# electron-builder 호환 별칭
shutil.copy2(png, BUILD / "icon-1024.png")
if sys.platform == "darwin":
try:
build_icns(png, BUILD / "icon.icns")
except Exception as e:
print(f"[build-icons] icns 실패 (png만 사용): {e}", file=sys.stderr)
else:
print("[build-icons] icns는 macOS에서만 생성합니다")
try:
build_ico(png, BUILD / "icon.ico")
except Exception as e:
print(f"[build-icons] ico 실패: {e}", file=sys.stderr)
return 1
print("[build-icons] 완료")
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,23 @@
/** 다운로드 산출물 파일명 (공백 포함 — URL 인코딩 필요) */
export const DOWNLOAD_ARTIFACTS = {
macIntelInstaller: "exAIChatbot 2.0-mac-intel.dmg",
macIntelPortable: "exAIChatbot 2.0-mac-intel.zip",
macSiliconInstaller: "exAIChatbot 2.0-mac-silicon.dmg",
macSiliconPortable: "exAIChatbot 2.0-mac-silicon.zip",
win32Installer: "exAIChatbot 2.0-win32-Setup.exe",
win32Portable: "exAIChatbot 2.0-win32-portable.exe",
win64Installer: "exAIChatbot 2.0-win64-Setup.exe",
win64Portable: "exAIChatbot 2.0-win64-portable.exe",
};
export const DOWNLOAD_ARTIFACT_LIST = Object.values(DOWNLOAD_ARTIFACTS);
/** 이전 배포 파일명 (정리용) */
export const OBSOLETE_DOWNLOAD_ARTIFACTS = [
"exAIChatbot 2.0-win32.zip",
"exAIChatbot 2.0-win64.zip",
"EX-AI-Chatbot-mac-universal.zip",
"EX-AI-Chatbot-Setup.exe",
"EX-AI-Chatbot-Setup.exe.blockmap",
"EX-AI-Chatbot-mac-universal.zip.blockmap",
];
+226
View File
@@ -0,0 +1,226 @@
#!/usr/bin/env node
/**
* Mac 산출물 정리
* - zip(포터블): .app + 실행하기.command
* - dmg(설치형): 동일 서명 .app + 「응용 프로그램에 설치하고 실행.command」
* (Gatekeeper 「손상됨」팝업 방지 — 설치 시 xattr -cr 수행)
*/
import { execFileSync } from "node:child_process";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { DOWNLOAD_ARTIFACTS } from "./download-artifacts.mjs";
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const distDir = path.join(root, "dist");
const appName = "EX AI Chatbot.app";
const packagingMac = path.join(root, "packaging", "mac");
const installCmdName = "응용 프로그램에 설치하고 실행.command";
const runCmdName = "실행하기.command";
const guideName = "설치안내.txt";
const TARGETS = [
{
appDirs: [path.join(distDir, "mac-x64", appName), path.join(distDir, "mac", appName)],
zipName: DOWNLOAD_ARTIFACTS.macIntelPortable,
dmgName: DOWNLOAD_ARTIFACTS.macIntelInstaller,
label: "intel (x64)",
},
{
appDirs: [path.join(distDir, "mac-arm64", appName)],
zipName: DOWNLOAD_ARTIFACTS.macSiliconPortable,
dmgName: DOWNLOAD_ARTIFACTS.macSiliconInstaller,
label: "silicon (arm64)",
},
];
function codesignApp(appPath, label) {
try {
execFileSync(
"codesign",
[
"--force",
"--deep",
"--sign",
"-",
"--entitlements",
path.join(packagingMac, "entitlements.plist"),
appPath,
],
{ stdio: "inherit" },
);
} catch (e) {
console.warn(`[finalize-mac] entitlements codesign 실패 (${label}), ad-hoc 재시도:`, e.message);
try {
execFileSync("codesign", ["--force", "--deep", "--sign", "-", appPath], {
stdio: "inherit",
});
} catch (e2) {
console.warn(`[finalize-mac] codesign 실패 (${label}):`, e2.message);
}
}
try {
execFileSync("xattr", ["-cr", appPath], { stdio: "ignore" });
} catch {
/* ignore */
}
}
function ensurePackagingFiles() {
for (const name of [runCmdName, installCmdName, guideName]) {
const p = path.join(packagingMac, name);
if (!fs.existsSync(p)) throw new Error(`packaging/mac 파일 없음: ${name}`);
}
}
function packZip(appPath, zipName, label) {
console.log(`[finalize-mac] zip ${label}: ${appPath}`);
const stage = fs.mkdtempSync(path.join(os.tmpdir(), "ex-ai-mac-zip-"));
try {
fs.cpSync(appPath, path.join(stage, appName), { recursive: true });
fs.copyFileSync(path.join(packagingMac, runCmdName), path.join(stage, runCmdName));
fs.copyFileSync(path.join(packagingMac, guideName), path.join(stage, guideName));
fs.chmodSync(path.join(stage, runCmdName), 0o755);
try {
execFileSync("xattr", ["-cr", stage], { stdio: "ignore" });
} catch {
/* ignore */
}
const zipPath = path.join(distDir, zipName);
if (fs.existsSync(zipPath)) fs.unlinkSync(zipPath);
execFileSync("zip", ["-r", "-y", zipPath, appName, runCmdName, guideName], {
cwd: stage,
stdio: "inherit",
});
const size = fs.statSync(zipPath).size;
console.log(`[finalize-mac] ✅ zip ${zipName} (${Math.round(size / 1024 / 1024)} MB)`);
return true;
} finally {
fs.rmSync(stage, { recursive: true, force: true });
}
}
function detachStaleVolumes() {
for (const vol of ["EX AI Chatbot", "EX AI Chatbot Intel", "EX AI Chatbot Silicon"]) {
try {
execFileSync("hdiutil", ["detach", `/Volumes/${vol}`, "-force"], { stdio: "ignore" });
} catch {
/* not mounted */
}
}
}
function packDmg(appPath, dmgName, label) {
console.log(`[finalize-mac] dmg ${label}: ${appPath}`);
const stage = fs.mkdtempSync(path.join(os.tmpdir(), "ex-ai-mac-dmg-"));
const rwDmg = path.join(os.tmpdir(), `ex-ai-mac-${Date.now()}-${process.pid}.dmg`);
// arch별 볼륨명 — 동시/잔여 마운트 충돌 방지
const volName = label.includes("silicon") ? "EX AI Chatbot Silicon" : "EX AI Chatbot Intel";
try {
fs.cpSync(appPath, path.join(stage, appName), { recursive: true });
fs.copyFileSync(path.join(packagingMac, installCmdName), path.join(stage, installCmdName));
fs.copyFileSync(path.join(packagingMac, guideName), path.join(stage, guideName));
fs.chmodSync(path.join(stage, installCmdName), 0o755);
// Applications 폴더 바로가기 (일반 dmg UX)
try {
fs.symlinkSync("/Applications", path.join(stage, "Applications"));
} catch {
/* ignore */
}
try {
execFileSync("xattr", ["-cr", stage], { stdio: "ignore" });
} catch {
/* ignore */
}
const outPath = path.join(distDir, dmgName);
if (fs.existsSync(outPath)) fs.unlinkSync(outPath);
if (fs.existsSync(rwDmg)) fs.unlinkSync(rwDmg);
detachStaleVolumes();
// 읽기 전용 압축 dmg 생성 (electron-builder DMG 미사용 — hdiutil 경합 회피)
// Finder/Spotlight가 잠깐 잡고 있으면 "리소스 사용 중"이 나므로 재시도한다.
const createArgs = [
"create",
"-volname",
volName,
"-srcfolder",
stage,
"-ov",
"-format",
"UDZO",
outPath,
];
let lastErr = null;
for (let attempt = 1; attempt <= 4; attempt += 1) {
try {
if (attempt > 1) {
console.warn(`[finalize-mac] hdiutil create 재시도 ${attempt}/4 (${label})`);
detachStaleVolumes();
try {
execFileSync("sleep", [String(1.5 * attempt)], { stdio: "ignore" });
} catch {
/* ignore */
}
}
execFileSync("hdiutil", createArgs, { stdio: "inherit" });
lastErr = null;
break;
} catch (e) {
lastErr = e;
const msg = String(e?.stderr || e?.message || e);
const busy = /리소스 사용 중|Resource busy|Device busy|hdiutil/i.test(msg) || e?.status === 1;
if (!busy || attempt === 4) break;
}
}
if (lastErr) throw lastErr;
const size = fs.statSync(outPath).size;
console.log(`[finalize-mac] ✅ dmg ${dmgName} (${Math.round(size / 1024 / 1024)} MB)`);
return true;
} finally {
fs.rmSync(stage, { recursive: true, force: true });
try {
if (fs.existsSync(rwDmg)) fs.unlinkSync(rwDmg);
} catch {
/* ignore */
}
}
}
if (!fs.existsSync(distDir)) {
console.error("[finalize-mac] dist 없음");
process.exit(1);
}
ensurePackagingFiles();
let done = 0;
for (const t of TARGETS) {
const appPath = t.appDirs.find((p) => fs.existsSync(p));
if (!appPath) {
console.warn(`[finalize-mac] skip ${t.label}: .app 없음`);
continue;
}
codesignApp(appPath, t.label);
if (packDmg(appPath, t.dmgName, t.label)) done += 1;
if (packZip(appPath, t.zipName, t.label)) done += 1;
}
// 빌더 raw zip/dmg 잔여 정리
for (const raw of fs.readdirSync(distDir)) {
if (/^raw-mac-/.test(raw) && (raw.endsWith(".zip") || raw.endsWith(".dmg"))) {
fs.unlinkSync(path.join(distDir, raw));
console.log(`[finalize-mac] removed ${raw}`);
}
}
if (done === 0) {
console.error("[finalize-mac] 패키징할 Mac 산출물이 없습니다.");
process.exit(1);
}
+69
View File
@@ -0,0 +1,69 @@
#!/usr/bin/env node
/**
* Windows 산출물 정리
* - Setup.exe (NSIS 설치형)
* - portable.exe (포터블)
*/
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { DOWNLOAD_ARTIFACTS } from "./download-artifacts.mjs";
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const distDir = path.join(root, "dist");
const MAP = [
{
patterns: [/^raw-win-x64-Setup\.exe$/i],
out: DOWNLOAD_ARTIFACTS.win64Installer,
},
{
patterns: [/^raw-win-x64-portable\.exe$/i],
out: DOWNLOAD_ARTIFACTS.win64Portable,
},
{
patterns: [/^raw-win-ia32-Setup\.exe$/i, /^raw-win-i386-Setup\.exe$/i],
out: DOWNLOAD_ARTIFACTS.win32Installer,
},
{
patterns: [/^raw-win-ia32-portable\.exe$/i, /^raw-win-i386-portable\.exe$/i],
out: DOWNLOAD_ARTIFACTS.win32Portable,
},
];
if (!fs.existsSync(distDir)) {
console.error("[finalize-win] dist 없음");
process.exit(1);
}
const files = fs.readdirSync(distDir);
let done = 0;
for (const rule of MAP) {
const srcName = files.find((f) => rule.patterns.some((re) => re.test(f)));
if (!srcName) {
console.warn(`[finalize-win] skip (원본 없음): ${rule.out}`);
continue;
}
const src = path.join(distDir, srcName);
const dest = path.join(distDir, rule.out);
if (src !== dest) {
if (fs.existsSync(dest)) fs.unlinkSync(dest);
fs.renameSync(src, dest);
}
const size = fs.statSync(dest).size;
console.log(`[finalize-win] ✅ ${rule.out} (${Math.round(size / 1024 / 1024)} MB) ← ${srcName}`);
done += 1;
}
for (const f of fs.readdirSync(distDir)) {
if (/^raw-win-/.test(f)) {
fs.unlinkSync(path.join(distDir, f));
console.log(`[finalize-win] removed ${f}`);
}
}
if (done === 0) {
console.error("[finalize-win] Windows 설치/포터블 산출물을 찾지 못했습니다.");
process.exit(1);
}
+76
View File
@@ -0,0 +1,76 @@
#!/usr/bin/env node
/**
* electron-builder 산출물 → chatbotApp public-ai/downloads/ 복사
*/
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import {
DOWNLOAD_ARTIFACTS,
DOWNLOAD_ARTIFACT_LIST,
OBSOLETE_DOWNLOAD_ARTIFACTS,
} from "./download-artifacts.mjs";
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const distDir = path.join(root, "dist");
const downloadsDir = path.resolve(
root,
"../chatbotApp-chatbot2.0-agent/public-ai/downloads",
);
const pkg = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf8"));
if (!fs.existsSync(distDir)) {
console.error(`[publish-downloads] dist 없음: ${distDir}`);
console.error("먼저 npm run dist:mac 또는 dist:win 을 실행하세요.");
process.exit(1);
}
fs.mkdirSync(downloadsDir, { recursive: true });
for (const name of OBSOLETE_DOWNLOAD_ARTIFACTS) {
const p = path.join(downloadsDir, name);
if (fs.existsSync(p)) {
fs.unlinkSync(p);
console.log(`[publish-downloads] removed obsolete ${name}`);
}
}
const copied = [];
for (const name of DOWNLOAD_ARTIFACT_LIST) {
const src = path.join(distDir, name);
if (!fs.existsSync(src)) {
console.warn(`[publish-downloads] skip (없음): ${name}`);
continue;
}
const dest = path.join(downloadsDir, name);
fs.copyFileSync(src, dest);
const stat = fs.statSync(dest);
copied.push({
file: name,
size: stat.size,
mtime: stat.mtime.toISOString(),
});
console.log(`[publish-downloads] ${name} → ${dest}`);
}
const manifest = {
version: pkg.version,
updatedAt: new Date().toISOString(),
files: { ...DOWNLOAD_ARTIFACTS },
artifacts: copied,
note:
"미서명 빌드 — Mac: dmg(설치) / zip(포터블·실행하기.command). Windows: Setup.exe(설치) / portable.exe(포터블).",
};
fs.writeFileSync(
path.join(downloadsDir, "manifest.json"),
`${JSON.stringify(manifest, null, 2)}\n`,
"utf8",
);
if (copied.length === 0) {
console.error("[publish-downloads] 복사된 파일이 없습니다.");
process.exit(1);
}
console.log(`[publish-downloads] ✅ ${copied.length}개 → ${downloadsDir}`);
Binary file not shown.
+346 -58
View File
@@ -1,30 +1,57 @@
#!/usr/bin/env bash
# GitHub upstream → monorepo submodule 최신 소스 반영 (pull only, push 없음)
# 5개 submodule: 로컬 변경 → 공식 GitHub chatbot2.0-agent commit + push
#
# ./git_fetch_all.sh # 4개 submodule fetch + fast-forward
# ★ 공식 GitHub(KoreaExpressWayCorp) 반영은 이 스크립트로만 수행한다.
# start-all-server.sh / push-to-gitea.sh 는 개발서버(Gitea/exdev)만 다룬다.
#
# ./git_fetch_all.sh # fetch/merge + commit + push (공식 GitHub)
# ./git_fetch_all.sh --init # submodule 미초기화 시 clone 포함
# ./git_fetch_all.sh --dry-run # 실행 없이 변경 예상만 출력
# ./git_fetch_all.sh --dry-run # 실행 없이 상태만 출력
# ./git_fetch_all.sh --no-push # commit까지, push 생략
# ./git_fetch_all.sh --no-commit # fetch/merge만 (commit·push 생략)
#
# 대상 (.gitmodules):
# chatbotApp-chatbot2.0-agent → KoreaExpressWayCorp/chatbotApp (chatbot2.0-agent)
# chatbotApi-chatbot2.0-agent → KoreaExpressWayCorp/chatbotApi (chatbot2.0-agent)
# exAiChatBot-chatbot2.0-agent → KoreaExpressWayCorp/exAiChatBot (chatbot2.0-agent)
# kakaoChatbotSkill-chatbot2.0-agent → KoreaExpressWayCorp/kakaoChatbotSkill (chatbot2.0-agent)
# ★ 운영(GitHub) push 전용 — 개발서버(exdev) 주소를 커밋/push 하지 않는다.
# start-all-server.sh 가 런타임 ENV 로만 exdev(127.0.0.1 Mongo / localhost Oracle TROAD /
# host.docker.internal RAG)를 적용한다.
# 이 스크립트는 commit 직전에 운영 기본값(172.16.*)을 파일에 복원한 뒤 push 한다.
# (.env / EXDEV_LOCAL / server-dev 오버레이는 GitHub 대상이 아님)
#
# 대상 (.gitmodules) — 모두 branch=chatbot2.0-agent (main 사용 안 함):
# chatbotApi-chatbot2.0-agent
# chatbotApp-chatbot2.0-agent
# chatbotApp-test
# exAiChatBot-chatbot2.0-agent
# kakaoChatbotSkill-chatbot2.0-agent
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# bare repo 배포 시 상위에서 GIT_DIR 이 export 되면 submodule git 이 깨짐
MONOREPO_GIT_DIR="${MONOREPO_GIT_DIR:-${GIT_DIR:-}}"
unset GIT_DIR GIT_WORK_TREE
INIT=false
DRY_RUN=false
DO_COMMIT=true
DO_PUSH=true
TARGET_BRANCH="chatbot2.0-agent"
# 명시 대상 (순서 고정). .gitmodules 와 일치해야 함.
TARGET_PATHS=(
"chatbotApi-chatbot2.0-agent"
"chatbotApp-chatbot2.0-agent"
"chatbotApp-test"
"exAiChatBot-chatbot2.0-agent"
"kakaoChatbotSkill-chatbot2.0-agent"
)
for arg in "$@"; do
case "$arg" in
--init) INIT=true ;;
--dry-run) DRY_RUN=true ;;
--init) INIT=true ;;
--dry-run) DRY_RUN=true ;;
--no-commit) DO_COMMIT=false; DO_PUSH=false ;;
--no-push) DO_PUSH=false ;;
-h|--help)
sed -n '2,14p' "$0"
sed -n '2,22p' "$0"
exit 0
;;
*)
@@ -36,6 +63,7 @@ done
log() { echo "[git_fetch_all] $*"; }
warn() { echo "[git_fetch_all] ⚠️ $*" >&2; }
ok() { echo "[git_fetch_all] ✅ $*"; }
cd "${ROOT_DIR}"
@@ -44,20 +72,6 @@ if [[ ! -f .gitmodules ]]; then
exit 1
fi
SUBMODULE_PATHS=()
while IFS= read -r _path; do
[[ -n "${_path}" ]] && SUBMODULE_PATHS+=("${_path}")
done < <(git config -f .gitmodules --get-regexp '^submodule\..*\.path$' | awk '{print $2}')
if [[ ${#SUBMODULE_PATHS[@]} -eq 0 ]]; then
echo "ERROR: .gitmodules 에 submodule 경로 없음"
exit 1
fi
if $INIT && ! $DRY_RUN; then
log "submodule init (direct clone)..."
fi
resolve_monorepo_git_dir() {
if [[ -n "${MONOREPO_GIT_DIR}" && -d "${MONOREPO_GIT_DIR}" ]]; then
echo "${MONOREPO_GIT_DIR}"
@@ -104,18 +118,181 @@ restore_monorepo_overlays() {
fi
}
# GitHub push 전: exdev 런타임 주소를 커밋하지 않고 운영 기본값(172.16.180.130) 유지
# - 런타임(exdev): start-all-server.sh ENV / .env / EXDEV_LOCAL=true → 127.0.0.1·host.docker.internal
# - 커밋/push: application.yml·env.template·chatbot_tool_client.py 기본값을 운영 IP로 고정
PROD_WAS_HOST="172.16.180.130"
PROD_WAS_API="http://${PROD_WAS_HOST}:8086/api"
PROD_RAG_CHAT="http://${PROD_WAS_HOST}:28012/agent/chat"
PROD_MONGO_URI="mongodb://exDev:ehfhrhdtk!!@${PROD_WAS_HOST}:27017/chatbot?heartbeatFrequencyMS=30000&minPoolSize=8&maxIdleTimeMS=18000000"
# 운영 TROAD Oracle (start-all 은 SPRING_DATASOURCE_TROAD_* ENV 로 localhost 오버라이드)
PROD_TROAD_JDBC_URL="jdbc:oracle:thin:@172.16.163.76:1522/TROAD"
PROD_TROAD_USERNAME="TROAD_APP"
PROD_TROAD_PASSWORD='!ryxhdapp2025'
restore_production_endpoints_before_commit() {
local path="$1"
local dir="${ROOT_DIR}/${path}"
case "${path}" in
chatbotApi-chatbot2.0-agent)
local yml="${dir}/src/main/resources/application.yml"
if [[ -f "${yml}" ]]; then
# 수동/임시로 바꾼 로컬 Mongo URI 를 운영 기본값으로 복원 (start-all 은 ENV 로만 오버라이드)
# URI 의 @ 는 perl 치환부 배열 보간을 피하기 위해 ENV 로 전달
PROD_MONGO_URI="${PROD_MONGO_URI}" perl -i -pe \
's|uri:\s*mongodb://\S+|uri: $ENV{PROD_MONGO_URI}|g' "${yml}"
# troad datasource 를 로컬 Oracle 로 바꿔 둔 경우 운영값 복원
PROD_TROAD_JDBC_URL="${PROD_TROAD_JDBC_URL}" \
PROD_TROAD_USERNAME="${PROD_TROAD_USERNAME}" \
PROD_TROAD_PASSWORD="${PROD_TROAD_PASSWORD}" \
perl -i -0pe '
s|(troad:\s*\n(?:[ \t]+[^\n]*\n)*?[ \t]+url:\s*)\S+|$1$ENV{PROD_TROAD_JDBC_URL}|g;
s|(troad:\s*\n(?:[ \t]+[^\n]*\n)*?[ \t]+username:\s*)\S+|$1$ENV{PROD_TROAD_USERNAME}|g;
s|(troad:\s*\n(?:[ \t]+[^\n]*\n)*?[ \t]+password:\s*).*|$1"$ENV{PROD_TROAD_PASSWORD}"|g;
' "${yml}"
fi
;;
kakaoChatbotSkill-chatbot2.0-agent)
local yml="${dir}/src/main/resources/application.yml"
if [[ -f "${yml}" ]]; then
# ${ENV:default} 형태의 default 만 운영 IP로 고정 (실행 시 ENV 로컬 오버라이드는 유지)
PROD_WAS_API="${PROD_WAS_API}" PROD_RAG_CHAT="${PROD_RAG_CHAT}" PROD_WAS_HOST="${PROD_WAS_HOST}" \
perl -i -pe '
s|CHATBOT_API_BASE_URL:[^}]+}|CHATBOT_API_BASE_URL:$ENV{PROD_WAS_API}/}|g;
s|RAG_AGENT_CHAT_URL:[^}]+}|RAG_AGENT_CHAT_URL:$ENV{PROD_RAG_CHAT}}|g;
s|base-url:\s*http://127\.0\.0\.1:8086/api/?|base-url: \${CHATBOT_API_BASE_URL:$ENV{PROD_WAS_API}/}|g;
s|base-url:\s*http://host\.docker\.internal:8086/api/?|base-url: \${CHATBOT_API_BASE_URL:$ENV{PROD_WAS_API}/}|g;
s|url:\s*http://127\.0\.0\.1:28012/agent/chat|url: \${RAG_AGENT_CHAT_URL:$ENV{PROD_RAG_CHAT}}|g;
s|url:\s*http://host\.docker\.internal:28012/agent/chat|url: \${RAG_AGENT_CHAT_URL:$ENV{PROD_RAG_CHAT}}|g;
' "${yml}"
fi
;;
exAiChatBot-chatbot2.0-agent)
if [[ -f "${dir}/env.template" ]]; then
PROD_WAS_API="${PROD_WAS_API}" perl -i -pe \
's|^CHATBOT_API_BASE_URL=.*|CHATBOT_API_BASE_URL=$ENV{PROD_WAS_API}|' "${dir}/env.template"
# EXDEV_LOCAL 은 커밋 템플릿에 넣지 않음 (server-dev 전용)
perl -i -ne 'print unless /^EXDEV_LOCAL=/' "${dir}/env.template"
fi
if [[ -f "${dir}/env.example" ]]; then
PROD_WAS_API="${PROD_WAS_API}" perl -i -pe \
's|^CHATBOT_API_BASE_URL=.*|CHATBOT_API_BASE_URL=$ENV{PROD_WAS_API}|' "${dir}/env.example" 2>/dev/null || true
perl -i -ne 'print unless /^EXDEV_LOCAL=/' "${dir}/env.example" 2>/dev/null || true
fi
if [[ -f "${dir}/scripts/agent/chatbot_tool_client.py" ]]; then
# 운영 기본값(_PROD_WAS_API / legacy getenv default)만 복원.
PROD_WAS_API="${PROD_WAS_API}" perl -i -pe '
s|_PROD_WAS_API = "http://[^"]+"|_PROD_WAS_API = "$ENV{PROD_WAS_API}"|g;
s|os\.getenv\("TOOL_API_BASE_URL", "http://[^"]+"\)|os.getenv("TOOL_API_BASE_URL", "$ENV{PROD_WAS_API}")|g;
s|os\.getenv\("CHATBOT_API_BASE_URL", "http://[^"]+"\)|os.getenv("CHATBOT_API_BASE_URL", "$ENV{PROD_WAS_API}")|g;
' "${dir}/scripts/agent/chatbot_tool_client.py"
fi
# monorepo overlay compose 는 push 대상에서 제외 (로컬 exdev 전용)
git -C "${dir}" checkout HEAD -- docker-compose.server.yml docker-compose.local.yml 2>/dev/null || true
# .env 는 gitignore — 스테이징 실수 방지
git -C "${dir}" reset HEAD -- .env .env.local 2>/dev/null || true
rm -f "${dir}/.env.local" 2>/dev/null || true
;;
esac
}
# 복원 후에도 개발서버 전용 호스트가 커밋 대상 설정 파일에 남으면 push 중단
assert_no_exdev_endpoints_for_push() {
local path="$1"
local dir="${ROOT_DIR}/${path}"
local hits=""
case "${path}" in
chatbotApi-chatbot2.0-agent)
hits="$(grep -nE 'mongodb://(127\.0\.0\.1|localhost)|host\.docker\.internal|jdbc:oracle:thin:@(127\.0\.0\.1|localhost)' \
"${dir}/src/main/resources/application.yml" 2>/dev/null || true)"
# troad 블록이 로컬 계정(OPR_MAIN)으로 바뀌었는지도 차단
if awk '
/^[[:space:]]*troad:[[:space:]]*$/ { in_troad=1; next }
in_troad && /^[[:space:]]*[a-zA-Z0-9_-]+:[[:space:]]*$/ && $0 !~ /^[[:space:]]*troad:/ { in_troad=0 }
in_troad && /username:[[:space:]]*OPR_MAIN/ { found=1 }
END { exit found ? 0 : 1 }
' "${dir}/src/main/resources/application.yml" 2>/dev/null; then
hits+=$'\n'"troad.username=OPR_MAIN (exdev local Oracle — must not commit)"
fi
;;
kakaoChatbotSkill-chatbot2.0-agent)
hits="$(grep -nE '127\.0\.0\.1:(8086|28012)|host\.docker\.internal:(8086|28012)' \
"${dir}/src/main/resources/application.yml" 2>/dev/null || true)"
;;
exAiChatBot-chatbot2.0-agent)
hits="$(grep -nE '^(CHATBOT_API_BASE_URL|TOOL_API_BASE_URL)=.*(127\.0\.0\.1|host\.docker\.internal)|EXDEV_LOCAL=' \
"${dir}/env.template" "${dir}/env.example" 2>/dev/null || true)"
hits+="$(grep -nE 'getenv\(\"TOOL_API_BASE_URL\", \"http://(127\.0\.0\.1|host\.docker\.internal)' \
"${dir}/scripts/agent/chatbot_tool_client.py" 2>/dev/null || true)"
;;
esac
if [[ -n "${hits}" ]]; then
warn "${path}: 개발서버(exdev) 주소가 남아 push 중단"
echo "${hits}" | sed 's/^/ /'
warn "start-all-server.sh 런타임 ENV 로만 exdev 주소를 쓰고, 소스 기본값은 운영 IP 를 유지하세요"
return 1
fi
return 0
}
submodule_is_cloned() {
local path="$1"
[[ -e "${ROOT_DIR}/${path}/.git" ]]
}
fetch_one() {
local path="$1"
local url branch old new dirty
repo_is_dirty() {
! git diff --quiet || ! git diff --cached --quiet || [[ -n "$(git ls-files --others --exclude-standard)" ]]
}
url="$(git config -f .gitmodules "submodule.${path}.url")"
branch="$(git config -f .gitmodules "submodule.${path}.branch" || echo main)"
branch="${branch:-main}"
ensure_branch() {
local branch="$1"
local git_dir
# submodule 은 .git 이 파일일 수 있음 → rev-parse 사용
git_dir="$(git rev-parse --git-dir 2>/dev/null || echo .git)"
if [[ -d "${git_dir}/rebase-merge" || -d "${git_dir}/rebase-apply" ]]; then
warn "rebase 진행 중 — 수동 해결 후 재실행 (git rebase --continue / --abort)"
return 1
fi
if [[ -f "${git_dir}/MERGE_HEAD" ]]; then
warn "merge 진행 중 — 수동 해결 후 재실행"
return 1
fi
local cur
cur="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo DETACHED)"
if [[ "${cur}" == "${branch}" ]]; then
return 0
fi
if git show-ref --verify --quiet "refs/heads/${branch}"; then
git checkout "${branch}"
elif git show-ref --verify --quiet "refs/remotes/origin/${branch}"; then
git checkout -B "${branch}" "origin/${branch}"
else
git checkout -B "${branch}"
fi
}
sync_one() {
local path="$1"
local url branch old new stashed=0 ahead
url="$(git config -f .gitmodules "submodule.${path}.url" 2>/dev/null || true)"
if [[ -z "${url}" ]]; then
warn "${path} — .gitmodules 에 없음, 건너뜀"
return 1
fi
# 사용자 요구: main 금지, chatbot2.0-agent 고정
branch="$(git config -f .gitmodules "submodule.${path}.branch" || echo "${TARGET_BRANCH}")"
branch="${branch:-${TARGET_BRANCH}}"
if [[ "${branch}" != "${TARGET_BRANCH}" ]]; then
warn "${path} — .gitmodules branch=${branch} → ${TARGET_BRANCH} 로 강제"
branch="${TARGET_BRANCH}"
fi
log ">>> ${path}"
log " url=${url} branch=${branch}"
@@ -135,52 +312,152 @@ fetch_one() {
(
cd "${ROOT_DIR}/${path}"
if ! git diff --quiet || ! git diff --cached --quiet; then
dirty=yes
warn "${path} — 로컬 변경 있음 (fetch는 진행, fast-forward 실패 가능)"
else
dirty=no
fi
unset GIT_DIR GIT_WORK_TREE
old="$(git rev-parse HEAD 2>/dev/null || echo none)"
if $DRY_RUN; then
ensure_branch "${branch}" || true
git fetch origin "${branch}" 2>/dev/null || git fetch origin
new="$(git rev-parse "origin/${branch}" 2>/dev/null || echo unknown)"
if [[ "${old}" == "${new}" ]]; then
log " [dry-run] 이미 최신: ${old:0:7}"
log " [dry-run] 원격 최신: ${old:0:7}"
else
log " [dry-run] ${old:0:7} → ${new:0:7}"
git log --oneline "${old}..origin/${branch}" 2>/dev/null | sed 's/^/ /' || true
log " [dry-run] 원격 변경 ${old:0:7} → ${new:0:7}"
git log --oneline "HEAD..origin/${branch}" 2>/dev/null | sed 's/^/ /' || true
fi
if repo_is_dirty; then
log " [dry-run] 로컬 미커밋 변경 있음 → commit/push 대상"
git status -sb | sed 's/^/ /'
else
log " [dry-run] 로컬 미커밋 변경 없음"
fi
exit 0
fi
# 1) 원격 fetch + 브랜치 고정
git fetch origin "${branch}"
git checkout "${branch}" 2>/dev/null || git checkout -B "${branch}" "origin/${branch}"
ensure_branch "${branch}" || exit 1
git branch --set-upstream-to="origin/${branch}" "${branch}" 2>/dev/null || true
if git merge-base --is-ancestor HEAD "origin/${branch}" 2>/dev/null \
&& [[ "$(git rev-parse HEAD)" != "$(git rev-parse "origin/${branch}")" ]]; then
git merge --ff-only "origin/${branch}"
elif [[ "$(git rev-parse HEAD)" != "$(git rev-parse "origin/${branch}")" ]]; then
warn "${path} — fast-forward 불가 (로컬 커밋/변경 존재). 수동 merge 필요"
# 2) 로컬 미커밋 변경이 pull 을 막으면 stash
if repo_is_dirty; then
log " 로컬 변경 stash 후 원격 반영..."
git stash push -u -m "git_fetch_all auto-stash $(date '+%Y-%m-%d %H:%M:%S')" || true
stashed=1
fi
# 3) GitHub 변경사항 merge (ff → rebase → merge)
if [[ "$(git rev-parse HEAD)" != "$(git rev-parse "origin/${branch}")" ]]; then
log " 원격 변경 merge: origin/${branch}"
if git merge-base --is-ancestor HEAD "origin/${branch}" 2>/dev/null; then
git merge --ff-only "origin/${branch}"
else
if ! git pull --rebase origin "${branch}"; then
warn "${path} — rebase 실패, merge 로 재시도"
git rebase --abort 2>/dev/null || true
if ! git pull --no-rebase origin "${branch}"; then
warn "${path} — merge 충돌. 수동 해결 필요"
git status -sb | sed 's/^/ /'
if [[ "${stashed}" -eq 1 ]]; then
git stash pop || true
fi
exit 1
fi
fi
fi
ok "${path} 원격 반영 $(git log -1 --oneline)"
else
log " 원격과 동일 (fetch 완료)"
fi
# 4) stash 복원
if [[ "${stashed}" -eq 1 ]]; then
log " stash 복원..."
if ! git stash pop; then
warn "${path} — stash pop 충돌. 수동 해결 후 commit/push"
git status -sb | sed 's/^/ /'
exit 1
fi
fi
# 5) 로컬 수정사항 commit (exdev 주소는 복원 후·검증 통과 시에만)
if $DO_COMMIT && repo_is_dirty; then
log " 로컬 변경 commit..."
# push 전에 운영 WAS/RAG/Mongo 기본 주소 복원 (exdev 주소는 start-all-server.sh ENV 전용)
restore_production_endpoints_before_commit "${path}"
if ! assert_no_exdev_endpoints_for_push "${path}"; then
exit 1
fi
log " 운영 엔드포인트 기본값 유지: WAS ${PROD_WAS_API} / Mongo ${PROD_WAS_HOST}"
git add -A
# .env 등 ignore 대상이 스테이징되지 않도록 한 번 더 정리
git reset HEAD -- .env .env.local 2>/dev/null || true
if git diff --cached --quiet; then
log " staged 변경 없음 (ignore 된 파일만 있을 수 있음)"
else
# staged diff 에 exdev 호스트가 남아 있으면 push 금지
if git diff --cached -U0 | grep -E '^\+' | grep -qE '127\.0\.0\.1:(27017|8086|28012)|host\.docker\.internal|EXDEV_LOCAL=true'; then
warn "${path}: staged diff 에 개발서버 주소가 포함됨 — commit 중단"
git diff --cached --stat | sed 's/^/ /'
exit 1
fi
git commit -m "$(cat <<EOF
sync: monorepo local updates ($(date '+%Y-%m-%d %H:%M'))
git_fetch_all.sh 로 chatbot2.0-agent 동기화 후 로컬 수정을 반영한다.
EOF
)"
ok "${path} commit $(git log -1 --oneline)"
fi
elif ! $DO_COMMIT && repo_is_dirty; then
log " [--no-commit] 미커밋 변경 유지 (운영 주소 복원 미적용)"
git status -sb | sed 's/^/ /'
exit 1
fi
# 6) push (chatbot2.0-agent 만) — push 직전 운영 주소 재검증
if $DO_PUSH; then
restore_production_endpoints_before_commit "${path}"
if ! assert_no_exdev_endpoints_for_push "${path}"; then
exit 1
fi
# 복원으로 생긴 미커밋이 있으면 반영
if $DO_COMMIT && repo_is_dirty; then
git add -A
git reset HEAD -- .env .env.local 2>/dev/null || true
if ! git diff --cached --quiet; then
git commit -m "$(cat <<EOF
chore: restore production endpoints before push
git_fetch_all.sh — exdev 런타임 주소를 커밋에서 제거한다.
EOF
)"
fi
fi
ahead="$(git rev-list --count "origin/${branch}..HEAD" 2>/dev/null || echo 0)"
if [[ "${ahead}" != "0" ]]; then
log " push origin ${branch} (ahead ${ahead})..."
if git push origin "${branch}"; then
ok "${path} push 완료"
else
warn "${path} — push 실패 (대용량 파일/권한 등). 로그 확인"
exit 1
fi
else
log " push 생략 (원격과 동일)"
fi
else
log " [--no-push] push 생략"
fi
new="$(git rev-parse HEAD)"
if [[ "${old}" == "${new}" ]]; then
log " ✅ 최신 유지 $(git log -1 --oneline)"
else
log " ✅ 갱신 ${old:0:7} → ${new:0:7} $(git log -1 --oneline)"
fi
log " HEAD ${old:0:7} → ${new:0:7} $(git log -1 --oneline)"
)
}
failures=0
for path in "${SUBMODULE_PATHS[@]}"; do
if ! fetch_one "${path}"; then
for path in "${TARGET_PATHS[@]}"; do
if ! sync_one "${path}"; then
failures=$((failures + 1))
fi
echo ""
@@ -192,7 +469,12 @@ fi
log "=========================================="
log "submodule 상태:"
git submodule status || true
git submodule status 2>/dev/null || true
for path in "${TARGET_PATHS[@]}"; do
if submodule_is_cloned "${path}"; then
printf " %-36s %s\n" "${path}" "$(git -C "${ROOT_DIR}/${path}" log -1 --oneline 2>/dev/null || echo '?')"
fi
done
log "=========================================="
if [[ ${failures} -gt 0 ]]; then
@@ -200,5 +482,11 @@ if [[ ${failures} -gt 0 ]]; then
exit 1
fi
log "완료 — GitHub → 로컬 반영 (push 없음)"
log "monorepo 커밋 갱신: git add .gitmodules *-chatbot2.0-agent && git status"
if $DRY_RUN; then
log "완료 — dry-run (변경 없음)"
elif $DO_PUSH; then
log "완료 — ${TARGET_BRANCH}: fetch/merge → commit → push"
else
log "완료 — ${TARGET_BRANCH}: fetch/merge$($DO_COMMIT && echo ' → commit' || true) (push 생략)"
fi
log "monorepo 포인터 갱신: git add *-chatbot2.0-agent chatbotApp-test && git status"
Binary file not shown.
Regular → Executable
+3 -3
View File
@@ -1,3 +1,3 @@
run/
logs/
*.pid
run/
logs/
*.pid
Regular → Executable
+109 -109
View File
@@ -1,109 +1,109 @@
# 로컬 개발 — exdev AI 연동
로컬에서 **chatbotApi · chatbotApp · exAiChatBot · kakaoChatbotSkill** 을 실행하고,
**LLM / Embedding / Reranker** 는 SSH 터널로, **MongoDB / Qdrant** 는 `stock.exdev.co.kr` 원격 인스턴스를 사용합니다.
## exdev AI 구조
| 포트 | 서비스 | API |
|------|--------|-----|
| 16000 | MLX LLM | `/v1/chat/completions` |
| 16001 | Embedding (MPS) | `/embed` (`EMBED_API_STYLE=tei`) |
| 16002 | Reranker | `/rerank` (`RERANK_API_STYLE=legacy`) |
`https://chatbot.exdev.co.kr` 은 RAG API URL이며 LLM 직접 URL이 아닙니다.
## 한 번에 기동 / 중지
```bash
chmod +x local-dev/*.sh
./local-dev/stop-all.sh # 먼저 중지
./local-dev/start-all.sh # 전체 기동 + 헬스체크
# 옵션
./local-dev/start-all.sh --no-tunnel # AI 터널이 이미 떠 있을 때
./local-dev/start-all.sh --skip-java # Docker(RAG + chatbotApp)만
./local-dev/start-all.sh --no-build # RAG 이미지 빌드 생략
./local-dev/stop-all.sh --tunnel # SSH 터널까지 종료
```
- RAG는 **`docker-compose.local.yml`** 사용 (Mac Docker `:28012` 포트 바인딩)
- Mongo: `stock.exdev.co.kr:27017` / Qdrant: `http://stock.exdev.co.kr:6333/dashboard`
- 로컬 Mongo·Qdrant 컨테이너는 기동하지 않습니다
기동 후 UI: `http://localhost:8089/chatbot/app/`
---
## 1. exdev AI 기동 (서버에서 한 번)
exdev SSH 접속 후:
```bash
bash /Users/aidev/dev/exAIChatbot2.0/scripts/exdev/start-host-ai.sh
curl -s http://127.0.0.1:28012/health # llm/tei_embed/tei_rerank: true 확인
```
## 2. 로컬 SSH 터널
```bash
chmod +x local-dev/start-exdev-ai-tunnel.sh
./local-dev/start-exdev-ai-tunnel.sh
```
터널 확인:
```bash
curl -s http://127.0.0.1:16000/v1/models | head
curl -s http://127.0.0.1:16001/health
curl -s -X POST http://127.0.0.1:16002/rerank \
-H 'Content-Type: application/json' \
-d '{"query":"test","documents":["doc"]}'
```
## 3. exAiChatBot .env
```bash
cp local-dev/env.exdev-ai.template exAiChatBot-chatbot2.0-agent/.env
./local-dev/start-all.sh --skip-java --no-build # RAG만 (원격 Mongo/Qdrant)
curl -s http://127.0.0.1:28012/health
```
RAG 컨테이너는 `.env` 의 `MONGO_HOST` / `QDRANT_HOST` (= `stock.exdev.co.kr`) 로 원격 DB에 접속합니다.
## 4. Java 서비스 + chatbotApp
```bash
# WAS (Mongo → stock.exdev.co.kr)
cd chatbotApi-chatbot2.0-agent
export INTERNAL_TOOL_API_KEY=local-dev-key
export MONGODB_URI='mongodb://exDev:ehfhrhdtk!!@stock.exdev.co.kr:27017/chatbot?authSource=chatbot'
export SKILL_INTERNAL_BASE_URL=http://127.0.0.1:8083
./gradlew bootRun
# Skill
cd kakaoChatbotSkill-chatbot2.0-agent
export AGENT_MODE=agent
export RAG_AGENT_CHAT_URL=http://127.0.0.1:28012/agent/chat
export CHATBOT_API_BASE_URL=http://127.0.0.1:8086/api/
export INTERNAL_TOOL_API_KEY=local-dev-key
./gradlew bootRun
# UI
cd chatbotApp-chatbot2.0-agent
CHATBOT_API_UPSTREAM=http://host.docker.internal:8083/web/ \
CHATBOT_API_HOST=host.docker.internal ./start.sh
```
## api_clients.py 스타일 변수
| 변수 | exdev 값 | 설명 |
|------|----------|------|
| `EMBED_API_STYLE` | `tei` | `/embed` |
| `RERANK_API_STYLE` | `legacy` | `/rerank` |
| `EMBED_API_STYLE` | `openai` | 게이트웨이 `/v1/embeddings` |
| `RERANK_API_STYLE` | `gateway` | 게이트웨이 `/score` |
로컬 exdev 연동 시 **`tei` + `legacy`** 조합을 사용합니다.
# 로컬 개발 — exdev AI 연동
로컬에서 **chatbotApi · chatbotApp · exAiChatBot · kakaoChatbotSkill** 을 실행하고,
**LLM / Embedding / Reranker** 는 SSH 터널로, **MongoDB / Qdrant** 는 `stock.exdev.co.kr` 원격 인스턴스를 사용합니다.
## exdev AI 구조
| 포트 | 서비스 | API |
|------|--------|-----|
| 16000 | MLX LLM | `/v1/chat/completions` |
| 16001 | Embedding (MPS) | `/embed` (`EMBED_API_STYLE=tei`) |
| 16002 | Reranker | `/rerank` (`RERANK_API_STYLE=legacy`) |
`https://chatbot.exdev.co.kr` 은 RAG API URL이며 LLM 직접 URL이 아닙니다.
## 한 번에 기동 / 중지
```bash
chmod +x local-dev/*.sh
./local-dev/stop-all.sh # 먼저 중지
./local-dev/start-all.sh # 전체 기동 + 헬스체크
# 옵션
./local-dev/start-all.sh --no-tunnel # AI 터널이 이미 떠 있을 때
./local-dev/start-all.sh --skip-java # Docker(RAG + chatbotApp)만
./local-dev/start-all.sh --no-build # RAG 이미지 빌드 생략
./local-dev/stop-all.sh --tunnel # SSH 터널까지 종료
```
- RAG는 **`docker-compose.local.yml`** 사용 (Mac Docker `:28012` 포트 바인딩)
- Mongo: `stock.exdev.co.kr:27017` / Qdrant: `http://stock.exdev.co.kr:6333/dashboard`
- 로컬 Mongo·Qdrant 컨테이너는 기동하지 않습니다
기동 후 UI: `http://localhost:8089/chatbot/app/`
---
## 1. exdev AI 기동 (서버에서 한 번)
exdev SSH 접속 후:
```bash
bash /Users/aidev/dev/exAIChatbot2.0/scripts/exdev/start-host-ai.sh
curl -s http://127.0.0.1:28012/health # llm/tei_embed/tei_rerank: true 확인
```
## 2. 로컬 SSH 터널
```bash
chmod +x local-dev/start-exdev-ai-tunnel.sh
./local-dev/start-exdev-ai-tunnel.sh
```
터널 확인:
```bash
curl -s http://127.0.0.1:16000/v1/models | head
curl -s http://127.0.0.1:16001/health
curl -s -X POST http://127.0.0.1:16002/rerank \
-H 'Content-Type: application/json' \
-d '{"query":"test","documents":["doc"]}'
```
## 3. exAiChatBot .env
```bash
cp local-dev/env.exdev-ai.template exAiChatBot-chatbot2.0-agent/.env
./local-dev/start-all.sh --skip-java --no-build # RAG만 (원격 Mongo/Qdrant)
curl -s http://127.0.0.1:28012/health
```
RAG 컨테이너는 `.env` 의 `MONGO_HOST` / `QDRANT_HOST` (= `stock.exdev.co.kr`) 로 원격 DB에 접속합니다.
## 4. Java 서비스 + chatbotApp
```bash
# WAS (Mongo → stock.exdev.co.kr)
cd chatbotApi-chatbot2.0-agent
export INTERNAL_TOOL_API_KEY=local-dev-key
export MONGODB_URI='mongodb://exDev:ehfhrhdtk!!@stock.exdev.co.kr:27017/chatbot?authSource=chatbot'
export SKILL_INTERNAL_BASE_URL=http://127.0.0.1:8083
./gradlew bootRun
# Skill
cd kakaoChatbotSkill-chatbot2.0-agent
export AGENT_MODE=agent
export RAG_AGENT_CHAT_URL=http://127.0.0.1:28012/agent/chat
export CHATBOT_API_BASE_URL=http://127.0.0.1:8086/api/
export INTERNAL_TOOL_API_KEY=local-dev-key
./gradlew bootRun
# UI
cd chatbotApp-chatbot2.0-agent
CHATBOT_API_UPSTREAM=http://host.docker.internal:8083/web/ \
CHATBOT_API_HOST=host.docker.internal ./start.sh
```
## api_clients.py 스타일 변수
| 변수 | exdev 값 | 설명 |
|------|----------|------|
| `EMBED_API_STYLE` | `tei` | `/embed` |
| `RERANK_API_STYLE` | `legacy` | `/rerank` |
| `EMBED_API_STYLE` | `openai` | 게이트웨이 `/v1/embeddings` |
| `RERANK_API_STYLE` | `gateway` | 게이트웨이 `/score` |
로컬 exdev 연동 시 **`tei` + `legacy`** 조합을 사용합니다.
+132
View File
@@ -0,0 +1,132 @@
#!/usr/bin/env bash
# Minimal rsync stand-in for Windows Git Bash (tar-over-ssh).
# Supports the flags used by server-dev/sync-submodules-rsync.sh:
# rsync -az [--delete] [--exclude PATTERN ...] SRC/ HOST:DEST/
set -euo pipefail
DELETE=false
EXCLUDES=()
ARGS=()
while (($#)); do
case "$1" in
-az|-a|-z|-v|-q|-P|--progress) shift ;;
--delete) DELETE=true; shift ;;
--exclude)
EXCLUDES+=("$2"); shift 2 ;;
--exclude=*)
EXCLUDES+=("${1#--exclude=}"); shift ;;
-*)
# ignore unknown short/long flags used by callers
shift ;;
*)
ARGS+=("$1"); shift ;;
esac
done
if ((${#ARGS[@]} < 2)); then
echo "rsync-shim: need SRC and DEST" >&2
exit 1
fi
SRC="${ARGS[0]}"
DEST="${ARGS[1]}"
# Git Bash /d/foo → Windows D:/foo (OpenSSH scp 용)
to_win_path() {
local p="$1"
if [[ "${p}" =~ ^/([a-zA-Z])/(.*)$ ]]; then
local drive rest
drive="$(echo "${BASH_REMATCH[1]}" | tr 'a-z' 'A-Z')"
rest="${BASH_REMATCH[2]}"
echo "${drive}:/${rest}"
else
echo "${p}"
fi
}
copy_file_remote() {
local src_file="$1"
local dest="$2"
local win_src
win_src="$(to_win_path "${src_file}")"
if [[ -f "${win_src}" || -f "${src_file}" ]]; then
local local_src="${src_file}"
[[ -f "${win_src}" ]] && local_src="${win_src}"
scp -o BatchMode=yes -q "${local_src}" "${dest}" && return 0
fi
# fallback: tar stream single file
local base dir
base="$(basename "${src_file}")"
dir="$(cd "$(dirname "${src_file}")" && pwd)"
local host="${dest%%:*}"
local remote="${dest#*:}"
local remote_dir remote_base
if [[ "${remote}" == */ ]]; then
remote_dir="${remote%/}"
remote_base="${base}"
else
remote_dir="$(dirname "${remote}")"
remote_base="$(basename "${remote}")"
fi
ssh -o BatchMode=yes "${host}" "mkdir -p '${remote_dir}'"
tar -C "${dir}" -cf - "${base}" \
| ssh -o BatchMode=yes "${host}" "tar -C '${remote_dir}' -xf - && if [[ '${remote_base}' != '${base}' ]]; then mv '${remote_dir}/${base}' '${remote_dir}/${remote_base}'; fi"
}
# file → file copy (overlay yml etc.)
if [[ -f "${SRC}" && "${DEST}" == *:* ]]; then
copy_file_remote "${SRC}" "${DEST}"
exit 0
fi
# normalize trailing slash semantics like rsync SRC/
SRC_DIR="${SRC%/}"
if [[ ! -d "${SRC_DIR}" ]]; then
# allow copying a single file into a remote dir
if [[ -f "${SRC_DIR}" ]]; then
copy_file_remote "${SRC_DIR}" "${DEST}"
exit 0
fi
echo "rsync-shim: source not found: ${SRC}" >&2
exit 1
fi
if [[ "${DEST}" != *:* ]]; then
echo "rsync-shim: only remote DEST (host:path) supported" >&2
exit 1
fi
HOST="${DEST%%:*}"
REMOTE_PATH="${DEST#*:}"
REMOTE_PATH="${REMOTE_PATH%/}"
TAR_EXCLUDES=()
for pat in "${EXCLUDES[@]}"; do
# tar 의 --exclude 는 'node_modules/' 처럼 슬래시로 끝나면 디렉터리에 매칭되지 않는다.
# (rsync 문법 그대로 넘기면 node_modules 가 통째로 전송돼 메모리 부족으로 죽는다)
pat="${pat%/}"
if [[ "${pat}" == /* ]]; then
# rsync 의 선행 슬래시 = 전송 루트 기준 고정. tar 멤버명은 './' 로 시작한다.
TAR_EXCLUDES+=(--anchored --exclude ".${pat}")
else
TAR_EXCLUDES+=(--no-anchored --exclude "${pat}")
fi
done
ssh -o BatchMode=yes "${HOST}" "mkdir -p '${REMOTE_PATH}'"
if $DELETE; then
# wipe remote dir contents then unpack (approx --delete)
# 서버 public-* 등이 root/docker 소유일 수 있어 실패해도 이어서 덮어쓴다
ssh -o BatchMode=yes "${HOST}" \
"chmod -R u+w '${REMOTE_PATH}' 2>/dev/null || true; \
find '${REMOTE_PATH}' -mindepth 1 -maxdepth 1 -exec rm -rf {} + 2>/dev/null || true" \
|| true
fi
# shellcheck disable=SC2086
tar -C "${SRC_DIR}" "${TAR_EXCLUDES[@]}" -cf - . \
| ssh -o BatchMode=yes "${HOST}" "tar -C '${REMOTE_PATH}' -xf -"
echo "rsync-shim: synced ${SRC_DIR}/ -> ${HOST}:${REMOTE_PATH}/"
+53 -53
View File
@@ -1,53 +1,53 @@
# 로컬 Mac 개발용 (start-all.sh / stop-all.sh)
# - network_mode:host 미사용 → :28012 / :28013 호스트 바인딩
# - Mongo / Qdrant 는 stock.exdev.co.kr (로컬 컨테이너 미기동)
# - AI 는 host.docker.internal 경유 SSH 터널 (.env)
name: exchatbot-local
services:
api:
image: ${RAG_API_IMAGE:-rag-api-slim:latest}
build:
context: .
dockerfile: docker/service-slim.Dockerfile
ports:
- "${RAG_API_PORT:-28012}:28012"
extra_hosts:
- "host.docker.internal:host-gateway"
env_file:
- .env
environment:
UVICORN_WORKERS: "${UVICORN_WORKERS:-2}"
volumes:
- ./data:/app/data
- ./scripts:/app/scripts
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:28012/health"]
interval: 10s
timeout: 10s
retries: 12
start_period: 45s
admin:
image: ${RAG_API_IMAGE:-rag-api-slim:latest}
ports:
- "${ADMIN_PORT:-28013}:28013"
extra_hosts:
- "host.docker.internal:host-gateway"
command:
- python
- -m
- uvicorn
- scripts.admin_service:app
- --host
- 0.0.0.0
- --port
- "28013"
working_dir: /app
env_file:
- .env
volumes:
- ./data:/app/data
- ./scripts:/app/scripts
restart: unless-stopped
# 로컬 Mac 개발용 (start-all.sh / stop-all.sh)
# - network_mode:host 미사용 → :28012 / :28013 호스트 바인딩
# - Mongo / Qdrant 는 stock.exdev.co.kr (로컬 컨테이너 미기동)
# - AI 는 host.docker.internal 경유 SSH 터널 (.env)
name: exchatbot-local
services:
api:
image: ${RAG_API_IMAGE:-rag-api-slim:latest}
build:
context: .
dockerfile: docker/service-slim.Dockerfile
ports:
- "${RAG_API_PORT:-28012}:28012"
extra_hosts:
- "host.docker.internal:host-gateway"
env_file:
- .env
environment:
UVICORN_WORKERS: "${UVICORN_WORKERS:-2}"
volumes:
- ./data:/app/data
- ./scripts:/app/scripts
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:28012/health"]
interval: 10s
timeout: 10s
retries: 12
start_period: 45s
admin:
image: ${RAG_API_IMAGE:-rag-api-slim:latest}
ports:
- "${ADMIN_PORT:-28013}:28013"
extra_hosts:
- "host.docker.internal:host-gateway"
command:
- python
- -m
- uvicorn
- scripts.admin_service:app
- --host
- 0.0.0.0
- --port
- "28013"
working_dir: /app
env_file:
- .env
volumes:
- ./data:/app/data
- ./scripts:/app/scripts
restart: unless-stopped
Regular → Executable
+59 -56
View File
@@ -1,56 +1,59 @@
# =============================================================================
# 로컬 Mac/Docker + exdev(chatbot.exdev.co.kr) 호스트 AI (SSH 터널)
# 사용법:
# 1) ./local-dev/start-exdev-ai-tunnel.sh (별도 터미널 유지)
# 2) cp local-dev/env.exdev-ai.template exAiChatBot-chatbot2.0-agent/.env
# 3) exAiChatBot / chatbotApi / kakaoChatbotSkill / chatbotApp 기동
# =============================================================================
# ── exdev AI (Mac localhost:16000~16002 → SSH 터널) ──
# Docker Desktop(Mac): host.docker.internal
# Linux host network / 로컬 python: 127.0.0.1
LLM_BASE_URL=http://host.docker.internal:16000
TEI_EMBED_URL=http://host.docker.internal:16001
TEI_RERANK_URL=http://host.docker.internal:16002
# exdev Mac Studio 실제 모델명 (curl http://127.0.0.1:16000/v1/models 참고)
LLM_MODEL_NAME=mlx-community/Qwen2.5-7B-Instruct-4bit
EMBED_MODEL_NAME=Qwen/Qwen3-Embedding-8B
TEI_RERANK_MODEL=qwen3-reranker-4b
# exdev 호스트 AI API 스타일 (게이트웨이와 다름)
EMBED_API_STYLE=tei
RERANK_API_STYLE=legacy
MODEL_VERIFY_SSL=false
API_TIMEOUT=120
# 게이트웨이 키 불필요 (exdev 호스트 AI는 Bearer 없음)
MODEL_API_KEY=
# ── exdev MongoDB / Qdrant (stock.exdev.co.kr, 로컬 미기동) ──
EXDEV_DATA_HOST=stock.exdev.co.kr
MONGO_HOST=stock.exdev.co.kr
MONGO_PORT=27017
MONGO_USER=
MONGO_PASSWORD=
MONGO_DATABASE=chat_history
MONGO_COLLECTION=rag_conversations
VECTOR_STORE=qdrant
QDRANT_HOST=stock.exdev.co.kr
QDRANT_PORT=6333
# stock.exdev.co.kr 운영 컬렉션 (8488 vectors, 2026-07)
QDRANT_COLLECTION=qa_vectors
# chatbotApi (WAS) — stock MongoDB chatbot DB
MONGODB_URI=mongodb://exDev:ehfhrhdtk!!@stock.exdev.co.kr:27017/chatbot?authSource=chatbot&heartbeatFrequencyMS=30000&minPoolSize=3&maxIdleTimeMS=1800000
# ── 로컬 WAS / Skill 연동 ──
CHATBOT_API_BASE_URL=http://127.0.0.1:8086/api
INTERNAL_TOOL_API_KEY=local-dev-key
AGENT_MAX_ROUNDS=6
CHATBOT_TOOL_TIMEOUT=60
ADMIN_PORT=28013
UVICORN_WORKERS=2
# =============================================================================
# 로컬 Mac/Docker + exdev(chatbot.exdev.co.kr) 호스트 AI (SSH 터널)
# 사용법:
# 1) ./local-dev/start-exdev-ai-tunnel.sh (별도 터미널 유지)
# 2) cp local-dev/env.exdev-ai.template exAiChatBot-chatbot2.0-agent/.env
# 3) exAiChatBot / chatbotApi / kakaoChatbotSkill / chatbotApp 기동
# =============================================================================
# ── exdev AI (Mac localhost:16000~16002 → SSH 터널) ──
# Docker Desktop(Mac): host.docker.internal
# Linux host network / 로컬 python: 127.0.0.1
LLM_BASE_URL=http://host.docker.internal:16000
TEI_EMBED_URL=http://host.docker.internal:16001
TEI_RERANK_URL=http://host.docker.internal:16002
# exdev Mac Studio 실제 모델명 (curl http://127.0.0.1:16000/v1/models 참고)
LLM_MODEL_NAME=mlx-community/Qwen2.5-7B-Instruct-4bit
EMBED_MODEL_NAME=Qwen/Qwen3-Embedding-8B
TEI_RERANK_MODEL=qwen3-reranker-4b
# exdev 호스트 AI API 스타일 (게이트웨이와 다름)
EMBED_API_STYLE=tei
RERANK_API_STYLE=legacy
MODEL_VERIFY_SSL=false
API_TIMEOUT=120
# 게이트웨이 키 불필요 (exdev 호스트 AI는 Bearer 없음)
MODEL_API_KEY=
# ── exdev MongoDB / Qdrant (stock.exdev.co.kr, 로컬 미기동) ──
EXDEV_DATA_HOST=stock.exdev.co.kr
MONGO_HOST=stock.exdev.co.kr
MONGO_PORT=27017
MONGO_USER=
MONGO_PASSWORD=
MONGO_DATABASE=chat_history
MONGO_COLLECTION=rag_conversations
MONGO_FEEDBACK_DATABASE=chatbot
MONGO_FEEDBACK_COLLECTION=answer_feedback
MONGO_IMPROVEMENT_COLLECTION=improvement_suggestions
VECTOR_STORE=qdrant
QDRANT_HOST=stock.exdev.co.kr
QDRANT_PORT=6333
# stock.exdev.co.kr 운영 컬렉션 (8488 vectors, 2026-07)
QDRANT_COLLECTION=qa_vectors_v2
# chatbotApi (WAS) — stock MongoDB chatbot DB
MONGODB_URI=mongodb://exDev:ehfhrhdtk!!@stock.exdev.co.kr:27017/chatbot?authSource=chatbot&heartbeatFrequencyMS=30000&minPoolSize=3&maxIdleTimeMS=1800000
# ── 로컬 WAS / Skill 연동 ──
CHATBOT_API_BASE_URL=http://127.0.0.1:8086/api
INTERNAL_TOOL_API_KEY=local-dev-key
AGENT_MAX_ROUNDS=6
CHATBOT_TOOL_TIMEOUT=60
ADMIN_PORT=28013
UVICORN_WORKERS=2
+29
View File
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
# Windows (Git Bash) helper for ./start-all-server.sh
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
export PATH="${ROOT_DIR}/local-dev/bin:/c/Program Files/nodejs:/c/Program Files/Git/usr/bin:${PATH}"
export GIT_SSH_COMMAND="${GIT_SSH_COMMAND:-ssh -o BatchMode=yes -o ConnectTimeout=20}"
# Git Bash/MSYS 가 /chatbot/app 같은 env 를 Windows 경로로 바꾸지 않게
export MSYS_NO_PATHCONV=1
export MSYS2_ARG_CONV_EXCL='*'
# Prefer Windows OpenSSH (has the exdev key)
if [[ -x /c/Windows/System32/OpenSSH/ssh.exe ]]; then
export GIT_SSH_COMMAND="/c/Windows/System32/OpenSSH/ssh.exe -o BatchMode=yes -o ConnectTimeout=20"
export PATH="/c/Windows/System32/OpenSSH:${PATH}"
fi
cd "${ROOT_DIR}"
echo "[windows] node=$(command -v node) $(node -v 2>/dev/null || true)"
echo "[windows] npm=$(command -v npm)"
echo "[windows] rsync=$(command -v rsync)"
echo "[windows] ssh=$(command -v ssh)"
# smoke checks
ssh -o BatchMode=yes -o ConnectTimeout=15 aidev@chatbot.exdev.co.kr 'echo SSH_CHATBOT_OK'
git ls-remote origin HEAD >/dev/null
echo "[windows] Gitea git OK"
exec bash ./start-all-server.sh "$@"
+43 -8
View File
@@ -1,11 +1,13 @@
#!/usr/bin/env bash
# 로컬 전체 스택 기동 (exdev AI SSH 터널 + 원격 Mongo/Qdrant + RAG + WAS + Skill + chatbotApp)
# 로컬 전체 스택 기동 (exdev AI SSH 터널 + 원격 Mongo/Qdrant + RAG + WAS + Skill + chatbotApp + Desktop)
# Mongo/Qdrant 는 stock.exdev.co.kr 를 사용 (로컬 컨테이너 미기동)
#
# ./local-dev/start-all.sh
# ./start-all.sh # 루트 래퍼
# ./local-dev/start-all.sh --no-tunnel
# ./local-dev/start-all.sh --skip-java
# ./local-dev/start-all.sh --no-build
# ./local-dev/start-all.sh --no-build # RAG/웹/데스크톱 빌드 생략
# ./local-dev/start-all.sh --skip-desktop # Electron 재빌드만 생략
#
# 종료: ./local-dev/stop-all.sh
set -euo pipefail
@@ -19,6 +21,7 @@ RAG_DIR="${ROOT_DIR}/exAiChatBot-chatbot2.0-agent"
API_DIR="${ROOT_DIR}/chatbotApi-chatbot2.0-agent"
SKILL_DIR="${ROOT_DIR}/kakaoChatbotSkill-chatbot2.0-agent"
APP_DIR="${ROOT_DIR}/chatbotApp-chatbot2.0-agent"
DESKTOP_DIR="${ROOT_DIR}/chatbotDesktopApp-chatbot2.0"
ENV_TEMPLATE="${LOCAL_DEV_DIR}/env.exdev-ai.template"
RAG_ENV="${RAG_DIR}/.env"
@@ -42,17 +45,19 @@ QDRANT_PORT="${QDRANT_PORT:-6333}"
SKIP_TUNNEL=false
SKIP_JAVA=false
NO_BUILD=false
SKIP_DESKTOP=false
for arg in "$@"; do
case "$arg" in
--no-tunnel) SKIP_TUNNEL=true ;;
--skip-java) SKIP_JAVA=true ;;
--no-build) NO_BUILD=true ;;
--skip-desktop) SKIP_DESKTOP=true ;;
--sync-qdrant)
echo "경고: 원격 Qdrant 사용 중이라 --sync-qdrant 는 무시됩니다."
;;
-h|--help)
sed -n '2,12p' "$0"
sed -n '2,14p' "$0"
exit 0
;;
*)
@@ -159,6 +164,7 @@ ensure_rag_env() {
patch_env "TEI_RERANK_URL" "http://host.docker.internal:${RERANK_PORT}"
patch_env "EMBED_API_STYLE" "tei"
patch_env "RERANK_API_STYLE" "legacy"
patch_env "EXDEV_LOCAL" "true"
patch_env "CHATBOT_API_BASE_URL" "http://host.docker.internal:${WAS_PORT}/api"
patch_env "INTERNAL_TOOL_API_KEY" "${INTERNAL_TOOL_API_KEY}"
@@ -171,7 +177,7 @@ ensure_rag_env() {
patch_env "MONGO_DATABASE" "chat_history"
patch_env "QDRANT_HOST" "${EXDEV_DATA_HOST}"
patch_env "QDRANT_PORT" "${QDRANT_PORT}"
patch_env "QDRANT_COLLECTION" "qa_vectors"
patch_env "QDRANT_COLLECTION" "qa_vectors_v2"
}
ensure_remote_data() {
@@ -288,7 +294,7 @@ verify_stack() {
curl -sf "http://127.0.0.1:${RAG_PORT}/health" | grep -q '"status"' || { log "❌ RAG health"; ok=false; }
wait_port "${WAS_PORT}" "chatbotApi" 5 || ok=false
wait_port "${SKILL_PORT}" "kakaoChatbotSkill" 5 || ok=false
curl -sf "http://127.0.0.1:${APP_PORT}/chatbot/app/" | grep -q 'data-chatbot-app' || { log "❌ chatbotApp UI"; ok=false; }
curl -sf "http://127.0.0.1:${APP_PORT}/chatbot/ai/" | grep -q 'data-chatbot-app' || { log "❌ chatbotApp UI"; ok=false; }
if $ok; then
log "✅ 전체 스택 정상"
@@ -298,6 +304,32 @@ verify_stack() {
return 1
}
build_chatbot_app() {
if $NO_BUILD && [[ -f "${APP_DIR}/public-ai/index.html" ]]; then
log "chatbotApp 빌드 생략 (--no-build)"
return 0
fi
log "chatbotApp Next.js 빌드 (수정사항 반영)..."
(
cd "${APP_DIR}/web"
npm ci --prefer-offline 2>/dev/null || npm install
)
# 로컬에는 운영 업무 DB가 없으므로 미납/환불 조회만 2초·1건 목업으로 빌드한다.
NEXT_PUBLIC_FARE_QUERY_MOCK=true bash "${APP_DIR}/build.sh"
[[ -f "${APP_DIR}/public-ai/index.html" ]] || fail "chatbotApp public-ai/ 빌드 실패"
}
build_desktop_app() {
if $NO_BUILD || $SKIP_DESKTOP; then
log "데스크톱 앱 빌드 생략 (--no-build/--skip-desktop)"
return 0
fi
[[ -d "${DESKTOP_DIR}" ]] || fail "데스크톱 앱 디렉터리 없음: ${DESKTOP_DIR}"
chmod +x "${DESKTOP_DIR}/build-and-publish.sh"
# 로컬은 Mac 위주 — Windows 크로스빌드는 시간이 길어 SKIP_WIN 기본 1 (서버 배포는 Win 포함)
SKIP_WIN="${SKIP_WIN:-1}" bash "${DESKTOP_DIR}/build-and-publish.sh"
}
# ── main ──
mkdir -p "${RUN_DIR}" "${LOG_DIR}"
@@ -332,12 +364,15 @@ if ! $SKIP_JAVA; then
"RAG_AGENT_CHAT_URL=http://127.0.0.1:${RAG_PORT}/agent/chat" \
"CHATBOT_API_BASE_URL=http://127.0.0.1:${WAS_PORT}/api/" \
"INTERNAL_TOOL_API_KEY=${INTERNAL_TOOL_API_KEY}" \
"CHATBOT_APP_URL=http://localhost:${APP_PORT}/chatbot/app/"
"CHATBOT_APP_URL=http://localhost:${APP_PORT}/chatbot/ai/"
wait_port "${WAS_PORT}" "chatbotApi" 240 || true
wait_port "${SKILL_PORT}" "kakaoChatbotSkill" 240 || true
fi
build_chatbot_app
build_desktop_app
log "chatbotApp 기동..."
docker rm -f ex-chatbot-app-web 2>/dev/null || true
(
@@ -347,11 +382,11 @@ docker rm -f ex-chatbot-app-web 2>/dev/null || true
docker compose up -d --force-recreate
)
wait_http "http://127.0.0.1:${APP_PORT}/chatbot/app/" "chatbotApp UI" 30 || true
wait_http "http://127.0.0.1:${APP_PORT}/chatbot/ai/" "chatbotApp UI" 30 || true
log "=========================================="
log "기동 완료"
log " UI http://127.0.0.1:${APP_PORT}/chatbot/app/"
log " UI http://127.0.0.1:${APP_PORT}/chatbot/ai/"
log " RAG http://127.0.0.1:${RAG_PORT}/health"
log " Admin http://127.0.0.1:${ADMIN_PORT}/"
log " Mongo ${EXDEV_DATA_HOST}:${MONGO_PORT} (원격, RAG+WAS)"
+526
View File
@@ -0,0 +1,526 @@
#!/usr/bin/env python3
"""간편조회 파라미터 분기(폼/부분선택/상세/위치/별칭) 구어체 테스트 → test.csv
운영 예:
PYTHONUNBUFFERED=1 python3 scripts/quick_inquiry_branch_test.py \\
--base https://chatbot.ex.co.kr/chatbot --insecure \\
--out test.csv --sleep-ask 2.0 --sleep-domain 1.2
"""
from __future__ import annotations
import argparse
import csv
import json
import re
import ssl
import time
import urllib.error
import urllib.request
from collections import Counter
from datetime import datetime
from typing import Any, Dict, List, Optional, Tuple
_SSL_CTX = ssl.create_default_context()
FIELDNAMES = [
"tested_at",
"feature",
"param_tier", # none | partial | full | alias | location
"expected_mode", # form | detail | clarify | list | location
"expected_intent",
"mode", # ask | domain-query
"question",
"params",
"http_status",
"elapsed_sec",
"actual_intent",
"actual_mode",
"api_status",
"route_type",
"form_flags",
"answer",
"result",
"reason",
"note",
]
def one_line(text: str, limit: int = 260) -> str:
t = re.sub(r"\s+", " ", (text or "").strip())
return (t[: limit - 1] + "…") if len(t) > limit else t
def post_json(url: str, body: Dict[str, Any], timeout: float) -> Tuple[Optional[int], Any, float]:
t0 = time.time()
data = json.dumps(body, ensure_ascii=False).encode("utf-8")
req = urllib.request.Request(
url, data=data, headers={"Content-Type": "application/json; charset=utf-8"}
)
try:
with urllib.request.urlopen(req, timeout=timeout, context=_SSL_CTX) as resp:
raw = resp.read().decode("utf-8", errors="replace")
try:
return resp.status, json.loads(raw), time.time() - t0
except json.JSONDecodeError:
return resp.status, raw, time.time() - t0
except urllib.error.HTTPError as e:
try:
payload = e.read().decode("utf-8", errors="replace")
try:
return e.code, json.loads(payload), time.time() - t0
except Exception:
return e.code, payload, time.time() - t0
except Exception:
return e.code, str(e), time.time() - t0
except Exception as e:
return None, str(e), time.time() - t0
def extract_answer(body: Any) -> str:
if not isinstance(body, dict):
return one_line(str(body))
for key in ("answer", "message", "text", "statusMsg", "llmSummary"):
val = body.get(key)
if isinstance(val, str) and val.strip():
return one_line(val)
dd = body.get("domainData")
if isinstance(dd, dict):
for key in ("llmSummary", "statusMsg", "answer"):
val = dd.get(key)
if isinstance(val, str) and val.strip():
return one_line(val)
return one_line(json.dumps(body, ensure_ascii=False))
def form_flags(body: Any) -> str:
flags = []
if not isinstance(body, dict):
return ""
dd = body.get("domainData") if isinstance(body.get("domainData"), dict) else {}
raw = body.get("rawData") if isinstance(body.get("rawData"), dict) else {}
raw_dd = raw.get("domainData") if isinstance(raw.get("domainData"), dict) else {}
for src in (body, dd, raw, raw_dd):
for k, v in src.items():
if str(k).startswith("needs") and v:
flags.append(f"{k}={v}")
if src.get("needsClarification"):
flags.append("needsClarification=True")
if src.get("listMode"):
flags.append(f"listMode={src.get('listMode')}")
# dedupe
seen = set()
out = []
for f in flags:
if f not in seen:
seen.add(f)
out.append(f)
return ";".join(out)
def detect_mode(body: Any, answer: str) -> str:
"""응답을 form/detail/clarify/list/location 으로 분류."""
if not isinstance(body, dict):
return "unknown"
flags = form_flags(body)
route = str(body.get("routeType") or "")
dd = body.get("domainData") if isinstance(body.get("domainData"), dict) else {}
ans = answer or ""
# 구체 데이터(전화·요금 등)가 있으면 form 플래그보다 detail 우선
if re.search(r"0\d{1,2}-\d{3,4}-\d{4}", ans) or "연락처입니다" in ans:
return "detail"
if route == "clarify" or "needsClarification=True" in flags:
return "clarify"
if "위치정보" in ans or ("동의" in ans and "위치" in ans):
return "location"
if any(p in ans for p in ("선택하면", "선택해 주세요", "알려주세요", "어느 노선", "어느 방향", "차량번호가 필요")):
if any(x in flags for x in ("needsRestAreaForm=True", "needsIcTelForm=True")):
return "form"
return "clarify"
if any(x in flags for x in ("needsRestAreaForm=True", "needsIcTelForm=True")):
return "form"
lst = dd.get("list") or dd.get("items")
if isinstance(lst, list) and len(lst) > 0:
return "list"
if any(
k in ans
for k in ("전화", "원", "km/h", "메뉴", "유가", "충전", "구조", "공사", "정체", "서행", "주소")
):
return "detail"
if body.get("status") is True and len(ans) > 15:
return "detail"
return "unknown"
def scenarios() -> List[Dict[str, Any]]:
"""기능 × 파라미터 단계 × 구어체/별칭/위치."""
rows: List[Dict[str, Any]] = []
def ask(
feature: str,
tier: str,
expected_mode: str,
intent: str,
question: str,
note: str = "",
) -> None:
rows.append(
{
"mode": "ask",
"feature": feature,
"param_tier": tier,
"expected_mode": expected_mode,
"expected_intent": intent,
"question": question,
"params": {},
"note": note,
}
)
def domain(
feature: str,
tier: str,
expected_mode: str,
intent: str,
question: str,
params: Dict[str, str],
note: str = "",
) -> None:
rows.append(
{
"mode": "domain-query",
"feature": feature,
"param_tier": tier,
"expected_mode": expected_mode,
"expected_intent": intent,
"question": question,
"params": params,
"note": note,
}
)
# ---- 정체/혼잡 ----
ask("노선혼잡", "none", "clarify", "TROAD_CONGESTION", "고속도로 정체구간 알려줘")
ask("노선혼잡", "none", "clarify", "TROAD_CONGESTION", "지금 어디가 막혀?")
ask("노선혼잡", "partial", "detail", "TROAD_CONGESTION", "경부선에 정체구간 있어?")
ask("노선혼잡", "partial", "detail", "TROAD_CONGESTION", "영동선 지금 막혀?")
ask("노선혼잡", "alias", "detail", "TROAD_CONGESTION", "경부고속도로 정체 어때?")
ask(
"노선혼잡",
"location",
"location",
"TROAD_CONGESTION",
"이 근처에 정체되는 구간 있어?",
"GPS 동의/근처 영업소 파생 가능",
)
domain(
"노선혼잡",
"full",
"detail",
"TROAD_CONGESTION",
"경부선 정체 상세",
{"routeName": "경부선"},
)
# ---- 영업소 정보 ----
ask("영업소정보", "none", "form", "IC_TEL", "영업소 전화번호 좀 알려줘")
ask("영업소정보", "full", "detail", "IC_TEL", "판교 톨게이트 전화번호 좀")
ask("영업소정보", "alias", "detail", "IC_TEL", "동김천 톨게이트 번호 뭐야?")
ask("영업소정보", "alias", "detail", "IC_TEL", "동김천ic 연락처 알려줘")
ask("영업소정보", "alias", "detail", "IC_TEL", "동감천 톨게이트 전화 있어?") # 오표기
ask("영업소정보", "alias", "detail", "IC_TEL", "판교영업소 대표번호")
ask(
"영업소정보",
"location",
"location",
"IC_TEL",
"여기 근처 영업소 전화번호 알려줘",
"위치기반 폼/상세",
)
domain("영업소정보", "none", "form", "IC_TEL", "영업소 조회 폼", {})
domain("영업소정보", "full", "detail", "IC_TEL", "동김천 상세", {"icName": "동김천"})
# ---- 통행요금 ----
ask("구간통행요금", "none", "clarify", "FARE_SEARCH", "톨비 얼마야?")
ask("구간통행요금", "partial", "clarify", "FARE_SEARCH", "서울에서 출발하면 요금 얼마야?")
ask("구간통행요금", "full", "detail", "FARE_SEARCH", "서울에서 부산까지 톨비 얼마 나와?")
ask("구간통행요금", "alias", "detail", "FARE_SEARCH", "판교IC에서 신갈 톨게이트까지 요금 어때?")
ask("구간통행요금", "alias", "detail", "FARE_SEARCH", "판교 영업소에서 수원까지 하이패스 얼마야?")
# ---- 통행시간 ----
ask("구간통행시간", "none", "clarify", "TROAD_TRAVEL_TIME", "지금 고속도로 얼마나 걸려?")
ask("구간통행시간", "full", "detail", "TROAD_TRAVEL_TIME", "서울에서 부산까지 지금 가면 얼마나 걸려?")
ask("구간통행시간", "alias", "detail", "TROAD_TRAVEL_TIME", "판교에서 신갈 지금 막혀? 몇 분 걸려?")
# ---- 교통속보 ----
ask("노선별교통속보", "none", "clarify", "TROAD_BREAKING_NEWS", "고속도로에 사고 났다는데 어디야?")
ask("노선별교통속보", "partial", "detail", "TROAD_BREAKING_NEWS", "경부선에 사고 났어?")
ask("노선별교통속보", "alias", "detail", "TROAD_BREAKING_NEWS", "영동고속도로 교통속보 있어?")
# ---- 차단계획 ----
ask("차단계획", "none", "clarify", "CONSTRUCTION_PLAN", "고속도로 공사하는 데 있어?")
ask("차단계획", "partial", "detail", "CONSTRUCTION_PLAN", "경부선 오늘 공사해서 막히는 데 있어?")
ask("차단계획", "alias", "detail", "CONSTRUCTION_PLAN", "경부고속도로 차로 막는 일정 있나?")
domain(
"차단계획",
"partial",
"detail",
"CONSTRUCTION_PLAN",
"영동선 차단계획",
{"routeName": "영동선"},
)
# ---- 긴급구조 ----
ask("긴급구조기관", "none", "form", "EMERGENCY_HELP_ORG", "고속도로에서 사고 나면 어디로 연락해?")
ask("긴급구조기관", "partial", "form", "EMERGENCY_HELP_ORG", "경부선 긴급구조기관 알려줘")
ask("긴급구조기관", "alias", "form", "EMERGENCY_HELP_ORG", "경부고속도로 긴급구조대 어디야?")
domain("긴급구조기관", "none", "form", "EMERGENCY_HELP_ORG", "긴급구조 폼", {})
domain(
"긴급구조기관",
"partial",
"form",
"EMERGENCY_HELP_ORG",
"경부선 선택 폼",
{"routeName": "경부선"},
)
# ---- 휴게소 음식/브랜드/시설 ----
ask("휴게소음식", "none", "clarify", "REST_AREA_FOOD_LIST", "휴게소에서 뭐 먹지?")
ask("휴게소음식", "full", "detail", "REST_AREA_FOOD_LIST", "죽전휴게소에서 뭐 먹을 거 있어?")
ask("휴게소음식", "alias", "detail", "REST_AREA_FOOD_LIST", "죽전 휴게소 밥 뭐 파나?")
ask("휴게소브랜드매장", "none", "clarify", "BRAND_SHOP", "휴게소에 카페 있어?")
ask("휴게소브랜드매장", "full", "detail", "BRAND_SHOP", "김천휴게소에 브랜드 매장 뭐 있어?")
ask("휴게소브랜드매장", "alias", "detail", "BRAND_SHOP", "안성 휴게소에 편의점 있나?")
ask("휴게소시설", "none", "clarify", "REST_AREA_FACILITY", "휴게소에 수유실 있어?")
ask("휴게소시설", "full", "detail", "REST_AREA_FACILITY", "죽전휴게소에 수유실 있나?")
ask("휴게소시설", "alias", "detail", "REST_AREA_FACILITY", "안성SA 샤워실 쓸 수 있어?")
# ---- 주유 ----
ask("휴게소주유", "none", "form", "GASSTATION", "고속도로 기름값 얼마야?")
ask("휴게소주유", "full", "detail", "GASSTATION", "죽전휴게소 기름값 얼마야?")
ask("휴게소주유", "partial", "detail", "GASSTATION", "경부선에서 기름 제일 싼 데 어디야?")
ask("휴게소주유", "alias", "detail", "GASSTATION", "안성 휴게소 휘발유값 어때?")
domain("휴게소주유", "none", "form", "GASSTATION", "주유 폼", {})
# ---- 충전 ----
ask("휴게소충전소", "none", "form", "REST_AREA_CHARGING", "고속도로에 전기차 충전소 있어?")
ask("휴게소충전소", "full", "detail", "REST_AREA_CHARGING", "죽전에서 전기차 충전돼?")
ask("휴게소충전소", "partial", "form", "REST_AREA_CHARGING", "경부선에 충전되는 휴게소 어디 있어?")
ask("휴게소충전소", "alias", "detail", "REST_AREA_CHARGING", "강릉휴게소충전소 있어?")
ask("휴게소충전소", "alias", "detail", "REST_AREA_CHARGING", "김천 휴게소에서 수소차 충전해?")
domain("휴게소충전소", "none", "form", "REST_AREA_CHARGING", "충전 폼", {})
domain(
"휴게소충전소",
"partial",
"form",
"REST_AREA_CHARGING",
"경부선 충전 폼",
{"routeName": "경부선"},
)
# ---- 청년창업 ----
ask("휴게소청년창업매장", "none", "form", "REST_AREA_YOUTH_SHOP", "고속도로에 청년창업 매장 있어?")
ask("휴게소청년창업매장", "full", "detail", "REST_AREA_YOUTH_SHOP", "죽전휴게소에 청년들 장사하는 가게 있어?")
ask(
"휴게소청년창업매장",
"alias",
"detail",
"REST_AREA_YOUTH_SHOP",
"안성 휴게소 청년몰 있나?",
)
# ---- 가까운 휴게소 ----
ask("가까운휴게소", "partial", "detail", "REST_AREA_NEAREST", "판교 근처 휴게소 어디 있어?")
ask(
"가까운휴게소",
"location",
"location",
"REST_AREA_NEAREST",
"여기 제일 가까운 휴게소 어디야?",
"GPS 경로",
)
ask("가까운휴게소", "alias", "detail", "REST_AREA_NEAREST", "기흥IC 근처에 쉴 데 있어?")
# ---- 미납/환불 (파라미터=차량번호) ----
ask("미납조회", "none", "clarify", "FARE_UNPAID", "미납요금 조회해줘")
ask("미납조회", "full", "detail", "FARE_UNPAID", "야 내 차 12가3456인데 미납 있어?")
ask("환불조회", "none", "clarify", "FARE_REFUND", "톨비 환불받을 거 있어?")
ask("환불조회", "full", "detail", "FARE_REFUND", "하이패스 환불금 들어왔나? 서울33하1122")
return rows
def mode_match(expected: str, actual: str) -> bool:
if expected == actual:
return True
# form↔clarify 는 둘 다 '추가 선택 유도'로 허용
if {expected, actual} <= {"form", "clarify"}:
return True
# location 질문은 form/clarify/detail 도 허용(클라이언트 GPS 없을 때)
if expected == "location" and actual in {"location", "form", "clarify", "detail"}:
return True
# list 는 detail 상위 개념으로 허용
if expected == "detail" and actual in {"detail", "list"}:
return True
if expected == "list" and actual in {"list", "form", "detail"}:
return True
return False
def intent_ok(expected: str, actual: str) -> bool:
if not actual:
return False
if actual == expected:
return True
aliases = {
"TROAD_BREAKING_NEWS": {"TROAD_BREAKING_NEWS", "TRAFFIC_NEWS"},
"TROAD_CONGESTION": {"TROAD_CONGESTION"},
"BRAND_SHOP": {"BRAND_SHOP", "REST_AREA_FACILITY"}, # 편의점 질문은 시설로도 갈 수 있음
}
return actual in aliases.get(expected, {expected})
def judge(
expected_intent: str,
actual_intent: str,
expected_mode: str,
actual_mode: str,
http_st: Optional[int],
answer: str,
) -> Tuple[str, str]:
if http_st != 200:
return "FAIL", f"HTTP {http_st}"
natural = len(answer or "") >= 6
i_ok = intent_ok(expected_intent, actual_intent)
m_ok = mode_match(expected_mode, actual_mode)
if i_ok and m_ok and natural:
return "PASS", "의도·응답모드 적합"
if i_ok and natural:
return "PARTIAL", f"모드상이 expected={expected_mode} actual={actual_mode}"
if m_ok and natural:
return "PARTIAL", f"의도상이 expected={expected_intent} actual={actual_intent or '-'}"
if natural:
return "PARTIAL", "응답만 존재"
return "FAIL", "응답 불량"
def append_row(path: str, row: Dict[str, str], write_header: bool) -> None:
with open(path, "a", newline="", encoding="utf-8-sig") as f:
w = csv.DictWriter(f, fieldnames=FIELDNAMES)
if write_header:
w.writeheader()
w.writerow(row)
f.flush()
def main() -> int:
global _SSL_CTX
ap = argparse.ArgumentParser()
ap.add_argument("--base", default="https://chatbot.ex.co.kr/chatbot")
ap.add_argument("--out", default="test.csv")
ap.add_argument("--timeout-ask", type=float, default=90.0)
ap.add_argument("--timeout-domain", type=float, default=45.0)
ap.add_argument("--sleep-ask", type=float, default=2.0)
ap.add_argument("--sleep-domain", type=float, default=1.2)
ap.add_argument("--insecure", action="store_true")
ap.add_argument("--limit", type=int, default=0)
ap.add_argument("--skip-domain", action="store_true")
ap.add_argument("--skip-ask", action="store_true")
args = ap.parse_args()
if args.insecure:
_SSL_CTX = ssl._create_unverified_context()
base = args.base.rstrip("/")
ask_url = base + "/ask"
domain_url = base + "/domain-query"
started = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
open(args.out, "w", encoding="utf-8-sig").close()
header = True
results: List[str] = []
suite = scenarios()
if args.skip_ask:
suite = [c for c in suite if c["mode"] != "ask"]
if args.skip_domain:
suite = [c for c in suite if c["mode"] != "domain-query"]
if args.limit > 0:
suite = suite[: args.limit]
total = len(suite)
for i, case in enumerate(suite, 1):
print(f"({i}/{total}) {case['mode']} {case['feature']} [{case['param_tier']}] {case['question'][:40]}", flush=True)
if case["mode"] == "ask":
http_st, body, elapsed = post_json(
ask_url,
{"query": case["question"], "botId": f"branch-ask-{i}"},
args.timeout_ask,
)
sleep = args.sleep_ask
else:
http_st, body, elapsed = post_json(
domain_url,
{
"intentType": case["expected_intent"],
"params": case["params"],
"botId": f"branch-dom-{i}",
},
args.timeout_domain,
)
sleep = args.sleep_domain
answer = extract_answer(body)
actual_intent = ""
api_status = ""
route_type = ""
if isinstance(body, dict):
actual_intent = str(body.get("intentType") or "")
api_status = str(body.get("status"))
route_type = str(body.get("routeType") or "")
if case["mode"] == "domain-query" and not actual_intent:
actual_intent = case["expected_intent"]
actual_mode = detect_mode(body, answer)
result, reason = judge(
case["expected_intent"],
actual_intent,
case["expected_mode"],
actual_mode,
http_st,
answer,
)
row = {
"tested_at": started,
"feature": case["feature"],
"param_tier": case["param_tier"],
"expected_mode": case["expected_mode"],
"expected_intent": case["expected_intent"],
"mode": case["mode"],
"question": case["question"],
"params": json.dumps(case.get("params") or {}, ensure_ascii=False),
"http_status": str(http_st or ""),
"elapsed_sec": f"{elapsed:.2f}",
"actual_intent": actual_intent,
"actual_mode": actual_mode,
"api_status": api_status,
"route_type": route_type,
"form_flags": form_flags(body),
"answer": answer,
"result": result,
"reason": reason,
"note": case.get("note") or "",
}
append_row(args.out, row, header)
header = False
results.append(result)
print(f" → {result:7} intent={actual_intent or '-':22} mode={actual_mode:8} | {answer[:70]}", flush=True)
time.sleep(sleep)
print("---", flush=True)
print(f"saved={args.out} total={len(results)} {dict(Counter(results))}", flush=True)
return 0
if __name__ == "__main__":
raise SystemExit(main())
+626
View File
@@ -0,0 +1,626 @@
#!/usr/bin/env python3
"""간편조회 기능 다양 질문 테스트 → test.csv
- domain-query: 간편조회 UI와 동일 경로 (다수 케이스, 빠름)
- /ask: 실제 고객 자연어 질문 (기능당 소수)
사용:
PYTHONUNBUFFERED=1 python3 scripts/quick_inquiry_nlu_test.py \\
--base http://127.0.0.1:8083/web --out test.csv
"""
from __future__ import annotations
import argparse
import csv
import json
import re
import ssl
import time
import urllib.error
import urllib.request
from collections import Counter
from datetime import datetime
from typing import Any, Dict, List, Optional, Tuple
# 운영 HTTPS 등에서 로컬 CA 이슈 시 사용
_SSL_CTX = ssl.create_default_context()
def one_line(text: str, limit: int = 280) -> str:
t = re.sub(r"\s+", " ", (text or "").strip())
return (t[: limit - 1] + "…") if len(t) > limit else t
def post_json(url: str, body: Dict[str, Any], timeout: float) -> Tuple[Optional[int], Any, float]:
t0 = time.time()
data = json.dumps(body, ensure_ascii=False).encode("utf-8")
req = urllib.request.Request(
url, data=data, headers={"Content-Type": "application/json; charset=utf-8"}
)
try:
with urllib.request.urlopen(req, timeout=timeout, context=_SSL_CTX) as resp:
raw = resp.read().decode("utf-8", errors="replace")
try:
return resp.status, json.loads(raw), time.time() - t0
except json.JSONDecodeError:
return resp.status, raw, time.time() - t0
except urllib.error.HTTPError as e:
try:
payload = e.read().decode("utf-8", errors="replace")
try:
return e.code, json.loads(payload), time.time() - t0
except Exception:
return e.code, payload, time.time() - t0
except Exception:
return e.code, str(e), time.time() - t0
except Exception as e:
return None, str(e), time.time() - t0
def get_json(url: str, timeout: float) -> Tuple[Optional[int], Any, float]:
t0 = time.time()
try:
with urllib.request.urlopen(url, timeout=timeout, context=_SSL_CTX) as resp:
return resp.status, json.loads(resp.read().decode("utf-8", errors="replace")), time.time() - t0
except Exception as e:
return None, str(e), time.time() - t0
def domain_cases_prod_light() -> List[Dict[str, Any]]:
"""운영용 — 기능당 1~2건만 (부하 최소화)."""
light: List[Tuple[str, str, str, Dict[str, str]]] = [
("미납조회", "FARE_UNPAID", "야 내 차 12가3456인데 미납 있어?", {"carNo": "12가3456"}),
("환불조회", "FARE_REFUND", "잘못 낸 톨비 환불받을 수 있어? 12가3456", {"carNo": "12가3456"}),
("구간통행요금", "FARE_SEARCH", "서울에서 부산까지 톨비 얼마 나와?", {"fromIc": "서울", "toIc": "부산"}),
("구간통행요금", "FARE_SEARCH", "판교에서 신갈 가면 요금이 어떻게 돼?", {"fromIc": "판교", "toIc": "신갈"}),
("구간통행시간", "TROAD_TRAVEL_TIME", "서울에서 부산까지 지금 가면 얼마나 걸려?",
{"fromIc": "서울", "toIc": "부산", "carType": "1"}),
("구간통행시간", "TROAD_TRAVEL_TIME", "판교에서 신갈 지금 막혀? 몇 분 걸려?",
{"fromIc": "판교", "toIc": "신갈", "carType": "1"}),
("차단계획", "CONSTRUCTION_PLAN", "경부선 오늘 공사해서 막히는 데 있어?", {"routeName": "경부선"}),
("차단계획", "CONSTRUCTION_PLAN", "영동선 차로 막는 일정 있나?", {"routeName": "영동선"}),
("영업소정보", "IC_TEL", "판교 톨게이트 전화번호 좀", {"icName": "판교"}),
("영업소정보", "IC_TEL", "기흥 톨게이트 주소랑 전화 좀", {"icName": "기흥"}),
("긴급구조기관", "EMERGENCY_HELP_ORG", "경부선에서 사고 나면 어디로 연락해?",
{"listMode": "true", "routeName": "경부선"}),
("휴게소음식", "REST_AREA_FOOD_LIST", "죽전휴게소에서 뭐 먹을 거 있어?", {"restAreaName": "죽전"}),
("휴게소브랜드매장", "BRAND_SHOP", "죽전에 편의점이나 카페 있어?", {"restAreaName": "죽전"}),
("휴게소시설", "REST_AREA_FACILITY", "죽전휴게소에 수유실 있나?", {"restAreaName": "죽전"}),
("휴게소주유", "GASSTATION", "죽전휴게소 기름값 얼마야?", {"restAreaName": "죽전"}),
("휴게소주유", "GASSTATION", "경부선에서 기름 제일 싼 데 어디야?",
{"compareMode": "cheapest", "fuelType": "휘발유", "routeName": "경부선"}),
("휴게소충전소", "REST_AREA_CHARGING", "죽전에서 전기차 충전돼?",
{"restAreaName": "죽전", "chargingType": "all"}),
("휴게소충전소", "REST_AREA_CHARGING", "강릉휴게소에 충전소 있어?",
{"restAreaName": "강릉", "chargingType": "all"}),
("휴게소청년창업매장", "REST_AREA_YOUTH_SHOP", "죽전휴게소에 청년들 장사하는 가게 있어?",
{"restAreaName": "죽전"}),
("가까운휴게소", "REST_AREA_NEAREST", "판교 근처 휴게소 어디 있어?", {"icName": "판교"}),
("노선혼잡", "TROAD_CONGESTION", "경부선 지금 막히는 구간 있어?", {"routeName": "경부선"}),
]
return [
{
"mode": "domain-query",
"feature": f,
"expected_intent": intent,
"question": q,
"params": params,
"note": "운영 경량 domain-query",
}
for f, intent, q, params in light
]
def extract_answer(body: Any) -> str:
if not isinstance(body, dict):
return one_line(str(body))
for key in ("answer", "message", "text", "statusMsg", "llmSummary", "formattedAnswer"):
val = body.get(key)
if isinstance(val, str) and val.strip():
return one_line(val)
for nest_key in ("domainData", "data", "rawData"):
nest = body.get(nest_key)
if isinstance(nest, dict):
for key in ("llmSummary", "statusMsg", "answer", "message"):
val = nest.get(key)
if isinstance(val, str) and val.strip():
return one_line(val)
# list summary
lst = nest.get("list") or nest.get("items")
if isinstance(lst, list) and lst:
return one_line(f"건수={len(lst)} 예시={json.dumps(lst[0], ensure_ascii=False)}")
if body.get("needsRestAreaForm") or body.get("needsIcTelForm"):
return one_line(str(body.get("statusMsg") or "폼 유도 응답"))
return one_line(json.dumps(body, ensure_ascii=False))
def intent_of(body: Any, fallback: str = "") -> str:
if not isinstance(body, dict):
return fallback
return str(body.get("intentType") or fallback)
def status_of(body: Any) -> str:
if not isinstance(body, dict):
return ""
if "status" in body:
return str(body.get("status"))
dd = body.get("domainData")
if isinstance(dd, dict) and "status" in dd:
return str(dd.get("status"))
return ""
INTENT_OK = {
"FARE_UNPAID": {"FARE_UNPAID"},
"FARE_REFUND": {"FARE_REFUND"},
"FARE_SEARCH": {"FARE_SEARCH"},
"TROAD_TRAVEL_TIME": {"TROAD_TRAVEL_TIME"},
"TROAD_BREAKING_NEWS": {"TROAD_BREAKING_NEWS", "TRAFFIC_NEWS"},
"TRAFFIC_NEWS": {"TRAFFIC_NEWS", "TROAD_BREAKING_NEWS"},
"CONSTRUCTION_PLAN": {"CONSTRUCTION_PLAN"},
"IC_TEL": {"IC_TEL"},
"EMERGENCY_HELP_ORG": {"EMERGENCY_HELP_ORG"},
"REST_AREA_FOOD_LIST": {"REST_AREA_FOOD_LIST"},
"BRAND_SHOP": {"BRAND_SHOP"},
"REST_AREA_FACILITY": {"REST_AREA_FACILITY"},
"GASSTATION": {"GASSTATION"},
"REST_AREA_CHARGING": {"REST_AREA_CHARGING"},
"REST_AREA_YOUTH_SHOP": {"REST_AREA_YOUTH_SHOP"},
"REST_AREA_NEAREST": {"REST_AREA_NEAREST"},
"TROAD_CONGESTION": {"TROAD_CONGESTION"},
}
def judge(expected: str, actual: str, status: str, answer: str, http_st: Optional[int]) -> Tuple[str, str]:
if http_st != 200:
return "FAIL", f"HTTP {http_st}"
natural = len(answer or "") >= 6 and "Traceback" not in (answer or "")
intent_ok = (actual or "") in INTENT_OK.get(expected, {expected}) or actual == expected
st_true = status in ("True", "true", "1")
infra = any(
h in (answer or "")
for h in ("일시적인 장애", "Failed to obtain", "Listener refused", "연결")
)
if intent_ok and st_true and natural:
return "PASS", "의도·응답 정상"
if intent_ok and natural and infra:
return "PARTIAL", "의도 일치, 인프라/DB 제약 안내"
if intent_ok and natural:
return "PARTIAL", "의도 일치, 데이터없음/안내성 응답"
if natural and actual:
return "PARTIAL", f"의도상이 expected={expected} actual={actual}"
if natural:
return "PARTIAL", "응답만 존재"
return "FAIL", f"의도/응답 불량 expected={expected} actual={actual or '-'}"
# ---- case builders ----
def domain_cases() -> List[Dict[str, Any]]:
"""간편조회 domain-query — 질문은 구어체, 호출은 폼/직조회 params."""
rows: List[Dict[str, Any]] = []
def add(feature: str, intent: str, question: str, params: Dict[str, str], note: str = "") -> None:
rows.append(
{
"mode": "domain-query",
"feature": feature,
"expected_intent": intent,
"question": question,
"params": params,
"note": note,
}
)
# 미납/환불
add("미납조회", "FARE_UNPAID", "야 내 차 12가3456인데 미납 있어?", {"carNo": "12가3456"}, "Oracle 미연결 시 PARTIAL 가능")
add("미납조회", "FARE_UNPAID", "하이패스 미납금 좀 봐줘 서울12가3456", {"carNo": "서울12가3456"}, "Oracle 미연결 시 PARTIAL 가능")
add("미납조회", "FARE_UNPAID", "톨비 밀린 거 있어요? 차량번호 123가4567요", {"carNo": "123가4567"}, "Oracle 미연결 시 PARTIAL 가능")
add("미납조회", "FARE_UNPAID", "98나1234 미납통행료 나와요?", {"carNo": "98나1234"}, "Oracle 미연결 시 PARTIAL 가능")
add("환불조회", "FARE_REFUND", "12가3456으로 환불받을 돈 있어요?", {"carNo": "12가3456"}, "Oracle 미연결 시 PARTIAL 가능")
add("환불조회", "FARE_REFUND", "잘못 낸 톨비 환불 내역 좀 확인해줘 서울12가3456", {"carNo": "서울12가3456"}, "Oracle 미연결 시 PARTIAL 가능")
add("환불조회", "FARE_REFUND", "과오납 환불금 나왔나? 123가4567", {"carNo": "123가4567"}, "Oracle 미연결 시 PARTIAL 가능")
add("환불조회", "FARE_REFUND", "하이패스 환불받을 거 있는지 봐줘 98나1234", {"carNo": "98나1234"}, "Oracle 미연결 시 PARTIAL 가능")
# 통행요금
fare_qs = [
("서울에서 부산까지 톨비 얼마 나와?", "서울", "부산"),
("판교에서 신갈 가면 요금이 어떻게 돼?", "판교", "신갈"),
("판교IC에서 신갈IC까지 하이패스 얼마야?", "판교IC", "신갈IC"),
("판교 영업소에서 수원까지 통행료 좀", "판교영업소", "수원"),
("대전에서 대구 가는 데 톨비 얼마쯤 해?", "대전", "대구"),
("천안에서 남이IC까지 요금 알려줄래?", "천안", "남이"),
("서울 톨게이트에서 기흥까지 얼마야?", "서울영업소", "기흥"),
("김포에서 인천 쪽 고속도로 요금 궁금해", "김포", "인천"),
]
for q, a, b in fare_qs:
add("구간통행요금", "FARE_SEARCH", q, {"fromIc": a, "toIc": b})
# 통행시간
time_qs = [
("서울에서 부산까지 지금 가면 얼마나 걸려?", "서울", "부산"),
("판교에서 신갈 지금 막혀? 몇 분 걸려?", "판교", "신갈"),
("대전에서 대구까지 지금 소요시간 어때?", "대전", "대구"),
("서울IC에서 부산IC 지금 가면 몇 시간이야?", "서울IC", "부산IC"),
("기흥에서 천안까지 지금 얼마나 걸릴까?", "기흥", "천안"),
]
for q, a, b in time_qs:
add("구간통행시간", "TROAD_TRAVEL_TIME", q, {"fromIc": a, "toIc": b, "carType": "1"})
# 차단계획
for q, route in [
("경부선 오늘 공사해서 막히는 데 있어?", "경부선"),
("영동선 차로 막는 일정 있나?", "영동선"),
("서해안선 공사구간 좀 알려줘", "서해안선"),
("호남선 이번 주 차단계획 있어?", "호남선"),
("경부고속도로 공사한다던데 어디야?", "경부고속도로"),
("중부내륙선 차로통제 있어?", "중부내륙선"),
]:
add("차단계획", "CONSTRUCTION_PLAN", q, {"routeName": route})
# 영업소
for q, ic in [
("판교 톨게이트 전화번호 좀", "판교"),
("판교IC 전화 어떻게 걸어?", "판교IC"),
("판교 영업소 연락처 알려줘", "판교영업소"),
("서울 영업소 번호 뭐야?", "서울"),
("기흥 톨게이트 주소랑 전화 좀", "기흥"),
("부산IC 영업소 정보 있어?", "부산IC"),
("신갈 영업소 전화 받나?", "신갈"),
("경부선 판교 쪽 영업소 번호 알려줘", "경부선판교"),
]:
add("영업소정보", "IC_TEL", q, {"icName": ic})
# 긴급구조
for q, route in [
("경부선에서 사고 나면 어디로 연락해?", "경부선"),
("영동선 긴급구조 가능한 데 어디야?", "영동선"),
("서해안선 긴급구조기관 좀 알려줘", "서해안선"),
]:
add("긴급구조기관", "EMERGENCY_HELP_ORG", q, {"listMode": "true", "routeName": route})
add("긴급구조기관", "EMERGENCY_HELP_ORG", "판교 근처 고속도로 긴급구조대 있어?", {"icName": "판교"})
# 휴게소
rest_sets = [
("죽전", "죽전휴게소에서 뭐 먹을 거 있어?", "죽전에 편의점이나 카페 있어?",
"죽전휴게소에 수유실 있나?", "죽전휴게소 기름값 얼마야?",
"죽전에서 전기차 충전돼?", "죽전휴게소에 청년들 장사하는 가게 있어?"),
("안성", "안성휴게소 밥 뭐 파나?", "안성휴게소에 브랜드 매장 뭐 있어?",
"안성휴게소 샤워실 쓸 수 있어?", "안성 휘발유 얼마야?",
"안성휴게소 전기차 충전소 있어?", "안성에 청년창업 매장 있어?"),
("김천", "김천휴게소에서 뭐 먹지?", "김천휴게소 입점 매장 뭐 있어?",
"김천휴게소 편의시설 뭐 있어?", "김천 경유값 어때?",
"김천휴게소에 수소차 충전해?", "김천에 청년몰 있어?"),
("금강", "금강휴게소 메뉴 추천해줘", "금강휴게소에 카페 있어?",
"금강휴게소 시설 뭐 있어?", "금강휴게소 주유소 있어?",
"금강에서 전기차 충전 가능해?", "금강휴게소 청년창업매장 있나?"),
("죽전휴게소", "죽전 휴게소 식당 뭐 있어?", "죽전 휴게소에 쇼핑할 데 있어?",
"죽전 휴게소에 애완동물 시설 있어?", "죽전 휴게소 기름 넣어?",
"죽전 휴게소 EV 충전돼?", "죽전 휴게소 청년가게 있어?"),
("강릉", "강릉휴게소에서 뭐 먹을까?", "강릉휴게소 매장 뭐 있어?",
"강릉휴게소 편의시설 알려줘", "강릉휴게소 주유소 유가 궁금해",
"강릉휴게소 충전소 있어?", "강릉에 청년창업 매장 있어?"),
]
for name, q_food, q_brand, q_fac, q_gas, q_chg, q_youth in rest_sets:
add("휴게소음식", "REST_AREA_FOOD_LIST", q_food, {"restAreaName": name})
add("휴게소브랜드매장", "BRAND_SHOP", q_brand, {"restAreaName": name})
add("휴게소시설", "REST_AREA_FACILITY", q_fac, {"restAreaName": name})
add("휴게소주유", "GASSTATION", q_gas, {"restAreaName": name})
add("휴게소충전소", "REST_AREA_CHARGING", q_chg, {"restAreaName": name, "chargingType": "all"})
add("휴게소청년창업매장", "REST_AREA_YOUTH_SHOP", q_youth, {"restAreaName": name})
add("휴게소주유", "GASSTATION", "경부선에서 기름 제일 싼 데 어디야?",
{"compareMode": "cheapest", "fuelType": "휘발유", "routeName": "경부선"})
add("휴게소주유", "GASSTATION", "고속도로에서 경유 제일 싼 곳 알려줘",
{"compareMode": "cheapest", "fuelType": "경유"})
add("휴게소충전소", "REST_AREA_CHARGING", "경부선에 전기차 충전되는 휴게소 어디 있어?",
{"listMode": "true", "routeName": "경부선", "chargingType": "electric"})
add("휴게소충전소", "REST_AREA_CHARGING", "강릉휴게소충전소 있어?",
{"restAreaName": "강릉휴게소충전소", "chargingType": "all"})
for q, ic in [
("판교 근처 휴게소 어디 있어?", "판교"),
("서울 톨게이트 지나서 바로 나오는 휴게소 어디야?", "서울"),
("기흥IC 근처에 쉴 데 있어?", "기흥IC"),
]:
add("가까운휴게소", "REST_AREA_NEAREST", q, {"icName": ic})
for q, route in [
("경부선 지금 막히는 구간 있어?", "경부선"),
("영동선 어디가 막혀?", "영동선"),
("서해안선 정체 심한 데 알려줘", "서해안선"),
]:
add("노선혼잡", "TROAD_CONGESTION", q, {"routeName": route})
return rows
def ask_cases() -> List[Dict[str, Any]]:
"""자연어 /ask — 일반 이용자 구어체 질문."""
pairs = [
("미납조회", "FARE_UNPAID", [
"야 내 차 12가3456인데 미납 있어?",
"하이패스 미납금 나왔나 봐줘 서울12가3456",
"톨비 밀린 거 있어요? 45다6789요",
]),
("환불조회", "FARE_REFUND", [
"잘못 낸 톨비 환불받을 수 있어? 12가3456",
"하이패스 환불금 들어왔나? 서울33하1122",
]),
("구간통행요금", "FARE_SEARCH", [
"서울에서 부산까지 톨비 얼마 나와?",
"판교에서 신갈 가면 요금이 어떻게 돼?",
"판교IC에서 신갈IC까지 하이패스 얼마야?",
"대전에서 대구 가는 데 톨비 얼마쯤 해?",
]),
("구간통행시간", "TROAD_TRAVEL_TIME", [
"서울에서 부산까지 지금 가면 얼마나 걸려?",
"판교에서 신갈 지금 막혀? 몇 분 걸려?",
"지금 대전에서 대구까지 가면 몇 시간이야?",
]),
("노선별교통속보", "TROAD_BREAKING_NEWS", [
"고속도로에 사고 났다는데 어디야?",
"경부선에 사고 났어?",
"영동선 지금 교통상황 어때?",
]),
("차단계획", "CONSTRUCTION_PLAN", [
"경부선 오늘 공사해서 막히는 데 있어?",
"영동선 차로 막는 일정 있나?",
"서해안선 공사구간 좀 알려줘",
]),
("영업소정보", "IC_TEL", [
"판교 톨게이트 전화번호 좀",
"기흥 톨게이트 주소랑 전화 좀",
"판교 영업소 연락처 알려줘",
]),
("긴급구조기관", "EMERGENCY_HELP_ORG", [
"경부선에서 사고 나면 어디로 연락해?",
"고속도로에서 사고 났는데 가까운 구조대 어디야?",
]),
("휴게소음식", "REST_AREA_FOOD_LIST", [
"죽전휴게소에서 뭐 먹을 거 있어?",
"안성휴게소 밥 뭐 파나?",
]),
("휴게소브랜드매장", "BRAND_SHOP", [
"죽전에 편의점이나 카페 있어?",
"김천휴게소에 브랜드 매장 뭐 있어?",
]),
("휴게소시설", "REST_AREA_FACILITY", [
"죽전휴게소에 수유실 있나?",
"안성휴게소 샤워실 쓸 수 있어?",
]),
("휴게소주유", "GASSTATION", [
"죽전휴게소 기름값 얼마야?",
"경부선에서 기름 제일 싼 데 어디야?",
"고속도로에서 휘발유 제일 싼 곳 알려줘",
]),
("휴게소충전소", "REST_AREA_CHARGING", [
"죽전에서 전기차 충전돼?",
"강릉휴게소에 충전소 있어?",
"김천휴게소에서 수소차 충전해?",
]),
("휴게소청년창업매장", "REST_AREA_YOUTH_SHOP", [
"죽전휴게소에 청년들 장사하는 가게 있어?",
"고속도로에 청년창업 매장 있는 휴게소 어디야?",
]),
("가까운휴게소", "REST_AREA_NEAREST", [
"판교 근처 휴게소 어디 있어?",
"서울 톨게이트 지나서 바로 나오는 휴게소 어디야?",
]),
("노선혼잡", "TROAD_CONGESTION", [
"경부선 지금 막히는 구간 있어?",
"영동선 어디가 막혀?",
]),
]
rows: List[Dict[str, Any]] = []
for feature, intent, qs in pairs:
for q in qs:
rows.append(
{
"mode": "ask",
"feature": feature,
"expected_intent": intent,
"question": q,
"params": {},
"note": "구어체 자연어 채팅",
}
)
return rows
FIELDNAMES = [
"tested_at",
"mode",
"feature",
"expected_intent",
"question",
"params",
"http_status",
"elapsed_sec",
"actual_intent",
"api_status",
"answer",
"result",
"reason",
"route_type",
"note",
]
def append_row(path: str, row: Dict[str, str], write_header: bool) -> None:
with open(path, "a", newline="", encoding="utf-8-sig") as f:
w = csv.DictWriter(f, fieldnames=FIELDNAMES)
if write_header:
w.writeheader()
w.writerow(row)
f.flush()
def main() -> int:
global _SSL_CTX
ap = argparse.ArgumentParser()
ap.add_argument("--base", default="http://127.0.0.1:8083/web")
ap.add_argument("--out", default="test.csv")
ap.add_argument("--timeout-domain", type=float, default=45.0)
ap.add_argument("--timeout-ask", type=float, default=90.0)
ap.add_argument("--sleep", type=float, default=0.15)
ap.add_argument("--sleep-ask", type=float, default=0.0, help="ask 전용 sleep(0이면 --sleep)")
ap.add_argument("--skip-ask", action="store_true")
ap.add_argument("--skip-domain", action="store_true")
ap.add_argument("--limit", type=int, default=0)
ap.add_argument(
"--profile",
choices=["full", "prod"],
default="full",
help="prod=기능당 소수 + 구어체(운영 부하 최소화)",
)
ap.add_argument("--insecure", action="store_true", help="SSL 검증 비활성화")
args = ap.parse_args()
if args.insecure:
_SSL_CTX = ssl._create_unverified_context()
base = args.base.rstrip("/")
domain_url = base + "/domain-query"
ask_url = base + "/ask"
traffic_url = base + "/traffic-news"
started = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
sleep_ask = args.sleep_ask if args.sleep_ask > 0 else max(args.sleep, 1.5)
# reset out
open(args.out, "w", encoding="utf-8-sig").close()
header_needed = True
results: List[str] = []
def emit(row: Dict[str, str]) -> None:
nonlocal header_needed
append_row(args.out, row, header_needed)
header_needed = False
results.append(row["result"])
print(
f"{row['result']:7} [{row['mode']:12}] {row['feature']:14} "
f"{row['expected_intent']:22} → {row['actual_intent'] or '-':22} | {row['question'][:42]}",
flush=True,
)
# traffic-news GET
http_st, body, elapsed = get_json(traffic_url, args.timeout_domain)
ans = extract_answer(body) if isinstance(body, (dict, list)) else one_line(str(body))
if isinstance(body, list):
ans = one_line(f"list={len(body)}")
ok = http_st == 200
else:
ok = http_st == 200 and (
(
isinstance(body, dict)
and (
body.get("status") is True
or "list" in body
or "items" in body
or "routes" in body
)
)
or isinstance(body, list)
)
emit(
{
"tested_at": started,
"mode": "domain-api",
"feature": "노선별교통속보",
"expected_intent": "TRAFFIC_NEWS",
"question": "오늘 고속도로에 사고나 통제 소식 있어?",
"params": "",
"http_status": str(http_st or ""),
"elapsed_sec": f"{elapsed:.2f}",
"actual_intent": "TRAFFIC_NEWS",
"api_status": "True" if ok else "False",
"answer": ans,
"result": "PASS" if ok else "FAIL",
"reason": "GET /traffic-news" if ok else "GET 실패",
"route_type": "GET",
"note": "간편조회 UI 전용",
}
)
suite: List[Dict[str, Any]] = []
if not args.skip_domain:
suite.extend(domain_cases_prod_light() if args.profile == "prod" else domain_cases())
if not args.skip_ask:
# prod: 기능당 질문 최대 2개로 축소
ask = ask_cases()
if args.profile == "prod":
by_feat: Dict[str, int] = {}
trimmed: List[Dict[str, Any]] = []
for c in ask:
n = by_feat.get(c["feature"], 0)
if n < 2:
trimmed.append(c)
by_feat[c["feature"]] = n + 1
ask = trimmed
suite.extend(ask)
if args.limit > 0:
suite = suite[: args.limit]
total = len(suite)
for i, case in enumerate(suite, 1):
mode = case["mode"]
print(f"({i}/{total}) …", flush=True)
if mode == "domain-query":
http_st, body, elapsed = post_json(
domain_url,
{
"intentType": case["expected_intent"],
"params": case["params"],
"botId": f"qi-dom-{i}",
},
args.timeout_domain,
)
actual = intent_of(body, case["expected_intent"])
# domain-query often echoes intent in request; keep expected if missing
if not actual:
actual = case["expected_intent"]
else:
http_st, body, elapsed = post_json(
ask_url,
{"query": case["question"], "botId": f"qi-ask-{i}"},
args.timeout_ask,
)
actual = intent_of(body)
status = status_of(body)
answer = extract_answer(body)
route_type = ""
if isinstance(body, dict):
route_type = str(body.get("routeType") or mode)
result, reason = judge(case["expected_intent"], actual, status, answer, http_st)
emit(
{
"tested_at": started,
"mode": mode,
"feature": case["feature"],
"expected_intent": case["expected_intent"],
"question": case["question"],
"params": json.dumps(case.get("params") or {}, ensure_ascii=False),
"http_status": str(http_st or ""),
"elapsed_sec": f"{elapsed:.2f}",
"actual_intent": actual,
"api_status": status,
"answer": answer,
"result": result,
"reason": reason,
"route_type": route_type,
"note": case.get("note") or "",
}
)
time.sleep(sleep_ask if mode == "ask" else args.sleep)
c = Counter(results)
print("---", flush=True)
print(f"saved={args.out} total={len(results)} {dict(c)}", flush=True)
return 0
if __name__ == "__main__":
raise SystemExit(main())
Regular → Executable
+23 -23
View File
@@ -1,23 +1,23 @@
run/
logs/
*.pid
# Qdrant / Mongo 데이터
exAiChatBot-chatbot2.0-agent/qdrant_data/
exAiChatBot-chatbot2.0-agent/.env
local-dev/run/
# Java / Node build
**/build/
**/.gradle/
**/node_modules/
chatbotApp-chatbot2.0-agent/public/
chatbotApp-chatbot2.0-agent/public-*/
# IDE / OS
.DS_Store
.idea/
*.log
# 스냅샷 (용량)
local-dev/run/qdrant-snapshots/
run/
logs/
*.pid
# Qdrant / Mongo 데이터
exAiChatBot-chatbot2.0-agent/qdrant_data/
exAiChatBot-chatbot2.0-agent/.env
local-dev/run/
# Java / Node build
**/build/
**/.gradle/
**/node_modules/
chatbotApp-chatbot2.0-agent/public/
chatbotApp-chatbot2.0-agent/public-*/
# IDE / OS
.DS_Store
.idea/
*.log
# 스냅샷 (용량)
local-dev/run/qdrant-snapshots/
Regular → Executable
+154 -130
View File
@@ -1,130 +1,154 @@
# exdev 서버 배포 — exAichatbot Agent 2.0
`chatbot.exdev.co.kr` Mac Studio 서버에 Agent 2.0 스택(RAG + WAS + Skill + chatbotApp)을 배포합니다.
## GitHub upstream (submodule)
4개 서비스 소스는 GitHub `KoreaExpressWayCorp` 저장소를 **git submodule**로 연결합니다.
| monorepo 경로 | GitHub | 브랜치 |
|---------------|--------|--------|
| `chatbotApp-chatbot2.0-agent` | https://github.com/KoreaExpressWayCorp/chatbotApp.git | `chatbot2.0-agent` |
| `chatbotApi-chatbot2.0-agent` | https://github.com/KoreaExpressWayCorp/chatbotApi.git | `chatbot2.0-agent` |
| `exAiChatBot-chatbot2.0-agent` | https://github.com/KoreaExpressWayCorp/exAiChatBot.git | `chatbot2.0-agent` |
| `kakaoChatbotSkill-chatbot2.0-agent` | https://github.com/KoreaExpressWayCorp/kakaoChatbotSkill.git | `chatbot2.0-agent` |
최초 clone:
```bash
git clone --recurse-submodules ssh://aidev@github.exdev.co.kr:2222/aidev/exAichatbot_agent.git
```
GitHub 최신 반영:
```bash
./git_fetch_all.sh # GitHub → 로컬 submodule fast-forward
./git_fetch_all.sh --dry-run # 변경 예상만 확인
./git_fetch_all.sh --init # submodule 최초 clone 포함
```
RAG Docker compose(`docker-compose.server.yml`)는 submodule 밖 **`server-dev/docker-compose.rag.server.yml`** 에 두고, 기동 시 `exAiChatBot-chatbot2.0-agent/`로 복사합니다.
## 디렉터리
| 경로 (서버) | 용도 |
|-------------|------|
| `/Users/aidev/dev/exAichatbot_agent` | Git work tree (배포 소스) |
| `/Volumes/ADATA/git/exAichatbot_agent.git` | Gitea bare repo |
| `/Volumes/ADATA/git/deploy-exAichatbot_agent.sh` | push → 배포 스크립트 |
## 1회 설정 (서버)
```bash
ssh aidev@chatbot.exdev.co.kr
bash /Users/aidev/dev/exAichatbot_agent/server-dev/setup-gitea.sh
```
Gitea(`https://github.exdev.co.kr`)에서 **`exAichatbot_agent`** 저장소 생성 (Initialize unchecked).
## 로컬 Mac → Gitea push → 서버 배포
개발 Mac에서 **한 번에** GitHub 최신 반영 · Gitea push · 서버 빌드·배포:
```bash
./start-all-server.sh
# = git_fetch_all (GitHub) → push-to-gitea → post-receive 배포 대기
```
| 옵션 | 설명 |
|------|------|
| `--local` | 예전처럼 `local-dev/start-all.sh` 로컬 개발 모드 |
| `--no-push` | Gitea push·원격 배포 생략 |
| `--no-pull` | GitHub submodule fetch 생략 |
| `--no-build` | Docker/Next 빌드 생략 (서버에서만 해당) |
수동 push만:
```bash
./server-dev/push-to-gitea.sh
./server-dev/push-to-gitea.sh --dry-run
```
**main push 시 자동:** `post-receive` → `deploy-exAichatbot_agent.sh` → checkout + `git_fetch_all --init` → `start-all-server.sh --no-pull --no-push`
서버에서 GitHub clone 이 안 되면 **로컬 `./start-all-server.sh`** 가 submodule rsync + chatbotApp 로컬 빌드 후 배포합니다.
배포 로그: `/Volumes/ADATA/logs/deploy/exAichatbot_agent.log`
## 로컬 → Gitea push (수동)
```bash
cd exChatbot_agent
# Gitea (이 서버는 git@ 가 아닌 aidev@ 사용)
git remote add origin ssh://aidev@github.exdev.co.kr:2222/aidev/exAichatbot_agent.git
git push -u origin main
# 잘못된 예 (Permission denied):
# git@github.exdev.co.kr:aidev/exAichatbot_agent.git
```
## 수동 기동 / 중지 (서버)
```bash
cd /Users/aidev/dev/exAichatbot_agent
./server-dev/stop-all-server.sh
./server-dev/start-all-server.sh # Gitea checkout → GitHub submodule → 빌드 → 기동
./server-dev/start-all-server.sh --no-build
./server-dev/start-all-server.sh --no-pull # git 동기화 생략
./server-dev/start-all-server.sh --no-push # Gitea push 생략 (서버 전용)
```
## 스택 구성
| 서비스 | 포트 | URL |
|--------|------|-----|
| HTTPS UI (Caddy) | 443 | https://chatbot.exdev.co.kr/chatbot/app/ |
| chatbotApp nginx | 8092 | 내부 |
| kakaoChatbotSkill | 8083 | /web/ask |
| chatbotApi WAS | 8086 | /api |
| RAG API | 28012 | /agent/chat |
| Vector Admin | 28013 | /chatbot/admin |
| Qdrant | 6333 | REST |
| 호스트 AI | 16000~16002 | MLX LLM/Embed/Rerank |
## Qdrant 데이터
- 최초 기동 시 `vector_count=0` 이면 레거시 `exAIChatbot2.0/exAiChatBot-chatbot2.0/qdrant_data` 를 자동 복사
- 이후 `qdrant_data/` 볼륨 영속 유지 (git 제외)
## 환경변수
```bash
cp server-dev/env.exdev-server.template exAiChatBot-chatbot2.0-agent/.env
```
## 레거시 스택
`start-all-server.sh`는 포트 충돌 방지를 위해 `exAIChatbot2.0/remote-stop-chatbot.sh` 로 레거시 스택을 중지합니다.
유지하려면 `--skip-legacy-stop` 옵션을 사용하세요.
# exdev 서버 배포 — exAichatbot Agent 2.0
`chatbot.exdev.co.kr` Mac Studio 서버에 Agent 2.0 스택(RAG + WAS + Skill + chatbotApp)을 배포합니다.
## GitHub upstream (submodule)
5개 소스는 GitHub `KoreaExpressWayCorp` 저장소를 **git submodule**로 연결합니다.
| monorepo 경로 | GitHub | 브랜치 |
|---------------|--------|--------|
| `chatbotApp-chatbot2.0-agent` | https://github.com/KoreaExpressWayCorp/chatbotApp.git | `chatbot2.0-agent` |
| `chatbotApi-chatbot2.0-agent` | https://github.com/KoreaExpressWayCorp/chatbotApi.git | `chatbot2.0-agent` |
| `chatbotApp-test` | https://github.com/KoreaExpressWayCorp/chatbotApp-test.git | `chatbot2.0-agent` |
| `exAiChatBot-chatbot2.0-agent` | https://github.com/KoreaExpressWayCorp/exAiChatBot.git | `chatbot2.0-agent` |
| `kakaoChatbotSkill-chatbot2.0-agent` | https://github.com/KoreaExpressWayCorp/kakaoChatbotSkill.git | `chatbot2.0-agent` |
최초 clone:
```bash
git clone --recurse-submodules ssh://aidev@github.exdev.co.kr:2222/aidev/exAichatbot_agent.git
```
GitHub 최신 반영:
```bash
./git_fetch_all.sh # GitHub → 로컬 submodule fast-forward
./git_fetch_all.sh --dry-run # 변경 예상만 확인
./git_fetch_all.sh --init # submodule 최초 clone 포함
```
RAG Docker compose(`docker-compose.server.yml`)는 submodule 밖 **`server-dev/docker-compose.rag.server.yml`** 에 두고, 기동 시 `exAiChatBot-chatbot2.0-agent/`로 복사합니다.
## 디렉터리
| 경로 (서버) | 용도 |
|-------------|------|
| `/Users/aidev/dev/exAichatbot_agent` | Git work tree (배포 소스) |
| `/Volumes/ADATA/git/exAichatbot_agent.git` | Gitea bare repo |
| `/Volumes/ADATA/git/deploy-exAichatbot_agent.sh` | push → 배포 스크립트 |
## 1회 설정 (서버)
```bash
ssh aidev@chatbot.exdev.co.kr
bash /Users/aidev/dev/exAichatbot_agent/server-dev/setup-gitea.sh
```
Gitea(`https://github.exdev.co.kr`)에서 **`exAichatbot_agent`** 저장소 생성 (Initialize unchecked).
## 로컬 Mac → Gitea push → 서버 배포
개발 Mac에서 **한 번에** Gitea 최신 반영 · 로컬 변경 commit/push · 서버 빌드·배포:
```bash
./start-all-server.sh
# = (push-to-gitea) Gitea fetch/merge → 로컬 commit → Gitea push → 원격 배포
# 공식 GitHub push 없음
./git_fetch_all.sh
# = 공식 GitHub(KoreaExpressWayCorp) submodule sync/commit/push 전용
```
`push-to-gitea.sh` 는 `git_fetch_all.sh` 와 같이 **원격(Gitea) 변경을 먼저 merge** 한 뒤 로컬을 올립니다.
충돌 시 스크립트가 멈추므로 수동 해결 후 재실행하세요.
(서버 work tree에만 있고 Gitea에 없는 수정은 포함되지 않습니다 — 배포는 Gitea 기준입니다.)
| 옵션 | 설명 |
|------|------|
| `--local` | 예전처럼 `local-dev/start-all.sh` 로컬 개발 모드 |
| `--no-push` | Gitea push·원격 배포 생략 |
| `--no-pull` | GitHub submodule fetch 생략 |
| `--no-build` | Docker/Next 빌드 생략 (서버에서만 해당) |
수동 push만:
```bash
./server-dev/push-to-gitea.sh
./server-dev/push-to-gitea.sh --dry-run
```
**main push 시 자동:** `post-receive` → `deploy-exAichatbot_agent.sh` → Gitea checkout → `start-all-server.sh --no-pull --no-push`
(공식 GitHub `git_fetch_all` 은 deploy 경로에서 호출하지 않음)
서버에서 GitHub clone 이 안 되면 **로컬 `./start-all-server.sh`** 가 submodule rsync + chatbotApp 로컬 빌드 후 배포합니다.
배포 로그: `/Volumes/ADATA/logs/deploy/exAichatbot_agent.log`
## 로컬 → Gitea push (수동)
```bash
cd exChatbot_agent
# Gitea (이 서버는 git@ 가 아닌 aidev@ 사용)
git remote add origin ssh://aidev@github.exdev.co.kr:2222/aidev/exAichatbot_agent.git
git push -u origin main
# 잘못된 예 (Permission denied):
# git@github.exdev.co.kr:aidev/exAichatbot_agent.git
```
## 수동 기동 / 중지 (서버)
```bash
cd /Users/aidev/dev/exAichatbot_agent
./server-dev/stop-all-server.sh
./server-dev/start-all-server.sh # Gitea checkout → GitHub submodule → 빌드 → 기동
./server-dev/start-all-server.sh --no-build
./server-dev/start-all-server.sh --no-pull # git 동기화 생략
./server-dev/start-all-server.sh --no-push # Gitea push 생략 (서버 전용)
```
## 스택 구성
| 서비스 | 포트 | URL |
|--------|------|-----|
| HTTPS UI (Caddy) | 443 | https://chatbot.exdev.co.kr/chatbot/app/ |
| chatbotApp nginx | 8092 | 내부 |
| kakaoChatbotSkill | 8083 | /web/ask, /kakao/skill (카카오 웹훅) |
| chatbotApi WAS | 8086 | /api |
| RAG API | 28012 | /agent/chat |
| Vector Admin | 28013 | /chatbot/admin |
| Qdrant | 6333 | REST |
| Oracle TROAD | 1521 | `localhost:1521/orcl2` (OPR_MAIN / test) |
| 호스트 AI | 16000~16002 | MLX LLM/Embed/Rerank |
## Oracle TROAD (교통정보)
- Docker Compose: `server-dev/docker-compose.oracle.yml` (`gvenzl/oracle-free:23-slim`, arm64 지원)
- 상세: [`server-dev/oracle/README.md`](oracle/README.md)
- `start-all-server.sh` 기동 시 Oracle 컨테이너 자동 시작 + WAS에
`SPRING_DATASOURCE_TROAD_URL/USERNAME/PASSWORD` 를 **localhost** 로 ENV 주입
(`application.yml` 운영 172.16.163.76 값은 파일에 그대로 둠 — `git_fetch_all.sh` push 시 복원·검증)
- `stop-all-server.sh` 중지 시 자동 중지(데이터 볼륨 유지)
- 업무 객체는 `server-dev/oracle/sql/*.sql` — 기동 후 비어 있으면 `oracle/apply-sql.sh` 가 자동 적용
- `OPR_MAIN.V_INCIDENT_FTMS` (돌발/정체 교통정보, 샘플 124건)
- `TROAD_APP.V_ROUTE_NEW_NM` / `V_ROUTE_TRFC_VER001` / `TLISDEV.T_TRMB_CD_INFO01M1` (노선별 혼잡 — **기존 chatbotApi 조회 SQL 그대로**)
- 옵션: `--skip-oracle`, `--keep-oracle`, `--purge-oracle`
## Qdrant 데이터
- 최초 기동 시 `vector_count=0` 이면 레거시 `exAIChatbot2.0/exAiChatBot-chatbot2.0/qdrant_data` 를 자동 복사
- 이후 `qdrant_data/` 볼륨 영속 유지 (git 제외)
## 환경변수
```bash
cp server-dev/env.exdev-server.template exAiChatBot-chatbot2.0-agent/.env
```
## 레거시 스택
`start-all-server.sh`는 포트 충돌 방지를 위해 `exAIChatbot2.0/remote-stop-chatbot.sh` 로 레거시 스택을 중지합니다.
유지하려면 `--skip-legacy-stop` 옵션을 사용하세요.
+30 -1
View File
@@ -37,7 +37,7 @@ https://{$CHATBOT_DOMAIN:chatbot.exdev.co.kr} {
import tls_certs
# 업스트림 nginx 가 HTTP 로 absolute redirect 해서 http:// 로 떨어지지 않게 Caddy 에서 처리
redir / /chatbot/app/ 302
redir / /chatbot/ai/ 302
handle /agent/* {
reverse_proxy host.docker.internal:{$RAG_API_PORT:28012} {
@@ -67,6 +67,35 @@ https://{$CHATBOT_DOMAIN:chatbot.exdev.co.kr} {
}
}
# 카카오 오픈빌더 Skill 웹훅 (/kakao/skill, /oakak/skill)
handle /kakao/* {
reverse_proxy host.docker.internal:{$SKILL_PORT:8083} {
transport http {
read_timeout 120s
write_timeout 120s
}
}
}
handle /oakak/* {
reverse_proxy host.docker.internal:{$SKILL_PORT:8083} {
transport http {
read_timeout 120s
write_timeout 120s
}
}
}
# iOS 홈화면 Web Clip — MIME 를 Caddy에서 강제 (인앱/프록시에서 text 로 깨지는 것 방지)
handle /chatbot/ai/downloads/*.mobileconfig {
header Content-Type application/x-apple-aspen-config
header Content-Disposition inline
header Cache-Control "no-cache, no-store, must-revalidate"
reverse_proxy host.docker.internal:{$CHATBOT_APP_PORT:8092} {
import proxy_std
}
}
handle {
reverse_proxy host.docker.internal:{$CHATBOT_APP_PORT:8092} {
import proxy_std
+56 -12
View File
@@ -29,7 +29,8 @@ if [[ -f "$LOCK_FILE" ]]; then
rm -f "$LOCK_FILE"
fi
echo $$ > "$LOCK_FILE"
trap 'rm -f "$LOCK_FILE"; log "락 해제"' EXIT
DEPLOY_OK=false
trap 'rm -f "$LOCK_FILE"; if ! $DEPLOY_OK; then log "[ERROR] 배포 실패"; fi; log "락 해제"' EXIT
for arg in "$@"; do
case "$arg" in
@@ -64,31 +65,73 @@ sync_worktree_submodules() {
fi
done
if [[ ${ready} -ge 4 ]]; then
log "submodule 소스 이미 존재 (rsync 또는 clone 완료) — GitHub fetch 생략"
log "submodule 소스 이미 존재 (Gitea/rsync) — 공식 GitHub fetch 생략"
if [[ -f "${tree}/server-dev/docker-compose.rag.server.yml" ]]; then
cp "${tree}/server-dev/docker-compose.rag.server.yml" \
"${tree}/exAiChatBot-chatbot2.0-agent/docker-compose.server.yml" 2>/dev/null || true
fi
return 0
fi
if [[ -x "${tree}/git_fetch_all.sh" ]]; then
log "GitHub submodule 동기화 (git_fetch_all.sh --init)..."
MONOREPO_GIT_DIR="${GIT_DIR}" "${tree}/git_fetch_all.sh" --init || log "[WARN] git_fetch_all 실패 — 로컬 rsync 필요"
else
log "[WARN] git_fetch_all.sh 없음 — 로컬 rsync 필요"
fi
# 공식 GitHub 는 deploy 경로에서 절대 동기화/push 하지 않음.
# 소스가 비어 있으면 로컬 Mac 의 rsync (sync-submodules-rsync.sh) 가 필요.
log "[WARN] submodule 소스 부족 (${ready}/4) — 공식 GitHub fetch 안 함. 로컬 rsync 필요"
}
log "[Phase 1] stop-all-server.sh"
"$WORK_TREE/server-dev/stop-all-server.sh" --keep-caddy || true
resolve_java17_home() {
local home="" candidate
for candidate in \
"/opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home" \
"/usr/local/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home"; do
if [[ -x "${candidate}/bin/java" ]]; then
home="${candidate}"
break
fi
done
if [[ -z "${home}" ]] && /usr/libexec/java_home -v 17 >/dev/null 2>&1; then
home="$(/usr/libexec/java_home -v 17)"
fi
[[ -n "${home}" ]] || fail "Java 17 필요 — brew install openjdk@17"
echo "${home}"
}
# 서비스 중지 전에 Java 컴파일만 검증 — 실패 시 가동 중인 스택을 유지한다.
# Gitea post-receive / 비로그인 SSH 는 PATH 에 brew java 가 없고 /usr/bin/java 는 stub 이므로
# JAVA_HOME 을 반드시 export 해야 gradlew 부트스트랩이 성공한다.
preflight_java_compile() {
local java_home dir
java_home="$(resolve_java17_home)"
export JAVA_HOME="${java_home}"
export PATH="${JAVA_HOME}/bin:/opt/homebrew/bin:/opt/homebrew/sbin:${PATH}"
log "[Phase 0] Java 사전 컴파일 검증 (Java 17: ${JAVA_HOME})"
for dir in \
"${WORK_TREE}/kakaoChatbotSkill-chatbot2.0-agent" \
"${WORK_TREE}/chatbotApi-chatbot2.0-agent"; do
[[ -x "${dir}/gradlew" ]] || fail "gradlew 없음: ${dir}"
log " compileJava: $(basename "${dir}")"
if ! (
cd "${dir}"
export JAVA_HOME
export PATH="${JAVA_HOME}/bin:${PATH}"
./gradlew -Dorg.gradle.java.home="${JAVA_HOME}" compileJava --quiet
); then
fail "사전 컴파일 실패: $(basename "${dir}") — 기존 서비스는 그대로 유지됨"
fi
done
log " ✅ Java 사전 컴파일 OK"
}
if ! $START_ONLY; then
log "[Phase 2] checkout + GitHub submodule"
log "[Phase 2] checkout (Gitea work tree) — 공식 GitHub 미사용"
git --work-tree="$WORK_TREE" --git-dir="$GIT_DIR" checkout -f "$BRANCH"
rm -f "$WORK_TREE/.git"
sync_worktree_submodules "$WORK_TREE"
fi
preflight_java_compile
log "[Phase 1] stop-all-server.sh"
"$WORK_TREE/server-dev/stop-all-server.sh" --keep-caddy || true
log "[Phase 3] .env 준비"
ENV_FILE="$WORK_TREE/exAiChatBot-chatbot2.0-agent/.env"
if [[ ! -f "$ENV_FILE" ]]; then
@@ -104,7 +147,8 @@ fi
"$WORK_TREE/server-dev/start-all-server.sh" "${START_ARGS[@]}"
COMMIT="$(git --git-dir="$GIT_DIR" rev-parse --short HEAD 2>/dev/null || echo unknown)"
DEPLOY_OK=true
log "======================================================"
log " 배포 완료 — $COMMIT"
log " UI: https://chatbot.exdev.co.kr/chatbot/app/"
log " UI: https://chatbot.exdev.co.kr/chatbot/ai/"
log "======================================================"
+27 -27
View File
@@ -1,27 +1,27 @@
# Agent 2.0 HTTPS — chatbot.exdev.co.kr (443)
# 인증서: exAIChatbot2.0/docker/nginx/certs/ (기존 obtain-cert-exdev.sh)
services:
caddy-agent:
image: caddy:2-alpine
container_name: exaichatbot-agent-caddy
restart: unless-stopped
ports:
- "${NGINX_HTTPS_PORT:-443}:443"
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
CHATBOT_DOMAIN: "${CHATBOT_DOMAIN:-chatbot.exdev.co.kr}"
CHATBOT_APP_PORT: "${CHATBOT_APP_PORT:-8092}"
RAG_API_PORT: "${RAG_API_PORT:-28012}"
SKILL_PORT: "${SKILL_PORT:-8083}"
ADMIN_PORT: "${ADMIN_PORT:-28013}"
CADDY_ACME_EMAIL: "${CADDY_ACME_EMAIL:-admin@exdev.co.kr}"
volumes:
- ./caddy/Caddyfile.agent.exdev:/etc/caddy/Caddyfile:ro
- "${LEGACY_CERTS_DIR:-/Users/aidev/dev/exAIChatbot2.0/docker/nginx/certs}:/etc/caddy/certs:ro"
- exaichatbot-agent-caddy-data:/data
- exaichatbot-agent-caddy-config:/config
volumes:
exaichatbot-agent-caddy-data:
exaichatbot-agent-caddy-config:
# Agent 2.0 HTTPS — chatbot.exdev.co.kr (443)
# 인증서: exAIChatbot2.0/docker/nginx/certs/ (기존 obtain-cert-exdev.sh)
services:
caddy-agent:
image: caddy:2-alpine
container_name: exaichatbot-agent-caddy
restart: unless-stopped
ports:
- "${NGINX_HTTPS_PORT:-443}:443"
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
CHATBOT_DOMAIN: "${CHATBOT_DOMAIN:-chatbot.exdev.co.kr}"
CHATBOT_APP_PORT: "${CHATBOT_APP_PORT:-8092}"
RAG_API_PORT: "${RAG_API_PORT:-28012}"
SKILL_PORT: "${SKILL_PORT:-8083}"
ADMIN_PORT: "${ADMIN_PORT:-28013}"
CADDY_ACME_EMAIL: "${CADDY_ACME_EMAIL:-admin@exdev.co.kr}"
volumes:
- ./caddy/Caddyfile.agent.exdev:/etc/caddy/Caddyfile:ro
- "${LEGACY_CERTS_DIR:-/Users/aidev/dev/exAIChatbot2.0/docker/nginx/certs}:/etc/caddy/certs:ro"
- exaichatbot-agent-caddy-data:/data
- exaichatbot-agent-caddy-config:/config
volumes:
exaichatbot-agent-caddy-data:
exaichatbot-agent-caddy-config:
+39
View File
@@ -0,0 +1,39 @@
# exdev 개발서버 — TROAD용 Oracle (Docker)
#
# chatbotApi application.yml 의 troad datasource 와 맞춤:
# jdbc:oracle:thin:@localhost:1521/orcl2
# username: OPR_MAIN
# password: test
#
# 테이블 DDL 은 oracle/apply-sql.sh 로 적용한다.
#
# 이미지: Oracle Database Free 23ai (linux/arm64 지원).
# 개발서버가 Apple Silicon(arm64) 이라 amd64 전용인 oracle-xe:21 은 사용할 수 없다.
services:
oracle-troad:
image: gvenzl/oracle-free:23-slim
container_name: exaichatbot-agent-oracle-troad
restart: unless-stopped
ports:
- "1521:1521"
environment:
# SYS / SYSTEM
ORACLE_PASSWORD: ${ORACLE_SYS_PASSWORD:-OracleExdev!2026}
# PDB 서비스명 → JDBC .../orcl2
ORACLE_DATABASE: ORCL2
# chatbotApi troad 계정
APP_USER: OPR_MAIN
APP_USER_PASSWORD: ${ORACLE_TROAD_PASSWORD:-test}
volumes:
- oracle-troad-data:/opt/oracle/oradata
- ./oracle/init:/container-entrypoint-initdb.d:ro
healthcheck:
test: ["CMD", "healthcheck.sh"]
interval: 20s
timeout: 10s
retries: 30
start_period: 90s
volumes:
oracle-troad-data:
name: exaichatbot-agent-oracle-troad-data
+80 -75
View File
@@ -1,75 +1,80 @@
# exdev Mac Studio 서버 — Agent RAG (Mac Docker: 포트 매핑 필수, host network 미지원)
name: exaichatbot-agent
services:
qdrant:
image: qdrant/qdrant:v1.18.2
ports:
- "6333:6333"
- "6334:6334"
volumes:
- ./qdrant_data:/qdrant/storage
restart: unless-stopped
api:
image: "${RAG_API_IMAGE:-rag-api-slim:latest}"
build:
context: .
dockerfile: docker/service-slim.Dockerfile
ports:
- "${RAG_API_PORT:-28012}:28012"
extra_hosts:
- "host.docker.internal:host-gateway"
depends_on:
- qdrant
env_file:
- .env
environment:
PYTHONUNBUFFERED: "1"
HTTP_PROXY: ""
HTTPS_PROXY: ""
QDRANT_HOST: qdrant
QDRANT_PORT: "6333"
MONGO_HOST: host.docker.internal
LLM_BASE_URL: http://host.docker.internal:16000
TEI_EMBED_URL: http://host.docker.internal:16001
TEI_RERANK_URL: http://host.docker.internal:16002
volumes:
- ./data:/app/data
- ./scripts:/app/scripts
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:28012/health"]
interval: 10s
timeout: 10s
retries: 12
start_period: 60s
admin:
image: "${RAG_API_IMAGE:-rag-api-slim:latest}"
ports:
- "${ADMIN_PORT:-28013}:28013"
extra_hosts:
- "host.docker.internal:host-gateway"
command:
- python
- -m
- uvicorn
- scripts.admin_service:app
- --host
- 0.0.0.0
- --port
- "28013"
working_dir: /app
depends_on:
- qdrant
env_file:
- .env
environment:
PYTHONUNBUFFERED: "1"
QDRANT_HOST: qdrant
QDRANT_PORT: "6333"
volumes:
- ./data:/app/data
- ./scripts:/app/scripts
restart: unless-stopped
# exdev Mac Studio 서버 — Agent RAG (Mac Docker: 포트 매핑 필수, host network 미지원)
name: exaichatbot-agent
services:
qdrant:
image: qdrant/qdrant:v1.18.2
ports:
- "6333:6333"
- "6334:6334"
volumes:
- ./qdrant_data:/qdrant/storage
restart: unless-stopped
api:
image: "${RAG_API_IMAGE:-rag-api-slim:latest}"
build:
context: .
dockerfile: docker/service-slim.Dockerfile
ports:
- "${RAG_API_PORT:-28012}:28012"
extra_hosts:
- "host.docker.internal:host-gateway"
depends_on:
- qdrant
env_file:
- .env
environment:
PYTHONUNBUFFERED: "1"
HTTP_PROXY: ""
HTTPS_PROXY: ""
QDRANT_HOST: qdrant
QDRANT_PORT: "6333"
MONGO_HOST: host.docker.internal
LLM_BASE_URL: http://host.docker.internal:16000
TEI_EMBED_URL: http://host.docker.internal:16001
TEI_RERANK_URL: http://host.docker.internal:16002
# exdev: 호스트 chatbotApi. 운영 IP(172.16.180.130)는 git_fetch_all 커밋 기본값에만 유지.
EXDEV_LOCAL: ${EXDEV_LOCAL:-true}
CHATBOT_API_BASE_URL: ${CHATBOT_API_BASE_URL:-http://host.docker.internal:8086/api}
INTERNAL_TOOL_API_KEY: ${INTERNAL_TOOL_API_KEY:-exdev-agent-tool-key}
CHATBOT_TOOL_TIMEOUT: ${CHATBOT_TOOL_TIMEOUT:-60}
volumes:
- ./data:/app/data
- ./scripts:/app/scripts
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:28012/health"]
interval: 10s
timeout: 10s
retries: 12
start_period: 60s
admin:
image: "${RAG_API_IMAGE:-rag-api-slim:latest}"
ports:
- "${ADMIN_PORT:-28013}:28013"
extra_hosts:
- "host.docker.internal:host-gateway"
command:
- python
- -m
- uvicorn
- scripts.admin_service:app
- --host
- 0.0.0.0
- --port
- "28013"
working_dir: /app
depends_on:
- qdrant
env_file:
- .env
environment:
PYTHONUNBUFFERED: "1"
QDRANT_HOST: qdrant
QDRANT_PORT: "6333"
volumes:
- ./data:/app/data
- ./scripts:/app/scripts
restart: unless-stopped
+45 -39
View File
@@ -1,39 +1,45 @@
# exdev 서버(chatbot.exdev.co.kr) — Agent 2.0 스택
# cp server-dev/env.exdev-server.template exAiChatBot-chatbot2.0-agent/.env
# ── 호스트 AI (Mac Studio MLX) ──
LLM_BASE_URL=http://127.0.0.1:16000
TEI_EMBED_URL=http://127.0.0.1:16001
TEI_RERANK_URL=http://127.0.0.1:16002
LLM_MODEL_NAME=mlx-community/Qwen2.5-7B-Instruct-4bit
EMBED_MODEL_NAME=Qwen/Qwen3-Embedding-8B
TEI_RERANK_MODEL=qwen3-reranker-4b
EMBED_API_STYLE=tei
RERANK_API_STYLE=legacy
MODEL_VERIFY_SSL=false
API_TIMEOUT=120
MODEL_API_KEY=
# ── MongoDB ──
MONGO_HOST=127.0.0.1
MONGO_PORT=27017
MONGO_USER=exlink
MONGO_PASSWORD=!wkcproqkf1
MONGO_DATABASE=chat_history
MONGO_COLLECTION=rag_conversations
# ── Qdrant ──
VECTOR_STORE=qdrant
QDRANT_HOST=127.0.0.1
QDRANT_PORT=6333
QDRANT_COLLECTION=qa_vectors_v2
# ── Agent / WAS ──
AGENT_MODE=agent
AGENT_MAX_ROUNDS=6
CHATBOT_API_BASE_URL=http://127.0.0.1:8086/api
INTERNAL_TOOL_API_KEY=exdev-agent-tool-key
CHATBOT_TOOL_TIMEOUT=60
ADMIN_PORT=28013
UVICORN_WORKERS=2
# exdev 서버(chatbot.exdev.co.kr) — Agent 2.0 스택
# cp server-dev/env.exdev-server.template exAiChatBot-chatbot2.0-agent/.env
# ── 호스트 AI (Mac Studio MLX) ──
LLM_BASE_URL=http://127.0.0.1:16000
TEI_EMBED_URL=http://127.0.0.1:16001
TEI_RERANK_URL=http://127.0.0.1:16002
LLM_MODEL_NAME=mlx-community/Qwen2.5-7B-Instruct-4bit
EMBED_MODEL_NAME=Qwen/Qwen3-Embedding-8B
TEI_RERANK_MODEL=qwen3-reranker-4b
EMBED_API_STYLE=tei
RERANK_API_STYLE=legacy
MODEL_VERIFY_SSL=false
API_TIMEOUT=120
MODEL_API_KEY=
# ── MongoDB ──
MONGO_HOST=127.0.0.1
MONGO_PORT=27017
MONGO_USER=exlink
MONGO_PASSWORD=!wkcproqkf1
MONGO_DATABASE=chat_history
MONGO_COLLECTION=rag_conversations
MONGO_FEEDBACK_DATABASE=chatbot
MONGO_FEEDBACK_COLLECTION=answer_feedback
MONGO_IMPROVEMENT_COLLECTION=improvement_suggestions
# ── Qdrant ──
VECTOR_STORE=qdrant
QDRANT_HOST=127.0.0.1
QDRANT_PORT=6333
QDRANT_COLLECTION=qa_vectors_v2
# ── Agent / WAS (Docker → 호스트 chatbotApi) ──
# EXDEV_LOCAL=true 이면 운영 WAS(172.16.180.130) 호출을 차단한다.
# (GitHub push 시 git_fetch_all.sh 가 커밋 파일의 운영 기본 주소를 복원한다.)
AGENT_MODE=agent
AGENT_MAX_ROUNDS=6
EXDEV_LOCAL=true
CHATBOT_API_BASE_URL=http://host.docker.internal:8086/api
INTERNAL_TOOL_API_KEY=exdev-agent-tool-key
CHATBOT_TOOL_TIMEOUT=60
ADMIN_PORT=28013
UVICORN_WORKERS=2
+111
View File
@@ -0,0 +1,111 @@
# exdev TROAD Oracle (Docker)
개발서버(`chatbot.exdev.co.kr`)에서 교통정보(TROAD) 조회용 Oracle 을 Docker 로 기동합니다.
## 접속 정보 (chatbotApi 와 동일)
| 항목 | 값 |
|------|-----|
| JDBC URL | `jdbc:oracle:thin:@localhost:1521/orcl2` |
| Username | `OPR_MAIN` |
| Password | `test` |
| Image | `gvenzl/oracle-free:23-slim` (Oracle Database Free 23ai) |
| Container | `exaichatbot-agent-oracle-troad` |
| Volume | `exaichatbot-agent-oracle-troad-data` |
`application.yml` 의 기본값은 운영 TROAD(`172.16.163.76`)를 유지합니다.
개발서버에서는 `start-all-server.sh` 가 아래 ENV 로만 localhost Oracle 을 주입합니다
(`SPRING_DATASOURCE_TROAD_URL` / `_USERNAME` / `_PASSWORD`).
`git_fetch_all.sh` 는 커밋 전 yml 을 운영값으로 되돌리므로 exdev 설정이 GitHub에 반영되지 않습니다.
개발서버가 Apple Silicon(arm64) 이므로 amd64 전용인 `gvenzl/oracle-xe:21` 대신
arm64 를 지원하는 `gvenzl/oracle-free:23-slim` 을 사용합니다.
SYS/SYSTEM 비밀번호 기본값: `OracleExdev!2026`
(`ORACLE_SYS_PASSWORD` 환경변수로 변경 가능)
## 기동 / 중지
`start-all-server.sh` / `stop-all-server.sh` 에 포함됩니다.
기동 후 교통정보 뷰가 비어 있으면 `apply-sql.sh` 가 자동 실행됩니다.
```bash
# 수동
cd /Users/aidev/dev/exAichatbot_agent/server-dev
docker compose -f docker-compose.oracle.yml up -d
docker compose -f docker-compose.oracle.yml down
# 데이터 볼륨까지 삭제
docker compose -f docker-compose.oracle.yml down -v
# 또는
./stop-all-server.sh --purge-oracle
```
옵션:
| 옵션 | 설명 |
|------|------|
| `start-all-server.sh --skip-oracle` | Oracle 기동 생략 |
| `stop-all-server.sh --purge-oracle` | 컨테이너 + 데이터 볼륨 삭제 |
## 디렉터리 구성
| 경로 | 설명 |
|------|------|
| `init/` | 컨테이너 최초 초기화 시 1회 실행 (OPR_MAIN 권한 부여) |
| `sql/` | 업무 객체 DDL + 데이터 (파일명 순서로 적용) |
| `data/` | 원본 CSV 덤프 |
| `tools/csv_to_insert.py` | CSV → INSERT 스크립트 변환 |
| `apply-sql.sh` | 컨테이너에 `sql/*.sql` 적용 + 결과 검증 |
## 업무 객체 적용
```bash
cd /Users/aidev/dev/exAichatbot_agent/server-dev/oracle
# sql/ 전체 적용
./apply-sql.sh
# 특정 파일만
./apply-sql.sh sql/10_v_incident_ftms.sql sql/20_v_incident_ftms_data.sql
```
### 적용된 객체
| 객체 | 설명 |
|------|------|
| `OPR_MAIN.T_INCIDENT_FTMS` | 뷰의 원본 데이터 테이블 (17 컬럼 + `LOADED_AT`) |
| `OPR_MAIN.V_INCIDENT_FTMS` | 운영과 동일한 컬럼·순서의 조회용 뷰 |
| `PUBLIC SYNONYM V_INCIDENT_FTMS` | 스키마 미지정 조회 지원 |
| `TLISDEV.T_TRMB_CD_INFO01M1` | 공통코드 (노선명 COM064 등) |
| `TROAD_APP.V_ROUTE_NEW_NM` | 노선명 조회 뷰 (`chatbotApi` 기존 쿼리 그대로 사용) |
| `TROAD_APP.V_ROUTE_TRFC_VER001` | 노선별 교통상황 뷰 (`chatbotApi` 기존 쿼리 그대로 사용) |
| `TROAD_APP.V_ACDT_BRNWS_VER001` | 교통속보 뷰 (`chatbotApi` 기존 쿼리 그대로 사용) |
| `OPR_MAIN.V_ROUTE_*` / `V_ACDT_*` | 스키마 미지정 조회용 미러 뷰 |
운영 뷰는 다수 기반 테이블을 참조하는 읽기 전용 뷰입니다. 개발서버에는 기반 테이블이
없으므로, 뷰 결과 CSV를 물리 테이블에 적재하고 동일 이름 뷰로 노출해
**기존 조회 로직/SQL을 변경하지 않고** 동작하게 합니다.
### 다른 CSV 덤프 추가
```bash
cd /Users/aidev/dev/exAichatbot_agent/server-dev/oracle
python3 tools/csv_to_insert.py data/<파일>.csv \
--table OPR_MAIN.<테이블> \
--numeric <숫자컬럼,콤마구분> \
--out sql/<번호>_<이름>_data.sql
./apply-sql.sh sql/<번호>_<이름>_data.sql
```
## 검증
```bash
docker exec -e NLS_LANG=.AL32UTF8 -it exaichatbot-agent-oracle-troad \
sqlplus OPR_MAIN/test@localhost:1521/ORCL2
SQL> SELECT COUNT(*) FROM V_INCIDENT_FTMS;
SQL> SELECT INCIDENT_TYPE, COUNT(*) FROM V_INCIDENT_FTMS GROUP BY INCIDENT_TYPE;
```
한글 데이터 조회 시 `NLS_LANG=.AL32UTF8` 을 지정해야 깨지지 않습니다.
+113
View File
@@ -0,0 +1,113 @@
#!/usr/bin/env bash
# TROAD Oracle 컨테이너에 sql/*.sql 을 순서대로 적용한다.
#
# 사용법:
# ./apply-sql.sh # sql/ 전체 (파일명 순)
# ./apply-sql.sh sql/10_v_incident_ftms.sql sql/20_v_incident_ftms_data.sql
#
# 컨테이너가 기동/healthy 상태여야 한다. (start-all-server.sh 또는 docker compose up)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONTAINER="${ORACLE_CONTAINER:-exaichatbot-agent-oracle-troad}"
PDB="${ORACLE_PDB:-ORCL2}"
SYS_PASSWORD="${ORACLE_SYS_PASSWORD:-OracleExdev!2026}"
REMOTE_DIR="/tmp/troad-sql"
log() { printf '\033[36m[oracle-sql]\033[0m %s\n' "$*"; }
err() { printf '\033[31m[oracle-sql]\033[0m %s\n' "$*" >&2; }
if ! docker inspect "$CONTAINER" >/dev/null 2>&1; then
err "컨테이너를 찾을 수 없습니다: $CONTAINER"
err "먼저 기동하세요: docker compose -f docker-compose.oracle.yml up -d"
exit 1
fi
state="$(docker inspect -f '{{.State.Status}}' "$CONTAINER")"
if [[ "$state" != "running" ]]; then
err "컨테이너가 running 상태가 아닙니다 (현재: $state)"
exit 1
fi
# healthcheck 통과 대기 (최대 10분)
for _ in $(seq 1 120); do
health="$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' "$CONTAINER")"
[[ "$health" == "healthy" || "$health" == "none" ]] && break
sleep 5
done
if [[ "${health:-}" != "healthy" && "${health:-}" != "none" ]]; then
err "Oracle 이 healthy 상태가 아닙니다 (현재: ${health:-unknown})"
exit 1
fi
if [[ $# -gt 0 ]]; then
FILES=("$@")
else
FILES=()
while IFS= read -r f; do FILES+=("$f"); done < <(find "$SCRIPT_DIR/sql" -maxdepth 1 -name '*.sql' | sort)
fi
if [[ ${#FILES[@]} -eq 0 ]]; then
err "적용할 SQL 파일이 없습니다."
exit 1
fi
docker exec "$CONTAINER" mkdir -p "$REMOTE_DIR"
for file in "${FILES[@]}"; do
path="$file"
[[ -f "$path" ]] || path="$SCRIPT_DIR/$file"
if [[ ! -f "$path" ]]; then
err "파일 없음: $file"
exit 1
fi
base="$(basename "$path")"
log "적용: $base"
docker cp "$path" "$CONTAINER:$REMOTE_DIR/$base"
# 한글 데이터를 위해 NLS_LANG 을 AL32UTF8 로 고정하고 PDB 에 접속한다.
output="$(docker exec -e NLS_LANG=.AL32UTF8 -i "$CONTAINER" bash -lc "
sqlplus -S -L sys/'${SYS_PASSWORD}'@localhost:1521/${PDB} as sysdba <<'EOSQL'
WHENEVER SQLERROR EXIT SQL.SQLCODE
WHENEVER OSERROR EXIT FAILURE
SET ECHO OFF
SET FEEDBACK OFF
SET PAGESIZE 0
SET LINESIZE 200
@${REMOTE_DIR}/${base}
EXIT
EOSQL
" 2>&1)" || {
err "실패: $base"
printf '%s\n' "$output" >&2
exit 1
}
[[ -n "${output// /}" ]] && printf '%s\n' "$output"
done
log "검증"
docker exec -e NLS_LANG=.AL32UTF8 -i "$CONTAINER" bash -lc "
sqlplus -S -L sys/'${SYS_PASSWORD}'@localhost:1521/${PDB} as sysdba <<'EOSQL'
SET PAGESIZE 50
SET LINESIZE 200
COLUMN OWNER FORMAT A12
COLUMN OBJECT_NAME FORMAT A30
COLUMN OBJECT_TYPE FORMAT A12
SELECT OWNER, OBJECT_NAME, OBJECT_TYPE, STATUS
FROM ALL_OBJECTS
WHERE (OWNER = 'OPR_MAIN' AND OBJECT_NAME IN ('T_INCIDENT_FTMS', 'V_INCIDENT_FTMS', 'V_ROUTE_NEW_NM', 'V_ROUTE_TRFC_VER001', 'V_ACDT_BRNWS_VER001'))
OR (OWNER = 'TROAD_APP' AND OBJECT_NAME IN ('V_ROUTE_NEW_NM', 'V_ROUTE_TRFC_VER001', 'V_ACDT_BRNWS_VER001', 'T_ROUTE_NEW_NM', 'T_ROUTE_TRFC_VER001', 'T_ACDT_BRNWS_VER001'))
OR (OWNER = 'TLISDEV' AND OBJECT_NAME IN ('T_TRMB_CD_INFO01M1'))
ORDER BY OWNER, OBJECT_TYPE, OBJECT_NAME;
SELECT (SELECT COUNT(*) FROM OPR_MAIN.V_INCIDENT_FTMS) AS V_INCIDENT_FTMS_ROWS FROM DUAL;
SELECT (SELECT COUNT(*) FROM TROAD_APP.V_ROUTE_NEW_NM) AS V_ROUTE_NEW_NM_ROWS FROM DUAL;
SELECT (SELECT COUNT(*) FROM TROAD_APP.V_ROUTE_TRFC_VER001) AS V_ROUTE_TRFC_ROWS FROM DUAL;
SELECT (SELECT COUNT(*) FROM TROAD_APP.V_ACDT_BRNWS_VER001) AS V_ACDT_BRNWS_ROWS FROM DUAL;
SELECT (SELECT COUNT(*) FROM TLISDEV.T_TRMB_CD_INFO01M1) AS T_TRMB_CD_INFO_ROWS FROM DUAL;
EXIT
EOSQL
"
log "완료"
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,89 @@
"ROUTECD","GRPID","BOUND","ROADNM","ROUTESORT","ROADSHORTNO","BOUNDNM","INCIDENT_ID","INCI_TP_ORDER","INCI_TP","MSG","INCIDENT_POS_NAME","OCRN_DSTNC","CNGS_LNGT","LAT","LON","CCTV_ID","CCTV_NM","THUMBIMAGE","HLS_URL","ST_D","EN_D","VVALUE01","VVALUE02","VVALUE03","VVALUE04","VVALUE05","CRCM_TIME","CRCM_MSG"
"4004","1",S,수도권제2순환선(화성-광주),"5","400",화성방향,"20260521143800","03",작업,K (2차로) 비탈면보수 작업중 (14시 38분부터),동탄방향 26.0,"0","0","0","0",cctv00007433,동탄JC,https://exmobile4.hscdn.com/cctv7433image/ch00007433_20260730.154600.000.jpg,https://live18.exmobile.hscdn.com/exlive/cctv7433.stream/playlist.m3u8,0,0, , , , , ,(14시 38분부터),K (2차로) 비탈면보수 작업중
"0650","1",E,동해선(삼척-속초),"6","65",속초방향,"20260703074200","03",작업,(2차로)졸음쉼터 설치 작업중 (07시 42분부터),쇄운교(15K)-지흥1교(16.7K),"15",-1,"37.486292","129.090703",cctv00005829,쇄운교,https://exmobile4.hscdn.com/cctv5829image/ch00005829_20260730.154600.000.jpg,https://live7.exmobile.hscdn.com/exlive/cctv5829.stream/playlist.m3u8,15,15, , , , , ,(07시 42분부터),(2차로)졸음쉼터 설치 작업중
"0652","1",E,동해선(부산-포항),"6","65",포항방향,"20260720082502","03",작업,"(2차로)노면보강 공사 작업중, 장기차단 (08시 25분부터)",남경주부근(68K)-문무대왕1터널(74K),"68",-1,"35.724019","129.296973",cctv00005797,냉천3교,https://exmobile8.hscdn.com/cctv5797image/ch00005797_20260730.154600.000.jpg,https://live17.exmobile.hscdn.com/exlive/cctv5797.stream/playlist.m3u8,68,68, , , , , ,(08시 25분부터),"(2차로)노면보강 공사 작업중, 장기차단 "
"4004","1",S,수도권제2순환선(화성-광주),"5","400",화성방향,"20260723135200","03",작업,null (13시 52분부터),동탄방향 9.8,"0","0","0","0",cctv00007433,동탄JC,https://exmobile4.hscdn.com/cctv7433image/ch00007433_20260730.154600.000.jpg,https://live18.exmobile.hscdn.com/exlive/cctv7433.stream/playlist.m3u8,0,0, , , , , ,(13시 52분부터),null
"1100","1",S,제2경인선,"6","110",인천방향,"20260730065400","04",정체, (06시 54분부터),서창분기점(9K)-남동부근(6K),"9","3","37.433276","126.729185",cctv00000762,서창분기점,https://exmobile8.hscdn.com/cctv0762image/ch00000762_20260730.154600.000.jpg,https://live1.exmobile.hscdn.com/exlive/cctv0762.stream/playlist.m3u8,9,9, , , , , ,(06시 54분부터),
"0150","1",E,서해안선,"2","15",서울방향,"20260730065451","04",정체, (06시 54분부터),광명역(334K)-금천(340K),"334","6","37.407933","126.88693",cctv00000215,충훈대교,https://exmobile8.hscdn.com/cctv0215image/ch00000215_20260730.154600.000.jpg,https://live1.exmobile.hscdn.com/exlive/cctv0215.stream/playlist.m3u8,334,334, , , , , ,(06시 54분부터),
"1000","1",S,수도권제1순환선,"5","100",일산방향,"20260730072448","04",정체, (07시 24분부터),시흥요금소(96K)-중동(86K),"96","10","37.449284","126.805207",cctv00002060,시흥TG_일산,https://exmobile4.hscdn.com/cctv2060image/ch00002060_20260730.154600.000.jpg,https://live11.exmobile.hscdn.com/exlive/cctv2060.stream/playlist.m3u8,96,96, , , , , ,(07시 24분부터),
"0351","1",S,통영대전선,"6","35",통영방향,"20260730081231","03",작업,(갓길) 시설물 보수 작업중 (08시 12분부터),오동터널부근(132K),"132",-1,"35.707033","127.624994",cctv00002182,오동2교,https://exmobile4.hscdn.com/cctv2182image/ch00002182_20260730.154600.000.jpg,https://live8.exmobile.hscdn.com/exlive/cctv2182.stream/playlist.m3u8,132,0, , , , , ,(08시 12분부터),(갓길) 시설물 보수 작업중
"0252","1",S,논산천안선,"6","25",논산방향,"20260730082406","04",정체,"3km 정체 (08시 24분부터)",차령터널 무학천교(266.0K)-차령터널 (263.0K),"269","0","36.72055","127.13463",cctv00007136,호정1교,https://exmobile4.hscdn.com/cctv7136image/ch00007136_20260730.154600.000.jpg,https://live11.exmobile.hscdn.com/exlive/cctv7136.stream/playlist.m3u8,269,269, , , , , ,(08시 24분부터),"3km 정체"
"0201","1",S,익산장수선,"6","20",익산방향,"20260730084122","03",작업,(갓길) 덩쿨제거 작업중 (08시 41분부터),소양(16K)-소양부근(15K),"16",-1,"35.865021","127.230784",cctv00003867,소양,https://exmobile8.hscdn.com/cctv3867image/ch00003867_20260730.154600.000.jpg,https://live4.exmobile.hscdn.com/exlive/cctv3867.stream/playlist.m3u8,16,16, , , , , ,(08시 41분부터),(갓길) 덩쿨제거 작업중
"0450","1",S,중부내륙선,"6","45",창원방향,"20260730094639","04",정체, (09시 46분부터),감곡부근(258K)-감곡부근(255K),"258","3","37.172225","127.622368",cctv00003204,삼승교,https://exmobile4.hscdn.com/cctv3204image/ch00003204_20260730.154600.000.jpg,https://live10.exmobile.hscdn.com/exlive/cctv3204.stream/playlist.m3u8,258,258, , , , , ,(09시 46분부터),
"0100","1",E,남해선(순천-부산),"6","10",부산방향,"20260730103250","04",정체, (10시 32분부터),함안2터널부근(119K)-함안2터널부근(120K),"119","1","35.288699","128.542006",cctv00000560,함안2터널(부산외부),https://exmobile4.hscdn.com/cctv0560image/ch00000560_20260730.154600.000.jpg,https://live13.exmobile.hscdn.com/exlive/cctv0560.stream/playlist.m3u8,119,119, , , , , ,(10시 32분부터),
"0252","1",S,논산천안선,"6","25",논산방향,"20260728140304","04",정체,"5km 정체 (14시 03분부터)",남풍세IC 호정 1교(268.0K)-차령터널 (263.0K),"269","0","36.72055","127.13463",cctv00007136,호정1교,https://exmobile4.hscdn.com/cctv7136image/ch00007136_20260730.154600.000.jpg,https://live11.exmobile.hscdn.com/exlive/cctv7136.stream/playlist.m3u8,269,269, , , , , ,(14시 03분부터),"5km 정체"
"1000","1",E,수도권제1순환선,"5","100",구리방향,"20260730051106","04",정체, (05시 11분부터),노오지분기점(79K)-송내(88K),"79","9","37.570368","126.753178",cctv00000227,노오지분기점,https://exmobile4.hscdn.com/cctv0227image/ch00000227_20260730.154600.000.jpg,https://live15.exmobile.hscdn.com/exlive/cctv0227.stream/playlist.m3u8,79,79, , , , , ,(05시 11분부터),
"0010","1",E,경부선,"1","1",서울방향,"20260730062713","04",정체, (06시 27분부터),양재부근(415K)-반포(420K),"415","5","37.456747","127.046344",cctv00000002,양재,https://exmobile4.hscdn.com/cctv0002image/ch00000002_20260730.154600.000.jpg,https://live1.exmobile.hscdn.com/exlive/cctv0002.stream/playlist.m3u8,415,415, , , , , ,(06시 27분부터),
"0010","1",S,경부선,"1","1",부산방향,"20260730105038","04",정체, (10시 50분부터),천안분기점부근(332K)-천안호두(휴)(324K),"332","8","36.766668","127.196939",cctv00003848,응원고개,https://exmobile4.hscdn.com/cctv3848image/ch00003848_20260730.154600.000.jpg,https://live4.exmobile.hscdn.com/exlive/cctv3848.stream/playlist.m3u8,332,332, , , , , ,(10시 50분부터),
"0450","1",E,중부내륙선,"6","45",양평방향,"20260730132759","04",정체, (13시 27분부터),충주분기점부근(238K)-충주분기점부근(241K),"238","3","37.041776","127.75111",cctv00003209,한포천,https://exmobile4.hscdn.com/cctv3209image/ch00003209_20260730.154600.000.jpg,https://live10.exmobile.hscdn.com/exlive/cctv3209.stream/playlist.m3u8,238,238, , , , , ,(13시 27분부터),
"0100","1",E,남해선(순천-부산),"6","10",부산방향,"20260730134538","04",정체, (13시 45분부터),대저분기점(163K)-덕천(166K),"163","3","35.219275","128.969671",cctv00003930,대저,https://exmobile4.hscdn.com/cctv3930image/ch00003930_20260730.154600.000.jpg,https://live15.exmobile.hscdn.com/exlive/cctv3930.stream/playlist.m3u8,163,163, , , , , ,(13시 45분부터),
"1100","1",E,제2경인선,"6","110",성남방향,"20260730135457","04",정체, (13시 54분부터),학익분기점(3K)-남동(8K),"3","5","37.438267","126.662356",cctv00001535,학익대교1,https://exmobile4.hscdn.com/cctv1535image/ch00001535_20260730.154600.000.jpg,https://live12.exmobile.hscdn.com/exlive/cctv1535.stream/playlist.m3u8,3,3, , , , , ,(13시 54분부터),
"0500","1",S,영동선,"4","50",인천방향,"20260730135951","04",정체, (13시 59분부터),군자분기점(7K)-월곶분기점부근(4K),"7","3","37.382693","126.762417",cctv00000854,군자분기점,https://exmobile4.hscdn.com/cctv0854image/ch00000854_20260730.154600.000.jpg,https://live2.exmobile.hscdn.com/exlive/cctv0854.stream/playlist.m3u8,7,7, , , , , ,(13시 59분부터),
"0150","1",E,서해안선,"2","15",서울방향,"20260730140943","04",정체, (14시 09분부터),서평택분기점부근(295K)-화성(휴)부근(303K),"295","8","37.08446","126.886438",cctv00000054,상신2교,https://exmobile4.hscdn.com/cctv0054image/ch00000054_20260730.154600.000.jpg,https://live1.exmobile.hscdn.com/exlive/cctv0054.stream/playlist.m3u8,295,295, , , , , ,(14시 09분부터),
"0150","1",E,서해안선,"2","15",서울방향,"20260730141000","04",정체, (14시 10분부터),매송(휴)부근(315K)-용담터널(319K),"315","4","37.260631","126.887041",cctv00002409,야목2교,https://exmobile8.hscdn.com/cctv2409image/ch00002409_20260730.154600.000.jpg,https://live3.exmobile.hscdn.com/exlive/cctv2409.stream/playlist.m3u8,315,315, , , , , ,(14시 10분부터),
"0352","1",S,중부선,"3","35",남이방향,"20260730141034","04",정체, (14시 10분부터),진천터널부근(277K)-진천터널부근(274K),"277","3","36.835086","127.494366",cctv00003845,백곡천교,https://exmobile8.hscdn.com/cctv3845image/ch00003845_20260730.154600.000.jpg,https://live9.exmobile.hscdn.com/exlive/cctv3845.stream/playlist.m3u8,277,277, , , , , ,(14시 10분부터),
"0202","1",E,새만금전주선,"6","202",새만금방향,"20260730141437","01",기타,(갓길)소형화물차 고장 처리중 (14시 14분부터),석구터널(46.1K),"46.1",-1,"35.773544","127.153308",cctv00002613,원은육교2,https://exmobile4.hscdn.com/cctv2613image/ch00002613_20260730.154600.000.jpg,https://live1.exmobile.hscdn.com/exlive/cctv2613.stream/playlist.m3u8,46.1,0, , , , , ,(14시 14분부터),(갓길)소형화물차 고장 처리중
"0500","1",S,영동선,"4","50",인천방향,"20260730142623","04",정체, (14시 26분부터),동수원(37K)-북수원(30K),"37","7","37.299117","127.051361",cctv00002415,동수원,https://exmobile4.hscdn.com/cctv2415image/ch00002415_20260730.154500.000.jpg,https://live3.exmobile.hscdn.com/exlive/cctv2415.stream/playlist.m3u8,37,37, , , , , ,(14시 26분부터),
"0010","1",E,경부선,"1","1",서울방향,"20260730143713","04",정체, (14시 37분부터),안성분기점(364K)-안성(휴)부근(368K),"364","4","37.028613","127.140833",cctv00000037,안성분기점2,https://exmobile8.hscdn.com/cctv0037image/ch00000037_20260730.154600.000.jpg,https://live4.exmobile.hscdn.com/exlive/cctv0037.stream/playlist.m3u8,364,364, , , , , ,(14시 37분부터),
"1100","1",S,제2경인선,"6","110",인천방향,"20260730143718","04",정체, (14시 37분부터),삼막(25.98K)-광명터널(22K),"25.98","4","37.425507","126.912049",cctv00000767,석수,https://exmobile8.hscdn.com/cctv0767image/ch00000767_20260730.154600.000.jpg,https://live1.exmobile.hscdn.com/exlive/cctv0767.stream/playlist.m3u8,25.98,25.98, , , , , ,(14시 37분부터),
"0651","1",S,부산울산선,"6","65",부산방향,"20260730144311","04",정체, (14시 43분부터),해운대터널부근(3K)-부산울산선시점(0K),"3","3","35.190683","129.201783",cctv00000728,고래진2교,https://exmobile8.hscdn.com/cctv0728image/ch00000728_20260730.154600.000.jpg,https://live17.exmobile.hscdn.com/exlive/cctv0728.stream/playlist.m3u8,3,3, , , , , ,(14시 43분부터),
"0010","1",E,경부선,"1","1",서울방향,"20260730144715","00",사고,"(3차로,갓길)화물차관련 사고 처리중 (14시 47분부터)",영천분기점(91.5K),"91.5",-1,"35.924733","128.998642",cctv00000819,반정1교,https://exmobile4.hscdn.com/cctv0819image/ch00000819_20260730.154600.000.jpg,https://live10.exmobile.hscdn.com/exlive/cctv0819.stream/playlist.m3u8,91.5,0, , , , , ,(14시 47분부터),"(3차로,갓길)화물차관련 사고 처리중"
"1000","1",E,수도권제1순환선,"5","100",구리방향,"20260730145917","04",정체, (14시 59분부터),자유로(72K)-김포(74K),"72","2","37.618882","126.799826",cctv00000224,자유로분기점,https://exmobile4.hscdn.com/cctv0224image/ch00000224_20260730.154600.000.jpg,https://live15.exmobile.hscdn.com/exlive/cctv0224.stream/playlist.m3u8,72,72, , , , , ,(14시 59분부터),
"0400","1",S,평택제천선,"6","40",평택방향,"20260730150604","04",정체, (15시 06분부터),서안성(25K)-안성분기점(24K),"25","1","37.036583","127.153094",cctv00005947,강문교,https://exmobile4.hscdn.com/cctv5947image/ch00005947_20260730.154600.000.jpg,https://live14.exmobile.hscdn.com/exlive/cctv5947.stream/playlist.m3u8,25,25, , , , , ,(15시 06분부터),
"1200","1",S,경인선,"6","120",인천방향,"20260730150911","04",정체, (15시 09분부터),인천요금소(16K)-서인천(11K),"16","5","37.523954","126.742937",cctv00005038,인천영업소,https://exmobile8.hscdn.com/cctv5038image/ch00005038_20260730.154600.000.jpg,https://live1.exmobile.hscdn.com/exlive/cctv5038.stream/playlist.m3u8,16,16, , , , , ,(15시 09분부터),
"0010","1",E,경부선,"1","1",서울방향,"20260730152029","04",정체, (15시 20분부터),입장거봉포도(휴)부근(355K)-안성(360K),"355","5","36.955513","127.181906",cctv00003102,연곡,https://exmobile8.hscdn.com/cctv3102image/ch00003102_20260730.154600.000.jpg,https://live4.exmobile.hscdn.com/exlive/cctv3102.stream/playlist.m3u8,355,355, , , , , ,(15시 20분부터),
"1200","1",E,경인선,"6","120",서울방향,"20260730152128","04",정체, (15시 21분부터),신월(23K)-신월(24K),"23","1","37.523394","126.821631",cctv00001451,신월-1,https://exmobile4.hscdn.com/cctv1451image/ch00001451_20260730.154600.000.jpg,https://live8.exmobile.hscdn.com/exlive/cctv1451.stream/playlist.m3u8,23,23, , , , , ,(15시 21분부터),
"1040","1",E,남해2지선,"6","104",서부산방향,"20260730152500","04",정체, (15시 25분부터),서부산(휴)(18K)-사상(20K),"18","2","35.156477","128.948907",cctv00003718,서부산,https://exmobile4.hscdn.com/cctv3718image/ch00003718_20260730.154600.000.jpg,https://live4.exmobile.hscdn.com/exlive/cctv3718.stream/playlist.m3u8,18,18, , , , , ,(15시 25분부터),
"0010","1",S,경부선,"1","1",부산방향,"20260730152539","01",기타,(갓길) 승용 고장차 처리중 (15시 25분부터),청주분기점(297K),"297",-1,"36.568675","127.429435",cctv00002129,청주분기점2,https://exmobile4.hscdn.com/cctv2129image/ch00002129_20260730.154600.000.jpg,https://live12.exmobile.hscdn.com/exlive/cctv2129.stream/playlist.m3u8,297,0, , , , , ,(15시 25분부터),(갓길) 승용 고장차 처리중
"0252","1",E,논산천안선,"6","25",천안방향,"20260730152731","04",정체,"3km 정체 (15시 27분부터)",남공주IC 오룡교(232.0K)-남공주IC 검상천교(235.0K),"225","0","36.34541","127.06794",cctv00007164,이인SA/남,https://exmobile4.hscdn.com/cctv7164image/ch00007164_20260730.154600.000.jpg,https://live11.exmobile.hscdn.com/exlive/cctv7164.stream/playlist.m3u8,225,225, , , , , ,(15시 27분부터),"3km 정체"
"6000","1",S,부산외곽선,"6","600",창원방향,"20260730152946","04",정체, (15시 29분부터),기장분기점(48K)-기장분기점부근(47K),"48","1","35.281987","129.2089",cctv00000517,용천교,https://exmobile4.hscdn.com/cctv0517image/ch00000517_20260730.154600.000.jpg,https://live11.exmobile.hscdn.com/exlive/cctv0517.stream/playlist.m3u8,48,48, , , , , ,(15시 29분부터),
"1300","1",S,인천공항선,"6","130",공항방향,"20260730153000","04",정체,청라IC 진출 1km 정체 (15시 30분부터),[본선-공항] 20.8Km,"20.8","0","37.569859","126.670011",cctv00007097,인천공항영업소,https://exmobile4.hscdn.com/cctv7097image/ch00007097_20260730.154600.000.jpg,https://live11.exmobile.hscdn.com/exlive/cctv7097.stream/playlist.m3u8,20.8,20.8, , , , , ,(15시 30분부터),청라IC 진출 1km 정체
"1000","1",S,수도권제1순환선,"5","100",일산방향,"20260730153338","04",정체, (15시 33분부터),안양터널(114K)-수리터널(112K),"114","2","37.37919","126.946985",cctv00000292,안양터널,https://exmobile4.hscdn.com/cctv0292image/ch00000292_20260730.154600.000.jpg,https://live15.exmobile.hscdn.com/exlive/cctv0292.stream/playlist.m3u8,114,114, , , , , ,(15시 33분부터),
"0500","1",S,영동선,"4","50",인천방향,"20260730153400","04",정체, (15시 34분부터),덕평부근(66K)-양지터널부근(58K),"66","8","37.250668","127.352923",cctv00000371,오천교,https://exmobile8.hscdn.com/cctv0371image/ch00000371_20260730.154600.000.jpg,https://live16.exmobile.hscdn.com/exlive/cctv0371.stream/playlist.m3u8,66,66, , , , , ,(15시 34분부터),
"2510","1",S,호남지선,"6","251",논산방향,"20260730154509","04",정체, (15시 45분부터),회덕분기점(54K)-북대전부근(52K),"54","2","0","0",cctv00000297,전민,https://exmobile4.hscdn.com/cctv0297image/ch00000297_20260730.154600.000.jpg,https://live12.exmobile.hscdn.com/exlive/cctv0297.stream/playlist.m3u8,54,54, , , , , ,(15시 45분부터),
"0400","1",S,평택제천선,"6","40",평택방향,"20260730155518","04",정체, (15시 55분부터),대소분기점(57K)-안진터널(52K),"57","5","36.941808","127.463959",cctv00003794,대소분기점,https://exmobile4.hscdn.com/cctv3794image/ch00003794_20260730.154600.000.jpg,https://live14.exmobile.hscdn.com/exlive/cctv3794.stream/playlist.m3u8,57,57, , , , , ,(15시 55분부터),
"0600","1",S,서울양양선,"6","60",서울방향,"20260730155707","04",정체, (15시 57분부터),화도(15K)-화도부근(13K),"15","2","37.63154","127.312837",cctv00000400,화도영업소,https://exmobile8.hscdn.com/cctv0400image/ch00000400_20260730.154600.000.jpg,https://live17.exmobile.hscdn.com/exlive/cctv0400.stream/playlist.m3u8,15,15, , , , , ,(15시 57분부터),
"0010","1",E,경부선,"1","1",서울방향,"20260730160049","04",정체,(순환선 진출로) (16시 00분부터),판교분기점(408K),"408","1","37.406461","127.09392",cctv00000006,판교분기점_경부,https://exmobile4.hscdn.com/cctv0006image/ch00000006_20260730.154600.000.jpg,https://live1.exmobile.hscdn.com/exlive/cctv0006.stream/playlist.m3u8,408,0, , , , , ,(16시 00분부터),(순환선 진출로)
"0251","1",E,호남선,"6","25",천안방향,"20260730160618","04",정체,교통량 증가 (16시 06분부터),동광주(74K),"74","1","35.183438","126.926925",cctv00003382,동광주,https://exmobile4.hscdn.com/cctv3382image/ch00003382_20260730.154600.000.jpg,https://live11.exmobile.hscdn.com/exlive/cctv3382.stream/playlist.m3u8,74,0, , , , , ,(16시 06분부터),교통량 증가
"1000","1",E,수도권제1순환선,"5","100",구리방향,"20260730160627","04",정체, (16시 06분부터),조남분기점(107K)-수암터널(108K),"107","1","37.368655","126.869846",cctv00000238,조남분기점,https://exmobile4.hscdn.com/cctv0238image/ch00000238_20260730.154600.000.jpg,https://live15.exmobile.hscdn.com/exlive/cctv0238.stream/playlist.m3u8,107,107, , , , , ,(16시 06분부터),
"0352","1",E,중부선,"3","35",하남방향,"20260730160933","04",정체, (16시 09분부터),일죽부근(304K)-일죽부근(309K),"304","5","37.070051","127.468948",cctv00000667,장암1,https://exmobile4.hscdn.com/cctv0667image/ch00000667_20260730.154600.000.jpg,https://live4.exmobile.hscdn.com/exlive/cctv0667.stream/playlist.m3u8,304,304, , , , , ,(16시 09분부터),
"0500","1",S,영동선,"4","50",인천방향,"20260730161003","04",정체, (16시 10분부터),서창분기점(1K)-서창(0K),"1","1","37.428961","126.737875",cctv00005669,서창,https://exmobile8.hscdn.com/cctv5669image/ch00005669_20260730.154600.000.jpg,https://live16.exmobile.hscdn.com/exlive/cctv5669.stream/playlist.m3u8,1,1, , , , , ,(16시 10분부터),
"0450","1",E,중부내륙선,"6","45",양평방향,"20260730161104","01",기타,(갓길)승합차고장 처리중 (16시 11분부터),감곡부근(252.1K),"252.1",-1,"37.129423","127.66049",cctv00005386,상우1교,https://exmobile8.hscdn.com/cctv5386image/ch00005386_20260730.154600.000.jpg,https://live14.exmobile.hscdn.com/exlive/cctv5386.stream/playlist.m3u8,252.1,0, , , , , ,(16시 11분부터),(갓길)승합차고장 처리중
"0150","1",E,서해안선,"2","15",서울방향,"20260730161342","01",기타,(갓길)중형화물차 고장 처리중 (16시 13분부터),서천(휴)부근(166.5K),"166.5",-1,"36.119755","126.636626",cctv00002043,종천1교,https://exmobile4.hscdn.com/cctv2043image/ch00002043_20260730.154600.000.jpg,https://live12.exmobile.hscdn.com/exlive/cctv2043.stream/playlist.m3u8,166.5,0, , , , , ,(16시 13분부터),(갓길)중형화물차 고장 처리중
"0500","1",S,영동선,"4","50",인천방향,"20260730161727","04",정체, (16시 17분부터),둔대분기점(23K)-반월터널부근(21K),"23","2","37.322581","126.907065",cctv00005041,둔대분기점,https://exmobile8.hscdn.com/cctv5041image/ch00005041_20260730.154600.000.jpg,https://live16.exmobile.hscdn.com/exlive/cctv5041.stream/playlist.m3u8,23,23, , , , , ,(16시 17분부터),
"0270","1",E,순천완주선,"6","27",완주방향,"20260730161748","01",기타,(갓길) 화물차 고장 처리중 (16시 17분부터),서면2터널부근(10.7K),"10.7",-1,"35.028166","127.507502",cctv00005578,서면2터널(완주외부1),https://exmobile8.hscdn.com/cctv5578image/ch00005578_20260730.154600.000.jpg,https://live14.exmobile.hscdn.com/exlive/cctv5578.stream/playlist.m3u8,10.7,0, , , , , ,(16시 17분부터),(갓길) 화물차 고장 처리중
"0160","1",E,울산선,"6","16",울산방향,"20260730161750","01",기타,(갓길)화물차 고장처리 중 (16시 17분부터),범서하이패스(10.3K),"10.3",-1,"35.570555","129.227118",cctv00005346,입암,https://exmobile4.hscdn.com/cctv5346image/ch00005346_20260730.154600.000.jpg,https://live14.exmobile.hscdn.com/exlive/cctv5346.stream/playlist.m3u8,10.3,0, , , , , ,(16시 17분부터),(갓길)화물차 고장처리 중
"0500","1",S,영동선,"4","50",인천방향,"20260730161757","04",정체,진출로 (16시 17분부터),서용인분기점(50K),"50","1","37.268988","127.186046",cctv00000363,마성터널(강릉),https://exmobile8.hscdn.com/cctv0363image/ch00000363_20260730.154600.000.jpg,https://live16.exmobile.hscdn.com/exlive/cctv0363.stream/playlist.m3u8,50,0, , , , , ,(16시 17분부터),진출로
"0150","1",E,서해안선,"2","15",서울방향,"20260730161803","01",기타,(갓길) 화물 고장차 처리중 (16시 18분부터),당진부근(267.3K),"267.3",-1,"36.906553","126.733865",cctv00000626,영천교(고정),https://exmobile4.hscdn.com/cctv0626image/ch00000626_20260730.154600.000.jpg,https://live4.exmobile.hscdn.com/exlive/cctv0626.stream/playlist.m3u8,267.3,0, , , , , ,(16시 18분부터),(갓길) 화물 고장차 처리중
"0550","2",S,중앙선,"6","55",부산방향,"20260730161902","04",정체, (16시 19분부터),초정(5K)-삼락(0K),"5","5","35.235254","128.980641",cctv00003672,초정,https://exmobile8.hscdn.com/cctv3672image/ch00003672_20260730.154600.000.jpg,https://live4.exmobile.hscdn.com/exlive/cctv3672.stream/playlist.m3u8,5,5, , , , , ,(16시 19분부터),
"0500","1",E,영동선,"4","50",강릉방향,"20260730161916","04",정체, (16시 19분부터),둔대분기점(22K)-부곡(27K),"22","5","37.322957","126.895948",cctv00000220,둔대교,https://exmobile8.hscdn.com/cctv0220image/ch00000220_20260730.154600.000.jpg,https://live2.exmobile.hscdn.com/exlive/cctv0220.stream/playlist.m3u8,22,22, , , , , ,(16시 19분부터),
"0252","1",E,논산천안선,"6","25",천안방향,"20260730162057","00",사고,"1차로 승용차 관련 사고발생 (16시 20분부터)",남공주IC 오룡교(232.1K),"225","0","36.34541","127.06794",cctv00007164,이인SA/남,https://exmobile4.hscdn.com/cctv7164image/ch00007164_20260730.154600.000.jpg,https://live11.exmobile.hscdn.com/exlive/cctv7164.stream/playlist.m3u8,225,225, , , , , ,(16시 20분부터),"1차로 승용차 관련 사고발생"
"1000","1",S,수도권제1순환선,"5","100",일산방향,"20260730162117","04",정체, (16시 21분부터),성남부근(3K)-판교분기점(0K),"3","3","37.416928","127.122446",cctv00005932,성남삼평교2,https://exmobile4.hscdn.com/cctv5932image/ch00005932_20260730.154600.000.jpg,https://live5.exmobile.hscdn.com/exlive/cctv5932.stream/playlist.m3u8,3,3, , , , , ,(16시 21분부터),
"1000","1",S,수도권제1순환선,"5","100",일산방향,"20260730162134","04",정체, (16시 21분부터),판교분기점(128K)-판교분기점부근(126K),"128","2","37.405686","127.094436",cctv00005666,금토,https://exmobile8.hscdn.com/cctv5666image/ch00005666_20260730.154600.000.jpg,https://live11.exmobile.hscdn.com/exlive/cctv5666.stream/playlist.m3u8,128,128, , , , , ,(16시 21분부터),
"1000","1",S,수도권제1순환선,"5","100",일산방향,"20260730162214","04",정체, (16시 22분부터),서하남분기점(16K)-송파부근(7K),"16","9","37.515281","127.169685",cctv00000251,광암터널2,https://exmobile4.hscdn.com/cctv0251image/ch00000251_20260730.154600.000.jpg,https://live15.exmobile.hscdn.com/exlive/cctv0251.stream/playlist.m3u8,16,16, , , , , ,(16시 22분부터),
"0600","1",S,서울양양선,"6","60",서울방향,"20260730162324","04",정체, (16시 23분부터),덕소삼패(3K)-강일(0K),"3","3","37.587067","127.199448",cctv00000427,미사대교종점,https://exmobile8.hscdn.com/cctv0427image/ch00000427_20260730.154600.000.jpg,https://live17.exmobile.hscdn.com/exlive/cctv0427.stream/playlist.m3u8,3,3, , , , , ,(16시 23분부터),
"0450","1",E,중부내륙선,"6","45",양평방향,"20260730162343","04",정체, (16시 23분부터),감곡(251K)-감곡부근(255K),"251","4","37.124313","127.670833",cctv00003206,감곡,https://exmobile4.hscdn.com/cctv3206image/ch00003206_20260730.154600.000.jpg,https://live10.exmobile.hscdn.com/exlive/cctv3206.stream/playlist.m3u8,251,251, , , , , ,(16시 23분부터),
"1000","1",E,수도권제1순환선,"5","100",구리방향,"20260730162344","04",정체, (16시 23분부터),강일(24K)-구리남양주요금소(27K),"24","3","37.566883","127.170658",cctv00000143,강일육교,https://exmobile8.hscdn.com/cctv0143image/ch00000143_20260730.154600.000.jpg,https://live1.exmobile.hscdn.com/exlive/cctv0143.stream/playlist.m3u8,24,24, , , , , ,(16시 23분부터),
"1100","1",E,제2경인선,"6","110",성남방향,"20260730162409","04",정체, (16시 24분부터),안현분기점(17K)-안현분기점(18K),"17","1","37.437119","126.816192",cctv00001536,안현분기점1,https://exmobile4.hscdn.com/cctv1536image/ch00001536_20260730.154600.000.jpg,https://live12.exmobile.hscdn.com/exlive/cctv1536.stream/playlist.m3u8,17,17, , , , , ,(16시 24분부터),
"0010","1",S,경부선,"1","1",부산방향,"20260730163326","04",정체, (16시 33분부터),회덕분기점(277K)-회덕분기점부근(276K),"277","1","36.396149","127.419059",cctv00000873,신대철교,https://exmobile4.hscdn.com/cctv0873image/ch00000873_20260730.154600.000.jpg,https://live4.exmobile.hscdn.com/exlive/cctv0873.stream/playlist.m3u8,277,277, , , , , ,(16시 33분부터),
"0270","1",E,순천완주선,"6","27",완주방향,"20260730163357","03",작업,(갓길) 노면보수 작업중 (16시 33분부터),황전(25.4K),"25.4",-1,"35.149569","127.455096",cctv00001436,황전,https://exmobile8.hscdn.com/cctv1436image/ch00001436_20260730.154600.000.jpg,https://live14.exmobile.hscdn.com/exlive/cctv1436.stream/playlist.m3u8,25.4,0, , , , , ,(16시 33분부터),(갓길) 노면보수 작업중
"0500","1",S,영동선,"4","50",인천방향,"20260730163548","04",정체, (16시 35분부터),이천부근(82K)-호법분기점부근(75K),"82","7","37.242627","127.522886",cctv00000359,가산리,https://exmobile4.hscdn.com/cctv0359image/ch00000359_20260730.154600.000.jpg,https://live16.exmobile.hscdn.com/exlive/cctv0359.stream/playlist.m3u8,82,82, , , , , ,(16시 35분부터),
"0352","1",E,중부선,"3","35",하남방향,"20260730164203","04",정체, (16시 42분부터),경기광주IC(352K)-중부1터널부근(355K),"352","3","37.447946","127.269718",cctv00000267,광주,https://exmobile4.hscdn.com/cctv0267image/ch00000267_20260730.154600.000.jpg,https://live1.exmobile.hscdn.com/exlive/cctv0267.stream/playlist.m3u8,352,352, , , , , ,(16시 42분부터),
"0600","1",S,서울양양선,"6","60",서울방향,"20260730164308","01",기타,(갓길) 승용차 고장 처리중 (16시 43분부터),남춘천부근(53.6K),"53.6",-1,"37.745234","127.694504",cctv00000172,행촌2교,https://exmobile4.hscdn.com/cctv0172image/ch00000172_20260730.154600.000.jpg,https://live17.exmobile.hscdn.com/exlive/cctv0172.stream/playlist.m3u8,53.6,0, , , , , ,(16시 43분부터),(갓길) 승용차 고장 처리중
"0500","1",E,영동선,"4","50",강릉방향,"20260730164416","00",사고,(인천 진출로)사고 처리중 (16시 44분부터),서창분기점(0.5K),.5,-1,"37.433432","126.738571",cctv00005927,서창JC,https://exmobile4.hscdn.com/cctv5927image/ch00005927_20260730.154600.000.jpg,https://live8.exmobile.hscdn.com/exlive/cctv5927.stream/playlist.m3u8,0.5,0, , , , , ,(16시 44분부터),(인천 진출로)사고 처리중
"0500","1",S,영동선,"4","50",인천방향,"20260730164625","01",기타,(2차로)고장차 처리중 (16시 46분부터),월곶분기점부근(6.3K),"6.3",-1,"37.386135","126.755797",cctv00000336,월곶,https://exmobile4.hscdn.com/cctv0336image/ch00000336_20260730.154600.000.jpg,https://live16.exmobile.hscdn.com/exlive/cctv0336.stream/playlist.m3u8,6.3,0, , , , , ,(16시 46분부터),(2차로)고장차 처리중
"0351","1",S,통영대전선,"6","35",통영방향,"20260730164648","01",기타,"(2차로,갓길)승용차 고장 처리중 (16시 46분부터)",마달터널부근(202.5K),"202.5",-1,"36.248086","127.474032",cctv00000463,공주교,https://exmobile8.hscdn.com/cctv0463image/ch00000463_20260730.154600.000.jpg,https://live17.exmobile.hscdn.com/exlive/cctv0463.stream/playlist.m3u8,202.5,0, , , , , ,(16시 46분부터),"(2차로,갓길)승용차 고장 처리중"
"1000","1",E,수도권제1순환선,"5","100",구리방향,"20260730164727","00",사고,"(3,4차로) 사고 처리중 (16시 47분부터)",자유로(72K),"72","2","37.618882","126.799826",cctv00000224,자유로분기점,https://exmobile4.hscdn.com/cctv0224image/ch00000224_20260730.154600.000.jpg,https://live15.exmobile.hscdn.com/exlive/cctv0224.stream/playlist.m3u8,72,0, , , , , ,(16시 47분부터),"(3,4차로) 사고 처리중"
"0010","1",E,경부선,"1","1",서울방향,"20260730164739","04",정체, (16시 47분부터),기흥(388K)-신갈분기점(394K),"388","6","37.228626","127.105739",cctv00000700,보정교,https://exmobile4.hscdn.com/cctv0700image/ch00000700_20260730.154600.000.jpg,https://live12.exmobile.hscdn.com/exlive/cctv0700.stream/playlist.m3u8,388,388, , , , , ,(16시 47분부터),
"0010","1",S,경부선,"1","1",부산방향,"20260730164817","04",정체, (16시 48분부터),신갈분기점부근(397K)-신갈분기점(394K),"397","3","37.309238","127.103578",cctv00000008,죽전,https://exmobile4.hscdn.com/cctv0008image/ch00000008_20260730.154600.000.jpg,https://live1.exmobile.hscdn.com/exlive/cctv0008.stream/playlist.m3u8,397,397, , , , , ,(16시 48분부터),
"0351","1",S,통영대전선,"6","35",통영방향,"20260730165102","01",기타,(갓길)화물차 고장 처리중 (16시 51분부터),동고성(14.3K),"14.3",-1,"34.970155","128.385918",cctv00001582,송산,https://exmobile4.hscdn.com/cctv1582image/ch00001582_20260730.154600.000.jpg,https://live14.exmobile.hscdn.com/exlive/cctv1582.stream/playlist.m3u8,14.3,0, , , , , ,(16시 51분부터),(갓길)화물차 고장 처리중
"0400","1",E,평택제천선,"6","40",제천방향,"20260730165135","04",정체, (16시 51분부터),안성분기점(23K)-안성분기점(24K),"23","1","37.034317","127.131112",cctv00000388,안성분기점_평택제천,https://exmobile4.hscdn.com/cctv0388image/ch00000388_20260730.154600.000.jpg,https://live14.exmobile.hscdn.com/exlive/cctv0388.stream/playlist.m3u8,23,23, , , , , ,(16시 51분부터),
"0010","1",S,경부선,"1","1",부산방향,"20260730165504","01",기타,(갓길)승용차 고장처리중 (16시 55분부터),동대구분기점(122.5K),"122.5",-1,"35.887948","128.690911",cctv00002300,동대구,https://exmobile8.hscdn.com/cctv2300image/ch00002300_20260730.154600.000.jpg,https://live1.exmobile.hscdn.com/exlive/cctv2300.stream/playlist.m3u8,122.5,0, , , , , ,(16시 55분부터),(갓길)승용차 고장처리중
"0600","1",S,서울양양선,"6","60",서울방향,"20260730165618","00",사고,"(2,3차로)승용차관련 사고처리중 (16시 56분부터)",남춘천부근(53.8K),"53.8","3","37.745877","127.696623",cctv00000172,행촌2교,https://exmobile4.hscdn.com/cctv0172image/ch00000172_20260730.154600.000.jpg,https://live17.exmobile.hscdn.com/exlive/cctv0172.stream/playlist.m3u8,53.8,0, , , , , ,(16시 56분부터),"(2,3차로)승용차관련 사고처리중"
"0010","1",E,경부선,"1","1",서울방향,"20260730165638","22",기타,(갓길)보행자 조치중 (16시 56분부터),안성(휴)(370K),"370",-1,"37.080963","127.127648",cctv00000097,산하,https://exmobile8.hscdn.com/cctv0097image/ch00000097_20260730.154600.000.jpg,https://live15.exmobile.hscdn.com/exlive/cctv0097.stream/playlist.m3u8,370,0, , , , , ,(16시 56분부터),(갓길)보행자 조치중
"1200","1",S,경인선,"6","120",인천방향,"20260730165724","04",정체, (16시 57분부터),부천(20K)-부천(19K),"20","1","37.523066","126.788085",cctv00005937,도당육교,https://exmobile4.hscdn.com/cctv5937image/ch00005937_20260730.154600.000.jpg,https://live12.exmobile.hscdn.com/exlive/cctv5937.stream/playlist.m3u8,20,20, , , , , ,(16시 57분부터),
"0450","1",E,중부내륙선,"6","45",양평방향,"20260730165823","01",기타,(진입로 갓길) 화물차 고장 처리 중 (16시 58분부터),영산(24K),"24",-1,"35.450343","128.508937",cctv00001539,봉산,https://exmobile4.hscdn.com/cctv1539image/ch00001539_20260730.154600.000.jpg,https://live3.exmobile.hscdn.com/exlive/cctv1539.stream/playlist.m3u8,24,0, , , , , ,(16시 58분부터),(진입로 갓길) 화물차 고장 처리 중
"0150","1",E,서해안선,"2","15",서울방향,"20260730165846","00",사고,(1차로)사고 처리중 (16시 58분부터),화성(휴)(301.5K),"301.5","1","37.141864","126.880157",cctv00002406,화성휴게소2,https://exmobile8.hscdn.com/cctv2406image/ch00002406_20260730.154600.000.jpg,https://live12.exmobile.hscdn.com/exlive/cctv2406.stream/playlist.m3u8,301.5,0, , , , , ,(16시 58분부터),(1차로)사고 처리중
"1100","1",S,제2경인선,"6","110",인천방향,"20260730170117","04",정체, (17시 01분부터),안현분기점(18K)-신천(14K),"18","4","37.440082","126.826665",cctv00001537,안현분기점2,https://exmobile4.hscdn.com/cctv1537image/ch00001537_20260730.154600.000.jpg,https://live12.exmobile.hscdn.com/exlive/cctv1537.stream/playlist.m3u8,18,18, , , , , ,(17시 01분부터),
"0450","1",E,중부내륙선,"6","45",양평방향,"20260730170123","01",기타,(갓길)승용차고장 처리중 (17시 01분부터),여주분기점부근(261K),"261",-1,"37.196645","127.61217",cctv00005146,금당교_중부내륙,https://exmobile8.hscdn.com/cctv5146image/ch00005146_20260730.154600.000.jpg,https://live5.exmobile.hscdn.com/exlive/cctv5146.stream/playlist.m3u8,261,0, , , , , ,(17시 01분부터),(갓길)승용차고장 처리중
"2510","1",E,호남지선,"6","251",대전방향,"20260730170212","04",정체, (17시 02분부터),북대전부근(52K)-회덕분기점(54K),"52","2","36.409214","127.399012",cctv00005468,탑립육교,https://exmobile4.hscdn.com/cctv5468image/ch00005468_20260730.154600.000.jpg,https://live7.exmobile.hscdn.com/exlive/cctv5468.stream/playlist.m3u8,52,52, , , , , ,(17시 02분부터),
1 ROUTECD GRPID BOUND ROADNM ROUTESORT ROADSHORTNO BOUNDNM INCIDENT_ID INCI_TP_ORDER INCI_TP MSG INCIDENT_POS_NAME OCRN_DSTNC CNGS_LNGT LAT LON CCTV_ID CCTV_NM THUMBIMAGE HLS_URL ST_D EN_D VVALUE01 VVALUE02 VVALUE03 VVALUE04 VVALUE05 CRCM_TIME CRCM_MSG
2 4004 1 S 수도권제2순환선(화성-광주) 5 400 화성방향 20260521143800 03 작업 K (2차로) 비탈면보수 작업중 (14시 38분부터) 동탄방향 26.0 0 0 0 0 cctv00007433 동탄JC https://exmobile4.hscdn.com/cctv7433image/ch00007433_20260730.154600.000.jpg https://live18.exmobile.hscdn.com/exlive/cctv7433.stream/playlist.m3u8 0 0 (14시 38분부터) K (2차로) 비탈면보수 작업중
3 0650 1 E 동해선(삼척-속초) 6 65 속초방향 20260703074200 03 작업 (2차로)졸음쉼터 설치 작업중 (07시 42분부터) 쇄운교(15K)-지흥1교(16.7K) 15 -1 37.486292 129.090703 cctv00005829 쇄운교 https://exmobile4.hscdn.com/cctv5829image/ch00005829_20260730.154600.000.jpg https://live7.exmobile.hscdn.com/exlive/cctv5829.stream/playlist.m3u8 15 15 (07시 42분부터) (2차로)졸음쉼터 설치 작업중
4 0652 1 E 동해선(부산-포항) 6 65 포항방향 20260720082502 03 작업 (2차로)노면보강 공사 작업중, 장기차단 (08시 25분부터) 남경주부근(68K)-문무대왕1터널(74K) 68 -1 35.724019 129.296973 cctv00005797 냉천3교 https://exmobile8.hscdn.com/cctv5797image/ch00005797_20260730.154600.000.jpg https://live17.exmobile.hscdn.com/exlive/cctv5797.stream/playlist.m3u8 68 68 (08시 25분부터) (2차로)노면보강 공사 작업중, 장기차단
5 4004 1 S 수도권제2순환선(화성-광주) 5 400 화성방향 20260723135200 03 작업 null (13시 52분부터) 동탄방향 9.8 0 0 0 0 cctv00007433 동탄JC https://exmobile4.hscdn.com/cctv7433image/ch00007433_20260730.154600.000.jpg https://live18.exmobile.hscdn.com/exlive/cctv7433.stream/playlist.m3u8 0 0 (13시 52분부터) null
6 1100 1 S 제2경인선 6 110 인천방향 20260730065400 04 정체 (06시 54분부터) 서창분기점(9K)-남동부근(6K) 9 3 37.433276 126.729185 cctv00000762 서창분기점 https://exmobile8.hscdn.com/cctv0762image/ch00000762_20260730.154600.000.jpg https://live1.exmobile.hscdn.com/exlive/cctv0762.stream/playlist.m3u8 9 9 (06시 54분부터)
7 0150 1 E 서해안선 2 15 서울방향 20260730065451 04 정체 (06시 54분부터) 광명역(334K)-금천(340K) 334 6 37.407933 126.88693 cctv00000215 충훈대교 https://exmobile8.hscdn.com/cctv0215image/ch00000215_20260730.154600.000.jpg https://live1.exmobile.hscdn.com/exlive/cctv0215.stream/playlist.m3u8 334 334 (06시 54분부터)
8 1000 1 S 수도권제1순환선 5 100 일산방향 20260730072448 04 정체 (07시 24분부터) 시흥요금소(96K)-중동(86K) 96 10 37.449284 126.805207 cctv00002060 시흥TG_일산 https://exmobile4.hscdn.com/cctv2060image/ch00002060_20260730.154600.000.jpg https://live11.exmobile.hscdn.com/exlive/cctv2060.stream/playlist.m3u8 96 96 (07시 24분부터)
9 0351 1 S 통영대전선 6 35 통영방향 20260730081231 03 작업 (갓길) 시설물 보수 작업중 (08시 12분부터) 오동터널부근(132K) 132 -1 35.707033 127.624994 cctv00002182 오동2교 https://exmobile4.hscdn.com/cctv2182image/ch00002182_20260730.154600.000.jpg https://live8.exmobile.hscdn.com/exlive/cctv2182.stream/playlist.m3u8 132 0 (08시 12분부터) (갓길) 시설물 보수 작업중
10 0252 1 S 논산천안선 6 25 논산방향 20260730082406 04 정체 3km 정체 (08시 24분부터) 차령터널 무학천교(266.0K)-차령터널 (263.0K) 269 0 36.72055 127.13463 cctv00007136 호정1교 https://exmobile4.hscdn.com/cctv7136image/ch00007136_20260730.154600.000.jpg https://live11.exmobile.hscdn.com/exlive/cctv7136.stream/playlist.m3u8 269 269 (08시 24분부터) 3km 정체
11 0201 1 S 익산장수선 6 20 익산방향 20260730084122 03 작업 (갓길) 덩쿨제거 작업중 (08시 41분부터) 소양(16K)-소양부근(15K) 16 -1 35.865021 127.230784 cctv00003867 소양 https://exmobile8.hscdn.com/cctv3867image/ch00003867_20260730.154600.000.jpg https://live4.exmobile.hscdn.com/exlive/cctv3867.stream/playlist.m3u8 16 16 (08시 41분부터) (갓길) 덩쿨제거 작업중
12 0450 1 S 중부내륙선 6 45 창원방향 20260730094639 04 정체 (09시 46분부터) 감곡부근(258K)-감곡부근(255K) 258 3 37.172225 127.622368 cctv00003204 삼승교 https://exmobile4.hscdn.com/cctv3204image/ch00003204_20260730.154600.000.jpg https://live10.exmobile.hscdn.com/exlive/cctv3204.stream/playlist.m3u8 258 258 (09시 46분부터)
13 0100 1 E 남해선(순천-부산) 6 10 부산방향 20260730103250 04 정체 (10시 32분부터) 함안2터널부근(119K)-함안2터널부근(120K) 119 1 35.288699 128.542006 cctv00000560 함안2터널(부산외부) https://exmobile4.hscdn.com/cctv0560image/ch00000560_20260730.154600.000.jpg https://live13.exmobile.hscdn.com/exlive/cctv0560.stream/playlist.m3u8 119 119 (10시 32분부터)
14 0252 1 S 논산천안선 6 25 논산방향 20260728140304 04 정체 5km 정체 (14시 03분부터) 남풍세IC 호정 1교(268.0K)-차령터널 (263.0K) 269 0 36.72055 127.13463 cctv00007136 호정1교 https://exmobile4.hscdn.com/cctv7136image/ch00007136_20260730.154600.000.jpg https://live11.exmobile.hscdn.com/exlive/cctv7136.stream/playlist.m3u8 269 269 (14시 03분부터) 5km 정체
15 1000 1 E 수도권제1순환선 5 100 구리방향 20260730051106 04 정체 (05시 11분부터) 노오지분기점(79K)-송내(88K) 79 9 37.570368 126.753178 cctv00000227 노오지분기점 https://exmobile4.hscdn.com/cctv0227image/ch00000227_20260730.154600.000.jpg https://live15.exmobile.hscdn.com/exlive/cctv0227.stream/playlist.m3u8 79 79 (05시 11분부터)
16 0010 1 E 경부선 1 1 서울방향 20260730062713 04 정체 (06시 27분부터) 양재부근(415K)-반포(420K) 415 5 37.456747 127.046344 cctv00000002 양재 https://exmobile4.hscdn.com/cctv0002image/ch00000002_20260730.154600.000.jpg https://live1.exmobile.hscdn.com/exlive/cctv0002.stream/playlist.m3u8 415 415 (06시 27분부터)
17 0010 1 S 경부선 1 1 부산방향 20260730105038 04 정체 (10시 50분부터) 천안분기점부근(332K)-천안호두(휴)(324K) 332 8 36.766668 127.196939 cctv00003848 응원고개 https://exmobile4.hscdn.com/cctv3848image/ch00003848_20260730.154600.000.jpg https://live4.exmobile.hscdn.com/exlive/cctv3848.stream/playlist.m3u8 332 332 (10시 50분부터)
18 0450 1 E 중부내륙선 6 45 양평방향 20260730132759 04 정체 (13시 27분부터) 충주분기점부근(238K)-충주분기점부근(241K) 238 3 37.041776 127.75111 cctv00003209 한포천 https://exmobile4.hscdn.com/cctv3209image/ch00003209_20260730.154600.000.jpg https://live10.exmobile.hscdn.com/exlive/cctv3209.stream/playlist.m3u8 238 238 (13시 27분부터)
19 0100 1 E 남해선(순천-부산) 6 10 부산방향 20260730134538 04 정체 (13시 45분부터) 대저분기점(163K)-덕천(166K) 163 3 35.219275 128.969671 cctv00003930 대저 https://exmobile4.hscdn.com/cctv3930image/ch00003930_20260730.154600.000.jpg https://live15.exmobile.hscdn.com/exlive/cctv3930.stream/playlist.m3u8 163 163 (13시 45분부터)
20 1100 1 E 제2경인선 6 110 성남방향 20260730135457 04 정체 (13시 54분부터) 학익분기점(3K)-남동(8K) 3 5 37.438267 126.662356 cctv00001535 학익대교1 https://exmobile4.hscdn.com/cctv1535image/ch00001535_20260730.154600.000.jpg https://live12.exmobile.hscdn.com/exlive/cctv1535.stream/playlist.m3u8 3 3 (13시 54분부터)
21 0500 1 S 영동선 4 50 인천방향 20260730135951 04 정체 (13시 59분부터) 군자분기점(7K)-월곶분기점부근(4K) 7 3 37.382693 126.762417 cctv00000854 군자분기점 https://exmobile4.hscdn.com/cctv0854image/ch00000854_20260730.154600.000.jpg https://live2.exmobile.hscdn.com/exlive/cctv0854.stream/playlist.m3u8 7 7 (13시 59분부터)
22 0150 1 E 서해안선 2 15 서울방향 20260730140943 04 정체 (14시 09분부터) 서평택분기점부근(295K)-화성(휴)부근(303K) 295 8 37.08446 126.886438 cctv00000054 상신2교 https://exmobile4.hscdn.com/cctv0054image/ch00000054_20260730.154600.000.jpg https://live1.exmobile.hscdn.com/exlive/cctv0054.stream/playlist.m3u8 295 295 (14시 09분부터)
23 0150 1 E 서해안선 2 15 서울방향 20260730141000 04 정체 (14시 10분부터) 매송(휴)부근(315K)-용담터널(319K) 315 4 37.260631 126.887041 cctv00002409 야목2교 https://exmobile8.hscdn.com/cctv2409image/ch00002409_20260730.154600.000.jpg https://live3.exmobile.hscdn.com/exlive/cctv2409.stream/playlist.m3u8 315 315 (14시 10분부터)
24 0352 1 S 중부선 3 35 남이방향 20260730141034 04 정체 (14시 10분부터) 진천터널부근(277K)-진천터널부근(274K) 277 3 36.835086 127.494366 cctv00003845 백곡천교 https://exmobile8.hscdn.com/cctv3845image/ch00003845_20260730.154600.000.jpg https://live9.exmobile.hscdn.com/exlive/cctv3845.stream/playlist.m3u8 277 277 (14시 10분부터)
25 0202 1 E 새만금전주선 6 202 새만금방향 20260730141437 01 기타 (갓길)소형화물차 고장 처리중 (14시 14분부터) 석구터널(46.1K) 46.1 -1 35.773544 127.153308 cctv00002613 원은육교2 https://exmobile4.hscdn.com/cctv2613image/ch00002613_20260730.154600.000.jpg https://live1.exmobile.hscdn.com/exlive/cctv2613.stream/playlist.m3u8 46.1 0 (14시 14분부터) (갓길)소형화물차 고장 처리중
26 0500 1 S 영동선 4 50 인천방향 20260730142623 04 정체 (14시 26분부터) 동수원(37K)-북수원(30K) 37 7 37.299117 127.051361 cctv00002415 동수원 https://exmobile4.hscdn.com/cctv2415image/ch00002415_20260730.154500.000.jpg https://live3.exmobile.hscdn.com/exlive/cctv2415.stream/playlist.m3u8 37 37 (14시 26분부터)
27 0010 1 E 경부선 1 1 서울방향 20260730143713 04 정체 (14시 37분부터) 안성분기점(364K)-안성(휴)부근(368K) 364 4 37.028613 127.140833 cctv00000037 안성분기점2 https://exmobile8.hscdn.com/cctv0037image/ch00000037_20260730.154600.000.jpg https://live4.exmobile.hscdn.com/exlive/cctv0037.stream/playlist.m3u8 364 364 (14시 37분부터)
28 1100 1 S 제2경인선 6 110 인천방향 20260730143718 04 정체 (14시 37분부터) 삼막(25.98K)-광명터널(22K) 25.98 4 37.425507 126.912049 cctv00000767 석수 https://exmobile8.hscdn.com/cctv0767image/ch00000767_20260730.154600.000.jpg https://live1.exmobile.hscdn.com/exlive/cctv0767.stream/playlist.m3u8 25.98 25.98 (14시 37분부터)
29 0651 1 S 부산울산선 6 65 부산방향 20260730144311 04 정체 (14시 43분부터) 해운대터널부근(3K)-부산울산선시점(0K) 3 3 35.190683 129.201783 cctv00000728 고래진2교 https://exmobile8.hscdn.com/cctv0728image/ch00000728_20260730.154600.000.jpg https://live17.exmobile.hscdn.com/exlive/cctv0728.stream/playlist.m3u8 3 3 (14시 43분부터)
30 0010 1 E 경부선 1 1 서울방향 20260730144715 00 사고 (3차로,갓길)화물차관련 사고 처리중 (14시 47분부터) 영천분기점(91.5K) 91.5 -1 35.924733 128.998642 cctv00000819 반정1교 https://exmobile4.hscdn.com/cctv0819image/ch00000819_20260730.154600.000.jpg https://live10.exmobile.hscdn.com/exlive/cctv0819.stream/playlist.m3u8 91.5 0 (14시 47분부터) (3차로,갓길)화물차관련 사고 처리중
31 1000 1 E 수도권제1순환선 5 100 구리방향 20260730145917 04 정체 (14시 59분부터) 자유로(72K)-김포(74K) 72 2 37.618882 126.799826 cctv00000224 자유로분기점 https://exmobile4.hscdn.com/cctv0224image/ch00000224_20260730.154600.000.jpg https://live15.exmobile.hscdn.com/exlive/cctv0224.stream/playlist.m3u8 72 72 (14시 59분부터)
32 0400 1 S 평택제천선 6 40 평택방향 20260730150604 04 정체 (15시 06분부터) 서안성(25K)-안성분기점(24K) 25 1 37.036583 127.153094 cctv00005947 강문교 https://exmobile4.hscdn.com/cctv5947image/ch00005947_20260730.154600.000.jpg https://live14.exmobile.hscdn.com/exlive/cctv5947.stream/playlist.m3u8 25 25 (15시 06분부터)
33 1200 1 S 경인선 6 120 인천방향 20260730150911 04 정체 (15시 09분부터) 인천요금소(16K)-서인천(11K) 16 5 37.523954 126.742937 cctv00005038 인천영업소 https://exmobile8.hscdn.com/cctv5038image/ch00005038_20260730.154600.000.jpg https://live1.exmobile.hscdn.com/exlive/cctv5038.stream/playlist.m3u8 16 16 (15시 09분부터)
34 0010 1 E 경부선 1 1 서울방향 20260730152029 04 정체 (15시 20분부터) 입장거봉포도(휴)부근(355K)-안성(360K) 355 5 36.955513 127.181906 cctv00003102 연곡 https://exmobile8.hscdn.com/cctv3102image/ch00003102_20260730.154600.000.jpg https://live4.exmobile.hscdn.com/exlive/cctv3102.stream/playlist.m3u8 355 355 (15시 20분부터)
35 1200 1 E 경인선 6 120 서울방향 20260730152128 04 정체 (15시 21분부터) 신월(23K)-신월(24K) 23 1 37.523394 126.821631 cctv00001451 신월-1 https://exmobile4.hscdn.com/cctv1451image/ch00001451_20260730.154600.000.jpg https://live8.exmobile.hscdn.com/exlive/cctv1451.stream/playlist.m3u8 23 23 (15시 21분부터)
36 1040 1 E 남해2지선 6 104 서부산방향 20260730152500 04 정체 (15시 25분부터) 서부산(휴)(18K)-사상(20K) 18 2 35.156477 128.948907 cctv00003718 서부산 https://exmobile4.hscdn.com/cctv3718image/ch00003718_20260730.154600.000.jpg https://live4.exmobile.hscdn.com/exlive/cctv3718.stream/playlist.m3u8 18 18 (15시 25분부터)
37 0010 1 S 경부선 1 1 부산방향 20260730152539 01 기타 (갓길) 승용 고장차 처리중 (15시 25분부터) 청주분기점(297K) 297 -1 36.568675 127.429435 cctv00002129 청주분기점2 https://exmobile4.hscdn.com/cctv2129image/ch00002129_20260730.154600.000.jpg https://live12.exmobile.hscdn.com/exlive/cctv2129.stream/playlist.m3u8 297 0 (15시 25분부터) (갓길) 승용 고장차 처리중
38 0252 1 E 논산천안선 6 25 천안방향 20260730152731 04 정체 3km 정체 (15시 27분부터) 남공주IC 오룡교(232.0K)-남공주IC 검상천교(235.0K) 225 0 36.34541 127.06794 cctv00007164 이인SA/남 https://exmobile4.hscdn.com/cctv7164image/ch00007164_20260730.154600.000.jpg https://live11.exmobile.hscdn.com/exlive/cctv7164.stream/playlist.m3u8 225 225 (15시 27분부터) 3km 정체
39 6000 1 S 부산외곽선 6 600 창원방향 20260730152946 04 정체 (15시 29분부터) 기장분기점(48K)-기장분기점부근(47K) 48 1 35.281987 129.2089 cctv00000517 용천교 https://exmobile4.hscdn.com/cctv0517image/ch00000517_20260730.154600.000.jpg https://live11.exmobile.hscdn.com/exlive/cctv0517.stream/playlist.m3u8 48 48 (15시 29분부터)
40 1300 1 S 인천공항선 6 130 공항방향 20260730153000 04 정체 청라IC 진출 1km 정체 (15시 30분부터) [본선-공항] 20.8Km 20.8 0 37.569859 126.670011 cctv00007097 인천공항영업소 https://exmobile4.hscdn.com/cctv7097image/ch00007097_20260730.154600.000.jpg https://live11.exmobile.hscdn.com/exlive/cctv7097.stream/playlist.m3u8 20.8 20.8 (15시 30분부터) 청라IC 진출 1km 정체
41 1000 1 S 수도권제1순환선 5 100 일산방향 20260730153338 04 정체 (15시 33분부터) 안양터널(114K)-수리터널(112K) 114 2 37.37919 126.946985 cctv00000292 안양터널 https://exmobile4.hscdn.com/cctv0292image/ch00000292_20260730.154600.000.jpg https://live15.exmobile.hscdn.com/exlive/cctv0292.stream/playlist.m3u8 114 114 (15시 33분부터)
42 0500 1 S 영동선 4 50 인천방향 20260730153400 04 정체 (15시 34분부터) 덕평부근(66K)-양지터널부근(58K) 66 8 37.250668 127.352923 cctv00000371 오천교 https://exmobile8.hscdn.com/cctv0371image/ch00000371_20260730.154600.000.jpg https://live16.exmobile.hscdn.com/exlive/cctv0371.stream/playlist.m3u8 66 66 (15시 34분부터)
43 2510 1 S 호남지선 6 251 논산방향 20260730154509 04 정체 (15시 45분부터) 회덕분기점(54K)-북대전부근(52K) 54 2 0 0 cctv00000297 전민 https://exmobile4.hscdn.com/cctv0297image/ch00000297_20260730.154600.000.jpg https://live12.exmobile.hscdn.com/exlive/cctv0297.stream/playlist.m3u8 54 54 (15시 45분부터)
44 0400 1 S 평택제천선 6 40 평택방향 20260730155518 04 정체 (15시 55분부터) 대소분기점(57K)-안진터널(52K) 57 5 36.941808 127.463959 cctv00003794 대소분기점 https://exmobile4.hscdn.com/cctv3794image/ch00003794_20260730.154600.000.jpg https://live14.exmobile.hscdn.com/exlive/cctv3794.stream/playlist.m3u8 57 57 (15시 55분부터)
45 0600 1 S 서울양양선 6 60 서울방향 20260730155707 04 정체 (15시 57분부터) 화도(15K)-화도부근(13K) 15 2 37.63154 127.312837 cctv00000400 화도영업소 https://exmobile8.hscdn.com/cctv0400image/ch00000400_20260730.154600.000.jpg https://live17.exmobile.hscdn.com/exlive/cctv0400.stream/playlist.m3u8 15 15 (15시 57분부터)
46 0010 1 E 경부선 1 1 서울방향 20260730160049 04 정체 (순환선 진출로) (16시 00분부터) 판교분기점(408K) 408 1 37.406461 127.09392 cctv00000006 판교분기점_경부 https://exmobile4.hscdn.com/cctv0006image/ch00000006_20260730.154600.000.jpg https://live1.exmobile.hscdn.com/exlive/cctv0006.stream/playlist.m3u8 408 0 (16시 00분부터) (순환선 진출로)
47 0251 1 E 호남선 6 25 천안방향 20260730160618 04 정체 교통량 증가 (16시 06분부터) 동광주(74K) 74 1 35.183438 126.926925 cctv00003382 동광주 https://exmobile4.hscdn.com/cctv3382image/ch00003382_20260730.154600.000.jpg https://live11.exmobile.hscdn.com/exlive/cctv3382.stream/playlist.m3u8 74 0 (16시 06분부터) 교통량 증가
48 1000 1 E 수도권제1순환선 5 100 구리방향 20260730160627 04 정체 (16시 06분부터) 조남분기점(107K)-수암터널(108K) 107 1 37.368655 126.869846 cctv00000238 조남분기점 https://exmobile4.hscdn.com/cctv0238image/ch00000238_20260730.154600.000.jpg https://live15.exmobile.hscdn.com/exlive/cctv0238.stream/playlist.m3u8 107 107 (16시 06분부터)
49 0352 1 E 중부선 3 35 하남방향 20260730160933 04 정체 (16시 09분부터) 일죽부근(304K)-일죽부근(309K) 304 5 37.070051 127.468948 cctv00000667 장암1 https://exmobile4.hscdn.com/cctv0667image/ch00000667_20260730.154600.000.jpg https://live4.exmobile.hscdn.com/exlive/cctv0667.stream/playlist.m3u8 304 304 (16시 09분부터)
50 0500 1 S 영동선 4 50 인천방향 20260730161003 04 정체 (16시 10분부터) 서창분기점(1K)-서창(0K) 1 1 37.428961 126.737875 cctv00005669 서창 https://exmobile8.hscdn.com/cctv5669image/ch00005669_20260730.154600.000.jpg https://live16.exmobile.hscdn.com/exlive/cctv5669.stream/playlist.m3u8 1 1 (16시 10분부터)
51 0450 1 E 중부내륙선 6 45 양평방향 20260730161104 01 기타 (갓길)승합차고장 처리중 (16시 11분부터) 감곡부근(252.1K) 252.1 -1 37.129423 127.66049 cctv00005386 상우1교 https://exmobile8.hscdn.com/cctv5386image/ch00005386_20260730.154600.000.jpg https://live14.exmobile.hscdn.com/exlive/cctv5386.stream/playlist.m3u8 252.1 0 (16시 11분부터) (갓길)승합차고장 처리중
52 0150 1 E 서해안선 2 15 서울방향 20260730161342 01 기타 (갓길)중형화물차 고장 처리중 (16시 13분부터) 서천(휴)부근(166.5K) 166.5 -1 36.119755 126.636626 cctv00002043 종천1교 https://exmobile4.hscdn.com/cctv2043image/ch00002043_20260730.154600.000.jpg https://live12.exmobile.hscdn.com/exlive/cctv2043.stream/playlist.m3u8 166.5 0 (16시 13분부터) (갓길)중형화물차 고장 처리중
53 0500 1 S 영동선 4 50 인천방향 20260730161727 04 정체 (16시 17분부터) 둔대분기점(23K)-반월터널부근(21K) 23 2 37.322581 126.907065 cctv00005041 둔대분기점 https://exmobile8.hscdn.com/cctv5041image/ch00005041_20260730.154600.000.jpg https://live16.exmobile.hscdn.com/exlive/cctv5041.stream/playlist.m3u8 23 23 (16시 17분부터)
54 0270 1 E 순천완주선 6 27 완주방향 20260730161748 01 기타 (갓길) 화물차 고장 처리중 (16시 17분부터) 서면2터널부근(10.7K) 10.7 -1 35.028166 127.507502 cctv00005578 서면2터널(완주외부1) https://exmobile8.hscdn.com/cctv5578image/ch00005578_20260730.154600.000.jpg https://live14.exmobile.hscdn.com/exlive/cctv5578.stream/playlist.m3u8 10.7 0 (16시 17분부터) (갓길) 화물차 고장 처리중
55 0160 1 E 울산선 6 16 울산방향 20260730161750 01 기타 (갓길)화물차 고장처리 중 (16시 17분부터) 범서하이패스(10.3K) 10.3 -1 35.570555 129.227118 cctv00005346 입암 https://exmobile4.hscdn.com/cctv5346image/ch00005346_20260730.154600.000.jpg https://live14.exmobile.hscdn.com/exlive/cctv5346.stream/playlist.m3u8 10.3 0 (16시 17분부터) (갓길)화물차 고장처리 중
56 0500 1 S 영동선 4 50 인천방향 20260730161757 04 정체 진출로 (16시 17분부터) 서용인분기점(50K) 50 1 37.268988 127.186046 cctv00000363 마성터널(강릉) https://exmobile8.hscdn.com/cctv0363image/ch00000363_20260730.154600.000.jpg https://live16.exmobile.hscdn.com/exlive/cctv0363.stream/playlist.m3u8 50 0 (16시 17분부터) 진출로
57 0150 1 E 서해안선 2 15 서울방향 20260730161803 01 기타 (갓길) 화물 고장차 처리중 (16시 18분부터) 당진부근(267.3K) 267.3 -1 36.906553 126.733865 cctv00000626 영천교(고정) https://exmobile4.hscdn.com/cctv0626image/ch00000626_20260730.154600.000.jpg https://live4.exmobile.hscdn.com/exlive/cctv0626.stream/playlist.m3u8 267.3 0 (16시 18분부터) (갓길) 화물 고장차 처리중
58 0550 2 S 중앙선 6 55 부산방향 20260730161902 04 정체 (16시 19분부터) 초정(5K)-삼락(0K) 5 5 35.235254 128.980641 cctv00003672 초정 https://exmobile8.hscdn.com/cctv3672image/ch00003672_20260730.154600.000.jpg https://live4.exmobile.hscdn.com/exlive/cctv3672.stream/playlist.m3u8 5 5 (16시 19분부터)
59 0500 1 E 영동선 4 50 강릉방향 20260730161916 04 정체 (16시 19분부터) 둔대분기점(22K)-부곡(27K) 22 5 37.322957 126.895948 cctv00000220 둔대교 https://exmobile8.hscdn.com/cctv0220image/ch00000220_20260730.154600.000.jpg https://live2.exmobile.hscdn.com/exlive/cctv0220.stream/playlist.m3u8 22 22 (16시 19분부터)
60 0252 1 E 논산천안선 6 25 천안방향 20260730162057 00 사고 1차로 승용차 관련 사고발생 (16시 20분부터) 남공주IC 오룡교(232.1K) 225 0 36.34541 127.06794 cctv00007164 이인SA/남 https://exmobile4.hscdn.com/cctv7164image/ch00007164_20260730.154600.000.jpg https://live11.exmobile.hscdn.com/exlive/cctv7164.stream/playlist.m3u8 225 225 (16시 20분부터) 1차로 승용차 관련 사고발생
61 1000 1 S 수도권제1순환선 5 100 일산방향 20260730162117 04 정체 (16시 21분부터) 성남부근(3K)-판교분기점(0K) 3 3 37.416928 127.122446 cctv00005932 성남삼평교2 https://exmobile4.hscdn.com/cctv5932image/ch00005932_20260730.154600.000.jpg https://live5.exmobile.hscdn.com/exlive/cctv5932.stream/playlist.m3u8 3 3 (16시 21분부터)
62 1000 1 S 수도권제1순환선 5 100 일산방향 20260730162134 04 정체 (16시 21분부터) 판교분기점(128K)-판교분기점부근(126K) 128 2 37.405686 127.094436 cctv00005666 금토 https://exmobile8.hscdn.com/cctv5666image/ch00005666_20260730.154600.000.jpg https://live11.exmobile.hscdn.com/exlive/cctv5666.stream/playlist.m3u8 128 128 (16시 21분부터)
63 1000 1 S 수도권제1순환선 5 100 일산방향 20260730162214 04 정체 (16시 22분부터) 서하남분기점(16K)-송파부근(7K) 16 9 37.515281 127.169685 cctv00000251 광암터널2 https://exmobile4.hscdn.com/cctv0251image/ch00000251_20260730.154600.000.jpg https://live15.exmobile.hscdn.com/exlive/cctv0251.stream/playlist.m3u8 16 16 (16시 22분부터)
64 0600 1 S 서울양양선 6 60 서울방향 20260730162324 04 정체 (16시 23분부터) 덕소삼패(3K)-강일(0K) 3 3 37.587067 127.199448 cctv00000427 미사대교종점 https://exmobile8.hscdn.com/cctv0427image/ch00000427_20260730.154600.000.jpg https://live17.exmobile.hscdn.com/exlive/cctv0427.stream/playlist.m3u8 3 3 (16시 23분부터)
65 0450 1 E 중부내륙선 6 45 양평방향 20260730162343 04 정체 (16시 23분부터) 감곡(251K)-감곡부근(255K) 251 4 37.124313 127.670833 cctv00003206 감곡 https://exmobile4.hscdn.com/cctv3206image/ch00003206_20260730.154600.000.jpg https://live10.exmobile.hscdn.com/exlive/cctv3206.stream/playlist.m3u8 251 251 (16시 23분부터)
66 1000 1 E 수도권제1순환선 5 100 구리방향 20260730162344 04 정체 (16시 23분부터) 강일(24K)-구리남양주요금소(27K) 24 3 37.566883 127.170658 cctv00000143 강일육교 https://exmobile8.hscdn.com/cctv0143image/ch00000143_20260730.154600.000.jpg https://live1.exmobile.hscdn.com/exlive/cctv0143.stream/playlist.m3u8 24 24 (16시 23분부터)
67 1100 1 E 제2경인선 6 110 성남방향 20260730162409 04 정체 (16시 24분부터) 안현분기점(17K)-안현분기점(18K) 17 1 37.437119 126.816192 cctv00001536 안현분기점1 https://exmobile4.hscdn.com/cctv1536image/ch00001536_20260730.154600.000.jpg https://live12.exmobile.hscdn.com/exlive/cctv1536.stream/playlist.m3u8 17 17 (16시 24분부터)
68 0010 1 S 경부선 1 1 부산방향 20260730163326 04 정체 (16시 33분부터) 회덕분기점(277K)-회덕분기점부근(276K) 277 1 36.396149 127.419059 cctv00000873 신대철교 https://exmobile4.hscdn.com/cctv0873image/ch00000873_20260730.154600.000.jpg https://live4.exmobile.hscdn.com/exlive/cctv0873.stream/playlist.m3u8 277 277 (16시 33분부터)
69 0270 1 E 순천완주선 6 27 완주방향 20260730163357 03 작업 (갓길) 노면보수 작업중 (16시 33분부터) 황전(25.4K) 25.4 -1 35.149569 127.455096 cctv00001436 황전 https://exmobile8.hscdn.com/cctv1436image/ch00001436_20260730.154600.000.jpg https://live14.exmobile.hscdn.com/exlive/cctv1436.stream/playlist.m3u8 25.4 0 (16시 33분부터) (갓길) 노면보수 작업중
70 0500 1 S 영동선 4 50 인천방향 20260730163548 04 정체 (16시 35분부터) 이천부근(82K)-호법분기점부근(75K) 82 7 37.242627 127.522886 cctv00000359 가산리 https://exmobile4.hscdn.com/cctv0359image/ch00000359_20260730.154600.000.jpg https://live16.exmobile.hscdn.com/exlive/cctv0359.stream/playlist.m3u8 82 82 (16시 35분부터)
71 0352 1 E 중부선 3 35 하남방향 20260730164203 04 정체 (16시 42분부터) 경기광주IC(352K)-중부1터널부근(355K) 352 3 37.447946 127.269718 cctv00000267 광주 https://exmobile4.hscdn.com/cctv0267image/ch00000267_20260730.154600.000.jpg https://live1.exmobile.hscdn.com/exlive/cctv0267.stream/playlist.m3u8 352 352 (16시 42분부터)
72 0600 1 S 서울양양선 6 60 서울방향 20260730164308 01 기타 (갓길) 승용차 고장 처리중 (16시 43분부터) 남춘천부근(53.6K) 53.6 -1 37.745234 127.694504 cctv00000172 행촌2교 https://exmobile4.hscdn.com/cctv0172image/ch00000172_20260730.154600.000.jpg https://live17.exmobile.hscdn.com/exlive/cctv0172.stream/playlist.m3u8 53.6 0 (16시 43분부터) (갓길) 승용차 고장 처리중
73 0500 1 E 영동선 4 50 강릉방향 20260730164416 00 사고 (인천 진출로)사고 처리중 (16시 44분부터) 서창분기점(0.5K) .5 -1 37.433432 126.738571 cctv00005927 서창JC https://exmobile4.hscdn.com/cctv5927image/ch00005927_20260730.154600.000.jpg https://live8.exmobile.hscdn.com/exlive/cctv5927.stream/playlist.m3u8 0.5 0 (16시 44분부터) (인천 진출로)사고 처리중
74 0500 1 S 영동선 4 50 인천방향 20260730164625 01 기타 (2차로)고장차 처리중 (16시 46분부터) 월곶분기점부근(6.3K) 6.3 -1 37.386135 126.755797 cctv00000336 월곶 https://exmobile4.hscdn.com/cctv0336image/ch00000336_20260730.154600.000.jpg https://live16.exmobile.hscdn.com/exlive/cctv0336.stream/playlist.m3u8 6.3 0 (16시 46분부터) (2차로)고장차 처리중
75 0351 1 S 통영대전선 6 35 통영방향 20260730164648 01 기타 (2차로,갓길)승용차 고장 처리중 (16시 46분부터) 마달터널부근(202.5K) 202.5 -1 36.248086 127.474032 cctv00000463 공주교 https://exmobile8.hscdn.com/cctv0463image/ch00000463_20260730.154600.000.jpg https://live17.exmobile.hscdn.com/exlive/cctv0463.stream/playlist.m3u8 202.5 0 (16시 46분부터) (2차로,갓길)승용차 고장 처리중
76 1000 1 E 수도권제1순환선 5 100 구리방향 20260730164727 00 사고 (3,4차로) 사고 처리중 (16시 47분부터) 자유로(72K) 72 2 37.618882 126.799826 cctv00000224 자유로분기점 https://exmobile4.hscdn.com/cctv0224image/ch00000224_20260730.154600.000.jpg https://live15.exmobile.hscdn.com/exlive/cctv0224.stream/playlist.m3u8 72 0 (16시 47분부터) (3,4차로) 사고 처리중
77 0010 1 E 경부선 1 1 서울방향 20260730164739 04 정체 (16시 47분부터) 기흥(388K)-신갈분기점(394K) 388 6 37.228626 127.105739 cctv00000700 보정교 https://exmobile4.hscdn.com/cctv0700image/ch00000700_20260730.154600.000.jpg https://live12.exmobile.hscdn.com/exlive/cctv0700.stream/playlist.m3u8 388 388 (16시 47분부터)
78 0010 1 S 경부선 1 1 부산방향 20260730164817 04 정체 (16시 48분부터) 신갈분기점부근(397K)-신갈분기점(394K) 397 3 37.309238 127.103578 cctv00000008 죽전 https://exmobile4.hscdn.com/cctv0008image/ch00000008_20260730.154600.000.jpg https://live1.exmobile.hscdn.com/exlive/cctv0008.stream/playlist.m3u8 397 397 (16시 48분부터)
79 0351 1 S 통영대전선 6 35 통영방향 20260730165102 01 기타 (갓길)화물차 고장 처리중 (16시 51분부터) 동고성(14.3K) 14.3 -1 34.970155 128.385918 cctv00001582 송산 https://exmobile4.hscdn.com/cctv1582image/ch00001582_20260730.154600.000.jpg https://live14.exmobile.hscdn.com/exlive/cctv1582.stream/playlist.m3u8 14.3 0 (16시 51분부터) (갓길)화물차 고장 처리중
80 0400 1 E 평택제천선 6 40 제천방향 20260730165135 04 정체 (16시 51분부터) 안성분기점(23K)-안성분기점(24K) 23 1 37.034317 127.131112 cctv00000388 안성분기점_평택제천 https://exmobile4.hscdn.com/cctv0388image/ch00000388_20260730.154600.000.jpg https://live14.exmobile.hscdn.com/exlive/cctv0388.stream/playlist.m3u8 23 23 (16시 51분부터)
81 0010 1 S 경부선 1 1 부산방향 20260730165504 01 기타 (갓길)승용차 고장처리중 (16시 55분부터) 동대구분기점(122.5K) 122.5 -1 35.887948 128.690911 cctv00002300 동대구 https://exmobile8.hscdn.com/cctv2300image/ch00002300_20260730.154600.000.jpg https://live1.exmobile.hscdn.com/exlive/cctv2300.stream/playlist.m3u8 122.5 0 (16시 55분부터) (갓길)승용차 고장처리중
82 0600 1 S 서울양양선 6 60 서울방향 20260730165618 00 사고 (2,3차로)승용차관련 사고처리중 (16시 56분부터) 남춘천부근(53.8K) 53.8 3 37.745877 127.696623 cctv00000172 행촌2교 https://exmobile4.hscdn.com/cctv0172image/ch00000172_20260730.154600.000.jpg https://live17.exmobile.hscdn.com/exlive/cctv0172.stream/playlist.m3u8 53.8 0 (16시 56분부터) (2,3차로)승용차관련 사고처리중
83 0010 1 E 경부선 1 1 서울방향 20260730165638 22 기타 (갓길)보행자 조치중 (16시 56분부터) 안성(휴)(370K) 370 -1 37.080963 127.127648 cctv00000097 산하 https://exmobile8.hscdn.com/cctv0097image/ch00000097_20260730.154600.000.jpg https://live15.exmobile.hscdn.com/exlive/cctv0097.stream/playlist.m3u8 370 0 (16시 56분부터) (갓길)보행자 조치중
84 1200 1 S 경인선 6 120 인천방향 20260730165724 04 정체 (16시 57분부터) 부천(20K)-부천(19K) 20 1 37.523066 126.788085 cctv00005937 도당육교 https://exmobile4.hscdn.com/cctv5937image/ch00005937_20260730.154600.000.jpg https://live12.exmobile.hscdn.com/exlive/cctv5937.stream/playlist.m3u8 20 20 (16시 57분부터)
85 0450 1 E 중부내륙선 6 45 양평방향 20260730165823 01 기타 (진입로 갓길) 화물차 고장 처리 중 (16시 58분부터) 영산(24K) 24 -1 35.450343 128.508937 cctv00001539 봉산 https://exmobile4.hscdn.com/cctv1539image/ch00001539_20260730.154600.000.jpg https://live3.exmobile.hscdn.com/exlive/cctv1539.stream/playlist.m3u8 24 0 (16시 58분부터) (진입로 갓길) 화물차 고장 처리 중
86 0150 1 E 서해안선 2 15 서울방향 20260730165846 00 사고 (1차로)사고 처리중 (16시 58분부터) 화성(휴)(301.5K) 301.5 1 37.141864 126.880157 cctv00002406 화성휴게소2 https://exmobile8.hscdn.com/cctv2406image/ch00002406_20260730.154600.000.jpg https://live12.exmobile.hscdn.com/exlive/cctv2406.stream/playlist.m3u8 301.5 0 (16시 58분부터) (1차로)사고 처리중
87 1100 1 S 제2경인선 6 110 인천방향 20260730170117 04 정체 (17시 01분부터) 안현분기점(18K)-신천(14K) 18 4 37.440082 126.826665 cctv00001537 안현분기점2 https://exmobile4.hscdn.com/cctv1537image/ch00001537_20260730.154600.000.jpg https://live12.exmobile.hscdn.com/exlive/cctv1537.stream/playlist.m3u8 18 18 (17시 01분부터)
88 0450 1 E 중부내륙선 6 45 양평방향 20260730170123 01 기타 (갓길)승용차고장 처리중 (17시 01분부터) 여주분기점부근(261K) 261 -1 37.196645 127.61217 cctv00005146 금당교_중부내륙 https://exmobile8.hscdn.com/cctv5146image/ch00005146_20260730.154600.000.jpg https://live5.exmobile.hscdn.com/exlive/cctv5146.stream/playlist.m3u8 261 0 (17시 01분부터) (갓길)승용차고장 처리중
89 2510 1 E 호남지선 6 251 대전방향 20260730170212 04 정체 (17시 02분부터) 북대전부근(52K)-회덕분기점(54K) 52 2 36.409214 127.399012 cctv00005468 탑립육교 https://exmobile4.hscdn.com/cctv5468image/ch00005468_20260730.154600.000.jpg https://live7.exmobile.hscdn.com/exlive/cctv5468.stream/playlist.m3u8 52 52 (17시 02분부터)
+125
View File
@@ -0,0 +1,125 @@
"ROUTE","ROAD_NO","ROUTE_ID","WEATHER","UPDWNAME","UPDOWN","MILEPOST","CONTENTS","RAISE_TIME","INCIDENT_TYPE","REGION_ID","REGION_NAME","START_MILEPOST","INITIALCHAR","SEQ_NO","INCIDENT_ID","CONGZONE_ID"
경인선,120,"12001",,서울방향,E,신월(23K)-신월(24K),"1km정체[2026-07-30 15:21- ]","20260730152128",차량증가,"250000",,"23","1200","120","20260730152128",
울산선,16,"01601",,울산방향,E,범서하이패스(10.3K),(갓길)화물차 고장처리 중[2026-07-30 16:17- ],"20260730161750",고장,"700000",,"10.3","0160","16","20260730161750",
경인선,120,"12001",,인천방향,S,부천(20K)-부천(19K),"1km정체[2026-07-30 16:57- ]","20260730165724",차량증가,"250000",,"20","1200","120","20260730165724",
경부선,1,"00101",,부산방향,S,동대구분기점(122.5K),(갓길)승용차 고장처리중[2026-07-30 16:55- ],"20260730165504",고장,"600000",,"122.5","0010","1","20260730165504",
서울양양선,60,"06001",,서울방향,S,남춘천부근(53.8K),"(2,3차로)승용차관련 사고처리중[2026-07-30 16:56- ] ==> 남춘천IC~남춘천IC, 3km정체","20260730165618",사고,"300000",,"53.8","0600","60","20260730165618",
통영대전선,35,"03511",,통영방향,S,오동터널부근(132K),(갓길) 시설물 보수 작업중[2026-07-30 08:12- ],"20260730081231",작업,"800000",,"132","0351","35","20260730081231",
경부선,1,"00101",,부산방향,S,천안분기점부근(332K)-천안호두(휴)(324K),"8km정체[2026-07-30 10:50- ]","20260730105038",차량증가,"400000",,"332","0010","1","20260730105038",
영동선,50,"05001",,인천방향,S,둔대분기점(23K)-반월터널부근(21K),"2km정체[2026-07-30 16:17- ]","20260730161727",차량증가,"250000",,"23","0500","50","20260730161727",
청주영덕선,30,"03001",,영덕방향,E,수한터널부근(28K)-탄부터널부근(31K),"3km정체[2026-07-30 17:04- ]","20260730170451",차량증가,"900000",,"28","0300","30","20260730170451",
논산천안선,25,"02521",,논산방향,S,차령터널 무학천교(266.0K)-차령터널 (263.0K),"3km 정체[2026-07-30 08:24- ]","20260730082406",차량증가,"400000",,"269","0252","25","20260730082406",
경부선,1,"00101",,서울방향,E,양재부근(415K)-반포(420K),"5km정체[2026-07-30 06:27- ]","20260730062713",차량증가,"200000",,"415","0010","1","20260730062713",
제2경인선,110,"11001",,성남방향,E,안현분기점(17K)-안현분기점(18K),"1km정체[2026-07-30 16:24- ]","20260730162409",차량증가,"250000",,"17","1100","110","20260730162409",
영동선,50,"05001",,인천방향,S,이천부근(82K)-호법분기점부근(75K),"7km정체[2026-07-30 16:35- ]","20260730163548",차량증가,"200000",,"82","0500","50","20260730163548",
수도권제1순환선,100,"10001",,판교방향,E,자유로(72K)-김포(74K),"2km정체[2026-07-30 14:59- ]","20260730145917",차량증가,"250000",,"72","1000","100","20260730145917",
순천완주선,27,"02701",,완주방향,E,황전(25.4K),(갓길) 노면보수 작업중[2026-07-30 16:33- ],"20260730163357",작업,"500000",,"25.4","0270","27","20260730163357",
수도권제1순환선,100,"10001",,일산방향,S,안양터널(114K)-수리터널(112K),"2km정체[2026-07-30 15:33- ]","20260730153338",차량증가,"250000",,"114","1000","100","20260730153338",
수도권제2순환선(화성-광주),400,"40041",,화성방향,S,동탄방향 9.8,null[2026-07-23 13:52- ],"20260723135200",작업,"200000",,"0","4004","400","20260723135200",
영동선,50,"05001",,인천방향,S,덕평부근(66K)-양지터널부근(58K),"8km정체[2026-07-30 15:34- ]","20260730153400",차량증가,"200000",,"66","0500","50","20260730153400",
호남선,25,"02511",,천안방향,E,동광주(74K),"1km정체[2026-07-30 16:06- ]","20260730160618",차량증가,"500000",,"74","0251","25","20260730160618",
영동선,50,"05001",,인천방향,S,서용인분기점(50K),"1km정체[2026-07-30 16:17- ]","20260730161757",차량증가,"250000",,"50","0500","50","20260730161757",
영동선,50,"05001",,강릉방향,E,둔대분기점(22K)-부곡(27K),"5km정체[2026-07-30 16:19- ]","20260730161916",차량증가,"250000",,"22","0500","50","20260730161916",
동해선(부산-포항),65,"06521",,포항방향,E,남경주(69.5K)-문무대왕1터널(74.1K),"** (포항방향 1,2차로교대) 장기차단 보강공사 7.20(월) ~ 9.18(금) **","20260714121717",홍보,"700000",,"69.5","0652","65","20260714121717",
제2경인선,110,"11001",,인천방향,S,삼막(25.98K)-광명터널(22K),"4km정체[2026-07-30 14:37- ]","20260730143718",차량증가,"250000",,"25.98","1100","110","20260730143718",
중부내륙선,45,"04501",,양평방향,E,여주분기점부근(261K),(갓길)승용차고장 처리중[2026-07-30 17:01- ],"20260730170123",고장,"900000",,"261","0450","45","20260730170123",
남해선(순천-부산),10,"01001",,부산방향,E,칠원분기점부근(117K)-함안2터널부근(120K),"3km정체[2026-07-30 10:32- ]","20260730103250",차량증가,"700000",,"117","0100","10","20260730103250",
부산외곽선,600,"60001",,창원방향,S,기장분기점(48K)-기장분기점부근(47K),"1km정체[2026-07-30 15:29- ]","20260730152946",차량증가,"700000",,"48","6000","600","20260730152946",
호남지선,251,"25101",,논산방향,S,회덕분기점(54K)-북대전부근(52K),"2km정체[2026-07-30 15:45- ]","20260730154509",차량증가,"400000",,"54","2510","251","20260730154509",
영동선,50,"05001",,인천방향,S,서창분기점(1K)-서창(0K),"1km정체[2026-07-30 16:10- ]","20260730161003",차량증가,"250000",,"1","0500","50","20260730161003",
수도권제1순환선,100,"10001",,판교방향,E,자유로(72K),"(3,4차로) 사고 처리중[2026-07-30 16:47- ] ==> 일산IC~자유로IC, 2km정체","20260730164727",사고,"250000",,"72","1000","100","20260730164727",
서울양양선,60,"06001",,서울방향,S,남춘천부근(53.6K),(갓길) 승용차 고장 처리중[2026-07-30 16:43- ],"20260730164308",고장,"300000",,"53.6","0600","60","20260730164308",
경부선,1,"00101",,서울방향,E,안성분기점(364K)-안성(휴)부근(368K),"4km정체[2026-07-30 14:37- ]","20260730143713",차량증가,"200000",,"364","0010","1","20260730143713",
동해선(포항-영덕),65,"06531",,영덕방향,E, ,** (영덕방향) 30k 영덕분기점 차로 증설 공사중 - 차로 좁아짐 주의(~12월) **,"20260721112431",홍보,"600000",,"0","0653","65","20260721112431",
서해안선,15,"01501",,서울방향,E,광명역(334K)-금천(340K),"6km정체[2026-07-30 06:54- ]","20260730065451",차량증가,"250000",,"334","0150","15","20260730065451",
통영대전선,35,"03511",,통영방향,S,마달터널부근(202.5K),"(2차로,갓길)승용차 고장 처리중[2026-07-30 16:46- ]","20260730164648",고장,"800000",,"202.5","0351","35","20260730164648",
통영대전선,35,"03511",,대전방향,E,진주졸음쉼터(57.3K),** (대전방향) 화장실 이용불가 **,"20260725060945",홍보,"700000",,"57.3","0351","35","20260725060945",
경부선,1,"00101",,부산방향,S,신갈분기점부근(397K)-신갈분기점(394K),"3km정체[2026-07-30 16:48- ]","20260730164817",차량증가,"200000",,"397","0010","1","20260730164817",
영동선,50,"05001",,강릉방향,E,서창분기점(0.5K),(인천 진출로)사고 처리중[2026-07-30 16:44- ],"20260730164416",사고,"250000",,.5,"0500","50","20260730164416",
평택제천선,40,"04001",,제천방향,E,안성분기점(23K)-안성분기점(24K),"1km정체[2026-07-30 16:51- ]","20260730165135",차량증가,"250000",,"23","0400","40","20260730165135",
광주대구선,12,"01201",,대구방향,E, ,** (광주방향)112k 남상졸음쉼터 폐쇄(~12월) **,"20260422234627",홍보,"600000",,"0","0120","12","20260422234627",
수도권제2순환선(화성-광주),400,"40041",,화성방향,S,동탄방향 26.0,K (2차로) 비탈면보수 작업중[2026-05-21 14:38- ],"20260521143800",작업,"200000",,"0","4004","400","20260521143800",
동해선(삼척-속초),65,"06501",,속초방향,E, ,** (속초방향) 동해 졸음쉼터 신설공사 [ ~ 8.13] **,"20260416171758",홍보,"300000",,"0","0650","65","20260416171758",
서천공주선,151,"15101",,공주방향,E, ,** 동서천분기점 공주방향 연결로 갓길 장기차단 26.5월~26.10월 **,"20260519074906",홍보,"400000",,"0","1510","151","20260519074906",
서해안선,15,"01501",,서울방향,E, ,** 서산(목포)주유소 영업중단(5.6~10.6)/휴게소 및 LPG충전소는 정상영업/행담도주유소 이용바람 **,"20260429135010",홍보,"400000",,"0","0150","15","20260429135010",
경부선,1,"00101",,서울방향,E, ,"** (부산)남사졸음쉼터 임시폐쇄(26.06.15~26.10.31),안성휴게소 이용바람 **","20260605215733",홍보,"200000",,"0","0010","1","20260605215733",
남해선(순천-부산),10,"01001",,부산방향,E,대저분기점(163K)-덕천(166K),"3km정체[2026-07-30 13:45- ]","20260730134538",차량증가,"700000",,"163","0100","10","20260730134538",
부산울산선,65,"06511",,부산방향,S,해운대터널부근(3K)-부산울산선시점(0K),"3km정체[2026-07-30 14:43- ]","20260730144311",차량증가,"700000",,"3","0651","65","20260730144311",
경부선,1,"00101",,부산방향,S,청주분기점(297K),(갓길) 승용 고장차 처리중[2026-07-30 15:25- ],"20260730152539",고장,"400000",,"297","0010","1","20260730152539",
남해2지선,104,"10401",,서부산방향,E,서부산(휴)(18K)-사상(20K),"2km정체[2026-07-30 15:25- ]","20260730152500",차량증가,"700000",,"18","1040","104","20260730152500",
동해선(삼척-속초),65,"06501",,속초방향,E,쇄운교(15K)-지흥1교(16.7K),(2차로)졸음쉼터 설치 작업중[2026-07-03 07:42- ],"20260703074200",작업,"300000",,"15","0650","65","20260703074200",
수도권제1순환선,100,"10001",,일산방향,S,시흥요금소(96K)-중동(86K),"10km정체[2026-07-30 07:24- ]","20260730072448",차량증가,"250000",,"96","1000","100","20260730072448",
논산천안선,25,"02521",,천안방향,E,남공주IC 오룡교(232.0K)-남공주IC 검상천교(235.0K),"3km 정체[2026-07-30 15:27- ]","20260730152731",차량증가,"400000",,"225","0252","25","20260730152731",
인천공항선,130,"13001",,공항방향,S,[본선-공항] 20.8Km,청라IC 진출 1km 정체[2026-07-30 15:30- ],"20260730153000",차량증가,"200000",,"20.8","1300","130","20260730153000",
수도권제1순환선,100,"10001",,판교방향,E,조남분기점(107K)-수암터널(108K),"1km정체[2026-07-30 16:06- ]","20260730160627",차량증가,"250000",,"107","1000","100","20260730160627",
서울양양선,60,"06001",,서울방향,S,화도(15K)-화도부근(13K),"2km정체[2026-07-30 15:57- ]","20260730155707",차량증가,"300000",,"15","0600","60","20260730155707",
경부선,1,"00101",,서울방향,E,영천분기점(91.5K),"(3차로,갓길)화물차관련 사고 처리중[2026-07-30 14:47- ]","20260730144715",사고,"600000",,"91.5","0010","1","20260730144715",
서해안선,15,"01501",,서울방향,E,서천(휴)부근(166.5K),(갓길)중형화물차 고장 처리중[2026-07-30 16:13- ],"20260730161342",고장,"800000",,"166.5","0150","15","20260730161342",
서해안선,15,"01501",,서울방향,E, ,** 서해대교(양방향) 정밀안전진단 3차로 주간 차단예정(6~10월) **,"20260605085938",홍보,"400000",,"0","0150","15","20260605085938",
논산천안선,25,"02521",,천안방향,E,남공주IC 오룡교(232.1K),"1차로 승용차 관련 사고발생[2026-07-30 16:20- ]","20260730162057",사고,"400000",,"225","0252","25","20260730162057",
호남지선,251,"25101",,대전방향,E,북대전부근(52K)-회덕분기점(54K),"2km정체[2026-07-30 17:02- ]","20260730170212",차량증가,"400000",,"52","2510","251","20260730170212",
인천대교선,110,"11021",,송도방향,E, ,** (민자 고속도로구간) 인천대교선 상황실 전화번호 032-745-8100 문의 바랍니다 **,"20250910001933",홍보,"250000",,"0","1102","110","20250910001933",
경인선,120,"12001",,서울방향,E, ,** 경인1지하차도 홍익병원사거리 1차로 통제 2025.7.9 (수)~공사완료시까지 **,"20250910001852",홍보,"250000",,"0","1200","120","20250910001852",
수도권제2순환선(인천-김포),400,"40011",,김포방향,E, ,** (민자 고속도로구간) 인천김포선 상황실 전화번호 032-292-7164 문의 바랍니다 **,"20251119153617",홍보,"250000",,"0","4001","400","20251119153617",
제3경인선,330,"33001",,시흥방향,E, ,** (민자 고속도로구간) 제3경인고속도로 상황실 031-8084-8901 문의바랍니다 **,"20240725161924",홍보,"200000",,"0","3300","330","20240725161924",
경부선,1,"00101",,서울방향,E, ,"** 천안IC-천안분기점(부산) 방음시설 작업/4차로 21시~06시, 5차로 06시~21시 차단 25.9월~26.12월 **","20250919075529",홍보,"400000",,"0","0010","1","20250919075529",
경인선,120,"12001",,서울방향,E, ,** 인천대로 일반화 공사중(2단계)[주안산단고가교~서인천IC]2025.11.17~2031.03 **,"20251016103404",홍보,"250000",,"0","1200","120","20251016103404",
영동선,50,"05001",,강릉방향,E, ,** (강릉방향) 생태습지 졸음쉼터 화장실 폐쇄 **,"20251117153247",홍보,"300000",,"0","0500","50","20251117153247",
수도권제1순환선,100,"10001",,일산방향,S,판교분기점(128K)-판교분기점부근(126K),"2km정체[2026-07-30 16:21- ]","20260730162134",차량증가,"200000",,"128","1000","100","20260730162134",
경부선,1,"00101",,서울방향,E,기흥(388K)-신갈분기점(394K),"6km정체[2026-07-30 16:47- ]","20260730164739",차량증가,"200000",,"388","0010","1","20260730164739",
수도권제1순환선,100,"10001",,일산방향,S,성남부근(3K)-판교분기점(0K),"3km정체[2026-07-30 16:21- ]","20260730162117",차량증가,"200000",,"3","1000","100","20260730162117",
중부내륙선,45,"04501",,양평방향,E,현풍졸음쉼터(51.4K),** (창원방향) 시설물 작업 중 쉼터이용불가 **,"20260710150735",홍보,"700000",,"51.4","0450","45","20260710150735",
수도권제1순환선,100,"10001",,일산방향,S,서하남분기점(16K)-송파부근(7K),"9km정체[2026-07-30 16:22- ]","20260730162214",차량증가,"200000",,"16","1000","100","20260730162214",
서해안선,15,"01501",,서울방향,E, ,** 서산(서울)주유소 영업중단(5.6~10.6)/휴게소 및 LPG충전소는 정상영업/홍성주유소 이용바람 **,"20260429075501",홍보,"400000",,"0","0150","15","20260429075501",
새만금전주선,20,"02021",,새만금방향,E,석구터널(46.1K),(갓길)소형화물차 고장 처리중[2026-07-30 14:14- ],"20260730141437",고장,"800000",,"46.1","0202","20","20260730141437",
영동선,50,"05001",,인천방향,S,동수원(37K)-북수원(30K),"7km정체[2026-07-30 14:26- ]","20260730142623",차량증가,"250000",,"37","0500","50","20260730142623",
경인선,120,"12001",,인천방향,S,인천요금소(16K)-서인천(11K),"5km정체[2026-07-30 15:09- ]","20260730150911",차량증가,"250000",,"16","1200","120","20260730150911",
제2경인선,110,"11001",,인천방향,S,서창분기점(9K)-남동부근(6K),"3km정체[2026-07-30 06:54- ]","20260730065400",차량증가,"250000",,"9","1100","110","20260730065400",
제2경인선,110,"11001",,인천방향,S,안현분기점(18K)-신천(14K),"4km정체[2026-07-30 17:01- ]","20260730170117",차량증가,"250000",,"18","1100","110","20260730170117",
서해안선,15,"01501",,서울방향,E, ,** 대천휴게소(양방향) 주유소 개선공사 이용불가 6. 1(월)~11.27(금) **,"20260531090003",홍보,"800000",,"0","0150","15","20260531090003",
영동선,50,"05001",,강릉방향,E, ,** 서안산~북수원 확장공사 제한속도변경 100- 80km/h (8.30~26.12.31 ) **,"20250828051816",홍보,"250000",,"0","0500","50","20250828051816",
평택시흥선,15,"01531",,시흥방향,E, ,** (민자 고속도로구간) 평택시흥선 상황실 전화번호 1661-5688 문의 바랍니다 **,"20250912112159",홍보,"250000",,"0","0153","153","20250912112159",
영동선,50,"05001",,강릉방향,E, ,** 영동선 이목졸음쉼터(강릉) 임시폐쇄 '24.07.15. ~ '26.08.29. **,"20251013121202",홍보,"250000",,"0","0500","50","20251013121202",
영동선,50,"05001",,강릉방향,E, ,** 영동선 이천졸음쉼터(인천방향) 폐쇄 (2025.8월~2027.5월 31. (23개월간) **,"20250814135609",홍보,"200000",,"0","0500","50","20250814135609",
인천공항선,130,"13001",,서울방향,E, ,** (민자 고속도로구간) 인천공항선 상황실 전화번호 032-560-6100 문의 바랍니다 **,"20250623050208",홍보,"200000",,"0","1300","130","20250623050208",
대전남부선,300,"30001",,산내방향,E, ,** 서대전부근(양방향) 방음벽 설치작업 26.7.10(금)~27.7.10(토) **,"20250910112809",홍보,"400000",,"0","3000","300","20250910112809",
수도권제1순환선,100,"10001",,판교방향,E,노오지분기점(79K)-송내(88K),"9km정체[2026-07-30 05:11- ]","20260730051106",차량증가,"250000",,"79","1000","100","20260730051106",
중부선,35,"03521",,하남방향,E,일죽부근(304K)-일죽부근(309K),"5km정체[2026-07-30 16:09- ]","20260730160933",차량증가,"900000",,"304","0352","35","20260730160933",
익산장수선,20,"02011",,익산방향,S,소양(16K)-소양부근(15K),(갓길) 덩쿨제거 작업중[2026-07-30 08:41- ],"20260730084122",작업,"800000",,"16","0201","20","20260730084122",
남해선(순천-부산),10,"01001",,부산방향,E, ,"** 섬진강휴게소(순천방향)주유소 영업중단, 개선공사 2026. 7.02~공사완료시까지 **","20260624020608",홍보,"500000",,"0","0100","10","20260624020608",
영동선,50,"05001",,인천방향,S,월곶분기점부근(6.3K),(2차로)고장차 처리중[2026-07-30 16:46- ],"20260730164625",고장,"250000",,"6.3","0500","50","20260730164625",
중앙선,55,"05502",,부산방향,S,초정(5K)-삼락(0K),"5km정체[2026-07-30 16:19- ]","20260730161902",차량증가,"700000",,"5","0550","55","20260730161902",
중부선,35,"03521",,하남방향,E, ,** 번천(통영)졸음쉼터 화장실 개선 공사로 인한 임시폐쇄 (2026.07.22(수)~2026.12.08(화)) **,"20260710122323",홍보,"200000",,"0","0352","35","20260710122323",
중부선,35,"03521",,남이방향,S,진천터널부근(277K)-진천터널부근(274K),"3km정체[2026-07-30 14:10- ]","20260730141034",차량증가,"900000",,"277","0352","35","20260730141034",
중부내륙선,45,"04501",,창원방향,S,감곡부근(258K)-감곡부근(255K),"3km정체[2026-07-30 09:46- ]","20260730094639",차량증가,"900000",,"258","0450","45","20260730094639",
서해안선,15,"01501",,서울방향,E,서평택분기점부근(295K)-화성(휴)부근(303K),"8km정체[2026-07-30 14:09- ]","20260730140943",차량증가,"250000",,"295","0150","15","20260730140943",
경부선,1,"00101",,서울방향,E, ,** 판교분기점-금토분기점(양방향) 갓길 개량공사중(2026.05.26~2027.11.30) **,"20260526065333",홍보,"200000",,"0","0010","1","20260526065333",
중부내륙선,45,"04501",,양평방향,E, ,** (양평방향) 96.5km 성주휴게소 수소충전소 이용불가 **,"20260725224834",홍보,"600000",,"0","0450","45","20260725224834",
통영대전선,35,"03511",,대전방향,E, ,** 통영대전선 111.9k~115.4k(양방향)갓길 장기차단(5.28(목)~9.30(수)) **,"20260521081134",홍보,"700000",,"0","0351","35","20260521081134",
중부내륙선,45,"04501",,양평방향,E,충주분기점부근(238K)-충주분기점부근(241K),"3km정체[2026-07-30 13:27- ]","20260730132759",차량증가,"900000",,"238","0450","45","20260730132759",
논산천안선,25,"02521",,논산방향,S,남풍세IC 호정 1교(268.0K)-차령터널 (263.0K),"5km 정체[2026-07-28 14:03- ]","20260728140304",차량증가,"400000",,"269","0252","25","20260728140304",
서해안선,15,"01501",,서울방향,E, ,** (갓길)동서천JCT(서울) 정체개선공사(2026. 5. 19 ~ 2026. 10. 30) **,"20260519113903",홍보,"800000",,"0","0150","15","20260519113903",
중부내륙선,45,"04501",,양평방향,E,영산(24K),(진입로 갓길) 화물차 고장 처리 중[2026-07-30 16:58- ],"20260730165823",고장,"700000",,"24","0450","45","20260730165823",
서해안선,15,"01501",,서울방향,E, ,"** 기상악화시 ""당진IC~서평택IC"" 제한속도 하향 단속(구간, 암행순찰) 시행 **","20260128113835",홍보,"400000",,"0","0150","15","20260128113835",
서해안선,15,"01501",,서울방향,E,당진부근(267.3K),(갓길) 화물 고장차 처리중[2026-07-30 16:18- ],"20260730161803",고장,"400000",,"267.3","0150","15","20260730161803",
수도권제1순환선,100,"10001",,판교방향,E,강일(24K)-구리남양주요금소(27K),"3km정체[2026-07-30 16:23- ]","20260730162344",차량증가,"200000",,"24","1000","100","20260730162344",
평택제천선,40,"04001",,평택방향,S,대소분기점(57K)-안진터널(52K),"5km정체[2026-07-30 15:55- ]","20260730155518",차량증가,"900000",,"57","0400","40","20260730155518",
평택제천선,40,"04001",,평택방향,S,서안성(25K)-안성분기점(24K),"1km정체[2026-07-30 15:06- ]","20260730150604",차량증가,"250000",,"25","0400","40","20260730150604",
경부선,1,"00101",,서울방향,E,판교분기점(408K),"1km정체[2026-07-30 16:00- ]","20260730160049",차량증가,"200000",,"408","0010","1","20260730160049",
동해선(부산-포항),65,"06521",,포항방향,E,남경주부근(68K)-문무대왕1터널(74K),"(2차로)노면보강 공사 작업중, 장기차단[2026-07-20 08:25- ]","20260720082502",작업,"700000",,"68","0652","65","20260720082502",
서울양양선,60,"06001",,서울방향,S,덕소삼패(3K)-강일(0K),"3km정체[2026-07-30 16:23- ]","20260730162324",차량증가,"300000",,"3","0600","60","20260730162324",
중부내륙선,45,"04501",,양평방향,E,감곡(251K)-감곡부근(255K),"4km정체[2026-07-30 16:23- ]","20260730162343",차량증가,"900000",,"251","0450","45","20260730162343",
경부선,1,"00101",,부산방향,S,회덕분기점(277K)-회덕분기점부근(276K),"1km정체[2026-07-30 16:33- ]","20260730163326",차량증가,"400000",,"277","0010","1","20260730163326",
호남선,25,"02511",,천안방향,E, ,** 백양사휴게소(천안)수소충전소 운영중단(2026.7.27~수리완료시까지) **,"20260727035539",홍보,"500000",,"0","0251","25","20260727035539",
경부선,1,"00101",,서울방향,E, ,** 평일 버스전용차로제 시행 중 (양방향) 한남-안성 (07시-21시) **,"20260704055541",홍보,"200000",,"0","0010","1","20260704055541",
남해선(순천-부산),10,"01001",,부산방향,E,김해졸음쉼터(153K),** (양방향) 화장실 이용불가 **,"20260616194929",홍보,"700000",,"153","0100","10","20260616194929",
경부선,1,"00101",,서울방향,E,입장거봉포도(휴)부근(355K)-안성(360K),"5km정체[2026-07-30 15:20- ]","20260730152029",차량증가,"400000",,"355","0010","1","20260730152029",
중부내륙선,45,"04501",,양평방향,E,감곡부근(252.1K),(갓길)승합차고장 처리중[2026-07-30 16:11- ],"20260730161104",고장,"900000",,"252.1","0450","45","20260730161104",
순천완주선,27,"02701",,완주방향,E,서면2터널부근(10.7K),(갓길) 화물차 고장 처리중[2026-07-30 16:17- ],"20260730161748",고장,"500000",,"10.7","0270","27","20260730161748",
서해안선,15,"01501",,서울방향,E, ,** 화성휴게소(목포) 수소충전소 이용 불가 2026.7.29(수)~2026.7.31(금) **,"20260729140605",홍보,"250000",,"0","0150","15","20260729140605",
통영대전선,35,"03511",,통영방향,S,동고성(14.3K),(갓길)화물차 고장 처리중[2026-07-30 16:51- ],"20260730165102",고장,"700000",,"14.3","0351","35","20260730165102",
경부선,1,"00101",,서울방향,E,안성(휴)(370K),(갓길)보행자 조치중[2026-07-30 16:56- ],"20260730165638",기타,"200000",,"370","0010","1","20260730165638",
영동선,50,"05001",,인천방향,S,군자분기점(7K)-월곶분기점부근(4K),"3km정체[2026-07-30 13:59- ]","20260730135951",차량증가,"250000",,"7","0500","50","20260730135951",
제2경인선,110,"11001",,성남방향,E,학익분기점(3K)-남동(8K),"5km정체[2026-07-30 13:54- ]","20260730135457",차량증가,"250000",,"3","1100","110","20260730135457",
서해안선,15,"01501",,서울방향,E,매송(휴)부근(315K)-용담터널(319K),"4km정체[2026-07-30 14:10- ]","20260730141000",차량증가,"250000",,"315","0150","15","20260730141000",
중부선,35,"03521",,하남방향,E,경기광주IC(352K)-중부1터널부근(355K),"3km정체[2026-07-30 16:42- ]","20260730164203",차량증가,"200000",,"352","0352","35","20260730164203",
1 ROUTE ROAD_NO ROUTE_ID WEATHER UPDWNAME UPDOWN MILEPOST CONTENTS RAISE_TIME INCIDENT_TYPE REGION_ID REGION_NAME START_MILEPOST INITIALCHAR SEQ_NO INCIDENT_ID CONGZONE_ID
2 경인선 120 12001 서울방향 E 신월(23K)-신월(24K) 1km정체[2026-07-30 15:21- ] 20260730152128 차량증가 250000 23 1200 120 20260730152128
3 울산선 16 01601 울산방향 E 범서하이패스(10.3K) (갓길)화물차 고장처리 중[2026-07-30 16:17- ] 20260730161750 고장 700000 10.3 0160 16 20260730161750
4 경인선 120 12001 인천방향 S 부천(20K)-부천(19K) 1km정체[2026-07-30 16:57- ] 20260730165724 차량증가 250000 20 1200 120 20260730165724
5 경부선 1 00101 부산방향 S 동대구분기점(122.5K) (갓길)승용차 고장처리중[2026-07-30 16:55- ] 20260730165504 고장 600000 122.5 0010 1 20260730165504
6 서울양양선 60 06001 서울방향 S 남춘천부근(53.8K) (2,3차로)승용차관련 사고처리중[2026-07-30 16:56- ] ==> 남춘천IC~남춘천IC, 3km정체 20260730165618 사고 300000 53.8 0600 60 20260730165618
7 통영대전선 35 03511 통영방향 S 오동터널부근(132K) (갓길) 시설물 보수 작업중[2026-07-30 08:12- ] 20260730081231 작업 800000 132 0351 35 20260730081231
8 경부선 1 00101 부산방향 S 천안분기점부근(332K)-천안호두(휴)(324K) 8km정체[2026-07-30 10:50- ] 20260730105038 차량증가 400000 332 0010 1 20260730105038
9 영동선 50 05001 인천방향 S 둔대분기점(23K)-반월터널부근(21K) 2km정체[2026-07-30 16:17- ] 20260730161727 차량증가 250000 23 0500 50 20260730161727
10 청주영덕선 30 03001 영덕방향 E 수한터널부근(28K)-탄부터널부근(31K) 3km정체[2026-07-30 17:04- ] 20260730170451 차량증가 900000 28 0300 30 20260730170451
11 논산천안선 25 02521 논산방향 S 차령터널 무학천교(266.0K)-차령터널 (263.0K) 3km 정체[2026-07-30 08:24- ] 20260730082406 차량증가 400000 269 0252 25 20260730082406
12 경부선 1 00101 서울방향 E 양재부근(415K)-반포(420K) 5km정체[2026-07-30 06:27- ] 20260730062713 차량증가 200000 415 0010 1 20260730062713
13 제2경인선 110 11001 성남방향 E 안현분기점(17K)-안현분기점(18K) 1km정체[2026-07-30 16:24- ] 20260730162409 차량증가 250000 17 1100 110 20260730162409
14 영동선 50 05001 인천방향 S 이천부근(82K)-호법분기점부근(75K) 7km정체[2026-07-30 16:35- ] 20260730163548 차량증가 200000 82 0500 50 20260730163548
15 수도권제1순환선 100 10001 판교방향 E 자유로(72K)-김포(74K) 2km정체[2026-07-30 14:59- ] 20260730145917 차량증가 250000 72 1000 100 20260730145917
16 순천완주선 27 02701 완주방향 E 황전(25.4K) (갓길) 노면보수 작업중[2026-07-30 16:33- ] 20260730163357 작업 500000 25.4 0270 27 20260730163357
17 수도권제1순환선 100 10001 일산방향 S 안양터널(114K)-수리터널(112K) 2km정체[2026-07-30 15:33- ] 20260730153338 차량증가 250000 114 1000 100 20260730153338
18 수도권제2순환선(화성-광주) 400 40041 화성방향 S 동탄방향 9.8 null[2026-07-23 13:52- ] 20260723135200 작업 200000 0 4004 400 20260723135200
19 영동선 50 05001 인천방향 S 덕평부근(66K)-양지터널부근(58K) 8km정체[2026-07-30 15:34- ] 20260730153400 차량증가 200000 66 0500 50 20260730153400
20 호남선 25 02511 천안방향 E 동광주(74K) 1km정체[2026-07-30 16:06- ] 20260730160618 차량증가 500000 74 0251 25 20260730160618
21 영동선 50 05001 인천방향 S 서용인분기점(50K) 1km정체[2026-07-30 16:17- ] 20260730161757 차량증가 250000 50 0500 50 20260730161757
22 영동선 50 05001 강릉방향 E 둔대분기점(22K)-부곡(27K) 5km정체[2026-07-30 16:19- ] 20260730161916 차량증가 250000 22 0500 50 20260730161916
23 동해선(부산-포항) 65 06521 포항방향 E 남경주(69.5K)-문무대왕1터널(74.1K) ** (포항방향 1,2차로교대) 장기차단 보강공사 7.20(월) ~ 9.18(금) ** 20260714121717 홍보 700000 69.5 0652 65 20260714121717
24 제2경인선 110 11001 인천방향 S 삼막(25.98K)-광명터널(22K) 4km정체[2026-07-30 14:37- ] 20260730143718 차량증가 250000 25.98 1100 110 20260730143718
25 중부내륙선 45 04501 양평방향 E 여주분기점부근(261K) (갓길)승용차고장 처리중[2026-07-30 17:01- ] 20260730170123 고장 900000 261 0450 45 20260730170123
26 남해선(순천-부산) 10 01001 부산방향 E 칠원분기점부근(117K)-함안2터널부근(120K) 3km정체[2026-07-30 10:32- ] 20260730103250 차량증가 700000 117 0100 10 20260730103250
27 부산외곽선 600 60001 창원방향 S 기장분기점(48K)-기장분기점부근(47K) 1km정체[2026-07-30 15:29- ] 20260730152946 차량증가 700000 48 6000 600 20260730152946
28 호남지선 251 25101 논산방향 S 회덕분기점(54K)-북대전부근(52K) 2km정체[2026-07-30 15:45- ] 20260730154509 차량증가 400000 54 2510 251 20260730154509
29 영동선 50 05001 인천방향 S 서창분기점(1K)-서창(0K) 1km정체[2026-07-30 16:10- ] 20260730161003 차량증가 250000 1 0500 50 20260730161003
30 수도권제1순환선 100 10001 판교방향 E 자유로(72K) (3,4차로) 사고 처리중[2026-07-30 16:47- ] ==> 일산IC~자유로IC, 2km정체 20260730164727 사고 250000 72 1000 100 20260730164727
31 서울양양선 60 06001 서울방향 S 남춘천부근(53.6K) (갓길) 승용차 고장 처리중[2026-07-30 16:43- ] 20260730164308 고장 300000 53.6 0600 60 20260730164308
32 경부선 1 00101 서울방향 E 안성분기점(364K)-안성(휴)부근(368K) 4km정체[2026-07-30 14:37- ] 20260730143713 차량증가 200000 364 0010 1 20260730143713
33 동해선(포항-영덕) 65 06531 영덕방향 E ** (영덕방향) 30k 영덕분기점 차로 증설 공사중 - 차로 좁아짐 주의(~12월) ** 20260721112431 홍보 600000 0 0653 65 20260721112431
34 서해안선 15 01501 서울방향 E 광명역(334K)-금천(340K) 6km정체[2026-07-30 06:54- ] 20260730065451 차량증가 250000 334 0150 15 20260730065451
35 통영대전선 35 03511 통영방향 S 마달터널부근(202.5K) (2차로,갓길)승용차 고장 처리중[2026-07-30 16:46- ] 20260730164648 고장 800000 202.5 0351 35 20260730164648
36 통영대전선 35 03511 대전방향 E 진주졸음쉼터(57.3K) ** (대전방향) 화장실 이용불가 ** 20260725060945 홍보 700000 57.3 0351 35 20260725060945
37 경부선 1 00101 부산방향 S 신갈분기점부근(397K)-신갈분기점(394K) 3km정체[2026-07-30 16:48- ] 20260730164817 차량증가 200000 397 0010 1 20260730164817
38 영동선 50 05001 강릉방향 E 서창분기점(0.5K) (인천 진출로)사고 처리중[2026-07-30 16:44- ] 20260730164416 사고 250000 .5 0500 50 20260730164416
39 평택제천선 40 04001 제천방향 E 안성분기점(23K)-안성분기점(24K) 1km정체[2026-07-30 16:51- ] 20260730165135 차량증가 250000 23 0400 40 20260730165135
40 광주대구선 12 01201 대구방향 E ** (광주방향)112k 남상졸음쉼터 폐쇄(~12월) ** 20260422234627 홍보 600000 0 0120 12 20260422234627
41 수도권제2순환선(화성-광주) 400 40041 화성방향 S 동탄방향 26.0 K (2차로) 비탈면보수 작업중[2026-05-21 14:38- ] 20260521143800 작업 200000 0 4004 400 20260521143800
42 동해선(삼척-속초) 65 06501 속초방향 E ** (속초방향) 동해 졸음쉼터 신설공사 [ ~ 8.13] ** 20260416171758 홍보 300000 0 0650 65 20260416171758
43 서천공주선 151 15101 공주방향 E ** 동서천분기점 공주방향 연결로 갓길 장기차단 26.5월~26.10월 ** 20260519074906 홍보 400000 0 1510 151 20260519074906
44 서해안선 15 01501 서울방향 E ** 서산(목포)주유소 영업중단(5.6~10.6)/휴게소 및 LPG충전소는 정상영업/행담도주유소 이용바람 ** 20260429135010 홍보 400000 0 0150 15 20260429135010
45 경부선 1 00101 서울방향 E ** (부산)남사졸음쉼터 임시폐쇄(26.06.15~26.10.31),안성휴게소 이용바람 ** 20260605215733 홍보 200000 0 0010 1 20260605215733
46 남해선(순천-부산) 10 01001 부산방향 E 대저분기점(163K)-덕천(166K) 3km정체[2026-07-30 13:45- ] 20260730134538 차량증가 700000 163 0100 10 20260730134538
47 부산울산선 65 06511 부산방향 S 해운대터널부근(3K)-부산울산선시점(0K) 3km정체[2026-07-30 14:43- ] 20260730144311 차량증가 700000 3 0651 65 20260730144311
48 경부선 1 00101 부산방향 S 청주분기점(297K) (갓길) 승용 고장차 처리중[2026-07-30 15:25- ] 20260730152539 고장 400000 297 0010 1 20260730152539
49 남해2지선 104 10401 서부산방향 E 서부산(휴)(18K)-사상(20K) 2km정체[2026-07-30 15:25- ] 20260730152500 차량증가 700000 18 1040 104 20260730152500
50 동해선(삼척-속초) 65 06501 속초방향 E 쇄운교(15K)-지흥1교(16.7K) (2차로)졸음쉼터 설치 작업중[2026-07-03 07:42- ] 20260703074200 작업 300000 15 0650 65 20260703074200
51 수도권제1순환선 100 10001 일산방향 S 시흥요금소(96K)-중동(86K) 10km정체[2026-07-30 07:24- ] 20260730072448 차량증가 250000 96 1000 100 20260730072448
52 논산천안선 25 02521 천안방향 E 남공주IC 오룡교(232.0K)-남공주IC 검상천교(235.0K) 3km 정체[2026-07-30 15:27- ] 20260730152731 차량증가 400000 225 0252 25 20260730152731
53 인천공항선 130 13001 공항방향 S [본선-공항] 20.8Km 청라IC 진출 1km 정체[2026-07-30 15:30- ] 20260730153000 차량증가 200000 20.8 1300 130 20260730153000
54 수도권제1순환선 100 10001 판교방향 E 조남분기점(107K)-수암터널(108K) 1km정체[2026-07-30 16:06- ] 20260730160627 차량증가 250000 107 1000 100 20260730160627
55 서울양양선 60 06001 서울방향 S 화도(15K)-화도부근(13K) 2km정체[2026-07-30 15:57- ] 20260730155707 차량증가 300000 15 0600 60 20260730155707
56 경부선 1 00101 서울방향 E 영천분기점(91.5K) (3차로,갓길)화물차관련 사고 처리중[2026-07-30 14:47- ] 20260730144715 사고 600000 91.5 0010 1 20260730144715
57 서해안선 15 01501 서울방향 E 서천(휴)부근(166.5K) (갓길)중형화물차 고장 처리중[2026-07-30 16:13- ] 20260730161342 고장 800000 166.5 0150 15 20260730161342
58 서해안선 15 01501 서울방향 E ** 서해대교(양방향) 정밀안전진단 3차로 주간 차단예정(6~10월) ** 20260605085938 홍보 400000 0 0150 15 20260605085938
59 논산천안선 25 02521 천안방향 E 남공주IC 오룡교(232.1K) 1차로 승용차 관련 사고발생[2026-07-30 16:20- ] 20260730162057 사고 400000 225 0252 25 20260730162057
60 호남지선 251 25101 대전방향 E 북대전부근(52K)-회덕분기점(54K) 2km정체[2026-07-30 17:02- ] 20260730170212 차량증가 400000 52 2510 251 20260730170212
61 인천대교선 110 11021 송도방향 E ** (민자 고속도로구간) 인천대교선 상황실 전화번호 032-745-8100 문의 바랍니다 ** 20250910001933 홍보 250000 0 1102 110 20250910001933
62 경인선 120 12001 서울방향 E ** 경인1지하차도 홍익병원사거리 1차로 통제 2025.7.9 (수)~공사완료시까지 ** 20250910001852 홍보 250000 0 1200 120 20250910001852
63 수도권제2순환선(인천-김포) 400 40011 김포방향 E ** (민자 고속도로구간) 인천김포선 상황실 전화번호 032-292-7164 문의 바랍니다 ** 20251119153617 홍보 250000 0 4001 400 20251119153617
64 제3경인선 330 33001 시흥방향 E ** (민자 고속도로구간) 제3경인고속도로 상황실 031-8084-8901 문의바랍니다 ** 20240725161924 홍보 200000 0 3300 330 20240725161924
65 경부선 1 00101 서울방향 E ** 천안IC-천안분기점(부산) 방음시설 작업/4차로 21시~06시, 5차로 06시~21시 차단 25.9월~26.12월 ** 20250919075529 홍보 400000 0 0010 1 20250919075529
66 경인선 120 12001 서울방향 E ** 인천대로 일반화 공사중(2단계)[주안산단고가교~서인천IC]2025.11.17~2031.03 ** 20251016103404 홍보 250000 0 1200 120 20251016103404
67 영동선 50 05001 강릉방향 E ** (강릉방향) 생태습지 졸음쉼터 화장실 폐쇄 ** 20251117153247 홍보 300000 0 0500 50 20251117153247
68 수도권제1순환선 100 10001 일산방향 S 판교분기점(128K)-판교분기점부근(126K) 2km정체[2026-07-30 16:21- ] 20260730162134 차량증가 200000 128 1000 100 20260730162134
69 경부선 1 00101 서울방향 E 기흥(388K)-신갈분기점(394K) 6km정체[2026-07-30 16:47- ] 20260730164739 차량증가 200000 388 0010 1 20260730164739
70 수도권제1순환선 100 10001 일산방향 S 성남부근(3K)-판교분기점(0K) 3km정체[2026-07-30 16:21- ] 20260730162117 차량증가 200000 3 1000 100 20260730162117
71 중부내륙선 45 04501 양평방향 E 현풍졸음쉼터(51.4K) ** (창원방향) 시설물 작업 중 쉼터이용불가 ** 20260710150735 홍보 700000 51.4 0450 45 20260710150735
72 수도권제1순환선 100 10001 일산방향 S 서하남분기점(16K)-송파부근(7K) 9km정체[2026-07-30 16:22- ] 20260730162214 차량증가 200000 16 1000 100 20260730162214
73 서해안선 15 01501 서울방향 E ** 서산(서울)주유소 영업중단(5.6~10.6)/휴게소 및 LPG충전소는 정상영업/홍성주유소 이용바람 ** 20260429075501 홍보 400000 0 0150 15 20260429075501
74 새만금전주선 20 02021 새만금방향 E 석구터널(46.1K) (갓길)소형화물차 고장 처리중[2026-07-30 14:14- ] 20260730141437 고장 800000 46.1 0202 20 20260730141437
75 영동선 50 05001 인천방향 S 동수원(37K)-북수원(30K) 7km정체[2026-07-30 14:26- ] 20260730142623 차량증가 250000 37 0500 50 20260730142623
76 경인선 120 12001 인천방향 S 인천요금소(16K)-서인천(11K) 5km정체[2026-07-30 15:09- ] 20260730150911 차량증가 250000 16 1200 120 20260730150911
77 제2경인선 110 11001 인천방향 S 서창분기점(9K)-남동부근(6K) 3km정체[2026-07-30 06:54- ] 20260730065400 차량증가 250000 9 1100 110 20260730065400
78 제2경인선 110 11001 인천방향 S 안현분기점(18K)-신천(14K) 4km정체[2026-07-30 17:01- ] 20260730170117 차량증가 250000 18 1100 110 20260730170117
79 서해안선 15 01501 서울방향 E ** 대천휴게소(양방향) 주유소 개선공사 이용불가 6. 1(월)~11.27(금) ** 20260531090003 홍보 800000 0 0150 15 20260531090003
80 영동선 50 05001 강릉방향 E ** 서안산~북수원 확장공사 제한속도변경 100- 80km/h (8.30~26.12.31 ) ** 20250828051816 홍보 250000 0 0500 50 20250828051816
81 평택시흥선 15 01531 시흥방향 E ** (민자 고속도로구간) 평택시흥선 상황실 전화번호 1661-5688 문의 바랍니다 ** 20250912112159 홍보 250000 0 0153 153 20250912112159
82 영동선 50 05001 강릉방향 E ** 영동선 이목졸음쉼터(강릉) 임시폐쇄 '24.07.15. ~ '26.08.29. ** 20251013121202 홍보 250000 0 0500 50 20251013121202
83 영동선 50 05001 강릉방향 E ** 영동선 이천졸음쉼터(인천방향) 폐쇄 (2025.8월~2027.5월 31. (23개월간) ** 20250814135609 홍보 200000 0 0500 50 20250814135609
84 인천공항선 130 13001 서울방향 E ** (민자 고속도로구간) 인천공항선 상황실 전화번호 032-560-6100 문의 바랍니다 ** 20250623050208 홍보 200000 0 1300 130 20250623050208
85 대전남부선 300 30001 산내방향 E ** 서대전부근(양방향) 방음벽 설치작업 26.7.10(금)~27.7.10(토) ** 20250910112809 홍보 400000 0 3000 300 20250910112809
86 수도권제1순환선 100 10001 판교방향 E 노오지분기점(79K)-송내(88K) 9km정체[2026-07-30 05:11- ] 20260730051106 차량증가 250000 79 1000 100 20260730051106
87 중부선 35 03521 하남방향 E 일죽부근(304K)-일죽부근(309K) 5km정체[2026-07-30 16:09- ] 20260730160933 차량증가 900000 304 0352 35 20260730160933
88 익산장수선 20 02011 익산방향 S 소양(16K)-소양부근(15K) (갓길) 덩쿨제거 작업중[2026-07-30 08:41- ] 20260730084122 작업 800000 16 0201 20 20260730084122
89 남해선(순천-부산) 10 01001 부산방향 E ** 섬진강휴게소(순천방향)주유소 영업중단, 개선공사 2026. 7.02~공사완료시까지 ** 20260624020608 홍보 500000 0 0100 10 20260624020608
90 영동선 50 05001 인천방향 S 월곶분기점부근(6.3K) (2차로)고장차 처리중[2026-07-30 16:46- ] 20260730164625 고장 250000 6.3 0500 50 20260730164625
91 중앙선 55 05502 부산방향 S 초정(5K)-삼락(0K) 5km정체[2026-07-30 16:19- ] 20260730161902 차량증가 700000 5 0550 55 20260730161902
92 중부선 35 03521 하남방향 E ** 번천(통영)졸음쉼터 화장실 개선 공사로 인한 임시폐쇄 (2026.07.22(수)~2026.12.08(화)) ** 20260710122323 홍보 200000 0 0352 35 20260710122323
93 중부선 35 03521 남이방향 S 진천터널부근(277K)-진천터널부근(274K) 3km정체[2026-07-30 14:10- ] 20260730141034 차량증가 900000 277 0352 35 20260730141034
94 중부내륙선 45 04501 창원방향 S 감곡부근(258K)-감곡부근(255K) 3km정체[2026-07-30 09:46- ] 20260730094639 차량증가 900000 258 0450 45 20260730094639
95 서해안선 15 01501 서울방향 E 서평택분기점부근(295K)-화성(휴)부근(303K) 8km정체[2026-07-30 14:09- ] 20260730140943 차량증가 250000 295 0150 15 20260730140943
96 경부선 1 00101 서울방향 E ** 판교분기점-금토분기점(양방향) 갓길 개량공사중(2026.05.26~2027.11.30) ** 20260526065333 홍보 200000 0 0010 1 20260526065333
97 중부내륙선 45 04501 양평방향 E ** (양평방향) 96.5km 성주휴게소 수소충전소 이용불가 ** 20260725224834 홍보 600000 0 0450 45 20260725224834
98 통영대전선 35 03511 대전방향 E ** 통영대전선 111.9k~115.4k(양방향)갓길 장기차단(5.28(목)~9.30(수)) ** 20260521081134 홍보 700000 0 0351 35 20260521081134
99 중부내륙선 45 04501 양평방향 E 충주분기점부근(238K)-충주분기점부근(241K) 3km정체[2026-07-30 13:27- ] 20260730132759 차량증가 900000 238 0450 45 20260730132759
100 논산천안선 25 02521 논산방향 S 남풍세IC 호정 1교(268.0K)-차령터널 (263.0K) 5km 정체[2026-07-28 14:03- ] 20260728140304 차량증가 400000 269 0252 25 20260728140304
101 서해안선 15 01501 서울방향 E ** (갓길)동서천JCT(서울) 정체개선공사(2026. 5. 19 ~ 2026. 10. 30) ** 20260519113903 홍보 800000 0 0150 15 20260519113903
102 중부내륙선 45 04501 양평방향 E 영산(24K) (진입로 갓길) 화물차 고장 처리 중[2026-07-30 16:58- ] 20260730165823 고장 700000 24 0450 45 20260730165823
103 서해안선 15 01501 서울방향 E ** 기상악화시 "당진IC~서평택IC" 제한속도 하향 단속(구간, 암행순찰) 시행 ** 20260128113835 홍보 400000 0 0150 15 20260128113835
104 서해안선 15 01501 서울방향 E 당진부근(267.3K) (갓길) 화물 고장차 처리중[2026-07-30 16:18- ] 20260730161803 고장 400000 267.3 0150 15 20260730161803
105 수도권제1순환선 100 10001 판교방향 E 강일(24K)-구리남양주요금소(27K) 3km정체[2026-07-30 16:23- ] 20260730162344 차량증가 200000 24 1000 100 20260730162344
106 평택제천선 40 04001 평택방향 S 대소분기점(57K)-안진터널(52K) 5km정체[2026-07-30 15:55- ] 20260730155518 차량증가 900000 57 0400 40 20260730155518
107 평택제천선 40 04001 평택방향 S 서안성(25K)-안성분기점(24K) 1km정체[2026-07-30 15:06- ] 20260730150604 차량증가 250000 25 0400 40 20260730150604
108 경부선 1 00101 서울방향 E 판교분기점(408K) 1km정체[2026-07-30 16:00- ] 20260730160049 차량증가 200000 408 0010 1 20260730160049
109 동해선(부산-포항) 65 06521 포항방향 E 남경주부근(68K)-문무대왕1터널(74K) (2차로)노면보강 공사 작업중, 장기차단[2026-07-20 08:25- ] 20260720082502 작업 700000 68 0652 65 20260720082502
110 서울양양선 60 06001 서울방향 S 덕소삼패(3K)-강일(0K) 3km정체[2026-07-30 16:23- ] 20260730162324 차량증가 300000 3 0600 60 20260730162324
111 중부내륙선 45 04501 양평방향 E 감곡(251K)-감곡부근(255K) 4km정체[2026-07-30 16:23- ] 20260730162343 차량증가 900000 251 0450 45 20260730162343
112 경부선 1 00101 부산방향 S 회덕분기점(277K)-회덕분기점부근(276K) 1km정체[2026-07-30 16:33- ] 20260730163326 차량증가 400000 277 0010 1 20260730163326
113 호남선 25 02511 천안방향 E ** 백양사휴게소(천안)수소충전소 운영중단(2026.7.27~수리완료시까지) ** 20260727035539 홍보 500000 0 0251 25 20260727035539
114 경부선 1 00101 서울방향 E ** 평일 버스전용차로제 시행 중 (양방향) 한남-안성 (07시-21시) ** 20260704055541 홍보 200000 0 0010 1 20260704055541
115 남해선(순천-부산) 10 01001 부산방향 E 김해졸음쉼터(153K) ** (양방향) 화장실 이용불가 ** 20260616194929 홍보 700000 153 0100 10 20260616194929
116 경부선 1 00101 서울방향 E 입장거봉포도(휴)부근(355K)-안성(360K) 5km정체[2026-07-30 15:20- ] 20260730152029 차량증가 400000 355 0010 1 20260730152029
117 중부내륙선 45 04501 양평방향 E 감곡부근(252.1K) (갓길)승합차고장 처리중[2026-07-30 16:11- ] 20260730161104 고장 900000 252.1 0450 45 20260730161104
118 순천완주선 27 02701 완주방향 E 서면2터널부근(10.7K) (갓길) 화물차 고장 처리중[2026-07-30 16:17- ] 20260730161748 고장 500000 10.7 0270 27 20260730161748
119 서해안선 15 01501 서울방향 E ** 화성휴게소(목포) 수소충전소 이용 불가 2026.7.29(수)~2026.7.31(금) ** 20260729140605 홍보 250000 0 0150 15 20260729140605
120 통영대전선 35 03511 통영방향 S 동고성(14.3K) (갓길)화물차 고장 처리중[2026-07-30 16:51- ] 20260730165102 고장 700000 14.3 0351 35 20260730165102
121 경부선 1 00101 서울방향 E 안성(휴)(370K) (갓길)보행자 조치중[2026-07-30 16:56- ] 20260730165638 기타 200000 370 0010 1 20260730165638
122 영동선 50 05001 인천방향 S 군자분기점(7K)-월곶분기점부근(4K) 3km정체[2026-07-30 13:59- ] 20260730135951 차량증가 250000 7 0500 50 20260730135951
123 제2경인선 110 11001 성남방향 E 학익분기점(3K)-남동(8K) 5km정체[2026-07-30 13:54- ] 20260730135457 차량증가 250000 3 1100 110 20260730135457
124 서해안선 15 01501 서울방향 E 매송(휴)부근(315K)-용담터널(319K) 4km정체[2026-07-30 14:10- ] 20260730141000 차량증가 250000 315 0150 15 20260730141000
125 중부선 35 03521 하남방향 E 경기광주IC(352K)-중부1터널부근(355K) 3km정체[2026-07-30 16:42- ] 20260730164203 차량증가 200000 352 0352 35 20260730164203
+139
View File
@@ -0,0 +1,139 @@
"ROUTECD","GRPID","ROUTESHORTNO","ROUTENM","ROUTESORT","UPDOWNDIR","ROUTEDIRNM","ROUTELAYOVERNM","OPER","HOINSTNM","RPRSTELNO","CLSSCD"
"0170","1","17",평택화성선,"6",S,오성,,공영,한국도로공사,"1588-2504","108"
"0200","1","20",대구포항선,"6",S,대구,,공영,한국도로공사,"1588-2504","101"
"0201","1","20",익산장수선,"6",S,익산,,공영,한국도로공사,"1588-2504","101"
"0251","1","25",호남선,"6",S,순천,,공영,한국도로공사,"1588-2504","101"
"0270","1","27",순천완주선,"6",S,순천,,공영,한국도로공사,"1588-2504","101"
"0290","1","29",세종포천선(안성-포천),"6",S,안성,,공영,한국도로공사,"1588-2504","101"
"0300","1","30",청주영덕선,"6",S,청주,,공영,한국도로공사,"1588-2504","101"
"0301","1","30",당진대전선,"6",S,당진,,공영,한국도로공사,"1588-2504","101"
"0351","1","35",통영대전선,"6",S,통영,,공영,한국도로공사,"1588-2504","101"
"0352","1","35",중부선,"3",S,남이,,공영,한국도로공사,"1588-2504","101"
"0370","1","37",제2중부선,"6",S,이천,,공영,한국도로공사,"1588-2504","101"
"0400","1","40",평택제천선,"6",S,평택,,공영,한국도로공사,"1588-2504","101"
"0450","1","45",중부내륙선,"6",S,창원,,공영,한국도로공사,"1588-2504","101"
"0500","1","50",영동선,"4",S,인천,,공영,한국도로공사,"1588-2504","101"
"0520","1","52",광주원주선,"6",S,광주,,공영,제이영동고속도로㈜,"1877-0200","109"
"0550","2","55",중앙선,"6",S,부산,,공영,한국도로공사,"1588-2504","101"
"0552","1","55",대구부산선,"6",S,부산,,공영,신대구부산고속도로㈜,"1688-7003","109"
"0600","1","60",서울양양선,"6",S,서울,,공영,한국도로공사,"1588-2504","101"
"0650","1","65",동해선(삼척-속초),"6",S,삼척,,공영,한국도로공사,"1588-2504","101"
"0651","1","65",부산울산선,"6",S,부산,,공영,한국도로공사,"1588-2504","108"
"0652","1","65",동해선(부산-포항),"6",S,부산,,공영,한국도로공사,"1588-2504","101"
"1000","1","100",수도권제1순환선,"5",S,일산,,공영,한국도로공사,"1588-2504","101"
"1020","1","102",남해1지선,"6",S,함안,,공영,한국도로공사,"1588-2504","101"
"1040","1","104",남해2지선,"6",S,김해,,공영,한국도로공사,"1588-2504","101"
"1100","1","110",제2경인선,"6",S,인천,,공영,한국도로공사,"1588-2504","101"
"1102","1","110",인천대교선,"6",S,공항,,공영,인천대교㈜,"032-745-8000","109"
"1200","1","120",경인선,"6",S,인천,,공영,한국도로공사,"1588-2504","101"
"1300","1","130",인천공항선,"6",S,공항,,공영,신공항하이웨이㈜,"032-560-6114","109"
"1510","1","151",서천공주선,"6",S,서천,,공영,한국도로공사,"1588-2504","101"
"1710","1","171",용인서울선,"6",S,용인,,공영,경수고속도로㈜,"1599-2505","109"
"2510","1","251",호남지선,"6",S,논산,,공영,한국도로공사,"1588-2504","101"
"3000","1","300",대전남부선,"6",S,서대전,,공영,한국도로공사,"1588-2504","101"
"3010","1","301",상주영천선,"6",S,상주,,공영,상주영천고속도로㈜,"1877-1925","109"
"3300","1","330",제3경인선,"6",S,인천,,공영,제삼경인고속도로㈜,"031-8084-8900","109"
"4000","1","400",수도권제2순환선(봉담-동탄),"6",S,동탄,,공영,한국도로공사,"1588-2504","108"
"4001","1","400",수도권제2순환선(인천-김포),"6",S,인천,,공영,인천김포고속도로㈜,"1566-7069","109"
"4002","1","400",수도권제2순환선(파주-포천),"6",S,포천,,공영,한국도로공사,"1588-2504","108"
"4510","1","451",중부내륙지선,"6",S,창원,,공영,한국도로공사,"1588-2504","101"
"5510","1","551",중앙선지선,"6",S,김해,,공영,한국도로공사,"1588-2504","101"
"0252","1","25",논산천안선,"6",S,논산,,공영,천안논산고속도로㈜,"041-850-6700","109"
"0320","1","32",당진청주선(옥산-오창),"6",S,옥산,,공영,옥산오창고속도로㈜,"1877-1108","109"
"6000","1","600",부산외곽선,"6",S,창원,,공영,한국도로공사,"1588-2504","101"
"0173","1","173",서울문산지선,"6",S,서울,,공영,한국도로공사,"1588-2504","108"
"0172","1","17",서울문산선,"6",S,서울,,공영,한국도로공사,"1588-2504","108"
"0141","1","14",함양울산선,"6",S,함양,,공영,한국도로공사,"1588-2504","108"
"4003","1","400",수도권제2순환선(송산-봉담),"6",S,봉담,,공영,경기동서순환고속도로㈜,"1877-0427","109"
"4004","1","400",수도권제2순환선(화성-광주),"6",S,화성,,공영,화성광주고속도로㈜,"1877-0380","109"
"0700","1","700",대구외곽선,"6",S,달서,,공영,한국도로공사,"1588-2504","101"
"4005","1","400",수도권제2순환선(화도-양평),"6",S,양평,,공영,포천화도고속도로㈜,"1877-1140","109"
"5000","1","500",광주외곽선,"6",S,광주,,공영,한국도로공사,"1588-2504","101"
"0010","1","1",경부선,"1",S,부산,,공영,한국도로공사,"1588-2504","101"
"0100","1","10",남해선(순천-부산),"6",S,순천,,공영,한국도로공사,"1588-2504","101"
"0101","1","101",남해선(영암-순천),"6",S,영암,,공영,한국도로공사,"1588-2504","101"
"0105","1","105",부산신항선,"6",S,신항,,공영,부산신항제이배후도로㈜,"055-339-7164","109"
"0120","1","12",광주대구선,"6",S,광주,,공영,한국도로공사,"1588-2504","101"
"0121","1","12",무안광주선,"6",S,무안,,공영,한국도로공사,"1588-2504","101"
"0140","1","253",고창담양선,"6",S,고창,,공영,한국도로공사,"1588-2504","101"
"0150","1","15",서해안선,"2",S,목포,,공영,한국도로공사,"1588-2504","101"
"0153","1","153",평택시흥선,"6",S,평택,,공영,제2서해안고속도로㈜,"1661-5688","109"
"0160","1","16",울산선,"6",S,언양,,공영,한국도로공사,"1588-2504","101"
"0170","3","171",오산화성선,"6",S,서오산,,공영,한국도로공사,"1588-2504","108"
"0170","2","17",수원광명선,"6",S,봉담,,공영,한국도로공사,"1588-2504","108"
"0321","1","32",당진청주선(아산-천안),"6",S,천안,,공영,한국도로공사,"1588-2504","108"
"4006","1","400",수도권제2순환선(시화-남안산),"6",S,남안산,,공영,한국도로공사,"1588-2504","101"
"4007","1","400",수도권제2순환선(포천-화도),"6",S,포천,,공영,포천화도고속도로㈜,"1877-1140","109"
"1730","1","173",익산평택지선,"6",S,현덕,,공영,서부내륙고속도로㈜,"070-7460-3896","109"
"0175","1","17",익산평택선,"6",S,익산,,공영,서부내륙고속도로㈜,"070-7460-3896","109"
"0653","1","65",동해선(포항-영덕),"6",S,포항,,공영,,,"101"
"0202","1","20",새만금전주선,"6",S,전주,,공영,,,"101"
"0170","1","17",평택화성선,"6",E,봉담,,공영,한국도로공사,"1588-2504","108"
"0200","1","20",대구포항선,"6",E,포항,,공영,한국도로공사,"1588-2504","101"
"0201","1","20",익산장수선,"6",E,장수,,공영,한국도로공사,"1588-2504","101"
"0251","1","25",호남선,"6",E,천안,,공영,한국도로공사,"1588-2504","101"
"0270","1","27",순천완주선,"6",E,완주,,공영,한국도로공사,"1588-2504","101"
"0290","1","29",세종포천선(안성-포천),"6",E,포천,,공영,한국도로공사,"1588-2504","101"
"0300","1","30",청주영덕선,"6",E,영덕,,공영,한국도로공사,"1588-2504","101"
"0301","1","30",당진대전선,"6",E,대전,,공영,한국도로공사,"1588-2504","101"
"0351","1","35",통영대전선,"6",E,대전,,공영,한국도로공사,"1588-2504","101"
"0352","1","35",중부선,"3",E,하남,,공영,한국도로공사,"1588-2504","101"
"0370","1","37",제2중부선,"6",E,하남,,공영,한국도로공사,"1588-2504","101"
"0400","1","40",평택제천선,"6",E,제천,,공영,한국도로공사,"1588-2504","101"
"0450","1","45",중부내륙선,"6",E,양평,,공영,한국도로공사,"1588-2504","101"
"0500","1","50",영동선,"4",E,강릉,,공영,한국도로공사,"1588-2504","101"
"0520","1","52",광주원주선,"6",E,원주,,공영,제이영동고속도로㈜,"1877-0200","109"
"0550","2","55",중앙선,"6",E,춘천,,공영,한국도로공사,"1588-2504","101"
"0552","1","55",대구부산선,"6",E,대구,,공영,신대구부산고속도로㈜,"1688-7003","109"
"0600","1","60",서울양양선,"6",E,양양,,공영,한국도로공사,"1588-2504","101"
"0650","1","65",동해선(삼척-속초),"6",E,속초,,공영,한국도로공사,"1588-2504","101"
"0651","1","65",부산울산선,"6",E,울산,,공영,한국도로공사,"1588-2504","108"
"0652","1","65",동해선(부산-포항),"6",E,포항,,공영,한국도로공사,"1588-2504","101"
"1000","1","100",수도권제1순환선,"5",E,판교,,공영,한국도로공사,"1588-2504","101"
"1020","1","102",남해1지선,"6",E,창원,,공영,한국도로공사,"1588-2504","101"
"1040","1","104",남해2지선,"6",E,서부산,,공영,한국도로공사,"1588-2504","101"
"1100","1","110",제2경인선,"6",E,성남,,공영,한국도로공사,"1588-2504","101"
"1102","1","110",인천대교선,"6",E,송도,,공영,인천대교㈜,"032-745-8000","109"
"1200","1","120",경인선,"6",E,서울,,공영,한국도로공사,"1588-2504","101"
"1300","1","130",인천공항선,"6",E,서울,,공영,신공항하이웨이㈜,"032-560-6114","109"
"1510","1","151",서천공주선,"6",E,공주,,공영,한국도로공사,"1588-2504","101"
"1710","1","171",용인서울선,"6",E,서울,,공영,경수고속도로㈜,"1599-2505","109"
"2510","1","251",호남지선,"6",E,대전,,공영,한국도로공사,"1588-2504","101"
"3000","1","300",대전남부선,"6",E,산내,,공영,한국도로공사,"1588-2504","101"
"3010","1","301",상주영천선,"6",E,영천,,공영,상주영천고속도로㈜,"1877-1925","109"
"3300","1","330",제3경인선,"6",E,시흥,,공영,제삼경인고속도로㈜,"031-8084-8900","109"
"4000","1","400",수도권제2순환선(봉담-동탄),"6",E,봉담,,공영,한국도로공사,"1588-2504","108"
"4001","1","400",수도권제2순환선(인천-김포),"6",E,김포,,공영,인천김포고속도로㈜,"1566-7069","109"
"4002","1","400",수도권제2순환선(파주-포천),"6",E,파주,,공영,한국도로공사,"1588-2504","108"
"4510","1","451",중부내륙지선,"6",E,대구,,공영,한국도로공사,"1588-2504","101"
"5510","1","551",중앙선지선,"6",E,양산,,공영,한국도로공사,"1588-2504","101"
"0252","1","25",논산천안선,"6",E,천안,,공영,천안논산고속도로㈜,"041-850-6700","109"
"0320","1","32",당진청주선(옥산-오창),"6",E,오창,,공영,옥산오창고속도로㈜,"1877-1108","109"
"6000","1","600",부산외곽선,"6",E,기장,,공영,한국도로공사,"1588-2504","101"
"0173","1","173",서울문산지선,"6",E,문산,,공영,한국도로공사,"1588-2504","108"
"0172","1","17",서울문산선,"6",E,문산,,공영,한국도로공사,"1588-2504","108"
"0141","1","14",함양울산선,"6",E,울산,,공영,한국도로공사,"1588-2504","108"
"4003","1","400",수도권제2순환선(송산-봉담),"6",E,송산,,공영,경기동서순환고속도로㈜,"1877-0427","109"
"4004","1","400",수도권제2순환선(화성-광주),"6",E,광주,,공영,화성광주고속도로㈜,"1877-0380","109"
"0700","1","700",대구외곽선,"6",E,상매,,공영,한국도로공사,"1588-2504","101"
"4005","1","400",수도권제2순환선(화도-양평),"6",E,화도,,공영,포천화도고속도로㈜,"1877-1140","109"
"5000","1","500",광주외곽선,"6",E,장성,,공영,한국도로공사,"1588-2504","101"
"0010","1","1",경부선,"1",E,서울,,공영,한국도로공사,"1588-2504","101"
"0100","1","10",남해선(순천-부산),"6",E,부산,,공영,한국도로공사,"1588-2504","101"
"0101","1","101",남해선(영암-순천),"6",E,순천,,공영,한국도로공사,"1588-2504","101"
"0105","1","105",부산신항선,"6",E,김해,,공영,부산신항제이배후도로㈜,"055-339-7164","109"
"0120","1","12",광주대구선,"6",E,대구,,공영,한국도로공사,"1588-2504","101"
"0121","1","12",무안광주선,"6",E,광주,,공영,한국도로공사,"1588-2504","101"
"0140","1","253",고창담양선,"6",E,담양,,공영,한국도로공사,"1588-2504","101"
"0150","1","15",서해안선,"2",E,서울,,공영,한국도로공사,"1588-2504","101"
"0153","1","153",평택시흥선,"6",E,시흥,,공영,제2서해안고속도로㈜,"1661-5688","109"
"0160","1","16",울산선,"6",E,울산,,공영,한국도로공사,"1588-2504","101"
"0170","3","171",오산화성선,"6",E,안녕,,공영,한국도로공사,"1588-2504","108"
"0170","2","17",수원광명선,"6",E,소하,,공영,한국도로공사,"1588-2504","108"
"0321","1","32",당진청주선(아산-천안),"6",E,아산,,공영,한국도로공사,"1588-2504","108"
"4006","1","400",수도권제2순환선(시화-남안산),"6",E,시화,,공영,한국도로공사,"1588-2504","101"
"4007","1","400",수도권제2순환선(포천-화도),"6",E,화도,,공영,포천화도고속도로㈜,"1877-1140","109"
"1730","1","173",익산평택지선,"6",E,포승,,공영,서부내륙고속도로㈜,"070-7460-3896","109"
"0175","1","17",익산평택선,"6",E,평택,,공영,서부내륙고속도로㈜,"070-7460-3896","109"
"0653","1","65",동해선(포항-영덕),"6",E,영덕,,공영,,,"101"
"0202","1","20",새만금전주선,"6",E,새만금,,공영,,,"101"
1 ROUTECD GRPID ROUTESHORTNO ROUTENM ROUTESORT UPDOWNDIR ROUTEDIRNM ROUTELAYOVERNM OPER HOINSTNM RPRSTELNO CLSSCD
2 0170 1 17 평택화성선 6 S 오성 공영 한국도로공사 1588-2504 108
3 0200 1 20 대구포항선 6 S 대구 공영 한국도로공사 1588-2504 101
4 0201 1 20 익산장수선 6 S 익산 공영 한국도로공사 1588-2504 101
5 0251 1 25 호남선 6 S 순천 공영 한국도로공사 1588-2504 101
6 0270 1 27 순천완주선 6 S 순천 공영 한국도로공사 1588-2504 101
7 0290 1 29 세종포천선(안성-포천) 6 S 안성 공영 한국도로공사 1588-2504 101
8 0300 1 30 청주영덕선 6 S 청주 공영 한국도로공사 1588-2504 101
9 0301 1 30 당진대전선 6 S 당진 공영 한국도로공사 1588-2504 101
10 0351 1 35 통영대전선 6 S 통영 공영 한국도로공사 1588-2504 101
11 0352 1 35 중부선 3 S 남이 공영 한국도로공사 1588-2504 101
12 0370 1 37 제2중부선 6 S 이천 공영 한국도로공사 1588-2504 101
13 0400 1 40 평택제천선 6 S 평택 공영 한국도로공사 1588-2504 101
14 0450 1 45 중부내륙선 6 S 창원 공영 한국도로공사 1588-2504 101
15 0500 1 50 영동선 4 S 인천 공영 한국도로공사 1588-2504 101
16 0520 1 52 광주원주선 6 S 광주 공영 제이영동고속도로㈜ 1877-0200 109
17 0550 2 55 중앙선 6 S 부산 공영 한국도로공사 1588-2504 101
18 0552 1 55 대구부산선 6 S 부산 공영 신대구부산고속도로㈜ 1688-7003 109
19 0600 1 60 서울양양선 6 S 서울 공영 한국도로공사 1588-2504 101
20 0650 1 65 동해선(삼척-속초) 6 S 삼척 공영 한국도로공사 1588-2504 101
21 0651 1 65 부산울산선 6 S 부산 공영 한국도로공사 1588-2504 108
22 0652 1 65 동해선(부산-포항) 6 S 부산 공영 한국도로공사 1588-2504 101
23 1000 1 100 수도권제1순환선 5 S 일산 공영 한국도로공사 1588-2504 101
24 1020 1 102 남해1지선 6 S 함안 공영 한국도로공사 1588-2504 101
25 1040 1 104 남해2지선 6 S 김해 공영 한국도로공사 1588-2504 101
26 1100 1 110 제2경인선 6 S 인천 공영 한국도로공사 1588-2504 101
27 1102 1 110 인천대교선 6 S 공항 공영 인천대교㈜ 032-745-8000 109
28 1200 1 120 경인선 6 S 인천 공영 한국도로공사 1588-2504 101
29 1300 1 130 인천공항선 6 S 공항 공영 신공항하이웨이㈜ 032-560-6114 109
30 1510 1 151 서천공주선 6 S 서천 공영 한국도로공사 1588-2504 101
31 1710 1 171 용인서울선 6 S 용인 공영 경수고속도로㈜ 1599-2505 109
32 2510 1 251 호남지선 6 S 논산 공영 한국도로공사 1588-2504 101
33 3000 1 300 대전남부선 6 S 서대전 공영 한국도로공사 1588-2504 101
34 3010 1 301 상주영천선 6 S 상주 공영 상주영천고속도로㈜ 1877-1925 109
35 3300 1 330 제3경인선 6 S 인천 공영 제삼경인고속도로㈜ 031-8084-8900 109
36 4000 1 400 수도권제2순환선(봉담-동탄) 6 S 동탄 공영 한국도로공사 1588-2504 108
37 4001 1 400 수도권제2순환선(인천-김포) 6 S 인천 공영 인천김포고속도로㈜ 1566-7069 109
38 4002 1 400 수도권제2순환선(파주-포천) 6 S 포천 공영 한국도로공사 1588-2504 108
39 4510 1 451 중부내륙지선 6 S 창원 공영 한국도로공사 1588-2504 101
40 5510 1 551 중앙선지선 6 S 김해 공영 한국도로공사 1588-2504 101
41 0252 1 25 논산천안선 6 S 논산 공영 천안논산고속도로㈜ 041-850-6700 109
42 0320 1 32 당진청주선(옥산-오창) 6 S 옥산 공영 옥산오창고속도로㈜ 1877-1108 109
43 6000 1 600 부산외곽선 6 S 창원 공영 한국도로공사 1588-2504 101
44 0173 1 173 서울문산지선 6 S 서울 공영 한국도로공사 1588-2504 108
45 0172 1 17 서울문산선 6 S 서울 공영 한국도로공사 1588-2504 108
46 0141 1 14 함양울산선 6 S 함양 공영 한국도로공사 1588-2504 108
47 4003 1 400 수도권제2순환선(송산-봉담) 6 S 봉담 공영 경기동서순환고속도로㈜ 1877-0427 109
48 4004 1 400 수도권제2순환선(화성-광주) 6 S 화성 공영 화성광주고속도로㈜ 1877-0380 109
49 0700 1 700 대구외곽선 6 S 달서 공영 한국도로공사 1588-2504 101
50 4005 1 400 수도권제2순환선(화도-양평) 6 S 양평 공영 포천화도고속도로㈜ 1877-1140 109
51 5000 1 500 광주외곽선 6 S 광주 공영 한국도로공사 1588-2504 101
52 0010 1 1 경부선 1 S 부산 공영 한국도로공사 1588-2504 101
53 0100 1 10 남해선(순천-부산) 6 S 순천 공영 한국도로공사 1588-2504 101
54 0101 1 101 남해선(영암-순천) 6 S 영암 공영 한국도로공사 1588-2504 101
55 0105 1 105 부산신항선 6 S 신항 공영 부산신항제이배후도로㈜ 055-339-7164 109
56 0120 1 12 광주대구선 6 S 광주 공영 한국도로공사 1588-2504 101
57 0121 1 12 무안광주선 6 S 무안 공영 한국도로공사 1588-2504 101
58 0140 1 253 고창담양선 6 S 고창 공영 한국도로공사 1588-2504 101
59 0150 1 15 서해안선 2 S 목포 공영 한국도로공사 1588-2504 101
60 0153 1 153 평택시흥선 6 S 평택 공영 제2서해안고속도로㈜ 1661-5688 109
61 0160 1 16 울산선 6 S 언양 공영 한국도로공사 1588-2504 101
62 0170 3 171 오산화성선 6 S 서오산 공영 한국도로공사 1588-2504 108
63 0170 2 17 수원광명선 6 S 봉담 공영 한국도로공사 1588-2504 108
64 0321 1 32 당진청주선(아산-천안) 6 S 천안 공영 한국도로공사 1588-2504 108
65 4006 1 400 수도권제2순환선(시화-남안산) 6 S 남안산 공영 한국도로공사 1588-2504 101
66 4007 1 400 수도권제2순환선(포천-화도) 6 S 포천 공영 포천화도고속도로㈜ 1877-1140 109
67 1730 1 173 익산평택지선 6 S 현덕 공영 서부내륙고속도로㈜ 070-7460-3896 109
68 0175 1 17 익산평택선 6 S 익산 공영 서부내륙고속도로㈜ 070-7460-3896 109
69 0653 1 65 동해선(포항-영덕) 6 S 포항 공영 101
70 0202 1 20 새만금전주선 6 S 전주 공영 101
71 0170 1 17 평택화성선 6 E 봉담 공영 한국도로공사 1588-2504 108
72 0200 1 20 대구포항선 6 E 포항 공영 한국도로공사 1588-2504 101
73 0201 1 20 익산장수선 6 E 장수 공영 한국도로공사 1588-2504 101
74 0251 1 25 호남선 6 E 천안 공영 한국도로공사 1588-2504 101
75 0270 1 27 순천완주선 6 E 완주 공영 한국도로공사 1588-2504 101
76 0290 1 29 세종포천선(안성-포천) 6 E 포천 공영 한국도로공사 1588-2504 101
77 0300 1 30 청주영덕선 6 E 영덕 공영 한국도로공사 1588-2504 101
78 0301 1 30 당진대전선 6 E 대전 공영 한국도로공사 1588-2504 101
79 0351 1 35 통영대전선 6 E 대전 공영 한국도로공사 1588-2504 101
80 0352 1 35 중부선 3 E 하남 공영 한국도로공사 1588-2504 101
81 0370 1 37 제2중부선 6 E 하남 공영 한국도로공사 1588-2504 101
82 0400 1 40 평택제천선 6 E 제천 공영 한국도로공사 1588-2504 101
83 0450 1 45 중부내륙선 6 E 양평 공영 한국도로공사 1588-2504 101
84 0500 1 50 영동선 4 E 강릉 공영 한국도로공사 1588-2504 101
85 0520 1 52 광주원주선 6 E 원주 공영 제이영동고속도로㈜ 1877-0200 109
86 0550 2 55 중앙선 6 E 춘천 공영 한국도로공사 1588-2504 101
87 0552 1 55 대구부산선 6 E 대구 공영 신대구부산고속도로㈜ 1688-7003 109
88 0600 1 60 서울양양선 6 E 양양 공영 한국도로공사 1588-2504 101
89 0650 1 65 동해선(삼척-속초) 6 E 속초 공영 한국도로공사 1588-2504 101
90 0651 1 65 부산울산선 6 E 울산 공영 한국도로공사 1588-2504 108
91 0652 1 65 동해선(부산-포항) 6 E 포항 공영 한국도로공사 1588-2504 101
92 1000 1 100 수도권제1순환선 5 E 판교 공영 한국도로공사 1588-2504 101
93 1020 1 102 남해1지선 6 E 창원 공영 한국도로공사 1588-2504 101
94 1040 1 104 남해2지선 6 E 서부산 공영 한국도로공사 1588-2504 101
95 1100 1 110 제2경인선 6 E 성남 공영 한국도로공사 1588-2504 101
96 1102 1 110 인천대교선 6 E 송도 공영 인천대교㈜ 032-745-8000 109
97 1200 1 120 경인선 6 E 서울 공영 한국도로공사 1588-2504 101
98 1300 1 130 인천공항선 6 E 서울 공영 신공항하이웨이㈜ 032-560-6114 109
99 1510 1 151 서천공주선 6 E 공주 공영 한국도로공사 1588-2504 101
100 1710 1 171 용인서울선 6 E 서울 공영 경수고속도로㈜ 1599-2505 109
101 2510 1 251 호남지선 6 E 대전 공영 한국도로공사 1588-2504 101
102 3000 1 300 대전남부선 6 E 산내 공영 한국도로공사 1588-2504 101
103 3010 1 301 상주영천선 6 E 영천 공영 상주영천고속도로㈜ 1877-1925 109
104 3300 1 330 제3경인선 6 E 시흥 공영 제삼경인고속도로㈜ 031-8084-8900 109
105 4000 1 400 수도권제2순환선(봉담-동탄) 6 E 봉담 공영 한국도로공사 1588-2504 108
106 4001 1 400 수도권제2순환선(인천-김포) 6 E 김포 공영 인천김포고속도로㈜ 1566-7069 109
107 4002 1 400 수도권제2순환선(파주-포천) 6 E 파주 공영 한국도로공사 1588-2504 108
108 4510 1 451 중부내륙지선 6 E 대구 공영 한국도로공사 1588-2504 101
109 5510 1 551 중앙선지선 6 E 양산 공영 한국도로공사 1588-2504 101
110 0252 1 25 논산천안선 6 E 천안 공영 천안논산고속도로㈜ 041-850-6700 109
111 0320 1 32 당진청주선(옥산-오창) 6 E 오창 공영 옥산오창고속도로㈜ 1877-1108 109
112 6000 1 600 부산외곽선 6 E 기장 공영 한국도로공사 1588-2504 101
113 0173 1 173 서울문산지선 6 E 문산 공영 한국도로공사 1588-2504 108
114 0172 1 17 서울문산선 6 E 문산 공영 한국도로공사 1588-2504 108
115 0141 1 14 함양울산선 6 E 울산 공영 한국도로공사 1588-2504 108
116 4003 1 400 수도권제2순환선(송산-봉담) 6 E 송산 공영 경기동서순환고속도로㈜ 1877-0427 109
117 4004 1 400 수도권제2순환선(화성-광주) 6 E 광주 공영 화성광주고속도로㈜ 1877-0380 109
118 0700 1 700 대구외곽선 6 E 상매 공영 한국도로공사 1588-2504 101
119 4005 1 400 수도권제2순환선(화도-양평) 6 E 화도 공영 포천화도고속도로㈜ 1877-1140 109
120 5000 1 500 광주외곽선 6 E 장성 공영 한국도로공사 1588-2504 101
121 0010 1 1 경부선 1 E 서울 공영 한국도로공사 1588-2504 101
122 0100 1 10 남해선(순천-부산) 6 E 부산 공영 한국도로공사 1588-2504 101
123 0101 1 101 남해선(영암-순천) 6 E 순천 공영 한국도로공사 1588-2504 101
124 0105 1 105 부산신항선 6 E 김해 공영 부산신항제이배후도로㈜ 055-339-7164 109
125 0120 1 12 광주대구선 6 E 대구 공영 한국도로공사 1588-2504 101
126 0121 1 12 무안광주선 6 E 광주 공영 한국도로공사 1588-2504 101
127 0140 1 253 고창담양선 6 E 담양 공영 한국도로공사 1588-2504 101
128 0150 1 15 서해안선 2 E 서울 공영 한국도로공사 1588-2504 101
129 0153 1 153 평택시흥선 6 E 시흥 공영 제2서해안고속도로㈜ 1661-5688 109
130 0160 1 16 울산선 6 E 울산 공영 한국도로공사 1588-2504 101
131 0170 3 171 오산화성선 6 E 안녕 공영 한국도로공사 1588-2504 108
132 0170 2 17 수원광명선 6 E 소하 공영 한국도로공사 1588-2504 108
133 0321 1 32 당진청주선(아산-천안) 6 E 아산 공영 한국도로공사 1588-2504 108
134 4006 1 400 수도권제2순환선(시화-남안산) 6 E 시화 공영 한국도로공사 1588-2504 101
135 4007 1 400 수도권제2순환선(포천-화도) 6 E 화도 공영 포천화도고속도로㈜ 1877-1140 109
136 1730 1 173 익산평택지선 6 E 포승 공영 서부내륙고속도로㈜ 070-7460-3896 109
137 0175 1 17 익산평택선 6 E 평택 공영 서부내륙고속도로㈜ 070-7460-3896 109
138 0653 1 65 동해선(포항-영덕) 6 E 영덕 공영 101
139 0202 1 20 새만금전주선 6 E 새만금 공영 101
File diff suppressed because it is too large Load Diff
+33
View File
@@ -0,0 +1,33 @@
-- TROAD 개발용 부트스트랩 (컨테이너 최초 초기화 시 1회 실행)
--
-- gvenzl 이미지는 이 스크립트를 CDB root 에서 실행할 수 있으므로
-- OPR_MAIN 이 있는 PDB(ORCL2)로 세션을 옮긴 뒤 권한을 부여한다.
-- 업무 뷰/데이터는 oracle/apply-sql.sh (sql/*.sql) 로 적용한다.
BEGIN
EXECUTE IMMEDIATE 'ALTER SESSION SET CONTAINER = ORCL2';
EXCEPTION
WHEN OTHERS THEN NULL; -- 이미 PDB 세션이면 무시
END;
/
DECLARE
TYPE t_privs IS TABLE OF VARCHAR2(60);
l_privs t_privs := t_privs (
'CREATE SESSION',
'CREATE TABLE',
'CREATE VIEW',
'CREATE SEQUENCE',
'CREATE SYNONYM',
'UNLIMITED TABLESPACE'
);
BEGIN
FOR i IN 1 .. l_privs.COUNT LOOP
BEGIN
EXECUTE IMMEDIATE 'GRANT ' || l_privs (i) || ' TO OPR_MAIN';
EXCEPTION
WHEN OTHERS THEN NULL;
END;
END LOOP;
END;
/
+99
View File
@@ -0,0 +1,99 @@
-- V_INCIDENT_FTMS (교통정보 돌발/정체) — 개발서버용 구성
--
-- 운영 DDL 은 TROAD_APP.V_INCIDENT_FTMS 로, 다수 기반 테이블(V_TRMB_ACDT_BRNWS_INFO01L1,
-- T_TRMB_ROUTE01M1, TLISDEV.T_TRMB_CD_INFO01M1 ...)을 union all 로 가공하는 읽기 전용 뷰다.
-- 개발서버에는 기반 테이블이 없고 뷰 자체에는 INSERT 가 불가하므로,
-- 뷰 결과와 동일한 17개 컬럼을 갖는 물리 테이블을 두고 그 위에 같은 이름의 뷰를 만든다.
-- 소유자는 chatbotApi 가 실제 접속하는 계정(OPR_MAIN)으로 맞춘다.
-- jdbc:oracle:thin:@localhost:1521/orcl2 / OPR_MAIN
SET DEFINE OFF
SET SERVEROUTPUT ON
-- 기존 뷰 제거 (테이블 재정의 순서 보장)
BEGIN
EXECUTE IMMEDIATE 'DROP VIEW OPR_MAIN.V_INCIDENT_FTMS';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN RAISE; END IF;
END;
/
-- 뷰의 원본 데이터 테이블
BEGIN
EXECUTE IMMEDIATE q'[
CREATE TABLE OPR_MAIN.T_INCIDENT_FTMS (
ROUTE VARCHAR2(100),
ROAD_NO NUMBER,
ROUTE_ID VARCHAR2(20),
WEATHER VARCHAR2(100),
UPDWNAME VARCHAR2(50),
UPDOWN VARCHAR2(1),
MILEPOST VARCHAR2(400),
CONTENTS VARCHAR2(2000),
RAISE_TIME VARCHAR2(14),
INCIDENT_TYPE VARCHAR2(20),
REGION_ID VARCHAR2(20),
REGION_NAME VARCHAR2(100),
START_MILEPOST NUMBER,
INITIALCHAR VARCHAR2(10),
SEQ_NO VARCHAR2(10),
INCIDENT_ID VARCHAR2(30),
CONGZONE_ID VARCHAR2(30),
LOADED_AT TIMESTAMP DEFAULT SYSTIMESTAMP
)
]';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -955 THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE 'CREATE INDEX OPR_MAIN.IX_INCIDENT_FTMS_ROUTE ON OPR_MAIN.T_INCIDENT_FTMS (ROAD_NO, UPDOWN)';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -955 AND SQLCODE != -1408 THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE 'CREATE INDEX OPR_MAIN.IX_INCIDENT_FTMS_TYPE ON OPR_MAIN.T_INCIDENT_FTMS (INCIDENT_TYPE)';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -955 AND SQLCODE != -1408 THEN RAISE; END IF;
END;
/
-- 운영과 동일한 컬럼·순서의 뷰
CREATE OR REPLACE FORCE VIEW OPR_MAIN.V_INCIDENT_FTMS (
"ROUTE", "ROAD_NO", "ROUTE_ID", "WEATHER", "UPDWNAME", "UPDOWN", "MILEPOST",
"CONTENTS", "RAISE_TIME", "INCIDENT_TYPE", "REGION_ID", "REGION_NAME",
"START_MILEPOST", "INITIALCHAR", "SEQ_NO", "INCIDENT_ID", "CONGZONE_ID"
) AS
SELECT ROUTE,
ROAD_NO,
ROUTE_ID,
WEATHER,
UPDWNAME,
UPDOWN,
MILEPOST,
CONTENTS,
RAISE_TIME,
INCIDENT_TYPE,
REGION_ID,
REGION_NAME,
START_MILEPOST,
INITIALCHAR,
SEQ_NO,
INCIDENT_ID,
CONGZONE_ID
FROM OPR_MAIN.T_INCIDENT_FTMS;
-- 운영 스키마명(TROAD_APP)으로도 접근할 수 있게 동의어 제공
BEGIN
EXECUTE IMMEDIATE 'CREATE OR REPLACE PUBLIC SYNONYM V_INCIDENT_FTMS FOR OPR_MAIN.V_INCIDENT_FTMS';
EXCEPTION
WHEN OTHERS THEN NULL;
END;
/
+137
View File
@@ -0,0 +1,137 @@
-- 자동 생성: V_INCIDENT_FTMS_202607301706.csv -> OPR_MAIN.T_INCIDENT_FTMS
-- 행 수: 124
-- 생성 도구: server-dev/oracle/tools/csv_to_insert.py
SET DEFINE OFF
SET SQLBLANKLINES ON
DELETE FROM OPR_MAIN.T_INCIDENT_FTMS;
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경인선', 120, '12001', NULL, '서울방향', 'E', '신월(23K)-신월(24K)', '1km정체[2026-07-30 15:21- ]', '20260730152128', '차량증가', '250000', NULL, 23, '1200', '120', '20260730152128', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('울산선', 16, '01601', NULL, '울산방향', 'E', '범서하이패스(10.3K)', '(갓길)화물차 고장처리 중[2026-07-30 16:17- ]', '20260730161750', '고장', '700000', NULL, 10.3, '0160', '16', '20260730161750', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경인선', 120, '12001', NULL, '인천방향', 'S', '부천(20K)-부천(19K)', '1km정체[2026-07-30 16:57- ]', '20260730165724', '차량증가', '250000', NULL, 20, '1200', '120', '20260730165724', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경부선', 1, '00101', NULL, '부산방향', 'S', '동대구분기점(122.5K)', '(갓길)승용차 고장처리중[2026-07-30 16:55- ]', '20260730165504', '고장', '600000', NULL, 122.5, '0010', '1', '20260730165504', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('서울양양선', 60, '06001', NULL, '서울방향', 'S', '남춘천부근(53.8K)', '(2,3차로)승용차관련 사고처리중[2026-07-30 16:56- ] ==> 남춘천IC~남춘천IC, 3km정체', '20260730165618', '사고', '300000', NULL, 53.8, '0600', '60', '20260730165618', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('통영대전선', 35, '03511', NULL, '통영방향', 'S', '오동터널부근(132K)', '(갓길) 시설물 보수 작업중[2026-07-30 08:12- ]', '20260730081231', '작업', '800000', NULL, 132, '0351', '35', '20260730081231', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경부선', 1, '00101', NULL, '부산방향', 'S', '천안분기점부근(332K)-천안호두(휴)(324K)', '8km정체[2026-07-30 10:50- ]', '20260730105038', '차량증가', '400000', NULL, 332, '0010', '1', '20260730105038', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('영동선', 50, '05001', NULL, '인천방향', 'S', '둔대분기점(23K)-반월터널부근(21K)', '2km정체[2026-07-30 16:17- ]', '20260730161727', '차량증가', '250000', NULL, 23, '0500', '50', '20260730161727', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('청주영덕선', 30, '03001', NULL, '영덕방향', 'E', '수한터널부근(28K)-탄부터널부근(31K)', '3km정체[2026-07-30 17:04- ]', '20260730170451', '차량증가', '900000', NULL, 28, '0300', '30', '20260730170451', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('논산천안선', 25, '02521', NULL, '논산방향', 'S', '차령터널 무학천교(266.0K)-차령터널 (263.0K)', '3km 정체[2026-07-30 08:24- ]', '20260730082406', '차량증가', '400000', NULL, 269, '0252', '25', '20260730082406', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경부선', 1, '00101', NULL, '서울방향', 'E', '양재부근(415K)-반포(420K)', '5km정체[2026-07-30 06:27- ]', '20260730062713', '차량증가', '200000', NULL, 415, '0010', '1', '20260730062713', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('제2경인선', 110, '11001', NULL, '성남방향', 'E', '안현분기점(17K)-안현분기점(18K)', '1km정체[2026-07-30 16:24- ]', '20260730162409', '차량증가', '250000', NULL, 17, '1100', '110', '20260730162409', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('영동선', 50, '05001', NULL, '인천방향', 'S', '이천부근(82K)-호법분기점부근(75K)', '7km정체[2026-07-30 16:35- ]', '20260730163548', '차량증가', '200000', NULL, 82, '0500', '50', '20260730163548', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('수도권제1순환선', 100, '10001', NULL, '판교방향', 'E', '자유로(72K)-김포(74K)', '2km정체[2026-07-30 14:59- ]', '20260730145917', '차량증가', '250000', NULL, 72, '1000', '100', '20260730145917', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('순천완주선', 27, '02701', NULL, '완주방향', 'E', '황전(25.4K)', '(갓길) 노면보수 작업중[2026-07-30 16:33- ]', '20260730163357', '작업', '500000', NULL, 25.4, '0270', '27', '20260730163357', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('수도권제1순환선', 100, '10001', NULL, '일산방향', 'S', '안양터널(114K)-수리터널(112K)', '2km정체[2026-07-30 15:33- ]', '20260730153338', '차량증가', '250000', NULL, 114, '1000', '100', '20260730153338', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('수도권제2순환선(화성-광주)', 400, '40041', NULL, '화성방향', 'S', '동탄방향 9.8', 'null[2026-07-23 13:52- ]', '20260723135200', '작업', '200000', NULL, 0, '4004', '400', '20260723135200', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('영동선', 50, '05001', NULL, '인천방향', 'S', '덕평부근(66K)-양지터널부근(58K)', '8km정체[2026-07-30 15:34- ]', '20260730153400', '차량증가', '200000', NULL, 66, '0500', '50', '20260730153400', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('호남선', 25, '02511', NULL, '천안방향', 'E', '동광주(74K)', '1km정체[2026-07-30 16:06- ]', '20260730160618', '차량증가', '500000', NULL, 74, '0251', '25', '20260730160618', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('영동선', 50, '05001', NULL, '인천방향', 'S', '서용인분기점(50K)', '1km정체[2026-07-30 16:17- ]', '20260730161757', '차량증가', '250000', NULL, 50, '0500', '50', '20260730161757', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('영동선', 50, '05001', NULL, '강릉방향', 'E', '둔대분기점(22K)-부곡(27K)', '5km정체[2026-07-30 16:19- ]', '20260730161916', '차량증가', '250000', NULL, 22, '0500', '50', '20260730161916', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('동해선(부산-포항)', 65, '06521', NULL, '포항방향', 'E', '남경주(69.5K)-문무대왕1터널(74.1K)', '** (포항방향 1,2차로교대) 장기차단 보강공사 7.20(월) ~ 9.18(금) **', '20260714121717', '홍보', '700000', NULL, 69.5, '0652', '65', '20260714121717', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('제2경인선', 110, '11001', NULL, '인천방향', 'S', '삼막(25.98K)-광명터널(22K)', '4km정체[2026-07-30 14:37- ]', '20260730143718', '차량증가', '250000', NULL, 25.98, '1100', '110', '20260730143718', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('중부내륙선', 45, '04501', NULL, '양평방향', 'E', '여주분기점부근(261K)', '(갓길)승용차고장 처리중[2026-07-30 17:01- ]', '20260730170123', '고장', '900000', NULL, 261, '0450', '45', '20260730170123', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('남해선(순천-부산)', 10, '01001', NULL, '부산방향', 'E', '칠원분기점부근(117K)-함안2터널부근(120K)', '3km정체[2026-07-30 10:32- ]', '20260730103250', '차량증가', '700000', NULL, 117, '0100', '10', '20260730103250', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('부산외곽선', 600, '60001', NULL, '창원방향', 'S', '기장분기점(48K)-기장분기점부근(47K)', '1km정체[2026-07-30 15:29- ]', '20260730152946', '차량증가', '700000', NULL, 48, '6000', '600', '20260730152946', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('호남지선', 251, '25101', NULL, '논산방향', 'S', '회덕분기점(54K)-북대전부근(52K)', '2km정체[2026-07-30 15:45- ]', '20260730154509', '차량증가', '400000', NULL, 54, '2510', '251', '20260730154509', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('영동선', 50, '05001', NULL, '인천방향', 'S', '서창분기점(1K)-서창(0K)', '1km정체[2026-07-30 16:10- ]', '20260730161003', '차량증가', '250000', NULL, 1, '0500', '50', '20260730161003', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('수도권제1순환선', 100, '10001', NULL, '판교방향', 'E', '자유로(72K)', '(3,4차로) 사고 처리중[2026-07-30 16:47- ] ==> 일산IC~자유로IC, 2km정체', '20260730164727', '사고', '250000', NULL, 72, '1000', '100', '20260730164727', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('서울양양선', 60, '06001', NULL, '서울방향', 'S', '남춘천부근(53.6K)', '(갓길) 승용차 고장 처리중[2026-07-30 16:43- ]', '20260730164308', '고장', '300000', NULL, 53.6, '0600', '60', '20260730164308', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경부선', 1, '00101', NULL, '서울방향', 'E', '안성분기점(364K)-안성(휴)부근(368K)', '4km정체[2026-07-30 14:37- ]', '20260730143713', '차량증가', '200000', NULL, 364, '0010', '1', '20260730143713', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('동해선(포항-영덕)', 65, '06531', NULL, '영덕방향', 'E', NULL, '** (영덕방향) 30k 영덕분기점 차로 증설 공사중 - 차로 좁아짐 주의(~12월) **', '20260721112431', '홍보', '600000', NULL, 0, '0653', '65', '20260721112431', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('서해안선', 15, '01501', NULL, '서울방향', 'E', '광명역(334K)-금천(340K)', '6km정체[2026-07-30 06:54- ]', '20260730065451', '차량증가', '250000', NULL, 334, '0150', '15', '20260730065451', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('통영대전선', 35, '03511', NULL, '통영방향', 'S', '마달터널부근(202.5K)', '(2차로,갓길)승용차 고장 처리중[2026-07-30 16:46- ]', '20260730164648', '고장', '800000', NULL, 202.5, '0351', '35', '20260730164648', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('통영대전선', 35, '03511', NULL, '대전방향', 'E', '진주졸음쉼터(57.3K)', '** (대전방향) 화장실 이용불가 **', '20260725060945', '홍보', '700000', NULL, 57.3, '0351', '35', '20260725060945', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경부선', 1, '00101', NULL, '부산방향', 'S', '신갈분기점부근(397K)-신갈분기점(394K)', '3km정체[2026-07-30 16:48- ]', '20260730164817', '차량증가', '200000', NULL, 397, '0010', '1', '20260730164817', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('영동선', 50, '05001', NULL, '강릉방향', 'E', '서창분기점(0.5K)', '(인천 진출로)사고 처리중[2026-07-30 16:44- ]', '20260730164416', '사고', '250000', NULL, .5, '0500', '50', '20260730164416', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('평택제천선', 40, '04001', NULL, '제천방향', 'E', '안성분기점(23K)-안성분기점(24K)', '1km정체[2026-07-30 16:51- ]', '20260730165135', '차량증가', '250000', NULL, 23, '0400', '40', '20260730165135', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('광주대구선', 12, '01201', NULL, '대구방향', 'E', NULL, '** (광주방향)112k 남상졸음쉼터 폐쇄(~12월) **', '20260422234627', '홍보', '600000', NULL, 0, '0120', '12', '20260422234627', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('수도권제2순환선(화성-광주)', 400, '40041', NULL, '화성방향', 'S', '동탄방향 26.0', 'K (2차로) 비탈면보수 작업중[2026-05-21 14:38- ]', '20260521143800', '작업', '200000', NULL, 0, '4004', '400', '20260521143800', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('동해선(삼척-속초)', 65, '06501', NULL, '속초방향', 'E', NULL, '** (속초방향) 동해 졸음쉼터 신설공사 [ ~ 8.13] **', '20260416171758', '홍보', '300000', NULL, 0, '0650', '65', '20260416171758', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('서천공주선', 151, '15101', NULL, '공주방향', 'E', NULL, '** 동서천분기점 공주방향 연결로 갓길 장기차단 26.5월~26.10월 **', '20260519074906', '홍보', '400000', NULL, 0, '1510', '151', '20260519074906', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('서해안선', 15, '01501', NULL, '서울방향', 'E', NULL, '** 서산(목포)주유소 영업중단(5.6~10.6)/휴게소 및 LPG충전소는 정상영업/행담도주유소 이용바람 **', '20260429135010', '홍보', '400000', NULL, 0, '0150', '15', '20260429135010', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경부선', 1, '00101', NULL, '서울방향', 'E', NULL, '** (부산)남사졸음쉼터 임시폐쇄(26.06.15~26.10.31),안성휴게소 이용바람 **', '20260605215733', '홍보', '200000', NULL, 0, '0010', '1', '20260605215733', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('남해선(순천-부산)', 10, '01001', NULL, '부산방향', 'E', '대저분기점(163K)-덕천(166K)', '3km정체[2026-07-30 13:45- ]', '20260730134538', '차량증가', '700000', NULL, 163, '0100', '10', '20260730134538', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('부산울산선', 65, '06511', NULL, '부산방향', 'S', '해운대터널부근(3K)-부산울산선시점(0K)', '3km정체[2026-07-30 14:43- ]', '20260730144311', '차량증가', '700000', NULL, 3, '0651', '65', '20260730144311', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경부선', 1, '00101', NULL, '부산방향', 'S', '청주분기점(297K)', '(갓길) 승용 고장차 처리중[2026-07-30 15:25- ]', '20260730152539', '고장', '400000', NULL, 297, '0010', '1', '20260730152539', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('남해2지선', 104, '10401', NULL, '서부산방향', 'E', '서부산(휴)(18K)-사상(20K)', '2km정체[2026-07-30 15:25- ]', '20260730152500', '차량증가', '700000', NULL, 18, '1040', '104', '20260730152500', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('동해선(삼척-속초)', 65, '06501', NULL, '속초방향', 'E', '쇄운교(15K)-지흥1교(16.7K)', '(2차로)졸음쉼터 설치 작업중[2026-07-03 07:42- ]', '20260703074200', '작업', '300000', NULL, 15, '0650', '65', '20260703074200', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('수도권제1순환선', 100, '10001', NULL, '일산방향', 'S', '시흥요금소(96K)-중동(86K)', '10km정체[2026-07-30 07:24- ]', '20260730072448', '차량증가', '250000', NULL, 96, '1000', '100', '20260730072448', NULL);
COMMIT;
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('논산천안선', 25, '02521', NULL, '천안방향', 'E', '남공주IC 오룡교(232.0K)-남공주IC 검상천교(235.0K)', '3km 정체[2026-07-30 15:27- ]', '20260730152731', '차량증가', '400000', NULL, 225, '0252', '25', '20260730152731', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('인천공항선', 130, '13001', NULL, '공항방향', 'S', '[본선-공항] 20.8Km', '청라IC 진출 1km 정체[2026-07-30 15:30- ]', '20260730153000', '차량증가', '200000', NULL, 20.8, '1300', '130', '20260730153000', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('수도권제1순환선', 100, '10001', NULL, '판교방향', 'E', '조남분기점(107K)-수암터널(108K)', '1km정체[2026-07-30 16:06- ]', '20260730160627', '차량증가', '250000', NULL, 107, '1000', '100', '20260730160627', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('서울양양선', 60, '06001', NULL, '서울방향', 'S', '화도(15K)-화도부근(13K)', '2km정체[2026-07-30 15:57- ]', '20260730155707', '차량증가', '300000', NULL, 15, '0600', '60', '20260730155707', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경부선', 1, '00101', NULL, '서울방향', 'E', '영천분기점(91.5K)', '(3차로,갓길)화물차관련 사고 처리중[2026-07-30 14:47- ]', '20260730144715', '사고', '600000', NULL, 91.5, '0010', '1', '20260730144715', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('서해안선', 15, '01501', NULL, '서울방향', 'E', '서천(휴)부근(166.5K)', '(갓길)중형화물차 고장 처리중[2026-07-30 16:13- ]', '20260730161342', '고장', '800000', NULL, 166.5, '0150', '15', '20260730161342', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('서해안선', 15, '01501', NULL, '서울방향', 'E', NULL, '** 서해대교(양방향) 정밀안전진단 3차로 주간 차단예정(6~10월) **', '20260605085938', '홍보', '400000', NULL, 0, '0150', '15', '20260605085938', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('논산천안선', 25, '02521', NULL, '천안방향', 'E', '남공주IC 오룡교(232.1K)', '1차로 승용차 관련 사고발생[2026-07-30 16:20- ]', '20260730162057', '사고', '400000', NULL, 225, '0252', '25', '20260730162057', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('호남지선', 251, '25101', NULL, '대전방향', 'E', '북대전부근(52K)-회덕분기점(54K)', '2km정체[2026-07-30 17:02- ]', '20260730170212', '차량증가', '400000', NULL, 52, '2510', '251', '20260730170212', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('인천대교선', 110, '11021', NULL, '송도방향', 'E', NULL, '** (민자 고속도로구간) 인천대교선 상황실 전화번호 032-745-8100 문의 바랍니다 **', '20250910001933', '홍보', '250000', NULL, 0, '1102', '110', '20250910001933', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경인선', 120, '12001', NULL, '서울방향', 'E', NULL, '** 경인1지하차도 홍익병원사거리 1차로 통제 2025.7.9 (수)~공사완료시까지 **', '20250910001852', '홍보', '250000', NULL, 0, '1200', '120', '20250910001852', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('수도권제2순환선(인천-김포)', 400, '40011', NULL, '김포방향', 'E', NULL, '** (민자 고속도로구간) 인천김포선 상황실 전화번호 032-292-7164 문의 바랍니다 **', '20251119153617', '홍보', '250000', NULL, 0, '4001', '400', '20251119153617', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('제3경인선', 330, '33001', NULL, '시흥방향', 'E', NULL, '** (민자 고속도로구간) 제3경인고속도로 상황실 031-8084-8901 문의바랍니다 **', '20240725161924', '홍보', '200000', NULL, 0, '3300', '330', '20240725161924', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경부선', 1, '00101', NULL, '서울방향', 'E', NULL, '** 천안IC-천안분기점(부산) 방음시설 작업/4차로 21시~06시, 5차로 06시~21시 차단 25.9월~26.12월 **', '20250919075529', '홍보', '400000', NULL, 0, '0010', '1', '20250919075529', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경인선', 120, '12001', NULL, '서울방향', 'E', NULL, '** 인천대로 일반화 공사중(2단계)[주안산단고가교~서인천IC]2025.11.17~2031.03 **', '20251016103404', '홍보', '250000', NULL, 0, '1200', '120', '20251016103404', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('영동선', 50, '05001', NULL, '강릉방향', 'E', NULL, '** (강릉방향) 생태습지 졸음쉼터 화장실 폐쇄 **', '20251117153247', '홍보', '300000', NULL, 0, '0500', '50', '20251117153247', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('수도권제1순환선', 100, '10001', NULL, '일산방향', 'S', '판교분기점(128K)-판교분기점부근(126K)', '2km정체[2026-07-30 16:21- ]', '20260730162134', '차량증가', '200000', NULL, 128, '1000', '100', '20260730162134', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경부선', 1, '00101', NULL, '서울방향', 'E', '기흥(388K)-신갈분기점(394K)', '6km정체[2026-07-30 16:47- ]', '20260730164739', '차량증가', '200000', NULL, 388, '0010', '1', '20260730164739', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('수도권제1순환선', 100, '10001', NULL, '일산방향', 'S', '성남부근(3K)-판교분기점(0K)', '3km정체[2026-07-30 16:21- ]', '20260730162117', '차량증가', '200000', NULL, 3, '1000', '100', '20260730162117', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('중부내륙선', 45, '04501', NULL, '양평방향', 'E', '현풍졸음쉼터(51.4K)', '** (창원방향) 시설물 작업 중 쉼터이용불가 **', '20260710150735', '홍보', '700000', NULL, 51.4, '0450', '45', '20260710150735', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('수도권제1순환선', 100, '10001', NULL, '일산방향', 'S', '서하남분기점(16K)-송파부근(7K)', '9km정체[2026-07-30 16:22- ]', '20260730162214', '차량증가', '200000', NULL, 16, '1000', '100', '20260730162214', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('서해안선', 15, '01501', NULL, '서울방향', 'E', NULL, '** 서산(서울)주유소 영업중단(5.6~10.6)/휴게소 및 LPG충전소는 정상영업/홍성주유소 이용바람 **', '20260429075501', '홍보', '400000', NULL, 0, '0150', '15', '20260429075501', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('새만금전주선', 20, '02021', NULL, '새만금방향', 'E', '석구터널(46.1K)', '(갓길)소형화물차 고장 처리중[2026-07-30 14:14- ]', '20260730141437', '고장', '800000', NULL, 46.1, '0202', '20', '20260730141437', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('영동선', 50, '05001', NULL, '인천방향', 'S', '동수원(37K)-북수원(30K)', '7km정체[2026-07-30 14:26- ]', '20260730142623', '차량증가', '250000', NULL, 37, '0500', '50', '20260730142623', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경인선', 120, '12001', NULL, '인천방향', 'S', '인천요금소(16K)-서인천(11K)', '5km정체[2026-07-30 15:09- ]', '20260730150911', '차량증가', '250000', NULL, 16, '1200', '120', '20260730150911', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('제2경인선', 110, '11001', NULL, '인천방향', 'S', '서창분기점(9K)-남동부근(6K)', '3km정체[2026-07-30 06:54- ]', '20260730065400', '차량증가', '250000', NULL, 9, '1100', '110', '20260730065400', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('제2경인선', 110, '11001', NULL, '인천방향', 'S', '안현분기점(18K)-신천(14K)', '4km정체[2026-07-30 17:01- ]', '20260730170117', '차량증가', '250000', NULL, 18, '1100', '110', '20260730170117', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('서해안선', 15, '01501', NULL, '서울방향', 'E', NULL, '** 대천휴게소(양방향) 주유소 개선공사 이용불가 6. 1(월)~11.27(금) **', '20260531090003', '홍보', '800000', NULL, 0, '0150', '15', '20260531090003', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('영동선', 50, '05001', NULL, '강릉방향', 'E', NULL, '** 서안산~북수원 확장공사 제한속도변경 100- 80km/h (8.30~26.12.31 ) **', '20250828051816', '홍보', '250000', NULL, 0, '0500', '50', '20250828051816', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('평택시흥선', 15, '01531', NULL, '시흥방향', 'E', NULL, '** (민자 고속도로구간) 평택시흥선 상황실 전화번호 1661-5688 문의 바랍니다 **', '20250912112159', '홍보', '250000', NULL, 0, '0153', '153', '20250912112159', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('영동선', 50, '05001', NULL, '강릉방향', 'E', NULL, '** 영동선 이목졸음쉼터(강릉) 임시폐쇄 ''24.07.15. ~ ''26.08.29. **', '20251013121202', '홍보', '250000', NULL, 0, '0500', '50', '20251013121202', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('영동선', 50, '05001', NULL, '강릉방향', 'E', NULL, '** 영동선 이천졸음쉼터(인천방향) 폐쇄 (2025.8월~2027.5월 31. (23개월간) **', '20250814135609', '홍보', '200000', NULL, 0, '0500', '50', '20250814135609', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('인천공항선', 130, '13001', NULL, '서울방향', 'E', NULL, '** (민자 고속도로구간) 인천공항선 상황실 전화번호 032-560-6100 문의 바랍니다 **', '20250623050208', '홍보', '200000', NULL, 0, '1300', '130', '20250623050208', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('대전남부선', 300, '30001', NULL, '산내방향', 'E', NULL, '** 서대전부근(양방향) 방음벽 설치작업 26.7.10(금)~27.7.10(토) **', '20250910112809', '홍보', '400000', NULL, 0, '3000', '300', '20250910112809', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('수도권제1순환선', 100, '10001', NULL, '판교방향', 'E', '노오지분기점(79K)-송내(88K)', '9km정체[2026-07-30 05:11- ]', '20260730051106', '차량증가', '250000', NULL, 79, '1000', '100', '20260730051106', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('중부선', 35, '03521', NULL, '하남방향', 'E', '일죽부근(304K)-일죽부근(309K)', '5km정체[2026-07-30 16:09- ]', '20260730160933', '차량증가', '900000', NULL, 304, '0352', '35', '20260730160933', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('익산장수선', 20, '02011', NULL, '익산방향', 'S', '소양(16K)-소양부근(15K)', '(갓길) 덩쿨제거 작업중[2026-07-30 08:41- ]', '20260730084122', '작업', '800000', NULL, 16, '0201', '20', '20260730084122', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('남해선(순천-부산)', 10, '01001', NULL, '부산방향', 'E', NULL, '** 섬진강휴게소(순천방향)주유소 영업중단, 개선공사 2026. 7.02~공사완료시까지 **', '20260624020608', '홍보', '500000', NULL, 0, '0100', '10', '20260624020608', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('영동선', 50, '05001', NULL, '인천방향', 'S', '월곶분기점부근(6.3K)', '(2차로)고장차 처리중[2026-07-30 16:46- ]', '20260730164625', '고장', '250000', NULL, 6.3, '0500', '50', '20260730164625', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('중앙선', 55, '05502', NULL, '부산방향', 'S', '초정(5K)-삼락(0K)', '5km정체[2026-07-30 16:19- ]', '20260730161902', '차량증가', '700000', NULL, 5, '0550', '55', '20260730161902', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('중부선', 35, '03521', NULL, '하남방향', 'E', NULL, '** 번천(통영)졸음쉼터 화장실 개선 공사로 인한 임시폐쇄 (2026.07.22(수)~2026.12.08(화)) **', '20260710122323', '홍보', '200000', NULL, 0, '0352', '35', '20260710122323', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('중부선', 35, '03521', NULL, '남이방향', 'S', '진천터널부근(277K)-진천터널부근(274K)', '3km정체[2026-07-30 14:10- ]', '20260730141034', '차량증가', '900000', NULL, 277, '0352', '35', '20260730141034', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('중부내륙선', 45, '04501', NULL, '창원방향', 'S', '감곡부근(258K)-감곡부근(255K)', '3km정체[2026-07-30 09:46- ]', '20260730094639', '차량증가', '900000', NULL, 258, '0450', '45', '20260730094639', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('서해안선', 15, '01501', NULL, '서울방향', 'E', '서평택분기점부근(295K)-화성(휴)부근(303K)', '8km정체[2026-07-30 14:09- ]', '20260730140943', '차량증가', '250000', NULL, 295, '0150', '15', '20260730140943', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경부선', 1, '00101', NULL, '서울방향', 'E', NULL, '** 판교분기점-금토분기점(양방향) 갓길 개량공사중(2026.05.26~2027.11.30) **', '20260526065333', '홍보', '200000', NULL, 0, '0010', '1', '20260526065333', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('중부내륙선', 45, '04501', NULL, '양평방향', 'E', NULL, '** (양평방향) 96.5km 성주휴게소 수소충전소 이용불가 **', '20260725224834', '홍보', '600000', NULL, 0, '0450', '45', '20260725224834', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('통영대전선', 35, '03511', NULL, '대전방향', 'E', NULL, '** 통영대전선 111.9k~115.4k(양방향)갓길 장기차단(5.28(목)~9.30(수)) **', '20260521081134', '홍보', '700000', NULL, 0, '0351', '35', '20260521081134', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('중부내륙선', 45, '04501', NULL, '양평방향', 'E', '충주분기점부근(238K)-충주분기점부근(241K)', '3km정체[2026-07-30 13:27- ]', '20260730132759', '차량증가', '900000', NULL, 238, '0450', '45', '20260730132759', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('논산천안선', 25, '02521', NULL, '논산방향', 'S', '남풍세IC 호정 1교(268.0K)-차령터널 (263.0K)', '5km 정체[2026-07-28 14:03- ]', '20260728140304', '차량증가', '400000', NULL, 269, '0252', '25', '20260728140304', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('서해안선', 15, '01501', NULL, '서울방향', 'E', NULL, '** (갓길)동서천JCT(서울) 정체개선공사(2026. 5. 19 ~ 2026. 10. 30) **', '20260519113903', '홍보', '800000', NULL, 0, '0150', '15', '20260519113903', NULL);
COMMIT;
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('중부내륙선', 45, '04501', NULL, '양평방향', 'E', '영산(24K)', '(진입로 갓길) 화물차 고장 처리 중[2026-07-30 16:58- ]', '20260730165823', '고장', '700000', NULL, 24, '0450', '45', '20260730165823', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('서해안선', 15, '01501', NULL, '서울방향', 'E', NULL, '** 기상악화시 "당진IC~서평택IC" 제한속도 하향 단속(구간, 암행순찰) 시행 **', '20260128113835', '홍보', '400000', NULL, 0, '0150', '15', '20260128113835', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('서해안선', 15, '01501', NULL, '서울방향', 'E', '당진부근(267.3K)', '(갓길) 화물 고장차 처리중[2026-07-30 16:18- ]', '20260730161803', '고장', '400000', NULL, 267.3, '0150', '15', '20260730161803', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('수도권제1순환선', 100, '10001', NULL, '판교방향', 'E', '강일(24K)-구리남양주요금소(27K)', '3km정체[2026-07-30 16:23- ]', '20260730162344', '차량증가', '200000', NULL, 24, '1000', '100', '20260730162344', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('평택제천선', 40, '04001', NULL, '평택방향', 'S', '대소분기점(57K)-안진터널(52K)', '5km정체[2026-07-30 15:55- ]', '20260730155518', '차량증가', '900000', NULL, 57, '0400', '40', '20260730155518', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('평택제천선', 40, '04001', NULL, '평택방향', 'S', '서안성(25K)-안성분기점(24K)', '1km정체[2026-07-30 15:06- ]', '20260730150604', '차량증가', '250000', NULL, 25, '0400', '40', '20260730150604', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경부선', 1, '00101', NULL, '서울방향', 'E', '판교분기점(408K)', '1km정체[2026-07-30 16:00- ]', '20260730160049', '차량증가', '200000', NULL, 408, '0010', '1', '20260730160049', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('동해선(부산-포항)', 65, '06521', NULL, '포항방향', 'E', '남경주부근(68K)-문무대왕1터널(74K)', '(2차로)노면보강 공사 작업중, 장기차단[2026-07-20 08:25- ]', '20260720082502', '작업', '700000', NULL, 68, '0652', '65', '20260720082502', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('서울양양선', 60, '06001', NULL, '서울방향', 'S', '덕소삼패(3K)-강일(0K)', '3km정체[2026-07-30 16:23- ]', '20260730162324', '차량증가', '300000', NULL, 3, '0600', '60', '20260730162324', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('중부내륙선', 45, '04501', NULL, '양평방향', 'E', '감곡(251K)-감곡부근(255K)', '4km정체[2026-07-30 16:23- ]', '20260730162343', '차량증가', '900000', NULL, 251, '0450', '45', '20260730162343', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경부선', 1, '00101', NULL, '부산방향', 'S', '회덕분기점(277K)-회덕분기점부근(276K)', '1km정체[2026-07-30 16:33- ]', '20260730163326', '차량증가', '400000', NULL, 277, '0010', '1', '20260730163326', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('호남선', 25, '02511', NULL, '천안방향', 'E', NULL, '** 백양사휴게소(천안)수소충전소 운영중단(2026.7.27~수리완료시까지) **', '20260727035539', '홍보', '500000', NULL, 0, '0251', '25', '20260727035539', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경부선', 1, '00101', NULL, '서울방향', 'E', NULL, '** 평일 버스전용차로제 시행 중 (양방향) 한남-안성 (07시-21시) **', '20260704055541', '홍보', '200000', NULL, 0, '0010', '1', '20260704055541', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('남해선(순천-부산)', 10, '01001', NULL, '부산방향', 'E', '김해졸음쉼터(153K)', '** (양방향) 화장실 이용불가 **', '20260616194929', '홍보', '700000', NULL, 153, '0100', '10', '20260616194929', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경부선', 1, '00101', NULL, '서울방향', 'E', '입장거봉포도(휴)부근(355K)-안성(360K)', '5km정체[2026-07-30 15:20- ]', '20260730152029', '차량증가', '400000', NULL, 355, '0010', '1', '20260730152029', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('중부내륙선', 45, '04501', NULL, '양평방향', 'E', '감곡부근(252.1K)', '(갓길)승합차고장 처리중[2026-07-30 16:11- ]', '20260730161104', '고장', '900000', NULL, 252.1, '0450', '45', '20260730161104', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('순천완주선', 27, '02701', NULL, '완주방향', 'E', '서면2터널부근(10.7K)', '(갓길) 화물차 고장 처리중[2026-07-30 16:17- ]', '20260730161748', '고장', '500000', NULL, 10.7, '0270', '27', '20260730161748', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('서해안선', 15, '01501', NULL, '서울방향', 'E', NULL, '** 화성휴게소(목포) 수소충전소 이용 불가 2026.7.29(수)~2026.7.31(금) **', '20260729140605', '홍보', '250000', NULL, 0, '0150', '15', '20260729140605', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('통영대전선', 35, '03511', NULL, '통영방향', 'S', '동고성(14.3K)', '(갓길)화물차 고장 처리중[2026-07-30 16:51- ]', '20260730165102', '고장', '700000', NULL, 14.3, '0351', '35', '20260730165102', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('경부선', 1, '00101', NULL, '서울방향', 'E', '안성(휴)(370K)', '(갓길)보행자 조치중[2026-07-30 16:56- ]', '20260730165638', '기타', '200000', NULL, 370, '0010', '1', '20260730165638', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('영동선', 50, '05001', NULL, '인천방향', 'S', '군자분기점(7K)-월곶분기점부근(4K)', '3km정체[2026-07-30 13:59- ]', '20260730135951', '차량증가', '250000', NULL, 7, '0500', '50', '20260730135951', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('제2경인선', 110, '11001', NULL, '성남방향', 'E', '학익분기점(3K)-남동(8K)', '5km정체[2026-07-30 13:54- ]', '20260730135457', '차량증가', '250000', NULL, 3, '1100', '110', '20260730135457', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('서해안선', 15, '01501', NULL, '서울방향', 'E', '매송(휴)부근(315K)-용담터널(319K)', '4km정체[2026-07-30 14:10- ]', '20260730141000', '차량증가', '250000', NULL, 315, '0150', '15', '20260730141000', NULL);
INSERT INTO OPR_MAIN.T_INCIDENT_FTMS (ROUTE, ROAD_NO, ROUTE_ID, WEATHER, UPDWNAME, UPDOWN, MILEPOST, CONTENTS, RAISE_TIME, INCIDENT_TYPE, REGION_ID, REGION_NAME, START_MILEPOST, INITIALCHAR, SEQ_NO, INCIDENT_ID, CONGZONE_ID) VALUES ('중부선', 35, '03521', NULL, '하남방향', 'E', '경기광주IC(352K)-중부1터널부근(355K)', '3km정체[2026-07-30 16:42- ]', '20260730164203', '차량증가', '200000', NULL, 352, '0352', '35', '20260730164203', NULL);
COMMIT;
+196
View File
@@ -0,0 +1,196 @@
-- 노선별 교통정보 개발서버용 스키마
--
-- 운영 뷰는 개발 Oracle에 없는 다수의 원천 테이블을 참조하므로,
-- 제공받은 뷰 결과 CSV를 물리 테이블에 적재하고 동일한 이름의 뷰로 노출한다.
SET DEFINE OFF
SET SERVEROUTPUT ON
BEGIN
EXECUTE IMMEDIATE 'CREATE USER TROAD_APP NO AUTHENTICATION';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -1920 THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE 'CREATE USER TLISDEV NO AUTHENTICATION';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -1920 THEN RAISE; END IF;
END;
/
GRANT CREATE SESSION, CREATE TABLE, CREATE VIEW, UNLIMITED TABLESPACE TO TROAD_APP;
GRANT CREATE SESSION, CREATE TABLE, CREATE VIEW, UNLIMITED TABLESPACE TO TLISDEV;
BEGIN
EXECUTE IMMEDIATE q'[
CREATE TABLE TLISDEV.T_TRMB_CD_INFO01M1 (
HGRN_CD_ID VARCHAR2(50) NOT NULL,
CMMN_CD VARCHAR2(20) NOT NULL,
USE_XN VARCHAR2(1),
CMMN_CD_NM VARCHAR2(200),
DETL_CTNT VARCHAR2(1000),
FSTTM_RGSR_ID VARCHAR2(30),
FSTTM_RGST_DTTM DATE,
LSTTM_MODFR_ID VARCHAR2(30),
LSTTM_ALTR_DTTM DATE
)
]';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -955 THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE
'CREATE INDEX TLISDEV.IX_TRMB_CD_INFO_HGRN_CMMN ' ||
'ON TLISDEV.T_TRMB_CD_INFO01M1 (HGRN_CD_ID, CMMN_CD)';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE NOT IN (-955, -1408) THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE q'[
CREATE TABLE TROAD_APP.T_ROUTE_NEW_NM (
ROUTECD VARCHAR2(4),
GRPID VARCHAR2(2),
ROUTESHORTNO NUMBER,
ROUTENM VARCHAR2(100),
ROUTESORT NUMBER,
UPDOWNDIR VARCHAR2(1),
ROUTEDIRNM VARCHAR2(100),
ROUTELAYOVERNM VARCHAR2(200),
OPER VARCHAR2(30),
HOINSTNM VARCHAR2(100),
RPRSTELNO VARCHAR2(30),
CLSSCD VARCHAR2(10)
)
]';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -955 THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE
'CREATE INDEX TROAD_APP.IX_ROUTE_NEW_NM_NAME ' ||
'ON TROAD_APP.T_ROUTE_NEW_NM (ROUTENM)';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE NOT IN (-955, -1408) THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE
'CREATE INDEX TROAD_APP.IX_ROUTE_NEW_NM_KEY ' ||
'ON TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, UPDOWNDIR)';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE NOT IN (-955, -1408) THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE q'[
CREATE TABLE TROAD_APP.T_ROUTE_TRFC_VER001 (
NODE_NM VARCHAR2(100),
CONZONE_ID VARCHAR2(30),
ROUTE_NO_LIST VARCHAR2(100),
LINK_LEN_KM NUMBER,
BUS_YN VARCHAR2(1),
ROUTESORT NUMBER,
SPEED NUMBER,
SPEED_BUS NUMBER,
TRAFFIC_GRADE VARCHAR2(1),
TRAFFIC_GRADE_BUS VARCHAR2(1),
CCTV_ID VARCHAR2(30),
CCTV_AREA VARCHAR2(200),
HLS_URL VARCHAR2(500),
FILEURL_IMG VARCHAR2(500),
INCIDENT_TYPE_CD VARCHAR2(10),
INCIDENT_DESC VARCHAR2(200),
MSG VARCHAR2(2000),
INCIDENT_POS_NAME VARCHAR2(500),
DETR_ID VARCHAR2(30),
SPEED_DETR NUMBER,
TRAFFIC_GRADE_DETR VARCHAR2(1),
RESTAREA_ID VARCHAR2(30),
RESTAREA_NM VARCHAR2(200),
CONZONE_X NUMBER,
CONZONE_Y NUMBER,
DRIVE_DRCT_CD VARCHAR2(1),
SECT_SQNO NUMBER,
ROUTE_CD VARCHAR2(4),
GRP_ID VARCHAR2(2),
WORK_CD VARCHAR2(10),
VVALUE01 VARCHAR2(2000),
VVALUE02 VARCHAR2(2000),
VVALUE03 VARCHAR2(2000),
VVALUE04 VARCHAR2(2000),
VVALUE05 VARCHAR2(2000),
VVALUE06 VARCHAR2(2000),
VVALUE07 VARCHAR2(2000),
VVALUE08 VARCHAR2(2000),
VVALUE09 VARCHAR2(2000)
)
]';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -955 THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE
'CREATE INDEX TROAD_APP.IX_ROUTE_TRFC_ROUTE ' ||
'ON TROAD_APP.T_ROUTE_TRFC_VER001 ' ||
'(ROUTE_CD, GRP_ID, DRIVE_DRCT_CD, SECT_SQNO)';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE NOT IN (-955, -1408) THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE
'CREATE INDEX TROAD_APP.IX_ROUTE_TRFC_CONZONE ' ||
'ON TROAD_APP.T_ROUTE_TRFC_VER001 (CONZONE_ID, DRIVE_DRCT_CD)';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE NOT IN (-955, -1408) THEN RAISE; END IF;
END;
/
CREATE OR REPLACE VIEW TROAD_APP.V_ROUTE_NEW_NM AS
SELECT ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR,
ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD
FROM TROAD_APP.T_ROUTE_NEW_NM;
CREATE OR REPLACE VIEW TROAD_APP.V_ROUTE_TRFC_VER001 AS
SELECT NODE_NM, CONZONE_ID, ROUTE_NO_LIST, LINK_LEN_KM, BUS_YN, ROUTESORT,
SPEED, SPEED_BUS, TRAFFIC_GRADE, TRAFFIC_GRADE_BUS, CCTV_ID, CCTV_AREA,
HLS_URL, FILEURL_IMG, INCIDENT_TYPE_CD, INCIDENT_DESC, MSG,
INCIDENT_POS_NAME, DETR_ID, SPEED_DETR, TRAFFIC_GRADE_DETR,
RESTAREA_ID, RESTAREA_NM, CONZONE_X, CONZONE_Y, DRIVE_DRCT_CD,
SECT_SQNO, ROUTE_CD, GRP_ID, WORK_CD, VVALUE01, VVALUE02, VVALUE03,
VVALUE04, VVALUE05, VVALUE06, VVALUE07, VVALUE08, VVALUE09
FROM TROAD_APP.T_ROUTE_TRFC_VER001;
GRANT SELECT ON TLISDEV.T_TRMB_CD_INFO01M1 TO OPR_MAIN;
GRANT SELECT ON TROAD_APP.V_ROUTE_NEW_NM TO OPR_MAIN;
GRANT SELECT ON TROAD_APP.V_ROUTE_TRFC_VER001 TO OPR_MAIN;
CREATE OR REPLACE VIEW OPR_MAIN.V_ROUTE_NEW_NM AS
SELECT * FROM TROAD_APP.V_ROUTE_NEW_NM;
CREATE OR REPLACE VIEW OPR_MAIN.V_ROUTE_TRFC_VER001 AS
SELECT * FROM TROAD_APP.V_ROUTE_TRFC_VER001;
File diff suppressed because it is too large Load Diff
+151
View File
@@ -0,0 +1,151 @@
-- 자동 생성: V_ROUTE_NEW_NM_202607310912.csv -> TROAD_APP.T_ROUTE_NEW_NM
-- 행 수: 138
-- 생성 도구: server-dev/oracle/tools/csv_to_insert.py
SET DEFINE OFF
SET SQLBLANKLINES ON
DELETE FROM TROAD_APP.T_ROUTE_NEW_NM;
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0170', '1', 17, '평택화성선', 6, 'S', '오성', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0200', '1', 20, '대구포항선', 6, 'S', '대구', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0201', '1', 20, '익산장수선', 6, 'S', '익산', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0251', '1', 25, '호남선', 6, 'S', '순천', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0270', '1', 27, '순천완주선', 6, 'S', '순천', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0290', '1', 29, '세종포천선(안성-포천)', 6, 'S', '안성', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0300', '1', 30, '청주영덕선', 6, 'S', '청주', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0301', '1', 30, '당진대전선', 6, 'S', '당진', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0351', '1', 35, '통영대전선', 6, 'S', '통영', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0352', '1', 35, '중부선', 3, 'S', '남이', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0370', '1', 37, '제2중부선', 6, 'S', '이천', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0400', '1', 40, '평택제천선', 6, 'S', '평택', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0450', '1', 45, '중부내륙선', 6, 'S', '창원', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0500', '1', 50, '영동선', 4, 'S', '인천', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0520', '1', 52, '광주원주선', 6, 'S', '광주', NULL, '공영', '제이영동고속도로㈜', '1877-0200', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0550', '2', 55, '중앙선', 6, 'S', '부산', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0552', '1', 55, '대구부산선', 6, 'S', '부산', NULL, '공영', '신대구부산고속도로㈜', '1688-7003', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0600', '1', 60, '서울양양선', 6, 'S', '서울', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0650', '1', 65, '동해선(삼척-속초)', 6, 'S', '삼척', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0651', '1', 65, '부산울산선', 6, 'S', '부산', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0652', '1', 65, '동해선(부산-포항)', 6, 'S', '부산', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1000', '1', 100, '수도권제1순환선', 5, 'S', '일산', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1020', '1', 102, '남해1지선', 6, 'S', '함안', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1040', '1', 104, '남해2지선', 6, 'S', '김해', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1100', '1', 110, '제2경인선', 6, 'S', '인천', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1102', '1', 110, '인천대교선', 6, 'S', '공항', NULL, '공영', '인천대교㈜', '032-745-8000', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1200', '1', 120, '경인선', 6, 'S', '인천', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1300', '1', 130, '인천공항선', 6, 'S', '공항', NULL, '공영', '신공항하이웨이㈜', '032-560-6114', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1510', '1', 151, '서천공주선', 6, 'S', '서천', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1710', '1', 171, '용인서울선', 6, 'S', '용인', NULL, '공영', '경수고속도로㈜', '1599-2505', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('2510', '1', 251, '호남지선', 6, 'S', '논산', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('3000', '1', 300, '대전남부선', 6, 'S', '서대전', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('3010', '1', 301, '상주영천선', 6, 'S', '상주', NULL, '공영', '상주영천고속도로㈜', '1877-1925', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('3300', '1', 330, '제3경인선', 6, 'S', '인천', NULL, '공영', '제삼경인고속도로㈜', '031-8084-8900', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('4000', '1', 400, '수도권제2순환선(봉담-동탄)', 6, 'S', '동탄', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('4001', '1', 400, '수도권제2순환선(인천-김포)', 6, 'S', '인천', NULL, '공영', '인천김포고속도로㈜', '1566-7069', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('4002', '1', 400, '수도권제2순환선(파주-포천)', 6, 'S', '포천', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('4510', '1', 451, '중부내륙지선', 6, 'S', '창원', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('5510', '1', 551, '중앙선지선', 6, 'S', '김해', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0252', '1', 25, '논산천안선', 6, 'S', '논산', NULL, '공영', '천안논산고속도로㈜', '041-850-6700', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0320', '1', 32, '당진청주선(옥산-오창)', 6, 'S', '옥산', NULL, '공영', '옥산오창고속도로㈜', '1877-1108', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('6000', '1', 600, '부산외곽선', 6, 'S', '창원', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0173', '1', 173, '서울문산지선', 6, 'S', '서울', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0172', '1', 17, '서울문산선', 6, 'S', '서울', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0141', '1', 14, '함양울산선', 6, 'S', '함양', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('4003', '1', 400, '수도권제2순환선(송산-봉담)', 6, 'S', '봉담', NULL, '공영', '경기동서순환고속도로㈜', '1877-0427', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('4004', '1', 400, '수도권제2순환선(화성-광주)', 6, 'S', '화성', NULL, '공영', '화성광주고속도로㈜', '1877-0380', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0700', '1', 700, '대구외곽선', 6, 'S', '달서', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('4005', '1', 400, '수도권제2순환선(화도-양평)', 6, 'S', '양평', NULL, '공영', '포천화도고속도로㈜', '1877-1140', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('5000', '1', 500, '광주외곽선', 6, 'S', '광주', NULL, '공영', '한국도로공사', '1588-2504', '101');
COMMIT;
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0010', '1', 1, '경부선', 1, 'S', '부산', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0100', '1', 10, '남해선(순천-부산)', 6, 'S', '순천', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0101', '1', 101, '남해선(영암-순천)', 6, 'S', '영암', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0105', '1', 105, '부산신항선', 6, 'S', '신항', NULL, '공영', '부산신항제이배후도로㈜', '055-339-7164', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0120', '1', 12, '광주대구선', 6, 'S', '광주', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0121', '1', 12, '무안광주선', 6, 'S', '무안', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0140', '1', 253, '고창담양선', 6, 'S', '고창', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0150', '1', 15, '서해안선', 2, 'S', '목포', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0153', '1', 153, '평택시흥선', 6, 'S', '평택', NULL, '공영', '제2서해안고속도로㈜', '1661-5688', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0160', '1', 16, '울산선', 6, 'S', '언양', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0170', '3', 171, '오산화성선', 6, 'S', '서오산', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0170', '2', 17, '수원광명선', 6, 'S', '봉담', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0321', '1', 32, '당진청주선(아산-천안)', 6, 'S', '천안', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('4006', '1', 400, '수도권제2순환선(시화-남안산)', 6, 'S', '남안산', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('4007', '1', 400, '수도권제2순환선(포천-화도)', 6, 'S', '포천', NULL, '공영', '포천화도고속도로㈜', '1877-1140', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1730', '1', 173, '익산평택지선', 6, 'S', '현덕', NULL, '공영', '서부내륙고속도로㈜', '070-7460-3896', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0175', '1', 17, '익산평택선', 6, 'S', '익산', NULL, '공영', '서부내륙고속도로㈜', '070-7460-3896', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0653', '1', 65, '동해선(포항-영덕)', 6, 'S', '포항', NULL, '공영', NULL, NULL, '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0202', '1', 20, '새만금전주선', 6, 'S', '전주', NULL, '공영', NULL, NULL, '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0170', '1', 17, '평택화성선', 6, 'E', '봉담', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0200', '1', 20, '대구포항선', 6, 'E', '포항', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0201', '1', 20, '익산장수선', 6, 'E', '장수', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0251', '1', 25, '호남선', 6, 'E', '천안', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0270', '1', 27, '순천완주선', 6, 'E', '완주', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0290', '1', 29, '세종포천선(안성-포천)', 6, 'E', '포천', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0300', '1', 30, '청주영덕선', 6, 'E', '영덕', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0301', '1', 30, '당진대전선', 6, 'E', '대전', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0351', '1', 35, '통영대전선', 6, 'E', '대전', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0352', '1', 35, '중부선', 3, 'E', '하남', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0370', '1', 37, '제2중부선', 6, 'E', '하남', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0400', '1', 40, '평택제천선', 6, 'E', '제천', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0450', '1', 45, '중부내륙선', 6, 'E', '양평', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0500', '1', 50, '영동선', 4, 'E', '강릉', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0520', '1', 52, '광주원주선', 6, 'E', '원주', NULL, '공영', '제이영동고속도로㈜', '1877-0200', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0550', '2', 55, '중앙선', 6, 'E', '춘천', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0552', '1', 55, '대구부산선', 6, 'E', '대구', NULL, '공영', '신대구부산고속도로㈜', '1688-7003', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0600', '1', 60, '서울양양선', 6, 'E', '양양', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0650', '1', 65, '동해선(삼척-속초)', 6, 'E', '속초', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0651', '1', 65, '부산울산선', 6, 'E', '울산', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0652', '1', 65, '동해선(부산-포항)', 6, 'E', '포항', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1000', '1', 100, '수도권제1순환선', 5, 'E', '판교', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1020', '1', 102, '남해1지선', 6, 'E', '창원', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1040', '1', 104, '남해2지선', 6, 'E', '서부산', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1100', '1', 110, '제2경인선', 6, 'E', '성남', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1102', '1', 110, '인천대교선', 6, 'E', '송도', NULL, '공영', '인천대교㈜', '032-745-8000', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1200', '1', 120, '경인선', 6, 'E', '서울', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1300', '1', 130, '인천공항선', 6, 'E', '서울', NULL, '공영', '신공항하이웨이㈜', '032-560-6114', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1510', '1', 151, '서천공주선', 6, 'E', '공주', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1710', '1', 171, '용인서울선', 6, 'E', '서울', NULL, '공영', '경수고속도로㈜', '1599-2505', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('2510', '1', 251, '호남지선', 6, 'E', '대전', NULL, '공영', '한국도로공사', '1588-2504', '101');
COMMIT;
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('3000', '1', 300, '대전남부선', 6, 'E', '산내', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('3010', '1', 301, '상주영천선', 6, 'E', '영천', NULL, '공영', '상주영천고속도로㈜', '1877-1925', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('3300', '1', 330, '제3경인선', 6, 'E', '시흥', NULL, '공영', '제삼경인고속도로㈜', '031-8084-8900', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('4000', '1', 400, '수도권제2순환선(봉담-동탄)', 6, 'E', '봉담', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('4001', '1', 400, '수도권제2순환선(인천-김포)', 6, 'E', '김포', NULL, '공영', '인천김포고속도로㈜', '1566-7069', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('4002', '1', 400, '수도권제2순환선(파주-포천)', 6, 'E', '파주', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('4510', '1', 451, '중부내륙지선', 6, 'E', '대구', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('5510', '1', 551, '중앙선지선', 6, 'E', '양산', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0252', '1', 25, '논산천안선', 6, 'E', '천안', NULL, '공영', '천안논산고속도로㈜', '041-850-6700', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0320', '1', 32, '당진청주선(옥산-오창)', 6, 'E', '오창', NULL, '공영', '옥산오창고속도로㈜', '1877-1108', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('6000', '1', 600, '부산외곽선', 6, 'E', '기장', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0173', '1', 173, '서울문산지선', 6, 'E', '문산', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0172', '1', 17, '서울문산선', 6, 'E', '문산', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0141', '1', 14, '함양울산선', 6, 'E', '울산', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('4003', '1', 400, '수도권제2순환선(송산-봉담)', 6, 'E', '송산', NULL, '공영', '경기동서순환고속도로㈜', '1877-0427', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('4004', '1', 400, '수도권제2순환선(화성-광주)', 6, 'E', '광주', NULL, '공영', '화성광주고속도로㈜', '1877-0380', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0700', '1', 700, '대구외곽선', 6, 'E', '상매', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('4005', '1', 400, '수도권제2순환선(화도-양평)', 6, 'E', '화도', NULL, '공영', '포천화도고속도로㈜', '1877-1140', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('5000', '1', 500, '광주외곽선', 6, 'E', '장성', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0010', '1', 1, '경부선', 1, 'E', '서울', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0100', '1', 10, '남해선(순천-부산)', 6, 'E', '부산', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0101', '1', 101, '남해선(영암-순천)', 6, 'E', '순천', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0105', '1', 105, '부산신항선', 6, 'E', '김해', NULL, '공영', '부산신항제이배후도로㈜', '055-339-7164', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0120', '1', 12, '광주대구선', 6, 'E', '대구', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0121', '1', 12, '무안광주선', 6, 'E', '광주', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0140', '1', 253, '고창담양선', 6, 'E', '담양', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0150', '1', 15, '서해안선', 2, 'E', '서울', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0153', '1', 153, '평택시흥선', 6, 'E', '시흥', NULL, '공영', '제2서해안고속도로㈜', '1661-5688', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0160', '1', 16, '울산선', 6, 'E', '울산', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0170', '3', 171, '오산화성선', 6, 'E', '안녕', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0170', '2', 17, '수원광명선', 6, 'E', '소하', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0321', '1', 32, '당진청주선(아산-천안)', 6, 'E', '아산', NULL, '공영', '한국도로공사', '1588-2504', '108');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('4006', '1', 400, '수도권제2순환선(시화-남안산)', 6, 'E', '시화', NULL, '공영', '한국도로공사', '1588-2504', '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('4007', '1', 400, '수도권제2순환선(포천-화도)', 6, 'E', '화도', NULL, '공영', '포천화도고속도로㈜', '1877-1140', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('1730', '1', 173, '익산평택지선', 6, 'E', '포승', NULL, '공영', '서부내륙고속도로㈜', '070-7460-3896', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0175', '1', 17, '익산평택선', 6, 'E', '평택', NULL, '공영', '서부내륙고속도로㈜', '070-7460-3896', '109');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0653', '1', 65, '동해선(포항-영덕)', 6, 'E', '영덕', NULL, '공영', NULL, NULL, '101');
INSERT INTO TROAD_APP.T_ROUTE_NEW_NM (ROUTECD, GRPID, ROUTESHORTNO, ROUTENM, ROUTESORT, UPDOWNDIR, ROUTEDIRNM, ROUTELAYOVERNM, OPER, HOINSTNM, RPRSTELNO, CLSSCD) VALUES ('0202', '1', 20, '새만금전주선', 6, 'E', '새만금', NULL, '공영', NULL, NULL, '101');
COMMIT;
File diff suppressed because it is too large Load Diff
+88
View File
@@ -0,0 +1,88 @@
-- 교통속보(V_ACDT_BRNWS_VER001) 개발서버용 스키마
-- chatbotApi TroadService.getBreakingNews 기존 SQL 그대로 사용
SET DEFINE OFF
SET SERVEROUTPUT ON
BEGIN
EXECUTE IMMEDIATE 'CREATE USER TROAD_APP NO AUTHENTICATION';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -1920 THEN RAISE; END IF;
END;
/
GRANT CREATE SESSION, CREATE TABLE, CREATE VIEW, UNLIMITED TABLESPACE TO TROAD_APP;
BEGIN
EXECUTE IMMEDIATE q'[
CREATE TABLE TROAD_APP.T_ACDT_BRNWS_VER001 (
ROUTECD VARCHAR2(4),
GRPID VARCHAR2(2),
BOUND VARCHAR2(1),
ROADNM VARCHAR2(100),
ROUTESORT NUMBER,
ROADSHORTNO NUMBER,
BOUNDNM VARCHAR2(100),
INCIDENT_ID VARCHAR2(30),
INCI_TP_ORDER VARCHAR2(10),
INCI_TP VARCHAR2(50),
MSG VARCHAR2(2000),
INCIDENT_POS_NAME VARCHAR2(500),
OCRN_DSTNC NUMBER,
CNGS_LNGT NUMBER,
LAT NUMBER,
LON NUMBER,
CCTV_ID VARCHAR2(30),
CCTV_NM VARCHAR2(200),
THUMBIMAGE VARCHAR2(500),
HLS_URL VARCHAR2(500),
ST_D NUMBER,
EN_D NUMBER,
VVALUE01 VARCHAR2(2000),
VVALUE02 VARCHAR2(2000),
VVALUE03 VARCHAR2(2000),
VVALUE04 VARCHAR2(2000),
VVALUE05 VARCHAR2(2000),
CRCM_TIME VARCHAR2(100),
CRCM_MSG VARCHAR2(2000)
)
]';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -955 THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE
'CREATE INDEX TROAD_APP.IX_ACDT_BRNWS_ROUTE ' ||
'ON TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, BOUND, ROADNM)';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE NOT IN (-955, -1408) THEN RAISE; END IF;
END;
/
CREATE OR REPLACE VIEW TROAD_APP.V_ACDT_BRNWS_VER001 AS
SELECT ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM,
INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME,
OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE,
HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04,
VVALUE05, CRCM_TIME, CRCM_MSG
FROM TROAD_APP.T_ACDT_BRNWS_VER001;
GRANT SELECT ON TROAD_APP.V_ACDT_BRNWS_VER001 TO OPR_MAIN;
GRANT SELECT ON TLISDEV.T_TRMB_CD_INFO01M1 TO OPR_MAIN;
CREATE OR REPLACE VIEW OPR_MAIN.V_ACDT_BRNWS_VER001 AS
SELECT * FROM TROAD_APP.V_ACDT_BRNWS_VER001;
BEGIN
EXECUTE IMMEDIATE
'CREATE OR REPLACE PUBLIC SYNONYM V_ACDT_BRNWS_VER001 ' ||
'FOR TROAD_APP.V_ACDT_BRNWS_VER001';
EXCEPTION
WHEN OTHERS THEN NULL;
END;
/
+100
View File
@@ -0,0 +1,100 @@
-- 자동 생성: V_ACDT_BRNWS_VER001_202607301705.csv -> TROAD_APP.T_ACDT_BRNWS_VER001
-- 행 수: 88
-- 생성 도구: server-dev/oracle/tools/csv_to_insert.py
SET DEFINE OFF
SET SQLBLANKLINES ON
DELETE FROM TROAD_APP.T_ACDT_BRNWS_VER001;
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('4004', '1', 'S', '수도권제2순환선(화성-광주)', 5, 400, '화성방향', '20260521143800', '03', '작업', 'K (2차로) 비탈면보수 작업중 (14시 38분부터)', '동탄방향 26.0', 0, 0, 0, 0, 'cctv00007433', '동탄JC', 'https://exmobile4.hscdn.com/cctv7433image/ch00007433_20260730.154600.000.jpg', 'https://live18.exmobile.hscdn.com/exlive/cctv7433.stream/playlist.m3u8', 0, 0, NULL, NULL, NULL, NULL, NULL, '(14시 38분부터)', 'K (2차로) 비탈면보수 작업중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0650', '1', 'E', '동해선(삼척-속초)', 6, 65, '속초방향', '20260703074200', '03', '작업', '(2차로)졸음쉼터 설치 작업중 (07시 42분부터)', '쇄운교(15K)-지흥1교(16.7K)', 15, -1, 37.486292, 129.090703, 'cctv00005829', '쇄운교', 'https://exmobile4.hscdn.com/cctv5829image/ch00005829_20260730.154600.000.jpg', 'https://live7.exmobile.hscdn.com/exlive/cctv5829.stream/playlist.m3u8', 15, 15, NULL, NULL, NULL, NULL, NULL, '(07시 42분부터)', '(2차로)졸음쉼터 설치 작업중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0652', '1', 'E', '동해선(부산-포항)', 6, 65, '포항방향', '20260720082502', '03', '작업', '(2차로)노면보강 공사 작업중, 장기차단 (08시 25분부터)', '남경주부근(68K)-문무대왕1터널(74K)', 68, -1, 35.724019, 129.296973, 'cctv00005797', '냉천3교', 'https://exmobile8.hscdn.com/cctv5797image/ch00005797_20260730.154600.000.jpg', 'https://live17.exmobile.hscdn.com/exlive/cctv5797.stream/playlist.m3u8', 68, 68, NULL, NULL, NULL, NULL, NULL, '(08시 25분부터)', '(2차로)노면보강 공사 작업중, 장기차단');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('4004', '1', 'S', '수도권제2순환선(화성-광주)', 5, 400, '화성방향', '20260723135200', '03', '작업', 'null (13시 52분부터)', '동탄방향 9.8', 0, 0, 0, 0, 'cctv00007433', '동탄JC', 'https://exmobile4.hscdn.com/cctv7433image/ch00007433_20260730.154600.000.jpg', 'https://live18.exmobile.hscdn.com/exlive/cctv7433.stream/playlist.m3u8', 0, 0, NULL, NULL, NULL, NULL, NULL, '(13시 52분부터)', 'null');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1100', '1', 'S', '제2경인선', 6, 110, '인천방향', '20260730065400', '04', '정체', '(06시 54분부터)', '서창분기점(9K)-남동부근(6K)', 9, 3, 37.433276, 126.729185, 'cctv00000762', '서창분기점', 'https://exmobile8.hscdn.com/cctv0762image/ch00000762_20260730.154600.000.jpg', 'https://live1.exmobile.hscdn.com/exlive/cctv0762.stream/playlist.m3u8', 9, 9, NULL, NULL, NULL, NULL, NULL, '(06시 54분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0150', '1', 'E', '서해안선', 2, 15, '서울방향', '20260730065451', '04', '정체', '(06시 54분부터)', '광명역(334K)-금천(340K)', 334, 6, 37.407933, 126.88693, 'cctv00000215', '충훈대교', 'https://exmobile8.hscdn.com/cctv0215image/ch00000215_20260730.154600.000.jpg', 'https://live1.exmobile.hscdn.com/exlive/cctv0215.stream/playlist.m3u8', 334, 334, NULL, NULL, NULL, NULL, NULL, '(06시 54분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1000', '1', 'S', '수도권제1순환선', 5, 100, '일산방향', '20260730072448', '04', '정체', '(07시 24분부터)', '시흥요금소(96K)-중동(86K)', 96, 10, 37.449284, 126.805207, 'cctv00002060', '시흥TG_일산', 'https://exmobile4.hscdn.com/cctv2060image/ch00002060_20260730.154600.000.jpg', 'https://live11.exmobile.hscdn.com/exlive/cctv2060.stream/playlist.m3u8', 96, 96, NULL, NULL, NULL, NULL, NULL, '(07시 24분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0351', '1', 'S', '통영대전선', 6, 35, '통영방향', '20260730081231', '03', '작업', '(갓길) 시설물 보수 작업중 (08시 12분부터)', '오동터널부근(132K)', 132, -1, 35.707033, 127.624994, 'cctv00002182', '오동2교', 'https://exmobile4.hscdn.com/cctv2182image/ch00002182_20260730.154600.000.jpg', 'https://live8.exmobile.hscdn.com/exlive/cctv2182.stream/playlist.m3u8', 132, 0, NULL, NULL, NULL, NULL, NULL, '(08시 12분부터)', '(갓길) 시설물 보수 작업중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0252', '1', 'S', '논산천안선', 6, 25, '논산방향', '20260730082406', '04', '정체', '3km 정체 (08시 24분부터)', '차령터널 무학천교(266.0K)-차령터널 (263.0K)', 269, 0, 36.72055, 127.13463, 'cctv00007136', '호정1교', 'https://exmobile4.hscdn.com/cctv7136image/ch00007136_20260730.154600.000.jpg', 'https://live11.exmobile.hscdn.com/exlive/cctv7136.stream/playlist.m3u8', 269, 269, NULL, NULL, NULL, NULL, NULL, '(08시 24분부터)', '3km 정체');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0201', '1', 'S', '익산장수선', 6, 20, '익산방향', '20260730084122', '03', '작업', '(갓길) 덩쿨제거 작업중 (08시 41분부터)', '소양(16K)-소양부근(15K)', 16, -1, 35.865021, 127.230784, 'cctv00003867', '소양', 'https://exmobile8.hscdn.com/cctv3867image/ch00003867_20260730.154600.000.jpg', 'https://live4.exmobile.hscdn.com/exlive/cctv3867.stream/playlist.m3u8', 16, 16, NULL, NULL, NULL, NULL, NULL, '(08시 41분부터)', '(갓길) 덩쿨제거 작업중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0450', '1', 'S', '중부내륙선', 6, 45, '창원방향', '20260730094639', '04', '정체', '(09시 46분부터)', '감곡부근(258K)-감곡부근(255K)', 258, 3, 37.172225, 127.622368, 'cctv00003204', '삼승교', 'https://exmobile4.hscdn.com/cctv3204image/ch00003204_20260730.154600.000.jpg', 'https://live10.exmobile.hscdn.com/exlive/cctv3204.stream/playlist.m3u8', 258, 258, NULL, NULL, NULL, NULL, NULL, '(09시 46분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0100', '1', 'E', '남해선(순천-부산)', 6, 10, '부산방향', '20260730103250', '04', '정체', '(10시 32분부터)', '함안2터널부근(119K)-함안2터널부근(120K)', 119, 1, 35.288699, 128.542006, 'cctv00000560', '함안2터널(부산외부)', 'https://exmobile4.hscdn.com/cctv0560image/ch00000560_20260730.154600.000.jpg', 'https://live13.exmobile.hscdn.com/exlive/cctv0560.stream/playlist.m3u8', 119, 119, NULL, NULL, NULL, NULL, NULL, '(10시 32분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0252', '1', 'S', '논산천안선', 6, 25, '논산방향', '20260728140304', '04', '정체', '5km 정체 (14시 03분부터)', '남풍세IC 호정 1교(268.0K)-차령터널 (263.0K)', 269, 0, 36.72055, 127.13463, 'cctv00007136', '호정1교', 'https://exmobile4.hscdn.com/cctv7136image/ch00007136_20260730.154600.000.jpg', 'https://live11.exmobile.hscdn.com/exlive/cctv7136.stream/playlist.m3u8', 269, 269, NULL, NULL, NULL, NULL, NULL, '(14시 03분부터)', '5km 정체');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1000', '1', 'E', '수도권제1순환선', 5, 100, '구리방향', '20260730051106', '04', '정체', '(05시 11분부터)', '노오지분기점(79K)-송내(88K)', 79, 9, 37.570368, 126.753178, 'cctv00000227', '노오지분기점', 'https://exmobile4.hscdn.com/cctv0227image/ch00000227_20260730.154600.000.jpg', 'https://live15.exmobile.hscdn.com/exlive/cctv0227.stream/playlist.m3u8', 79, 79, NULL, NULL, NULL, NULL, NULL, '(05시 11분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0010', '1', 'E', '경부선', 1, 1, '서울방향', '20260730062713', '04', '정체', '(06시 27분부터)', '양재부근(415K)-반포(420K)', 415, 5, 37.456747, 127.046344, 'cctv00000002', '양재', 'https://exmobile4.hscdn.com/cctv0002image/ch00000002_20260730.154600.000.jpg', 'https://live1.exmobile.hscdn.com/exlive/cctv0002.stream/playlist.m3u8', 415, 415, NULL, NULL, NULL, NULL, NULL, '(06시 27분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0010', '1', 'S', '경부선', 1, 1, '부산방향', '20260730105038', '04', '정체', '(10시 50분부터)', '천안분기점부근(332K)-천안호두(휴)(324K)', 332, 8, 36.766668, 127.196939, 'cctv00003848', '응원고개', 'https://exmobile4.hscdn.com/cctv3848image/ch00003848_20260730.154600.000.jpg', 'https://live4.exmobile.hscdn.com/exlive/cctv3848.stream/playlist.m3u8', 332, 332, NULL, NULL, NULL, NULL, NULL, '(10시 50분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0450', '1', 'E', '중부내륙선', 6, 45, '양평방향', '20260730132759', '04', '정체', '(13시 27분부터)', '충주분기점부근(238K)-충주분기점부근(241K)', 238, 3, 37.041776, 127.75111, 'cctv00003209', '한포천', 'https://exmobile4.hscdn.com/cctv3209image/ch00003209_20260730.154600.000.jpg', 'https://live10.exmobile.hscdn.com/exlive/cctv3209.stream/playlist.m3u8', 238, 238, NULL, NULL, NULL, NULL, NULL, '(13시 27분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0100', '1', 'E', '남해선(순천-부산)', 6, 10, '부산방향', '20260730134538', '04', '정체', '(13시 45분부터)', '대저분기점(163K)-덕천(166K)', 163, 3, 35.219275, 128.969671, 'cctv00003930', '대저', 'https://exmobile4.hscdn.com/cctv3930image/ch00003930_20260730.154600.000.jpg', 'https://live15.exmobile.hscdn.com/exlive/cctv3930.stream/playlist.m3u8', 163, 163, NULL, NULL, NULL, NULL, NULL, '(13시 45분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1100', '1', 'E', '제2경인선', 6, 110, '성남방향', '20260730135457', '04', '정체', '(13시 54분부터)', '학익분기점(3K)-남동(8K)', 3, 5, 37.438267, 126.662356, 'cctv00001535', '학익대교1', 'https://exmobile4.hscdn.com/cctv1535image/ch00001535_20260730.154600.000.jpg', 'https://live12.exmobile.hscdn.com/exlive/cctv1535.stream/playlist.m3u8', 3, 3, NULL, NULL, NULL, NULL, NULL, '(13시 54분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0500', '1', 'S', '영동선', 4, 50, '인천방향', '20260730135951', '04', '정체', '(13시 59분부터)', '군자분기점(7K)-월곶분기점부근(4K)', 7, 3, 37.382693, 126.762417, 'cctv00000854', '군자분기점', 'https://exmobile4.hscdn.com/cctv0854image/ch00000854_20260730.154600.000.jpg', 'https://live2.exmobile.hscdn.com/exlive/cctv0854.stream/playlist.m3u8', 7, 7, NULL, NULL, NULL, NULL, NULL, '(13시 59분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0150', '1', 'E', '서해안선', 2, 15, '서울방향', '20260730140943', '04', '정체', '(14시 09분부터)', '서평택분기점부근(295K)-화성(휴)부근(303K)', 295, 8, 37.08446, 126.886438, 'cctv00000054', '상신2교', 'https://exmobile4.hscdn.com/cctv0054image/ch00000054_20260730.154600.000.jpg', 'https://live1.exmobile.hscdn.com/exlive/cctv0054.stream/playlist.m3u8', 295, 295, NULL, NULL, NULL, NULL, NULL, '(14시 09분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0150', '1', 'E', '서해안선', 2, 15, '서울방향', '20260730141000', '04', '정체', '(14시 10분부터)', '매송(휴)부근(315K)-용담터널(319K)', 315, 4, 37.260631, 126.887041, 'cctv00002409', '야목2교', 'https://exmobile8.hscdn.com/cctv2409image/ch00002409_20260730.154600.000.jpg', 'https://live3.exmobile.hscdn.com/exlive/cctv2409.stream/playlist.m3u8', 315, 315, NULL, NULL, NULL, NULL, NULL, '(14시 10분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0352', '1', 'S', '중부선', 3, 35, '남이방향', '20260730141034', '04', '정체', '(14시 10분부터)', '진천터널부근(277K)-진천터널부근(274K)', 277, 3, 36.835086, 127.494366, 'cctv00003845', '백곡천교', 'https://exmobile8.hscdn.com/cctv3845image/ch00003845_20260730.154600.000.jpg', 'https://live9.exmobile.hscdn.com/exlive/cctv3845.stream/playlist.m3u8', 277, 277, NULL, NULL, NULL, NULL, NULL, '(14시 10분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0202', '1', 'E', '새만금전주선', 6, 202, '새만금방향', '20260730141437', '01', '기타', '(갓길)소형화물차 고장 처리중 (14시 14분부터)', '석구터널(46.1K)', 46.1, -1, 35.773544, 127.153308, 'cctv00002613', '원은육교2', 'https://exmobile4.hscdn.com/cctv2613image/ch00002613_20260730.154600.000.jpg', 'https://live1.exmobile.hscdn.com/exlive/cctv2613.stream/playlist.m3u8', 46.1, 0, NULL, NULL, NULL, NULL, NULL, '(14시 14분부터)', '(갓길)소형화물차 고장 처리중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0500', '1', 'S', '영동선', 4, 50, '인천방향', '20260730142623', '04', '정체', '(14시 26분부터)', '동수원(37K)-북수원(30K)', 37, 7, 37.299117, 127.051361, 'cctv00002415', '동수원', 'https://exmobile4.hscdn.com/cctv2415image/ch00002415_20260730.154500.000.jpg', 'https://live3.exmobile.hscdn.com/exlive/cctv2415.stream/playlist.m3u8', 37, 37, NULL, NULL, NULL, NULL, NULL, '(14시 26분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0010', '1', 'E', '경부선', 1, 1, '서울방향', '20260730143713', '04', '정체', '(14시 37분부터)', '안성분기점(364K)-안성(휴)부근(368K)', 364, 4, 37.028613, 127.140833, 'cctv00000037', '안성분기점2', 'https://exmobile8.hscdn.com/cctv0037image/ch00000037_20260730.154600.000.jpg', 'https://live4.exmobile.hscdn.com/exlive/cctv0037.stream/playlist.m3u8', 364, 364, NULL, NULL, NULL, NULL, NULL, '(14시 37분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1100', '1', 'S', '제2경인선', 6, 110, '인천방향', '20260730143718', '04', '정체', '(14시 37분부터)', '삼막(25.98K)-광명터널(22K)', 25.98, 4, 37.425507, 126.912049, 'cctv00000767', '석수', 'https://exmobile8.hscdn.com/cctv0767image/ch00000767_20260730.154600.000.jpg', 'https://live1.exmobile.hscdn.com/exlive/cctv0767.stream/playlist.m3u8', 25.98, 25.98, NULL, NULL, NULL, NULL, NULL, '(14시 37분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0651', '1', 'S', '부산울산선', 6, 65, '부산방향', '20260730144311', '04', '정체', '(14시 43분부터)', '해운대터널부근(3K)-부산울산선시점(0K)', 3, 3, 35.190683, 129.201783, 'cctv00000728', '고래진2교', 'https://exmobile8.hscdn.com/cctv0728image/ch00000728_20260730.154600.000.jpg', 'https://live17.exmobile.hscdn.com/exlive/cctv0728.stream/playlist.m3u8', 3, 3, NULL, NULL, NULL, NULL, NULL, '(14시 43분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0010', '1', 'E', '경부선', 1, 1, '서울방향', '20260730144715', '00', '사고', '(3차로,갓길)화물차관련 사고 처리중 (14시 47분부터)', '영천분기점(91.5K)', 91.5, -1, 35.924733, 128.998642, 'cctv00000819', '반정1교', 'https://exmobile4.hscdn.com/cctv0819image/ch00000819_20260730.154600.000.jpg', 'https://live10.exmobile.hscdn.com/exlive/cctv0819.stream/playlist.m3u8', 91.5, 0, NULL, NULL, NULL, NULL, NULL, '(14시 47분부터)', '(3차로,갓길)화물차관련 사고 처리중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1000', '1', 'E', '수도권제1순환선', 5, 100, '구리방향', '20260730145917', '04', '정체', '(14시 59분부터)', '자유로(72K)-김포(74K)', 72, 2, 37.618882, 126.799826, 'cctv00000224', '자유로분기점', 'https://exmobile4.hscdn.com/cctv0224image/ch00000224_20260730.154600.000.jpg', 'https://live15.exmobile.hscdn.com/exlive/cctv0224.stream/playlist.m3u8', 72, 72, NULL, NULL, NULL, NULL, NULL, '(14시 59분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0400', '1', 'S', '평택제천선', 6, 40, '평택방향', '20260730150604', '04', '정체', '(15시 06분부터)', '서안성(25K)-안성분기점(24K)', 25, 1, 37.036583, 127.153094, 'cctv00005947', '강문교', 'https://exmobile4.hscdn.com/cctv5947image/ch00005947_20260730.154600.000.jpg', 'https://live14.exmobile.hscdn.com/exlive/cctv5947.stream/playlist.m3u8', 25, 25, NULL, NULL, NULL, NULL, NULL, '(15시 06분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1200', '1', 'S', '경인선', 6, 120, '인천방향', '20260730150911', '04', '정체', '(15시 09분부터)', '인천요금소(16K)-서인천(11K)', 16, 5, 37.523954, 126.742937, 'cctv00005038', '인천영업소', 'https://exmobile8.hscdn.com/cctv5038image/ch00005038_20260730.154600.000.jpg', 'https://live1.exmobile.hscdn.com/exlive/cctv5038.stream/playlist.m3u8', 16, 16, NULL, NULL, NULL, NULL, NULL, '(15시 09분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0010', '1', 'E', '경부선', 1, 1, '서울방향', '20260730152029', '04', '정체', '(15시 20분부터)', '입장거봉포도(휴)부근(355K)-안성(360K)', 355, 5, 36.955513, 127.181906, 'cctv00003102', '연곡', 'https://exmobile8.hscdn.com/cctv3102image/ch00003102_20260730.154600.000.jpg', 'https://live4.exmobile.hscdn.com/exlive/cctv3102.stream/playlist.m3u8', 355, 355, NULL, NULL, NULL, NULL, NULL, '(15시 20분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1200', '1', 'E', '경인선', 6, 120, '서울방향', '20260730152128', '04', '정체', '(15시 21분부터)', '신월(23K)-신월(24K)', 23, 1, 37.523394, 126.821631, 'cctv00001451', '신월-1', 'https://exmobile4.hscdn.com/cctv1451image/ch00001451_20260730.154600.000.jpg', 'https://live8.exmobile.hscdn.com/exlive/cctv1451.stream/playlist.m3u8', 23, 23, NULL, NULL, NULL, NULL, NULL, '(15시 21분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1040', '1', 'E', '남해2지선', 6, 104, '서부산방향', '20260730152500', '04', '정체', '(15시 25분부터)', '서부산(휴)(18K)-사상(20K)', 18, 2, 35.156477, 128.948907, 'cctv00003718', '서부산', 'https://exmobile4.hscdn.com/cctv3718image/ch00003718_20260730.154600.000.jpg', 'https://live4.exmobile.hscdn.com/exlive/cctv3718.stream/playlist.m3u8', 18, 18, NULL, NULL, NULL, NULL, NULL, '(15시 25분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0010', '1', 'S', '경부선', 1, 1, '부산방향', '20260730152539', '01', '기타', '(갓길) 승용 고장차 처리중 (15시 25분부터)', '청주분기점(297K)', 297, -1, 36.568675, 127.429435, 'cctv00002129', '청주분기점2', 'https://exmobile4.hscdn.com/cctv2129image/ch00002129_20260730.154600.000.jpg', 'https://live12.exmobile.hscdn.com/exlive/cctv2129.stream/playlist.m3u8', 297, 0, NULL, NULL, NULL, NULL, NULL, '(15시 25분부터)', '(갓길) 승용 고장차 처리중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0252', '1', 'E', '논산천안선', 6, 25, '천안방향', '20260730152731', '04', '정체', '3km 정체 (15시 27분부터)', '남공주IC 오룡교(232.0K)-남공주IC 검상천교(235.0K)', 225, 0, 36.34541, 127.06794, 'cctv00007164', '이인SA/남', 'https://exmobile4.hscdn.com/cctv7164image/ch00007164_20260730.154600.000.jpg', 'https://live11.exmobile.hscdn.com/exlive/cctv7164.stream/playlist.m3u8', 225, 225, NULL, NULL, NULL, NULL, NULL, '(15시 27분부터)', '3km 정체');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('6000', '1', 'S', '부산외곽선', 6, 600, '창원방향', '20260730152946', '04', '정체', '(15시 29분부터)', '기장분기점(48K)-기장분기점부근(47K)', 48, 1, 35.281987, 129.2089, 'cctv00000517', '용천교', 'https://exmobile4.hscdn.com/cctv0517image/ch00000517_20260730.154600.000.jpg', 'https://live11.exmobile.hscdn.com/exlive/cctv0517.stream/playlist.m3u8', 48, 48, NULL, NULL, NULL, NULL, NULL, '(15시 29분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1300', '1', 'S', '인천공항선', 6, 130, '공항방향', '20260730153000', '04', '정체', '청라IC 진출 1km 정체 (15시 30분부터)', '[본선-공항] 20.8Km', 20.8, 0, 37.569859, 126.670011, 'cctv00007097', '인천공항영업소', 'https://exmobile4.hscdn.com/cctv7097image/ch00007097_20260730.154600.000.jpg', 'https://live11.exmobile.hscdn.com/exlive/cctv7097.stream/playlist.m3u8', 20.8, 20.8, NULL, NULL, NULL, NULL, NULL, '(15시 30분부터)', '청라IC 진출 1km 정체');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1000', '1', 'S', '수도권제1순환선', 5, 100, '일산방향', '20260730153338', '04', '정체', '(15시 33분부터)', '안양터널(114K)-수리터널(112K)', 114, 2, 37.37919, 126.946985, 'cctv00000292', '안양터널', 'https://exmobile4.hscdn.com/cctv0292image/ch00000292_20260730.154600.000.jpg', 'https://live15.exmobile.hscdn.com/exlive/cctv0292.stream/playlist.m3u8', 114, 114, NULL, NULL, NULL, NULL, NULL, '(15시 33분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0500', '1', 'S', '영동선', 4, 50, '인천방향', '20260730153400', '04', '정체', '(15시 34분부터)', '덕평부근(66K)-양지터널부근(58K)', 66, 8, 37.250668, 127.352923, 'cctv00000371', '오천교', 'https://exmobile8.hscdn.com/cctv0371image/ch00000371_20260730.154600.000.jpg', 'https://live16.exmobile.hscdn.com/exlive/cctv0371.stream/playlist.m3u8', 66, 66, NULL, NULL, NULL, NULL, NULL, '(15시 34분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('2510', '1', 'S', '호남지선', 6, 251, '논산방향', '20260730154509', '04', '정체', '(15시 45분부터)', '회덕분기점(54K)-북대전부근(52K)', 54, 2, 0, 0, 'cctv00000297', '전민', 'https://exmobile4.hscdn.com/cctv0297image/ch00000297_20260730.154600.000.jpg', 'https://live12.exmobile.hscdn.com/exlive/cctv0297.stream/playlist.m3u8', 54, 54, NULL, NULL, NULL, NULL, NULL, '(15시 45분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0400', '1', 'S', '평택제천선', 6, 40, '평택방향', '20260730155518', '04', '정체', '(15시 55분부터)', '대소분기점(57K)-안진터널(52K)', 57, 5, 36.941808, 127.463959, 'cctv00003794', '대소분기점', 'https://exmobile4.hscdn.com/cctv3794image/ch00003794_20260730.154600.000.jpg', 'https://live14.exmobile.hscdn.com/exlive/cctv3794.stream/playlist.m3u8', 57, 57, NULL, NULL, NULL, NULL, NULL, '(15시 55분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0600', '1', 'S', '서울양양선', 6, 60, '서울방향', '20260730155707', '04', '정체', '(15시 57분부터)', '화도(15K)-화도부근(13K)', 15, 2, 37.63154, 127.312837, 'cctv00000400', '화도영업소', 'https://exmobile8.hscdn.com/cctv0400image/ch00000400_20260730.154600.000.jpg', 'https://live17.exmobile.hscdn.com/exlive/cctv0400.stream/playlist.m3u8', 15, 15, NULL, NULL, NULL, NULL, NULL, '(15시 57분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0010', '1', 'E', '경부선', 1, 1, '서울방향', '20260730160049', '04', '정체', '(순환선 진출로) (16시 00분부터)', '판교분기점(408K)', 408, 1, 37.406461, 127.09392, 'cctv00000006', '판교분기점_경부', 'https://exmobile4.hscdn.com/cctv0006image/ch00000006_20260730.154600.000.jpg', 'https://live1.exmobile.hscdn.com/exlive/cctv0006.stream/playlist.m3u8', 408, 0, NULL, NULL, NULL, NULL, NULL, '(16시 00분부터)', '(순환선 진출로)');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0251', '1', 'E', '호남선', 6, 25, '천안방향', '20260730160618', '04', '정체', '교통량 증가 (16시 06분부터)', '동광주(74K)', 74, 1, 35.183438, 126.926925, 'cctv00003382', '동광주', 'https://exmobile4.hscdn.com/cctv3382image/ch00003382_20260730.154600.000.jpg', 'https://live11.exmobile.hscdn.com/exlive/cctv3382.stream/playlist.m3u8', 74, 0, NULL, NULL, NULL, NULL, NULL, '(16시 06분부터)', '교통량 증가');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1000', '1', 'E', '수도권제1순환선', 5, 100, '구리방향', '20260730160627', '04', '정체', '(16시 06분부터)', '조남분기점(107K)-수암터널(108K)', 107, 1, 37.368655, 126.869846, 'cctv00000238', '조남분기점', 'https://exmobile4.hscdn.com/cctv0238image/ch00000238_20260730.154600.000.jpg', 'https://live15.exmobile.hscdn.com/exlive/cctv0238.stream/playlist.m3u8', 107, 107, NULL, NULL, NULL, NULL, NULL, '(16시 06분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0352', '1', 'E', '중부선', 3, 35, '하남방향', '20260730160933', '04', '정체', '(16시 09분부터)', '일죽부근(304K)-일죽부근(309K)', 304, 5, 37.070051, 127.468948, 'cctv00000667', '장암1', 'https://exmobile4.hscdn.com/cctv0667image/ch00000667_20260730.154600.000.jpg', 'https://live4.exmobile.hscdn.com/exlive/cctv0667.stream/playlist.m3u8', 304, 304, NULL, NULL, NULL, NULL, NULL, '(16시 09분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0500', '1', 'S', '영동선', 4, 50, '인천방향', '20260730161003', '04', '정체', '(16시 10분부터)', '서창분기점(1K)-서창(0K)', 1, 1, 37.428961, 126.737875, 'cctv00005669', '서창', 'https://exmobile8.hscdn.com/cctv5669image/ch00005669_20260730.154600.000.jpg', 'https://live16.exmobile.hscdn.com/exlive/cctv5669.stream/playlist.m3u8', 1, 1, NULL, NULL, NULL, NULL, NULL, '(16시 10분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0450', '1', 'E', '중부내륙선', 6, 45, '양평방향', '20260730161104', '01', '기타', '(갓길)승합차고장 처리중 (16시 11분부터)', '감곡부근(252.1K)', 252.1, -1, 37.129423, 127.66049, 'cctv00005386', '상우1교', 'https://exmobile8.hscdn.com/cctv5386image/ch00005386_20260730.154600.000.jpg', 'https://live14.exmobile.hscdn.com/exlive/cctv5386.stream/playlist.m3u8', 252.1, 0, NULL, NULL, NULL, NULL, NULL, '(16시 11분부터)', '(갓길)승합차고장 처리중');
COMMIT;
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0150', '1', 'E', '서해안선', 2, 15, '서울방향', '20260730161342', '01', '기타', '(갓길)중형화물차 고장 처리중 (16시 13분부터)', '서천(휴)부근(166.5K)', 166.5, -1, 36.119755, 126.636626, 'cctv00002043', '종천1교', 'https://exmobile4.hscdn.com/cctv2043image/ch00002043_20260730.154600.000.jpg', 'https://live12.exmobile.hscdn.com/exlive/cctv2043.stream/playlist.m3u8', 166.5, 0, NULL, NULL, NULL, NULL, NULL, '(16시 13분부터)', '(갓길)중형화물차 고장 처리중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0500', '1', 'S', '영동선', 4, 50, '인천방향', '20260730161727', '04', '정체', '(16시 17분부터)', '둔대분기점(23K)-반월터널부근(21K)', 23, 2, 37.322581, 126.907065, 'cctv00005041', '둔대분기점', 'https://exmobile8.hscdn.com/cctv5041image/ch00005041_20260730.154600.000.jpg', 'https://live16.exmobile.hscdn.com/exlive/cctv5041.stream/playlist.m3u8', 23, 23, NULL, NULL, NULL, NULL, NULL, '(16시 17분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0270', '1', 'E', '순천완주선', 6, 27, '완주방향', '20260730161748', '01', '기타', '(갓길) 화물차 고장 처리중 (16시 17분부터)', '서면2터널부근(10.7K)', 10.7, -1, 35.028166, 127.507502, 'cctv00005578', '서면2터널(완주외부1)', 'https://exmobile8.hscdn.com/cctv5578image/ch00005578_20260730.154600.000.jpg', 'https://live14.exmobile.hscdn.com/exlive/cctv5578.stream/playlist.m3u8', 10.7, 0, NULL, NULL, NULL, NULL, NULL, '(16시 17분부터)', '(갓길) 화물차 고장 처리중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0160', '1', 'E', '울산선', 6, 16, '울산방향', '20260730161750', '01', '기타', '(갓길)화물차 고장처리 중 (16시 17분부터)', '범서하이패스(10.3K)', 10.3, -1, 35.570555, 129.227118, 'cctv00005346', '입암', 'https://exmobile4.hscdn.com/cctv5346image/ch00005346_20260730.154600.000.jpg', 'https://live14.exmobile.hscdn.com/exlive/cctv5346.stream/playlist.m3u8', 10.3, 0, NULL, NULL, NULL, NULL, NULL, '(16시 17분부터)', '(갓길)화물차 고장처리 중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0500', '1', 'S', '영동선', 4, 50, '인천방향', '20260730161757', '04', '정체', '진출로 (16시 17분부터)', '서용인분기점(50K)', 50, 1, 37.268988, 127.186046, 'cctv00000363', '마성터널(강릉)', 'https://exmobile8.hscdn.com/cctv0363image/ch00000363_20260730.154600.000.jpg', 'https://live16.exmobile.hscdn.com/exlive/cctv0363.stream/playlist.m3u8', 50, 0, NULL, NULL, NULL, NULL, NULL, '(16시 17분부터)', '진출로');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0150', '1', 'E', '서해안선', 2, 15, '서울방향', '20260730161803', '01', '기타', '(갓길) 화물 고장차 처리중 (16시 18분부터)', '당진부근(267.3K)', 267.3, -1, 36.906553, 126.733865, 'cctv00000626', '영천교(고정)', 'https://exmobile4.hscdn.com/cctv0626image/ch00000626_20260730.154600.000.jpg', 'https://live4.exmobile.hscdn.com/exlive/cctv0626.stream/playlist.m3u8', 267.3, 0, NULL, NULL, NULL, NULL, NULL, '(16시 18분부터)', '(갓길) 화물 고장차 처리중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0550', '2', 'S', '중앙선', 6, 55, '부산방향', '20260730161902', '04', '정체', '(16시 19분부터)', '초정(5K)-삼락(0K)', 5, 5, 35.235254, 128.980641, 'cctv00003672', '초정', 'https://exmobile8.hscdn.com/cctv3672image/ch00003672_20260730.154600.000.jpg', 'https://live4.exmobile.hscdn.com/exlive/cctv3672.stream/playlist.m3u8', 5, 5, NULL, NULL, NULL, NULL, NULL, '(16시 19분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0500', '1', 'E', '영동선', 4, 50, '강릉방향', '20260730161916', '04', '정체', '(16시 19분부터)', '둔대분기점(22K)-부곡(27K)', 22, 5, 37.322957, 126.895948, 'cctv00000220', '둔대교', 'https://exmobile8.hscdn.com/cctv0220image/ch00000220_20260730.154600.000.jpg', 'https://live2.exmobile.hscdn.com/exlive/cctv0220.stream/playlist.m3u8', 22, 22, NULL, NULL, NULL, NULL, NULL, '(16시 19분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0252', '1', 'E', '논산천안선', 6, 25, '천안방향', '20260730162057', '00', '사고', '1차로 승용차 관련 사고발생 (16시 20분부터)', '남공주IC 오룡교(232.1K)', 225, 0, 36.34541, 127.06794, 'cctv00007164', '이인SA/남', 'https://exmobile4.hscdn.com/cctv7164image/ch00007164_20260730.154600.000.jpg', 'https://live11.exmobile.hscdn.com/exlive/cctv7164.stream/playlist.m3u8', 225, 225, NULL, NULL, NULL, NULL, NULL, '(16시 20분부터)', '1차로 승용차 관련 사고발생');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1000', '1', 'S', '수도권제1순환선', 5, 100, '일산방향', '20260730162117', '04', '정체', '(16시 21분부터)', '성남부근(3K)-판교분기점(0K)', 3, 3, 37.416928, 127.122446, 'cctv00005932', '성남삼평교2', 'https://exmobile4.hscdn.com/cctv5932image/ch00005932_20260730.154600.000.jpg', 'https://live5.exmobile.hscdn.com/exlive/cctv5932.stream/playlist.m3u8', 3, 3, NULL, NULL, NULL, NULL, NULL, '(16시 21분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1000', '1', 'S', '수도권제1순환선', 5, 100, '일산방향', '20260730162134', '04', '정체', '(16시 21분부터)', '판교분기점(128K)-판교분기점부근(126K)', 128, 2, 37.405686, 127.094436, 'cctv00005666', '금토', 'https://exmobile8.hscdn.com/cctv5666image/ch00005666_20260730.154600.000.jpg', 'https://live11.exmobile.hscdn.com/exlive/cctv5666.stream/playlist.m3u8', 128, 128, NULL, NULL, NULL, NULL, NULL, '(16시 21분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1000', '1', 'S', '수도권제1순환선', 5, 100, '일산방향', '20260730162214', '04', '정체', '(16시 22분부터)', '서하남분기점(16K)-송파부근(7K)', 16, 9, 37.515281, 127.169685, 'cctv00000251', '광암터널2', 'https://exmobile4.hscdn.com/cctv0251image/ch00000251_20260730.154600.000.jpg', 'https://live15.exmobile.hscdn.com/exlive/cctv0251.stream/playlist.m3u8', 16, 16, NULL, NULL, NULL, NULL, NULL, '(16시 22분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0600', '1', 'S', '서울양양선', 6, 60, '서울방향', '20260730162324', '04', '정체', '(16시 23분부터)', '덕소삼패(3K)-강일(0K)', 3, 3, 37.587067, 127.199448, 'cctv00000427', '미사대교종점', 'https://exmobile8.hscdn.com/cctv0427image/ch00000427_20260730.154600.000.jpg', 'https://live17.exmobile.hscdn.com/exlive/cctv0427.stream/playlist.m3u8', 3, 3, NULL, NULL, NULL, NULL, NULL, '(16시 23분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0450', '1', 'E', '중부내륙선', 6, 45, '양평방향', '20260730162343', '04', '정체', '(16시 23분부터)', '감곡(251K)-감곡부근(255K)', 251, 4, 37.124313, 127.670833, 'cctv00003206', '감곡', 'https://exmobile4.hscdn.com/cctv3206image/ch00003206_20260730.154600.000.jpg', 'https://live10.exmobile.hscdn.com/exlive/cctv3206.stream/playlist.m3u8', 251, 251, NULL, NULL, NULL, NULL, NULL, '(16시 23분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1000', '1', 'E', '수도권제1순환선', 5, 100, '구리방향', '20260730162344', '04', '정체', '(16시 23분부터)', '강일(24K)-구리남양주요금소(27K)', 24, 3, 37.566883, 127.170658, 'cctv00000143', '강일육교', 'https://exmobile8.hscdn.com/cctv0143image/ch00000143_20260730.154600.000.jpg', 'https://live1.exmobile.hscdn.com/exlive/cctv0143.stream/playlist.m3u8', 24, 24, NULL, NULL, NULL, NULL, NULL, '(16시 23분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1100', '1', 'E', '제2경인선', 6, 110, '성남방향', '20260730162409', '04', '정체', '(16시 24분부터)', '안현분기점(17K)-안현분기점(18K)', 17, 1, 37.437119, 126.816192, 'cctv00001536', '안현분기점1', 'https://exmobile4.hscdn.com/cctv1536image/ch00001536_20260730.154600.000.jpg', 'https://live12.exmobile.hscdn.com/exlive/cctv1536.stream/playlist.m3u8', 17, 17, NULL, NULL, NULL, NULL, NULL, '(16시 24분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0010', '1', 'S', '경부선', 1, 1, '부산방향', '20260730163326', '04', '정체', '(16시 33분부터)', '회덕분기점(277K)-회덕분기점부근(276K)', 277, 1, 36.396149, 127.419059, 'cctv00000873', '신대철교', 'https://exmobile4.hscdn.com/cctv0873image/ch00000873_20260730.154600.000.jpg', 'https://live4.exmobile.hscdn.com/exlive/cctv0873.stream/playlist.m3u8', 277, 277, NULL, NULL, NULL, NULL, NULL, '(16시 33분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0270', '1', 'E', '순천완주선', 6, 27, '완주방향', '20260730163357', '03', '작업', '(갓길) 노면보수 작업중 (16시 33분부터)', '황전(25.4K)', 25.4, -1, 35.149569, 127.455096, 'cctv00001436', '황전', 'https://exmobile8.hscdn.com/cctv1436image/ch00001436_20260730.154600.000.jpg', 'https://live14.exmobile.hscdn.com/exlive/cctv1436.stream/playlist.m3u8', 25.4, 0, NULL, NULL, NULL, NULL, NULL, '(16시 33분부터)', '(갓길) 노면보수 작업중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0500', '1', 'S', '영동선', 4, 50, '인천방향', '20260730163548', '04', '정체', '(16시 35분부터)', '이천부근(82K)-호법분기점부근(75K)', 82, 7, 37.242627, 127.522886, 'cctv00000359', '가산리', 'https://exmobile4.hscdn.com/cctv0359image/ch00000359_20260730.154600.000.jpg', 'https://live16.exmobile.hscdn.com/exlive/cctv0359.stream/playlist.m3u8', 82, 82, NULL, NULL, NULL, NULL, NULL, '(16시 35분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0352', '1', 'E', '중부선', 3, 35, '하남방향', '20260730164203', '04', '정체', '(16시 42분부터)', '경기광주IC(352K)-중부1터널부근(355K)', 352, 3, 37.447946, 127.269718, 'cctv00000267', '광주', 'https://exmobile4.hscdn.com/cctv0267image/ch00000267_20260730.154600.000.jpg', 'https://live1.exmobile.hscdn.com/exlive/cctv0267.stream/playlist.m3u8', 352, 352, NULL, NULL, NULL, NULL, NULL, '(16시 42분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0600', '1', 'S', '서울양양선', 6, 60, '서울방향', '20260730164308', '01', '기타', '(갓길) 승용차 고장 처리중 (16시 43분부터)', '남춘천부근(53.6K)', 53.6, -1, 37.745234, 127.694504, 'cctv00000172', '행촌2교', 'https://exmobile4.hscdn.com/cctv0172image/ch00000172_20260730.154600.000.jpg', 'https://live17.exmobile.hscdn.com/exlive/cctv0172.stream/playlist.m3u8', 53.6, 0, NULL, NULL, NULL, NULL, NULL, '(16시 43분부터)', '(갓길) 승용차 고장 처리중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0500', '1', 'E', '영동선', 4, 50, '강릉방향', '20260730164416', '00', '사고', '(인천 진출로)사고 처리중 (16시 44분부터)', '서창분기점(0.5K)', .5, -1, 37.433432, 126.738571, 'cctv00005927', '서창JC', 'https://exmobile4.hscdn.com/cctv5927image/ch00005927_20260730.154600.000.jpg', 'https://live8.exmobile.hscdn.com/exlive/cctv5927.stream/playlist.m3u8', 0.5, 0, NULL, NULL, NULL, NULL, NULL, '(16시 44분부터)', '(인천 진출로)사고 처리중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0500', '1', 'S', '영동선', 4, 50, '인천방향', '20260730164625', '01', '기타', '(2차로)고장차 처리중 (16시 46분부터)', '월곶분기점부근(6.3K)', 6.3, -1, 37.386135, 126.755797, 'cctv00000336', '월곶', 'https://exmobile4.hscdn.com/cctv0336image/ch00000336_20260730.154600.000.jpg', 'https://live16.exmobile.hscdn.com/exlive/cctv0336.stream/playlist.m3u8', 6.3, 0, NULL, NULL, NULL, NULL, NULL, '(16시 46분부터)', '(2차로)고장차 처리중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0351', '1', 'S', '통영대전선', 6, 35, '통영방향', '20260730164648', '01', '기타', '(2차로,갓길)승용차 고장 처리중 (16시 46분부터)', '마달터널부근(202.5K)', 202.5, -1, 36.248086, 127.474032, 'cctv00000463', '공주교', 'https://exmobile8.hscdn.com/cctv0463image/ch00000463_20260730.154600.000.jpg', 'https://live17.exmobile.hscdn.com/exlive/cctv0463.stream/playlist.m3u8', 202.5, 0, NULL, NULL, NULL, NULL, NULL, '(16시 46분부터)', '(2차로,갓길)승용차 고장 처리중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1000', '1', 'E', '수도권제1순환선', 5, 100, '구리방향', '20260730164727', '00', '사고', '(3,4차로) 사고 처리중 (16시 47분부터)', '자유로(72K)', 72, 2, 37.618882, 126.799826, 'cctv00000224', '자유로분기점', 'https://exmobile4.hscdn.com/cctv0224image/ch00000224_20260730.154600.000.jpg', 'https://live15.exmobile.hscdn.com/exlive/cctv0224.stream/playlist.m3u8', 72, 0, NULL, NULL, NULL, NULL, NULL, '(16시 47분부터)', '(3,4차로) 사고 처리중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0010', '1', 'E', '경부선', 1, 1, '서울방향', '20260730164739', '04', '정체', '(16시 47분부터)', '기흥(388K)-신갈분기점(394K)', 388, 6, 37.228626, 127.105739, 'cctv00000700', '보정교', 'https://exmobile4.hscdn.com/cctv0700image/ch00000700_20260730.154600.000.jpg', 'https://live12.exmobile.hscdn.com/exlive/cctv0700.stream/playlist.m3u8', 388, 388, NULL, NULL, NULL, NULL, NULL, '(16시 47분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0010', '1', 'S', '경부선', 1, 1, '부산방향', '20260730164817', '04', '정체', '(16시 48분부터)', '신갈분기점부근(397K)-신갈분기점(394K)', 397, 3, 37.309238, 127.103578, 'cctv00000008', '죽전', 'https://exmobile4.hscdn.com/cctv0008image/ch00000008_20260730.154600.000.jpg', 'https://live1.exmobile.hscdn.com/exlive/cctv0008.stream/playlist.m3u8', 397, 397, NULL, NULL, NULL, NULL, NULL, '(16시 48분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0351', '1', 'S', '통영대전선', 6, 35, '통영방향', '20260730165102', '01', '기타', '(갓길)화물차 고장 처리중 (16시 51분부터)', '동고성(14.3K)', 14.3, -1, 34.970155, 128.385918, 'cctv00001582', '송산', 'https://exmobile4.hscdn.com/cctv1582image/ch00001582_20260730.154600.000.jpg', 'https://live14.exmobile.hscdn.com/exlive/cctv1582.stream/playlist.m3u8', 14.3, 0, NULL, NULL, NULL, NULL, NULL, '(16시 51분부터)', '(갓길)화물차 고장 처리중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0400', '1', 'E', '평택제천선', 6, 40, '제천방향', '20260730165135', '04', '정체', '(16시 51분부터)', '안성분기점(23K)-안성분기점(24K)', 23, 1, 37.034317, 127.131112, 'cctv00000388', '안성분기점_평택제천', 'https://exmobile4.hscdn.com/cctv0388image/ch00000388_20260730.154600.000.jpg', 'https://live14.exmobile.hscdn.com/exlive/cctv0388.stream/playlist.m3u8', 23, 23, NULL, NULL, NULL, NULL, NULL, '(16시 51분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0010', '1', 'S', '경부선', 1, 1, '부산방향', '20260730165504', '01', '기타', '(갓길)승용차 고장처리중 (16시 55분부터)', '동대구분기점(122.5K)', 122.5, -1, 35.887948, 128.690911, 'cctv00002300', '동대구', 'https://exmobile8.hscdn.com/cctv2300image/ch00002300_20260730.154600.000.jpg', 'https://live1.exmobile.hscdn.com/exlive/cctv2300.stream/playlist.m3u8', 122.5, 0, NULL, NULL, NULL, NULL, NULL, '(16시 55분부터)', '(갓길)승용차 고장처리중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0600', '1', 'S', '서울양양선', 6, 60, '서울방향', '20260730165618', '00', '사고', '(2,3차로)승용차관련 사고처리중 (16시 56분부터)', '남춘천부근(53.8K)', 53.8, 3, 37.745877, 127.696623, 'cctv00000172', '행촌2교', 'https://exmobile4.hscdn.com/cctv0172image/ch00000172_20260730.154600.000.jpg', 'https://live17.exmobile.hscdn.com/exlive/cctv0172.stream/playlist.m3u8', 53.8, 0, NULL, NULL, NULL, NULL, NULL, '(16시 56분부터)', '(2,3차로)승용차관련 사고처리중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0010', '1', 'E', '경부선', 1, 1, '서울방향', '20260730165638', '22', '기타', '(갓길)보행자 조치중 (16시 56분부터)', '안성(휴)(370K)', 370, -1, 37.080963, 127.127648, 'cctv00000097', '산하', 'https://exmobile8.hscdn.com/cctv0097image/ch00000097_20260730.154600.000.jpg', 'https://live15.exmobile.hscdn.com/exlive/cctv0097.stream/playlist.m3u8', 370, 0, NULL, NULL, NULL, NULL, NULL, '(16시 56분부터)', '(갓길)보행자 조치중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1200', '1', 'S', '경인선', 6, 120, '인천방향', '20260730165724', '04', '정체', '(16시 57분부터)', '부천(20K)-부천(19K)', 20, 1, 37.523066, 126.788085, 'cctv00005937', '도당육교', 'https://exmobile4.hscdn.com/cctv5937image/ch00005937_20260730.154600.000.jpg', 'https://live12.exmobile.hscdn.com/exlive/cctv5937.stream/playlist.m3u8', 20, 20, NULL, NULL, NULL, NULL, NULL, '(16시 57분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0450', '1', 'E', '중부내륙선', 6, 45, '양평방향', '20260730165823', '01', '기타', '(진입로 갓길) 화물차 고장 처리 중 (16시 58분부터)', '영산(24K)', 24, -1, 35.450343, 128.508937, 'cctv00001539', '봉산', 'https://exmobile4.hscdn.com/cctv1539image/ch00001539_20260730.154600.000.jpg', 'https://live3.exmobile.hscdn.com/exlive/cctv1539.stream/playlist.m3u8', 24, 0, NULL, NULL, NULL, NULL, NULL, '(16시 58분부터)', '(진입로 갓길) 화물차 고장 처리 중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0150', '1', 'E', '서해안선', 2, 15, '서울방향', '20260730165846', '00', '사고', '(1차로)사고 처리중 (16시 58분부터)', '화성(휴)(301.5K)', 301.5, 1, 37.141864, 126.880157, 'cctv00002406', '화성휴게소2', 'https://exmobile8.hscdn.com/cctv2406image/ch00002406_20260730.154600.000.jpg', 'https://live12.exmobile.hscdn.com/exlive/cctv2406.stream/playlist.m3u8', 301.5, 0, NULL, NULL, NULL, NULL, NULL, '(16시 58분부터)', '(1차로)사고 처리중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('1100', '1', 'S', '제2경인선', 6, 110, '인천방향', '20260730170117', '04', '정체', '(17시 01분부터)', '안현분기점(18K)-신천(14K)', 18, 4, 37.440082, 126.826665, 'cctv00001537', '안현분기점2', 'https://exmobile4.hscdn.com/cctv1537image/ch00001537_20260730.154600.000.jpg', 'https://live12.exmobile.hscdn.com/exlive/cctv1537.stream/playlist.m3u8', 18, 18, NULL, NULL, NULL, NULL, NULL, '(17시 01분부터)', NULL);
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('0450', '1', 'E', '중부내륙선', 6, 45, '양평방향', '20260730170123', '01', '기타', '(갓길)승용차고장 처리중 (17시 01분부터)', '여주분기점부근(261K)', 261, -1, 37.196645, 127.61217, 'cctv00005146', '금당교_중부내륙', 'https://exmobile8.hscdn.com/cctv5146image/ch00005146_20260730.154600.000.jpg', 'https://live5.exmobile.hscdn.com/exlive/cctv5146.stream/playlist.m3u8', 261, 0, NULL, NULL, NULL, NULL, NULL, '(17시 01분부터)', '(갓길)승용차고장 처리중');
INSERT INTO TROAD_APP.T_ACDT_BRNWS_VER001 (ROUTECD, GRPID, BOUND, ROADNM, ROUTESORT, ROADSHORTNO, BOUNDNM, INCIDENT_ID, INCI_TP_ORDER, INCI_TP, MSG, INCIDENT_POS_NAME, OCRN_DSTNC, CNGS_LNGT, LAT, LON, CCTV_ID, CCTV_NM, THUMBIMAGE, HLS_URL, ST_D, EN_D, VVALUE01, VVALUE02, VVALUE03, VVALUE04, VVALUE05, CRCM_TIME, CRCM_MSG) VALUES ('2510', '1', 'E', '호남지선', 6, 251, '대전방향', '20260730170212', '04', '정체', '(17시 02분부터)', '북대전부근(52K)-회덕분기점(54K)', 52, 2, 36.409214, 127.399012, 'cctv00005468', '탑립육교', 'https://exmobile4.hscdn.com/cctv5468image/ch00005468_20260730.154600.000.jpg', 'https://live7.exmobile.hscdn.com/exlive/cctv5468.stream/playlist.m3u8', 52, 52, NULL, NULL, NULL, NULL, NULL, '(17시 02분부터)', NULL);
COMMIT;
+110
View File
@@ -0,0 +1,110 @@
#!/usr/bin/env python3
"""TROAD CSV 덤프를 Oracle INSERT 스크립트로 변환한다.
사용법:
python3 csv_to_insert.py <csv> --table OPR_MAIN.T_INCIDENT_FTMS \
--numeric ROAD_NO,START_MILEPOST --out ../sql/20_v_incident_ftms_data.sql
CSV 헤더가 대상 테이블의 컬럼명과 같아야 한다.
공백만 있는 값은 NULL 로 넣는다.
"""
from __future__ import annotations
import argparse
import csv
import sys
from pathlib import Path
BATCH_COMMIT = 50
def sql_literal(value: str, numeric: bool, date: bool) -> str:
text = value.strip()
if not text:
return "NULL"
if date:
escaped = text.replace("'", "''")
return (
f"TO_TIMESTAMP('{escaped}', "
"'YYYY-MM-DD HH24:MI:SS.FF')"
)
if numeric:
try:
float(text)
except ValueError:
return "NULL"
return text
return "'" + text.replace("'", "''") + "'"
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("csv_path")
parser.add_argument("--table", required=True)
parser.add_argument("--numeric", default="", help="숫자 컬럼 목록(콤마 구분)")
parser.add_argument(
"--date",
default="",
help="날짜/시간 컬럼 목록(콤마 구분, YYYY-MM-DD HH24:MI:SS.FF)",
)
parser.add_argument("--encoding", default="utf-8")
parser.add_argument("--out", required=True)
parser.add_argument(
"--no-truncate",
action="store_true",
help="기존 데이터 삭제 구문을 생략한다",
)
args = parser.parse_args()
numeric_cols = {c.strip().upper() for c in args.numeric.split(",") if c.strip()}
date_cols = {c.strip().upper() for c in args.date.split(",") if c.strip()}
overlap = numeric_cols & date_cols
if overlap:
parser.error(f"--numeric과 --date에 중복된 컬럼: {', '.join(sorted(overlap))}")
csv_path = Path(args.csv_path)
with csv_path.open(newline="", encoding=args.encoding) as fp:
rows = list(csv.reader(fp))
if not rows:
print(f"빈 CSV: {csv_path}", file=sys.stderr)
return 1
header = [h.strip().strip('"').upper() for h in rows[0]]
data = [r for r in rows[1:] if any(v.strip() for v in r)]
bad = [i for i, r in enumerate(data, start=2) if len(r) != len(header)]
if bad:
print(f"컬럼 수 불일치 라인: {bad[:10]}", file=sys.stderr)
return 1
out_path = Path(args.out)
out_path.parent.mkdir(parents=True, exist_ok=True)
with out_path.open("w", encoding="utf-8") as out:
out.write(f"-- 자동 생성: {csv_path.name} -> {args.table}\n")
out.write(f"-- 행 수: {len(data)}\n")
out.write("-- 생성 도구: server-dev/oracle/tools/csv_to_insert.py\n\n")
out.write("SET DEFINE OFF\n")
out.write("SET SQLBLANKLINES ON\n\n")
if not args.no_truncate:
out.write(f"DELETE FROM {args.table};\n\n")
cols = ", ".join(header)
for idx, row in enumerate(data, start=1):
values = ", ".join(
sql_literal(v, h in numeric_cols, h in date_cols)
for h, v in zip(header, row)
)
out.write(f"INSERT INTO {args.table} ({cols}) VALUES ({values});\n")
if idx % BATCH_COMMIT == 0:
out.write("COMMIT;\n")
out.write("\nCOMMIT;\n")
print(f"{len(data)} rows -> {out_path}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+98 -16
View File
@@ -1,8 +1,17 @@
#!/usr/bin/env bash
# 로컬 monorepo + GitHub submodule 포인터 → Gitea push (post-receive 배포 트리거)
# 로컬 monorepo → Gitea(exdev) 동기화 후 push (post-receive / 원격 배포 트리거)
#
# ./server-dev/push-to-gitea.sh
# ./server-dev/push-to-gitea.sh --dry-run
#
# 흐름 (git_fetch_all.sh 와 유사):
# 1) Gitea(main) fetch
# 2) 원격 변경을 현재 소스에 merge
# 3) 로컬 변경 commit
# 4) Gitea push
#
# 공식 GitHub(KoreaExpressWayCorp) 에는 push 하지 않음.
# 공식 GitHub 반영은 ./git_fetch_all.sh 전용.
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
@@ -14,7 +23,7 @@ for arg in "$@"; do
case "$arg" in
--dry-run) DRY_RUN=true ;;
-h|--help)
sed -n '2,6p' "$0"
sed -n '2,16p' "$0"
exit 0
;;
*)
@@ -36,16 +45,7 @@ if [[ ! -f .gitmodules ]]; then
fail ".gitmodules 없음 — submodule 설정 후 다시 실행"
fi
if [[ -x "${ROOT_DIR}/git_fetch_all.sh" ]]; then
log "GitHub submodule 동기화..."
if ! $DRY_RUN; then
"${ROOT_DIR}/git_fetch_all.sh"
else
"${ROOT_DIR}/git_fetch_all.sh" --dry-run
fi
else
warn "git_fetch_all.sh 없음 — submodule GitHub 동기화 생략"
fi
log "공식 GitHub 동기화/push 생략 (Gitea 전용 배포)"
# 서버 env.template·overlay와 중복되는 submodule 작업트리 변경은 되돌림
reset_submodule_noise() {
@@ -71,6 +71,72 @@ reset_submodule_noise "exAiChatBot-chatbot2.0-agent" \
reset_submodule_noise "chatbotApi-chatbot2.0-agent" gradlew
reset_submodule_noise "kakaoChatbotSkill-chatbot2.0-agent" gradlew
working_tree_dirty() {
! git diff --quiet || ! git diff --cached --quiet
}
# Gitea 원격 변경을 현재 브랜치에 반영 (commit 전에 수행)
sync_from_gitea() {
log "Gitea fetch ${GITEA_REMOTE}/${GIT_BRANCH}..."
if ! git fetch "${GITEA_REMOTE}" "${GIT_BRANCH}"; then
warn "Gitea fetch 실패 — 네트워크/원격 확인 필요. 로컬만으로 계속합니다."
return 0
fi
if ! git rev-parse "${GITEA_REMOTE}/${GIT_BRANCH}" >/dev/null 2>&1; then
log "원격 브랜치 없음 — 최초 push 대상"
return 0
fi
local local_rev remote_rev
local_rev="$(git rev-parse HEAD)"
remote_rev="$(git rev-parse "${GITEA_REMOTE}/${GIT_BRANCH}")"
if [[ "${local_rev}" == "${remote_rev}" ]]; then
log "Gitea 와 HEAD 동일 (${local_rev:0:7}) — merge 생략"
return 0
fi
if git merge-base --is-ancestor "${remote_rev}" "${local_rev}" 2>/dev/null; then
log "로컬이 Gitea 보다 앞섬 (${local_rev:0:7} → 원격 ${remote_rev:0:7}) — merge 생략"
return 0
fi
log "Gitea 변경 반영: merge ${GITEA_REMOTE}/${GIT_BRANCH} (${remote_rev:0:7})"
if $DRY_RUN; then
log "[dry-run] git merge --no-edit ${GITEA_REMOTE}/${GIT_BRANCH}"
git log --oneline "HEAD..${GITEA_REMOTE}/${GIT_BRANCH}" | head -20 || true
return 0
fi
local stashed=false
if working_tree_dirty; then
log "로컬 미커밋 변경 stash 후 merge..."
git stash push -u -m "push-to-gitea: pre-merge $(date '+%Y-%m-%d %H:%M:%S')"
stashed=true
fi
if ! git merge --no-edit "${GITEA_REMOTE}/${GIT_BRANCH}"; then
if $stashed; then
warn "merge 충돌 — stash 는 유지됨. 해결 후: git stash pop && ./server-dev/push-to-gitea.sh"
else
warn "merge 충돌 — 해결 후 ./server-dev/push-to-gitea.sh 재실행"
fi
fail "Gitea merge 실패 (충돌 수동 해결 필요)"
fi
if $stashed; then
log "stash 복원..."
if ! git stash pop; then
fail "stash pop 충돌 — git status 확인 후 해결·재실행"
fi
fi
log "✅ Gitea 변경 merge 완료"
}
sync_from_gitea
if $DRY_RUN; then
log "[dry-run] git add / commit / push 생략"
git status -sb
@@ -86,7 +152,8 @@ git add local-dev/ server-dev/ scripts/ git_fetch_all.sh 2>/dev/null || true
git add start-all-server.sh stop-all-server.sh 2>/dev/null || true
for path in chatbotApp-chatbot2.0-agent chatbotApi-chatbot2.0-agent \
exAiChatBot-chatbot2.0-agent kakaoChatbotSkill-chatbot2.0-agent; do
exAiChatBot-chatbot2.0-agent kakaoChatbotSkill-chatbot2.0-agent \
chatbotDesktopApp-chatbot2.0; do
[[ -d "${path}" ]] && git add "${path}" 2>/dev/null || true
done
@@ -94,14 +161,13 @@ done
git add -u
if ! git diff --cached --quiet; then
msg="Deploy: GitHub submodule sync $(date '+%Y-%m-%d %H:%M:%S')"
msg="Deploy: exdev sync $(date '+%Y-%m-%d %H:%M:%S')"
log "monorepo 커밋: ${msg}"
git commit -m "${msg}"
else
log "monorepo 스테이징 변경 없음"
fi
git fetch "${GITEA_REMOTE}" "${GIT_BRANCH}" 2>/dev/null || true
local_rev="$(git rev-parse HEAD)"
remote_rev=""
if git rev-parse "${GITEA_REMOTE}/${GIT_BRANCH}" >/dev/null 2>&1; then
@@ -113,6 +179,22 @@ if [[ -n "${remote_rev}" && "${local_rev}" == "${remote_rev}" ]]; then
exit 0
fi
# push 직전 한 번 더 원격 확인 (동시 배포 대비)
git fetch "${GITEA_REMOTE}" "${GIT_BRANCH}" 2>/dev/null || true
if git rev-parse "${GITEA_REMOTE}/${GIT_BRANCH}" >/dev/null 2>&1; then
remote_rev="$(git rev-parse "${GITEA_REMOTE}/${GIT_BRANCH}")"
if [[ "${local_rev}" != "${remote_rev}" ]] \
&& ! git merge-base --is-ancestor "${remote_rev}" "${local_rev}" 2>/dev/null; then
log "push 직전 원격 추가 커밋 발견 — 재 merge..."
if ! git merge --no-edit "${GITEA_REMOTE}/${GIT_BRANCH}"; then
fail "push 직전 merge 실패 — 충돌 해결 후 재실행"
fi
local_rev="$(git rev-parse HEAD)"
fi
fi
log "Gitea push ${GITEA_REMOTE} ${GIT_BRANCH} (${local_rev:0:7})..."
git push "${GITEA_REMOTE}" "${GIT_BRANCH}"
if ! git push "${GITEA_REMOTE}" "${GIT_BRANCH}"; then
fail "Gitea push 실패 — 다른 사람이 먼저 push 했을 수 있음. 재실행: ./server-dev/push-to-gitea.sh"
fi
log "✅ Gitea push 완료 — post-receive 배포 트리거됨"
Regular → Executable
+5 -5
View File
@@ -1,5 +1,5 @@
Host github.exdev.co.kr
HostName github.exdev.co.kr
Port 2222
User aidev
IdentityFile ~/.ssh/id_ed25519
Host github.exdev.co.kr
HostName github.exdev.co.kr
Port 2222
User aidev
IdentityFile ~/.ssh/id_ed25519
+297 -59
View File
@@ -3,11 +3,24 @@
#
# ./server-dev/start-all-server.sh
# ./server-dev/start-all-server.sh --no-build
# ./server-dev/start-all-server.sh --skip-desktop
# ./server-dev/start-all-server.sh --skip-java
# ./server-dev/start-all-server.sh --skip-legacy-stop
# ./server-dev/start-all-server.sh --no-pull # git 동기화 생략
# ./server-dev/start-all-server.sh --no-push # Gitea push 생략
# ./server-dev/start-all-server.sh --skip-oracle # TROAD Oracle 기동 생략
# ./server-dev/start-all-server.sh --local # 로컬 Mac 개발 모드 (local-dev 위임)
#
# ★ 개발서버(exdev) 주소/설정은 이 스크립트가 런타임 ENV 로만 적용한다.
# - WAS Mongo → 127.0.0.1 (SPRING_DATA_MONGODB_URI)
# - WAS TROAD Oracle → 127.0.0.1:1521/ORCL2 (SPRING_DATASOURCE_TROAD_*)
# - Skill → 로컬 WAS/RAG (CHATBOT_API_BASE_URL, RAG_AGENT_CHAT_URL)
# - RAG .env → host.docker.internal + EXDEV_LOCAL=true
# application.yml 등 커밋 파일은 운영 기본값(172.16.*)을 유지한다.
# 공식 GitHub 반영은 ./git_fetch_all.sh 전용 (exdev 주소를 push 하지 않음).
#
# 로컬 Mac 실행 시: Gitea(exdev) 최신 merge → 현재 소스 commit/push → 원격 배포.
# 공식 GitHub(KoreaExpressWayCorp) push 는 하지 않음 — ./git_fetch_all.sh 전용.
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
@@ -23,16 +36,25 @@ RAG_DIR="${ROOT_DIR}/exAiChatBot-chatbot2.0-agent"
API_DIR="${ROOT_DIR}/chatbotApi-chatbot2.0-agent"
SKILL_DIR="${ROOT_DIR}/kakaoChatbotSkill-chatbot2.0-agent"
APP_DIR="${ROOT_DIR}/chatbotApp-chatbot2.0-agent"
DESKTOP_DIR="${ROOT_DIR}/chatbotDesktopApp-chatbot2.0"
ENV_TEMPLATE="${SERVER_DEV_DIR}/env.exdev-server.template"
RAG_ENV="${RAG_DIR}/.env"
COMPOSE_SERVER="${RAG_DIR}/docker-compose.server.yml"
COMPOSE_CADDY="${SERVER_DEV_DIR}/docker-compose.caddy.yml"
COMPOSE_ORACLE="${SERVER_DEV_DIR}/docker-compose.oracle.yml"
LEGACY_STACK_DIR="${LEGACY_STACK_DIR:-/Users/aidev/dev/exAIChatbot2.0}"
MONGO_CONTAINER="${MONGO_CONTAINER:-exaichatbot-agent-mongo}"
ORACLE_CONTAINER="${ORACLE_CONTAINER:-exaichatbot-agent-oracle-troad}"
INTERNAL_TOOL_API_KEY="${INTERNAL_TOOL_API_KEY:-exdev-agent-tool-key}"
PUBLIC_BASE_URL="${PUBLIC_BASE_URL:-https://chatbot.exdev.co.kr}"
# exdev 전용 — 소스(application.yml)를 수정하지 않고 ENV 로만 주입
EXDEV_MONGO_URI="${EXDEV_MONGO_URI:-mongodb://127.0.0.1:27017/chatbot?heartbeatFrequencyMS=30000&minPoolSize=8&maxIdleTimeMS=18000000}"
# Docker Oracle (server-dev/docker-compose.oracle.yml) — 운영 172.16.163.76 대신 로컬
EXDEV_TROAD_JDBC_URL="${EXDEV_TROAD_JDBC_URL:-jdbc:oracle:thin:@127.0.0.1:1521/ORCL2}"
EXDEV_TROAD_USERNAME="${EXDEV_TROAD_USERNAME:-OPR_MAIN}"
EXDEV_TROAD_PASSWORD="${EXDEV_TROAD_PASSWORD:-${ORACLE_TROAD_PASSWORD:-test}}"
LLM_PORT="${LLM_PORT:-16000}"
EMBED_PORT="${EMBED_PORT:-16001}"
@@ -47,6 +69,8 @@ NO_BUILD=false
SKIP_JAVA=false
SKIP_LEGACY_STOP=false
SKIP_CADDY=false
SKIP_DESKTOP=false
SKIP_ORACLE=false
NO_PULL=false
NO_PUSH=false
LOCAL_DEV=false
@@ -58,11 +82,13 @@ for arg in "$@"; do
--skip-java) SKIP_JAVA=true ;;
--skip-legacy-stop) SKIP_LEGACY_STOP=true ;;
--skip-caddy) SKIP_CADDY=true ;;
--skip-desktop) SKIP_DESKTOP=true ;;
--skip-oracle) SKIP_ORACLE=true ;;
--no-pull) NO_PULL=true ;;
--no-push) NO_PUSH=true ;;
--local) LOCAL_DEV=true ;;
-h|--help)
sed -n '2,12p' "$0"
sed -n '2,15p' "$0"
exit 0
;;
*)
@@ -78,29 +104,8 @@ log() { echo "[$(date '+%H:%M:%S')] $*"; }
fail() { log "ERROR: $*"; exit 1; }
warn() { log "⚠️ $*"; }
sync_github_submodules() {
local tree="$1"
local fetch_script="${tree}/git_fetch_all.sh"
local -a fetch_args=()
if is_exdev_server; then
fetch_args+=(--init)
fi
if [[ ! -x "${fetch_script}" ]]; then
log "git_fetch_all.sh 없음 — submodule GitHub 동기화 생략"
return 0
fi
log "GitHub submodule 최신 동기화 (git_fetch_all.sh)..."
if [[ ${#fetch_args[@]} -gt 0 ]]; then
if ! "${fetch_script}" "${fetch_args[@]}"; then
warn "GitHub submodule 동기화 실패 — ./git_fetch_all.sh 수동 실행"
return 1
fi
elif ! "${fetch_script}"; then
warn "GitHub submodule 동기화 실패 — ./git_fetch_all.sh 수동 실행"
return 1
fi
return 0
}
# 공식 GitHub 동기화/push 는 start-all-server 경로에서 절대 수행하지 않음.
# (과거: git_fetch_all.sh 호출 → 로컬 수정이 공식 GitHub 로 올라가던 문제 방지)
push_source_to_gitea() {
if $NO_PUSH; then
@@ -126,7 +131,7 @@ wait_remote_deploy() {
EXDEV_SSH="${EXDEV_SSH}" PUBLIC_BASE_URL="${PUBLIC_BASE_URL}" "${wait_script}" || \
warn "원격 배포 대기 실패 — ssh ${EXDEV_SSH} tail /Volumes/ADATA/logs/deploy/exAichatbot_agent.log"
else
warn "wait-remote-deploy.sh 없음 — https://chatbot.exdev.co.kr/chatbot/app/ 수동 확인"
warn "wait-remote-deploy.sh 없음 — https://chatbot.exdev.co.kr/chatbot/ai/ 수동 확인"
fi
}
@@ -146,12 +151,14 @@ trigger_remote_deploy() {
rm -f \"\${WT}/.git\" /tmp/exAichatbot_agent_deploy.lock"
sync_submodules_to_server
log "원격 deploy (빌드 + 기동)..."
ssh -o BatchMode=yes "${EXDEV_SSH}" \
# SSH 세션에서 deploy 가 끝나므로, 실패 시 즉시 중단 (wait 900s 방지)
if ! ssh -o BatchMode=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=120 "${EXDEV_SSH}" \
"cp /Users/aidev/dev/exAichatbot_agent/server-dev/deploy.sh /Volumes/ADATA/git/deploy-exAichatbot_agent.sh 2>/dev/null || true; \
chmod +x /Volumes/ADATA/git/deploy-exAichatbot_agent.sh; \
export PATH=\"/opt/homebrew/bin:/Applications/Docker.app/Contents/Resources/bin:\$PATH\"; \
bash /Volumes/ADATA/git/deploy-exAichatbot_agent.sh --start-only" \
|| warn "원격 deploy 실패"
bash /Volumes/ADATA/git/deploy-exAichatbot_agent.sh --start-only"; then
fail "원격 deploy 실패 — ssh ${EXDEV_SSH} 'tail -80 /Volumes/ADATA/logs/deploy/exAichatbot_agent.log'"
fi
}
build_chatbot_app_for_deploy() {
@@ -162,22 +169,35 @@ build_chatbot_app_for_deploy() {
cd "${APP_DIR}/web"
npm ci --prefer-offline 2>/dev/null || npm install
)
bash "${APP_DIR}/build.sh"
NEXT_PUBLIC_FARE_QUERY_MOCK=true bash "${APP_DIR}/build.sh"
[[ -f "${APP_DIR}/public/index.html" ]] || fail "chatbotApp public/ 빌드 실패"
[[ -f "${APP_DIR}/public-ai/index.html" ]] || fail "chatbotApp public-ai/ 빌드 실패"
build_desktop_app
}
build_desktop_app() {
if $NO_BUILD || $SKIP_DESKTOP; then
log "데스크톱 앱 빌드 생략 (--no-build/--skip-desktop)"
return 0
fi
[[ -d "${DESKTOP_DIR}" ]] || fail "데스크톱 앱 디렉터리 없음: ${DESKTOP_DIR}"
chmod +x "${DESKTOP_DIR}/build-and-publish.sh"
log "chatbotDesktopApp Electron 재빌드 + downloads 배포..."
# 서버/원격 배포용: Mac + Windows 모두 생성
SKIP_WIN="${SKIP_WIN:-0}" SKIP_MAC="${SKIP_MAC:-0}" \
bash "${DESKTOP_DIR}/build-and-publish.sh"
}
deploy_from_local_mac() {
log "로컬 Mac → Gitea push → chatbot.exdev.co.kr 배포"
if ! $NO_PULL; then
sync_github_submodules "${ROOT_DIR}" || true
fi
log "로컬 Mac → Gitea(exdev) sync(merge) → push → chatbot.exdev.co.kr 배포"
log "공식 GitHub push 생략 (필요 시 ./git_fetch_all.sh)"
build_chatbot_app_for_deploy
push_source_to_gitea
trigger_remote_deploy
wait_remote_deploy
log "=========================================="
log "원격 배포 요청 완료"
log " UI ${PUBLIC_BASE_URL}/chatbot/app/"
log " UI ${PUBLIC_BASE_URL}/chatbot/ai/"
log " 로그 ssh ${EXDEV_SSH} tail -f /Volumes/ADATA/logs/deploy/exAichatbot_agent.log"
log "=========================================="
exit 0
@@ -199,19 +219,23 @@ sync_source_from_git() {
fail "브랜치 없음: ${branch} (GIT_DIR=${GIT_DIR})"
fi
git --work-tree="${tree}" --git-dir="${GIT_DIR}" checkout -f "${branch}"
sync_github_submodules "${tree}" || true
# Gitea work tree 만 사용 — 공식 GitHub fetch/push 없음
if [[ -f "${tree}/.gitmodules" ]]; then
log "Gitea submodule 포인터 checkout..."
git -C "${tree}" submodule update --init --recursive 2>/dev/null || \
warn "submodule update 실패 — rsync/배포 산출물로 계속"
fi
local commit
commit="$(git --git-dir="${GIT_DIR}" rev-parse --short HEAD)"
log "✅ 소스 동기화: ${commit} (${branch})"
log "✅ 소스 동기화(Gitea): ${commit} (${branch})"
elif [[ -d "${ROOT_DIR}/.git" ]]; then
log "git pull origin ${branch}..."
log "git pull origin ${branch} (Gitea/monorepo)..."
(
cd "${ROOT_DIR}"
git fetch origin "${branch}"
git checkout "${branch}"
git pull --ff-only origin "${branch}"
)
sync_github_submodules "${ROOT_DIR}" || true
log "✅ git pull 완료: $(git -C "${ROOT_DIR}" rev-parse --short HEAD)"
tree="${ROOT_DIR}"
else
@@ -222,7 +246,8 @@ sync_source_from_git() {
chmod +x "${tree}/server-dev/"*.sh 2>/dev/null || true
chmod +x "${tree}/git_fetch_all.sh" 2>/dev/null || true
chmod +x "${tree}/chatbotApp-chatbot2.0-agent/build.sh" 2>/dev/null || true
chmod +x "${tree}/start-all-server.sh" "${tree}/stop-all-server.sh" 2>/dev/null || true
chmod +x "${tree}/chatbotDesktopApp-chatbot2.0/build-and-publish.sh" 2>/dev/null || true
chmod +x "${tree}/start-all-server.sh" "${tree}/stop-all-server.sh" "${tree}/start-all.sh" 2>/dev/null || true
}
is_exdev_server() {
@@ -235,6 +260,7 @@ run_local_dev() {
local -a args=()
$NO_BUILD && args+=(--no-build)
$SKIP_JAVA && args+=(--skip-java)
$SKIP_DESKTOP && args+=(--skip-desktop)
if ((${#args[@]} > 0)); then
exec "${ROOT_DIR}/local-dev/start-all.sh" "${args[@]}"
else
@@ -318,10 +344,34 @@ stop_legacy_stack() {
}
ensure_rag_env() {
# .env 키=값 갱신 (없으면 append)
patch_env() {
local key="$1" value="$2" tmp
tmp="$(mktemp)"
if [[ -f "${RAG_ENV}" ]]; then
grep -vE "^${key}=" "${RAG_ENV}" > "${tmp}" || true
else
: > "${tmp}"
fi
printf '%s\n%s=%s\n' "$(cat "${tmp}")" "${key}" "${value}" > "${RAG_ENV}"
rm -f "${tmp}"
}
if [[ ! -f "${RAG_ENV}" ]]; then
log ".env 없음 → env.exdev-server.template 복사"
cp "${ENV_TEMPLATE}" "${RAG_ENV}"
fi
# RAG(Docker) → 호스트 chatbotApi (exdev 로컬 WAS). 운영 IP(172.16.180.130) 사용 금지.
# GitHub 커밋 기본값은 운영 IP 유지 — git_fetch_all.sh 가 push 전 복원.
patch_env "EXDEV_LOCAL" "true"
patch_env "CHATBOT_API_BASE_URL" "http://host.docker.internal:${WAS_PORT}/api"
patch_env "INTERNAL_TOOL_API_KEY" "${INTERNAL_TOOL_API_KEY}"
patch_env "CHATBOT_TOOL_TIMEOUT" "60"
if grep -qE 'CHATBOT_API_BASE_URL=.*172\.16\.180\.130' "${RAG_ENV}" 2>/dev/null; then
fail "exdev RAG .env 에 운영 WAS(172.16.180.130) 가 남아 있습니다"
fi
log "RAG .env WAS: host.docker.internal:${WAS_PORT} (로컬 chatbotApi, EXDEV_LOCAL=true)"
}
ensure_mongo() {
@@ -340,6 +390,91 @@ ensure_mongo() {
wait_port 27017 "MongoDB" 30 || true
}
oracle_container_running() {
docker ps --format '{{.Names}}' 2>/dev/null | grep -qx "${ORACLE_CONTAINER}"
}
wait_oracle_ready() {
local max="${1:-300}" i=0
log "Oracle TROAD 준비 대기 (최대 ${max}s)..."
while (( i < max )); do
if oracle_container_running && docker exec "${ORACLE_CONTAINER}" healthcheck.sh >/dev/null 2>&1; then
log "✅ Oracle TROAD ready (localhost:1521/orcl2, OPR_MAIN)"
return 0
fi
sleep 5
i=$((i + 5))
done
warn "Oracle TROAD 타임아웃 — docker logs ${ORACLE_CONTAINER}"
docker logs --tail 40 "${ORACLE_CONTAINER}" 2>/dev/null | sed 's/^/ /' || true
return 1
}
# 교통정보 뷰가 비어 있으면 oracle/apply-sql.sh 로 적용한다.
# (기존 chatbotApi SQL: TROAD_APP.V_ROUTE_NEW_NM / V_ROUTE_TRFC_VER001 등 — 앱 로직 변경 없음)
ensure_troad_schema() {
local apply="${SERVER_DEV_DIR}/oracle/apply-sql.sh"
[[ -x "$apply" ]] || return 0
local rows route_rows
rows="$(docker exec -e NLS_LANG=.AL32UTF8 "${ORACLE_CONTAINER}" bash -lc \
"sqlplus -S -L OPR_MAIN/${ORACLE_TROAD_PASSWORD:-test}@localhost:1521/ORCL2 <<'EOSQL'
SET HEADING OFF
SET FEEDBACK OFF
SET PAGESIZE 0
SELECT COUNT(*) FROM V_INCIDENT_FTMS;
EXIT
EOSQL" 2>/dev/null | tr -dc '0-9')"
route_rows="$(docker exec -e NLS_LANG=.AL32UTF8 "${ORACLE_CONTAINER}" bash -lc \
"sqlplus -S -L OPR_MAIN/${ORACLE_TROAD_PASSWORD:-test}@localhost:1521/ORCL2 <<'EOSQL'
SET HEADING OFF
SET FEEDBACK OFF
SET PAGESIZE 0
SELECT COUNT(*) FROM TROAD_APP.V_ROUTE_NEW_NM;
EXIT
EOSQL" 2>/dev/null | tr -dc '0-9')"
if [[ -n "$rows" && "$rows" -gt 0 && -n "$route_rows" && "$route_rows" -gt 0 ]]; then
log "✅ TROAD 교통정보 뷰 확인 (V_INCIDENT_FTMS ${rows}건, V_ROUTE_NEW_NM ${route_rows}건)"
return 0
fi
log "TROAD 교통정보 뷰/데이터 적용 (oracle/apply-sql.sh)..."
"$apply" >/dev/null 2>&1 \
&& log "✅ TROAD 교통정보 뷰 적용 완료" \
|| warn "TROAD 스키마 적용 실패 — server-dev/oracle/apply-sql.sh 를 직접 실행해 확인하세요"
}
ensure_oracle() {
if $SKIP_ORACLE; then
log "Oracle TROAD 기동 생략 (--skip-oracle)"
return 0
fi
[[ -f "${COMPOSE_ORACLE}" ]] || fail "server-dev/docker-compose.oracle.yml 없음"
# 이미 다른 프로세스가 1521 을 쓰는 경우(비-Oracle 컨테이너)만 경고
if ! oracle_container_running && lsof -iTCP:1521 -sTCP:LISTEN >/dev/null 2>&1; then
if docker ps --format '{{.Names}} {{.Ports}}' 2>/dev/null | grep -qE '1521'; then
log "Oracle :1521 이미 Docker 로 사용 중 — 기존 인스턴스 재사용"
wait_oracle_ready 120 && ensure_troad_schema || true
return 0
fi
warn "호스트 :1521 이 이미 점유됨 — TROAD Oracle 기동 실패 가능"
fi
log "Oracle TROAD 기동 (docker-compose.oracle.yml)..."
(
cd "${SERVER_DEV_DIR}"
docker compose -f docker-compose.oracle.yml up -d
) || fail "Oracle TROAD docker compose up 실패"
if wait_oracle_ready 360; then
ensure_troad_schema
else
warn "Oracle 미준비 — chatbotApi TROAD 조회가 실패할 수 있음"
fi
}
bootstrap_qdrant_if_empty() {
local collection="${QDRANT_COLLECTION:-qa_vectors_v2}"
if [[ -f "${RAG_ENV}" ]]; then
@@ -371,17 +506,38 @@ start_rag() {
ensure_rag_env
ensure_rag_compose
[[ -f "${COMPOSE_SERVER}" ]] || fail "docker-compose.server.yml 없음"
# compose environment 보간 + 컨테이너 env (로컬 WAS)
export EXDEV_LOCAL=true
export CHATBOT_API_BASE_URL="http://host.docker.internal:${WAS_PORT}/api"
export INTERNAL_TOOL_API_KEY="${INTERNAL_TOOL_API_KEY}"
export CHATBOT_TOOL_TIMEOUT="${CHATBOT_TOOL_TIMEOUT:-60}"
cd "${RAG_DIR}"
docker compose -f "${COMPOSE_SERVER}" down --remove-orphans 2>/dev/null || true
local -a up_flags=(-d)
if $NO_BUILD; then up_flags+=(--no-build); else up_flags+=(--build); fi
log "RAG 스택 기동 (docker-compose.server.yml)..."
log " EXDEV_LOCAL=${EXDEV_LOCAL} CHATBOT_API_BASE_URL=${CHATBOT_API_BASE_URL}"
docker compose -f "${COMPOSE_SERVER}" up "${up_flags[@]}"
wait_http "http://127.0.0.1:6333/collections" "Qdrant" 30 || true
bootstrap_qdrant_if_empty
(cd "${RAG_DIR}" && docker compose -f "${COMPOSE_SERVER}" up -d) || true
wait_http "http://127.0.0.1:${RAG_PORT}/health" "RAG API" 180 || true
wait_port "${ADMIN_PORT}" "Vector Admin" 30 || true
ensure_mongo_schema
}
# 새 소스에만 있는 Mongo 컬렉션(예: usage_sessions)이 배포 대상 DB 에 없을 수 있다.
# 기동 시 API 가 스스로 만들지만, 배포 로그에 결과를 남겨 누락을 바로 확인한다.
ensure_mongo_schema() {
local container="exaichatbot-agent-api-1"
if ! docker ps --format '{{.Names}}' | grep -qx "${container}"; then
warn "Mongo 스키마 점검 생략 — ${container} 미기동"
return 0
fi
log "Mongo 컬렉션·인덱스 점검..."
if ! docker exec "${container}" python /app/scripts/mongo_schema.py 2>&1 | sed 's/^/ /'; then
warn "Mongo 컬렉션·인덱스 일부 누락 — 위 로그 확인 (챗봇 기동은 계속됨)"
fi
}
ensure_java() {
@@ -403,16 +559,50 @@ ensure_java() {
start_java_service() {
local name="$1" dir="$2" pid_file="$3" log_file="$4"
shift 4
local port=""
case "${name}" in
chatbotApi) port="${WAS_PORT}" ;;
kakaoChatbotSkill) port="${SKILL_PORT}" ;;
esac
# exdev ENV(로컬 Mongo/WAS/RAG) 재적용을 위해 기존 프로세스는 항상 재기동한다.
if [[ -f "${pid_file}" ]]; then
local old_pid
old_pid="$(cat "${pid_file}")"
if kill -0 "$old_pid" 2>/dev/null; then
log "${name} 이미 실행 중 (PID ${old_pid})"
return 0
log "${name} 재기동 (기존 PID ${old_pid})"
kill "$old_pid" 2>/dev/null || true
sleep 2
kill -9 "$old_pid" 2>/dev/null || true
fi
rm -f "${pid_file}"
fi
if [[ -n "${port}" ]]; then
local pids
pids="$(lsof -tiTCP:"${port}" -sTCP:LISTEN 2>/dev/null || true)"
if [[ -n "${pids}" ]]; then
log "${name} :${port} 점유 프로세스 종료"
# shellcheck disable=SC2086
kill ${pids} 2>/dev/null || true
sleep 1
# shellcheck disable=SC2086
kill -9 ${pids} 2>/dev/null || true
fi
fi
[[ -n "${JAVA_HOME}" ]] || ensure_java
chmod +x "${dir}/gradlew"
# release=8 프로젝트는 Java 8 API만 허용. 기동 전 컴파일로 실패를 즉시 드러낸다.
log "${name} 컴파일 확인 (Java ${JAVA_HOME})..."
if ! (
cd "${dir}"
export JAVA_HOME
./gradlew -Dorg.gradle.java.home="${JAVA_HOME}" compileJava --quiet
); then
fail "${name} 컴파일 실패 — ${dir} 소스/JDK 확인 (Java 8 API만 사용, isBlank/List.of 금지)"
fi
log "${name} 기동 중..."
: > "${log_file}"
(
@@ -423,6 +613,15 @@ start_java_service() {
echo $! > "${pid_file}"
)
log "${name} PID $(cat "${pid_file}") → ${log_file}"
if [[ -n "${port}" ]]; then
if ! wait_port "${port}" "${name}" 240; then
warn "${name} :${port} 미개방 — 최근 로그:"
tail -40 "${log_file}" 2>/dev/null | sed 's/^/ /' || true
return 1
fi
fi
return 0
}
build_chatbot_app() {
@@ -435,7 +634,8 @@ build_chatbot_app() {
cd "${APP_DIR}/web"
npm ci --prefer-offline 2>/dev/null || npm install
)
bash "${APP_DIR}/build.sh"
NEXT_PUBLIC_FARE_QUERY_MOCK=true bash "${APP_DIR}/build.sh"
build_desktop_app
}
start_chatbot_app() {
@@ -448,7 +648,7 @@ start_chatbot_app() {
export CHATBOT_API_HOST="host.docker.internal"
docker compose up -d --force-recreate
)
wait_http "http://127.0.0.1:${APP_PORT}/chatbot/app/" "chatbotApp UI" 60 || true
wait_http "http://127.0.0.1:${APP_PORT}/chatbot/ai/" "chatbotApp UI" 60 || true
}
start_caddy() {
@@ -466,7 +666,7 @@ start_caddy() {
export LEGACY_CERTS_DIR="${cert_dir}"
docker compose -f docker-compose.caddy.yml up -d --force-recreate
)
wait_http "https://chatbot.exdev.co.kr/chatbot/app/" "HTTPS UI" 30 || true
wait_http "https://chatbot.exdev.co.kr/chatbot/ai/" "HTTPS UI" 30 || true
}
verify_stack() {
@@ -475,7 +675,36 @@ verify_stack() {
curl -sf "http://127.0.0.1:${RAG_PORT}/health" | grep -q '"status"' || { log "❌ RAG health"; ok=false; }
wait_port "${WAS_PORT}" "chatbotApi" 5 || ok=false
wait_port "${SKILL_PORT}" "kakaoChatbotSkill" 5 || ok=false
curl -sf "http://127.0.0.1:${APP_PORT}/chatbot/app/" | grep -q 'data-chatbot-app' || { log "❌ chatbotApp UI"; ok=false; }
curl -sf "http://127.0.0.1:${APP_PORT}/chatbot/ai/" | grep -q 'data-chatbot-app="ai-mode"' || { log "❌ chatbotApp UI"; ok=false; }
# exdev 는 운영 WAS IP 를 절대 참조하지 않아야 한다
local rag_was
rag_was="$(docker exec exaichatbot-agent-api-1 printenv CHATBOT_API_BASE_URL 2>/dev/null || true)"
if [[ "${rag_was}" == *172.16.180.130* ]]; then
log "❌ RAG 가 운영 WAS(172.16.180.130) 를 참조 중: ${rag_was}"
ok=false
fi
# 로컬 WAS tool 정의 로드 (음식메뉴 등 WEB tool 전제)
local tools_json
tools_json="$(curl -sf -m 8 -H "X-Internal-Tool-Key: ${INTERNAL_TOOL_API_KEY}" \
"http://127.0.0.1:${WAS_PORT}/api/v1/tools/definitions" 2>/dev/null || true)"
if ! echo "${tools_json}" | grep -q 'REST_AREA_FOOD_LIST'; then
log "❌ chatbotApi tool 정의에 REST_AREA_FOOD_LIST 없음 (WAS 미기동/연동 실패)"
ok=false
else
log "✅ chatbotApi domain tools OK"
fi
# TROAD Oracle 은 반드시 로컬 Docker(127.0.0.1:1521) — 운영 172.16.163.76 타임아웃 방지
if ! $SKIP_ORACLE && ! $SKIP_JAVA; then
local cong_code
cong_code="$(curl -sS -m 25 -o /tmp/exdev-cong.json -w '%{http_code}' \
"http://127.0.0.1:${WAS_PORT}/api/troad/congestion?routeName=%EA%B2%BD%EB%B6%80%EC%84%A0" 2>/dev/null || echo 000)"
if [[ "${cong_code}" != "200" ]] || ! grep -q '"status"[[:space:]]*:[[:space:]]*true' /tmp/exdev-cong.json 2>/dev/null; then
log "❌ TROAD 정체 조회 실패 (http=${cong_code}) — WAS 가 localhost Oracle 을 보는지 확인"
ok=false
else
log "✅ TROAD Oracle(localhost) congestion OK"
fi
fi
if $ok; then log "✅ 전체 스택 정상"; return 0; fi
log "⚠️ 일부 서비스 미응답 — ${LOG_DIR}/ 확인"
return 1
@@ -505,27 +734,34 @@ log "exdev 서버 모드"
stop_legacy_stack
ensure_host_ai
ensure_mongo
ensure_oracle
start_rag
if ! $SKIP_JAVA; then
ensure_java
# Skill 먼저 (WAS WEB tool 이 Skill data-portal 을 역호출)
log "exdev Java ENV: Skill→127.0.0.1 WAS/RAG, WAS Mongo/TROAD Oracle→127.0.0.1 (소스 yml 미변경)"
start_java_service "kakaoChatbotSkill" "${SKILL_DIR}" \
"${RUN_DIR}/kakao-skill.pid" "${LOG_DIR}/kakao-skill.log" \
"EXDEV_LOCAL=true" \
"AGENT_MODE=agent" \
"RAG_AGENT_CHAT_URL=http://127.0.0.1:${RAG_PORT}/agent/chat" \
"CHATBOT_API_BASE_URL=http://127.0.0.1:${WAS_PORT}/api/" \
"INTERNAL_TOOL_API_KEY=${INTERNAL_TOOL_API_KEY}" \
"CHATBOT_APP_URL=${PUBLIC_BASE_URL}/chatbot/ai/" \
|| warn "kakaoChatbotSkill 기동 실패"
start_java_service "chatbotApi" "${API_DIR}" \
"${RUN_DIR}/chatbot-api.pid" "${LOG_DIR}/chatbot-api.log" \
"INTERNAL_TOOL_API_KEY=${INTERNAL_TOOL_API_KEY}" \
"SKILL_INTERNAL_BASE_URL=http://127.0.0.1:${SKILL_PORT}" \
"RAG_SERVER_HOST=127.0.0.1" \
"RAG_SERVER_PORT=${RAG_PORT}"
start_java_service "kakaoChatbotSkill" "${SKILL_DIR}" \
"${RUN_DIR}/kakao-skill.pid" "${LOG_DIR}/kakao-skill.log" \
"AGENT_MODE=agent" \
"RAG_AGENT_CHAT_URL=http://127.0.0.1:${RAG_PORT}/agent/chat" \
"CHATBOT_API_BASE_URL=http://127.0.0.1:${WAS_PORT}/api/" \
"INTERNAL_TOOL_API_KEY=${INTERNAL_TOOL_API_KEY}" \
"CHATBOT_APP_URL=${PUBLIC_BASE_URL}/chatbot/app/"
wait_port "${WAS_PORT}" "chatbotApi" 240 || true
wait_port "${SKILL_PORT}" "kakaoChatbotSkill" 240 || true
"RAG_SERVER_PORT=${RAG_PORT}" \
"SPRING_DATA_MONGODB_URI=${EXDEV_MONGO_URI}" \
"SPRING_DATASOURCE_TROAD_URL=${EXDEV_TROAD_JDBC_URL}" \
"SPRING_DATASOURCE_TROAD_USERNAME=${EXDEV_TROAD_USERNAME}" \
"SPRING_DATASOURCE_TROAD_PASSWORD=${EXDEV_TROAD_PASSWORD}" \
|| warn "chatbotApi 기동 실패"
fi
start_chatbot_app
@@ -533,11 +769,13 @@ start_caddy
log "=========================================="
log "기동 완료"
log " HTTPS UI ${PUBLIC_BASE_URL}/chatbot/app/"
log " HTTPS UI ${PUBLIC_BASE_URL}/chatbot/ai/"
log " RAG http://127.0.0.1:${RAG_PORT}/health"
log " Admin http://127.0.0.1:${ADMIN_PORT}/"
log " WAS http://127.0.0.1:${WAS_PORT}/"
log " Skill http://127.0.0.1:${SKILL_PORT}/web/ask"
log " Skill http://127.0.0.1:${SKILL_PORT}/web/ask"
log " Oracle localhost:1521/orcl2 (OPR_MAIN / TROAD)"
log " Kakao ${PUBLIC_BASE_URL}/kakao/skill"
log " 로그 ${LOG_DIR}/"
log " 종료 ./server-dev/stop-all-server.sh"
log "=========================================="
+23 -1
View File
@@ -4,6 +4,8 @@
# ./server-dev/stop-all-server.sh
# ./server-dev/stop-all-server.sh --keep-caddy
# ./server-dev/stop-all-server.sh --purge-mongo
# ./server-dev/stop-all-server.sh --purge-oracle
# ./server-dev/stop-all-server.sh --keep-oracle
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
@@ -14,21 +16,27 @@ RAG_DIR="${ROOT_DIR}/exAiChatBot-chatbot2.0-agent"
APP_DIR="${ROOT_DIR}/chatbotApp-chatbot2.0-agent"
COMPOSE_SERVER="${RAG_DIR}/docker-compose.server.yml"
COMPOSE_CADDY="${SERVER_DEV_DIR}/docker-compose.caddy.yml"
COMPOSE_ORACLE="${SERVER_DEV_DIR}/docker-compose.oracle.yml"
MONGO_CONTAINER="${MONGO_CONTAINER:-exaichatbot-agent-mongo}"
ORACLE_CONTAINER="${ORACLE_CONTAINER:-exaichatbot-agent-oracle-troad}"
LEGACY_STACK_DIR="${LEGACY_STACK_DIR:-/Users/aidev/dev/exAIChatbot2.0}"
KEEP_CADDY=false
KEEP_ORACLE=false
PURGE_MONGO=false
PURGE_ORACLE=false
STOP_HOST_AI=false
for arg in "$@"; do
case "$arg" in
--keep-caddy) KEEP_CADDY=true ;;
--keep-oracle) KEEP_ORACLE=true ;;
--purge-mongo) PURGE_MONGO=true ;;
--purge-oracle) PURGE_ORACLE=true ;;
--stop-host-ai) STOP_HOST_AI=true ;;
-h|--help)
sed -n '2,8p' "$0"
sed -n '2,10p' "$0"
exit 0
;;
esac
@@ -87,6 +95,20 @@ if ! $KEEP_CADDY && [[ -f "${COMPOSE_CADDY}" ]]; then
log "Caddy(HTTPS) 중지"
fi
if $KEEP_ORACLE; then
log "Oracle TROAD 유지 (--keep-oracle)"
elif [[ -f "${COMPOSE_ORACLE}" ]]; then
if $PURGE_ORACLE; then
(cd "${SERVER_DEV_DIR}" && docker compose -f docker-compose.oracle.yml down -v --remove-orphans 2>/dev/null) || true
docker rm -f "${ORACLE_CONTAINER}" 2>/dev/null || true
log "Oracle TROAD 컨테이너·볼륨 삭제 (${ORACLE_CONTAINER})"
else
(cd "${SERVER_DEV_DIR}" && docker compose -f docker-compose.oracle.yml stop 2>/dev/null) || true
docker stop "${ORACLE_CONTAINER}" 2>/dev/null || true
log "Oracle TROAD 중지 (${ORACLE_CONTAINER}, 데이터 볼륨 유지)"
fi
fi
if $PURGE_MONGO; then
docker stop "${MONGO_CONTAINER}" 2>/dev/null || true
docker rm -f "${MONGO_CONTAINER}" 2>/dev/null || true
+36 -3
View File
@@ -14,6 +14,7 @@ SUBMODULES=(
chatbotApi-chatbot2.0-agent
exAiChatBot-chatbot2.0-agent
kakaoChatbotSkill-chatbot2.0-agent
chatbotDesktopApp-chatbot2.0
)
log "원격 동기화: ${EXDEV_SSH}:${REMOTE_WT}"
@@ -22,22 +23,32 @@ for path in "${SUBMODULES[@]}"; do
local_src="${ROOT_DIR}/${path}"
[[ -d "${local_src}" ]] || { echo "ERROR: ${local_src} 없음"; exit 1; }
log ">>> rsync ${path}"
# build/dist/logs 는 자바 패키지명(예: kakao.response.build)과 충돌하므로
# 선행 슬래시로 프로젝트 최상위에만 적용한다.
rsync -az --delete \
--exclude 'node_modules/' \
--exclude 'build/' \
--exclude '.gradle/' \
--exclude 'qdrant_data/' \
--exclude 'logs/' \
--exclude '.next/' \
--exclude '.git/' \
--exclude '/build/' \
--exclude '/dist/' \
--exclude '/logs/' \
--exclude '/web/out/' \
"${local_src}/" "${EXDEV_SSH}:${REMOTE_WT}/${path}/"
done
log "overlay 복사..."
rsync -az "${ROOT_DIR}/server-dev/docker-compose.rag.server.yml" \
"${EXDEV_SSH}:${REMOTE_WT}/server-dev/docker-compose.rag.server.yml"
rsync -az "${ROOT_DIR}/server-dev/docker-compose.oracle.yml" \
"${EXDEV_SSH}:${REMOTE_WT}/server-dev/docker-compose.oracle.yml"
rsync -az "${ROOT_DIR}/server-dev/oracle/" \
"${EXDEV_SSH}:${REMOTE_WT}/server-dev/oracle/"
rsync -az "${ROOT_DIR}/local-dev/docker-compose.rag.local.yml" \
"${EXDEV_SSH}:${REMOTE_WT}/local-dev/docker-compose.rag.local.yml" 2>/dev/null || true
ssh -o BatchMode=yes "${EXDEV_SSH}" "mkdir -p '${REMOTE_WT}/exAiChatBot-chatbot2.0-agent' && \
ssh -o BatchMode=yes "${EXDEV_SSH}" "mkdir -p '${REMOTE_WT}/exAiChatBot-chatbot2.0-agent' '${REMOTE_WT}/server-dev/oracle/init' && \
cp '${REMOTE_WT}/server-dev/docker-compose.rag.server.yml' '${REMOTE_WT}/exAiChatBot-chatbot2.0-agent/docker-compose.server.yml' 2>/dev/null || true"
if [[ -d "${ROOT_DIR}/chatbotApp-chatbot2.0-agent/public" ]]; then
@@ -46,4 +57,26 @@ if [[ -d "${ROOT_DIR}/chatbotApp-chatbot2.0-agent/public" ]]; then
"${EXDEV_SSH}:${REMOTE_WT}/chatbotApp-chatbot2.0-agent/public/"
fi
if [[ -d "${ROOT_DIR}/chatbotApp-chatbot2.0-agent/public-ai" ]]; then
log ">>> rsync chatbotApp/public-ai (AI 모드 빌드 산출물)"
rsync -az "${ROOT_DIR}/chatbotApp-chatbot2.0-agent/public-ai/" \
"${EXDEV_SSH}:${REMOTE_WT}/chatbotApp-chatbot2.0-agent/public-ai/"
fi
# Windows 체크아웃(core.autocrlf)에서 넘어온 CRLF 는 macOS 에서
# "/bin/sh^M: bad interpreter" 로 죽는다. 전송 후 실행 진입점만 LF 로 강제한다.
log "원격 실행 스크립트 LF 정규화..."
ssh -o BatchMode=yes "${EXDEV_SSH}" "bash -s" <<EOSSH
set -e
WT="${REMOTE_WT}"
for f in \$(find "\${WT}" -name gradlew -not -path '*/node_modules/*' 2>/dev/null) \
\$(find "\${WT}" -name '*.sh' -not -path '*/node_modules/*' 2>/dev/null); do
if head -c 4000 "\$f" | grep -q \$'\r'; then
tr -d '\r' < "\$f" > "\$f.lf" && mv "\$f.lf" "\$f"
echo " LF 변환: \$f"
fi
chmod +x "\$f" 2>/dev/null || true
done
EOSSH
log "✅ submodule rsync 완료"
+51 -8
View File
@@ -1,10 +1,12 @@
#!/usr/bin/env bash
# Gitea push 후 chatbot.exdev.co.kr 배포 완료 대기
# - UI 응답 또는 배포 로그의 "배포 완료" 확인
# - "배포 실패"/컴파일 오류는 즉시 종료 (900s 무의미 대기 방지)
set -euo pipefail
EXDEV_SSH="${EXDEV_SSH:-aidev@chatbot.exdev.co.kr}"
DEPLOY_LOG="${DEPLOY_LOG:-/Volumes/ADATA/logs/deploy/exAichatbot_agent.log}"
PUBLIC_URL="${PUBLIC_BASE_URL:-https://chatbot.exdev.co.kr}/chatbot/app/"
PUBLIC_URL="${PUBLIC_BASE_URL:-https://chatbot.exdev.co.kr}/chatbot/ai/"
MAX_WAIT="${DEPLOY_WAIT_SEC:-900}"
log() { echo "[wait-deploy] $*"; }
@@ -18,26 +20,67 @@ if ! ssh_cmd "test -f '${DEPLOY_LOG}'" 2>/dev/null; then
ssh_cmd "bash /Volumes/ADATA/git/deploy-exAichatbot_agent.sh" || true
fi
# 대기 시작 시점의 로그 길이 — 이후 새로 찍힌 줄만 성공/실패 판정에 사용
LOG_BASE_BYTES="$(ssh_cmd "wc -c < '${DEPLOY_LOG}' 2>/dev/null || echo 0" | tr -d '[:space:]')"
LOG_BASE_BYTES="${LOG_BASE_BYTES:-0}"
log "배포 완료 대기 (최대 ${MAX_WAIT}s) — ${EXDEV_SSH}"
start_ts="$(date +%s)"
deadline=$((start_ts + MAX_WAIT))
new_log_tail() {
ssh_cmd "tail -c +$((LOG_BASE_BYTES + 1)) '${DEPLOY_LOG}' 2>/dev/null | tail -80" || true
}
while (( $(date +%s) < deadline )); do
if curl -sf --max-time 5 "${PUBLIC_URL}" 2>/dev/null | grep -q 'data-chatbot-app'; then
log "✅ UI 응답: ${PUBLIC_URL}"
ssh_cmd "tail -8 '${DEPLOY_LOG}'" 2>/dev/null || true
exit 0
recent="$(new_log_tail)"
# 신규 로그에 실패 마커가 있으면 즉시 종료
if echo "${recent}" | grep -qE '\[ERROR\] 배포 실패|ERROR: chatbotApi 컴파일 실패|BUILD FAILED|\[ERROR\] 다른 배포 진행 중'; then
log "⚠️ 원격 배포 실패 감지 — 최근 로그:"
echo "${recent}" | tail -40
exit 1
fi
if ssh_cmd "grep -q '배포 완료' '${DEPLOY_LOG}'" 2>/dev/null; then
if curl -sf --max-time 5 "${PUBLIC_URL}" 2>/dev/null | grep -q 'data-chatbot-app'; then
# UI 살아있어도, 이번 배포가 아직 실패로 끝났으면 성공으로 치지 않음
if echo "${recent}" | grep -qE '\[ERROR\] 배포 실패|ERROR: chatbotApi 컴파일 실패|BUILD FAILED'; then
log "⚠️ UI는 응답하나 이번 배포 로그에 실패가 있습니다"
echo "${recent}" | tail -40
exit 1
fi
if echo "${recent}" | grep -q '배포 완료'; then
log "✅ UI 응답 + 배포 완료 로그: ${PUBLIC_URL}"
ssh_cmd "tail -8 '${DEPLOY_LOG}'" 2>/dev/null || true
exit 0
fi
# start-only 직후 UI 가 이전 빌드로 살아 있을 수 있음 — 신규 성공 로그를 우선
if echo "${recent}" | grep -q '배포 시작'; then
:
else
log "✅ UI 응답: ${PUBLIC_URL}"
ssh_cmd "tail -8 '${DEPLOY_LOG}'" 2>/dev/null || true
exit 0
fi
fi
if echo "${recent}" | grep -q '배포 완료'; then
last_line="$(ssh_cmd "tail -1 '${DEPLOY_LOG}'" 2>/dev/null || true)"
if [[ "${last_line}" == *"배포 완료"* ]]; then
if [[ "${last_line}" == *"배포 완료"* ]] || [[ "${last_line}" == *"락 해제"* ]]; then
# 성공 후 trap 이 락 해제를 찍을 수 있음
if echo "${recent}" | grep -qE '\[ERROR\] 배포 실패|BUILD FAILED'; then
log "⚠️ 배포 실패 로그 감지"
echo "${recent}" | tail -40
exit 1
fi
log "✅ 배포 로그 확인"
ssh_cmd "tail -8 '${DEPLOY_LOG}'" 2>/dev/null || true
exit 0
fi
fi
sleep 10
sleep 5
done
log "⚠️ 배포 대기 타임아웃 — 로그 확인: ssh ${EXDEV_SSH} tail -50 ${DEPLOY_LOG}"
new_log_tail | tail -40
exit 1