Commit Graph

25 Commits

Author SHA1 Message Date
infraurp
28a0329114 MariaDB sql_mode에서 ONLY_FULL_GROUP_BY 제거
원본 MySQL 8과 동작을 맞추려고 이 모드를 켰던 것이 역효과였다. MySQL 8은
GROUP BY 컬럼에 대한 함수 종속성을 판정해 집계에 없는 컬럼도 통과시키지만
MariaDB는 그 판정을 하지 않는다. 같은 sql_mode를 그대로 옮기면 로컬에서
잘 돌던 쿼리가 서버에서만 터진다.

증상: 관리자 2차인증 로그인 직후 /mnt/main.do 가 404. 실제로는 대시보드
쿼리가 'Z.STATUS1' isn't in GROUP BY 로 실패하고 예외 처리가 404로 이어진 것.

ONLY_FULL_GROUP_BY 제외는 MariaDB의 기본값이기도 하다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 15:11:19 +09:00
infraurp
6c9d88aa2e csv.wise.ai.kr vhost에 압축·정적 캐시 추가
메인 화면 하나가 woff 폰트만 3MB 넘게 끌어오는데 압축도 캐시 헤더도 없었다.
유선망에서는 티가 안 나지만(같은 폰트 0.15초) 테더링에서는 25초가 걸려
브라우저가 로딩을 끝내지 못하고 "접속 안 됨"처럼 보인다.

- mod_deflate: HTML 52,665B → 9,516B (82% 감소)
- 폰트 1년 immutable, 이미지 7일, css/js 1시간 캐시 — 재방문 시 3MB 재다운로드 제거

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 11:42:47 +09:00
infraurp
ddacd1b7f5 csv.wise.ai.kr 배포 파이프라인 신설 (PC → git → web → was)
Some checks failed
deploy-wise / deploy (push) Failing after 11s
웹서버(175.118.124.176)의 Gitea 러너가 JDK8 로 WAR 을 빌드해 WAS(27.255.76.2)의
Tomcat·MariaDB 컨테이너로 배포한다. WAS 는 웹서버를 통해서만 닿고, Tomcat 은
127.0.0.1 바인딩이라 웹서버가 SSH 터널로 잇는다.

- WAS 는 가용 메모리가 3G 안팎(llama-server 200G+ 점유)이라 빌드를 웹서버에서 한다
- claudeops 가 sudo 를 쓸 수 없어 Tomcat·MariaDB 를 컨테이너로 올렸다
- 배포 스크립트를 매 실행마다 저장소본으로 덮어써 서버 사본 드리프트를 막는다

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 11:16:10 +09:00
infraurp
7a8ec86642 개인정보보호 기능개선 6차 — DtaUseStatsVO userNmSe 누락으로 인한 기동실패 수정
545b49d(4차 델타)에서 EgovDtaUseStats_SQL_Mysql.xml resultMap에
userNmSe 컬럼 매핑만 추가하고 대응 Java 필드/DAO 조건부복호화 배선을
누락했다. iBatis2는 이 프로퍼티 부재를 컴파일타임이 아닌 Spring
컨텍스트 기동시 sql-map-config 전체 파싱 단계에서 검증하므로,
컴파일은 성공했지만 실제 WAS 재기동 시 ProbeException으로 컨텍스트
전체가 기동 실패해 로컬 ROOT가 다운되는 사고로 이어졌다.

- DtaUseStats.java: userNmSe 필드 + getter/setter 추가
- DtaUseStatsDAO.selectDtaUseStats(): GNR일 때만 조건부 복호화 배선

재기동 후 컨텍스트 정상 기동 확인(오류 0건), /frt/main.do 200,
/mnt/sec/accountPolicy/policyView.do 302로 검증.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 10:52:44 +09:00
infraurp
1be7d84e88 개인정보보호 기능개선 5차 — comvnusermaster/comvnuserinfo 뷰 GNR 컷오버 DDL 실행분 커밋
회원정보 암호화(Action4)의 마지막 단계. 545b49d로 반영한 소비자 정비(66개 표시 +
전체 검색전환)를 전제로, 두 공유 뷰의 GNR 분기를 MBER_NM(평문)에서 MBER_NM_ENC(암호문)로
전환하고 검색용 USER_NM_HASH 컬럼을 추가하는 DDL을 127.0.0.1:3306 dev DB에 실제 실행했다.

- information_schema.views.VIEW_DEFINITION을 서버사이드 REPLACE()로 최소 치환(PREPARE/
  EXECUTE) — comvnuserinfo의 한글 리터럴(USER_GUBUN_NM)을 클라이언트에서 재입력하지
  않아 터미널 인코딩 문제를 원천 회피
- 실행 전 원본 정의를 privacy_view_def_backup 테이블에 백업, 치환 건수/컬럼 존재
  여부를 assertion으로 강제해 잘못된 정의 반영을 차단
- 행 수(USER_SE/USER_GUBUN별 COUNT) 실행 전후 동일 확인, GNR 표본 암호문+해시 노출
  확인, USR/ENT 표본 평문 그대로 유지 확인 — 상세 로그는 _workspace/deploy/20260811_0850/
  DB_APPLY_LOG.md(gitignored, 로컬 전용)

주의: 이번엔 코드(545b49d) 커밋 후 로컬 WAS 재기동 전에 DB DDL을 먼저 실행했다 —
다음 반영 시 코드부터 배포하고 재기동할 것(LAST_DEPLOYED.md 참조).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 09:14:38 +09:00
infraurp
545b49daf7 개인정보보호 기능개선 4차 — 회원정보 암호화 읽기전환/검색전환 완료(뷰 재정의 대비)
일반회원 이름(COMTNGNRLMBER.MBER_NM) 암호화 저장(추가제안 Action4)의 마지막 단계로,
comvnusermaster/comvnuserinfo 뷰를 거쳐 이름을 표시·검색하는 전체 소비자(66개 표시
구문 + 신규 발견된 검색(LIKE/exact-match) 구문)를 뷰 재정의 이전에 전수 정비했다.

- 표시: 판별 컬럼(USER_SE 등) 추가 후 GNR일 때만 조건부 복호화
- 검색: LIKE/exact-match를 (HASH = #hash# OR 원본 조건) 패턴으로 전환
- 과정에서 발견한 기존 버그(EgovBBSLoneMaster/EgovBoard의 columnIndex 위치
  불일치, BizPrvol/EgovLoginUsr/BizPrapp의 누락된 검색 전환 지점)를 최소 범위로
  수정하거나(내 필드에 한해) 영향받지 않도록 우회 처리

뷰 자체(ALTER VIEW)는 아직 미실행 — 모든 소비자 정비가 끝나야 실행 가능한
all-or-nothing 게이트가 있어 별도로 진행한다.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 08:50:04 +09:00
infraurp
e35aa9db06 로그인 실패 계정잠금 예외(SER-001 #24) — 최고관리자 완전 잠김 방지
관리자 계정이 5회 실패로 잠기면 해제 화면도 로그인이 있어야 들어갈 수 있어
아무도 풀 수 없는 상태가 될 수 있었다. 지정 계정을 LOGIN_LOCK_EXEMPT
화이트리스트로 등록하면 실패 잠금 판정만 면제되고, LOGIN_HISTORY 감사이력과
2단계 인증(OTP)은 예외 없이 그대로 적용된다. 캐시는 fail-closed로 조회
실패 시 전 계정 정상 잠금 판정을 유지한다.

접근통제 정책 화면에 '잠금 예외 계정' 섹션을 추가해 등록/해제하며,
같은 화면의 '잠금 해제 방식'은 실사용 중인 단일 옵션만 남기도록 단순화했다.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 17:35:04 +09:00
infraurp
363138eef5 장기 미사용 계정 현황 화면명에 "관리자" 명시 + 행별 조치 버튼 축소
미사용계정 현황(#11, 메뉴 9100037)이 대상이 개인정보취급자(EMP) 계정임을
화면·메뉴명에서 알 수 없어 오해 소지가 있었다. "장기 미사용 계정" →
"장기 미사용 관리자 계정"으로 명시(요약표/목록 캡션, 메뉴명, 프로그램 설명).
이미 배포된 환경을 위해 재실행 안전한 UPDATE 문을 DML에 추가.

목록 행별 "말소"/"잠금" 버튼은 시각적으로 과도하게 커서 축소(.btn3.mini).
상단 "선택 말소" 일괄 버튼은 그대로 둠.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 16:59:37 +09:00
infraurp
4413c5aaea 장기 미사용 계정 파기 배치를 관리자(EMP) 계정 한정으로 변경
일반회원(GNR)은 탈퇴 즉시 하드 DELETE되어 휴면 전환 기반 지연 파기 대상이
아니었으므로 배치에서 제외. 관리자(개인정보취급자) 계정은 SFR-002 핵심요건
(개인정보보호위 점검 지적사항 — 휴면 대상이 일반회원에 한정되고 개인정보
취급자가 미포함)이라 로직은 그대로 유지하고 대상만 EMP로 좁혔다.
정책 화면(계정 관리 정책) 안내 문구도 관리자 계정 대상임을 명시.

스키마 변경 없음(ACCOUNT_MNG_POLICY.DELETE_PRESERVE_DAY/PURGE_USE_YN,
ACCOUNT_DELETE_HISTORY 재사용).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 16:40:46 +09:00
infraurp
94da0fe9ae 개인정보보호 기능개선 3차 — 접근통제 정책 화면 외 미커밋 산출물 일괄 커밋
5개 세션에 걸쳐 쌓인 미커밋 변경분을 한 번에 정리한다. 주 산출물은 이번 세션의
접근통제 정책 적용(SER-001 요건 4·5)이고, 나머지는 앞선 세션들의 백로그다.

■ 접근통제 정책 적용 (SER-001 요건 4·5, 이번 세션)
「개인정보보호강화 파일럿 개발항목」 접근통제 정책 적용(Action2) 시안 반영.

- ACCESS_CONTROL_POLICY(단일행) + 관리자 화면 신규 (메뉴 9100047)
  · 계정 잠금: 인증 실패 임계값(10 -> 5), 잠금 해제 방식(관리자화면+이력 / +사유필수)
  · 자동 로그아웃: 미사용 시간(60 -> 30분), 만료 임박 안내 사용여부·시점
  · 세션 재발급: 2차 인증 성공 시 세션 고정(Session Fixation) 차단 여부
- SessionPolicyInterceptor 신규 — /mnt/ 요청마다 정책값으로 세션 타임아웃 적용.
  web.xml 재배포 없이 값이 바뀐다(2025.9 자료요청 3번 "시간 설정 기능 없음" 해소).
  web.xml <session-timeout>30 은 이제 폴백값이다.
- 잠금 임계값 저장 시 인증 경로가 읽는 LOGIN_LOCK_COUNT 를 함께 동기화.
  정책 테이블만 고치면 화면 숫자만 바뀌고 실제 인증은 옛 값을 계속 쓰기 때문이다.
- 관리자 상단(top.jsp): 로그인 후 경과시간 + 자동 로그아웃 잔여 카운트다운,
  만료 임박 안내와 연장(/mnt/session/extend.do).
  세션 상태를 주기 폴링하지 않는다 — 그 요청 자체가 세션을 갱신해
  '미사용 자동 로그아웃'이 영원히 오지 않기 때문이다.
- 자동 로그아웃 시 로그인 화면 이동: actionLogout.do?expired=Y 로 세션 invalidate 후
  로그인 화면 + 사유 안내. 수동 로그아웃(프론트 메인 이동)은 기존 동작 유지.
- 계정잠금관리: 정책이 '사유 필수'면 해제 사유 강제, ACCOUNT_UNLOCK_HISTORY 적재.

■ EgovLoginLogAspect fail-safe (회귀 수정)
접속기록 적재 예외가 @Before 어드바이스 밖으로 나가 로그인·로그아웃이 통째로 500 이
되고 있었다(로컬: MySQL 8 + mysql-connector 5.1.17 의 tx_isolation 조회 실패).
클래스 Javadoc 이 이미 fail-safe 를 명세하고 있었으나 구현이 따르지 않았다.
try/catch 로 인증 흐름을 살리되, 접속기록 유실은 SFR-004 직결이라 ERROR 로 남긴다.

■ 앞선 세션 백로그
- 접속기록(SFR-004): 조회·CSV 비동기 다운로드(PDAL_DOWNLOAD_JOB), 업무유형 매핑
- 로그인 접속기록(#62): COMTNLOGINLOG 접속IP·접속ID 유실 복구 + 접속위치 스냅샷
- 권한관리(SFR-001): 권한변경 이력 CSV 비동기 다운로드, 신청·승인 워크플로 화면 정리
- 미사용계정(SFR-002): 현황 화면 시안 반영(요약·역할·잠금/말소·조치 이력)
- 회원정보 암호화(추가제안 Action4): AES 암복호화·검색용 해시, 이관 배치와 사전 백업

■ 커밋 제외
font/(글꼴 설치본 22M), 제안서 문서(pptx/hwp), .claude/(하네스) 는 소스가 아니라 제외.
.claude/ 버전관리 여부는 별도 판단이 필요하다.

배포 산출물: _workspace/deploy/20260810_1300/ (DELTA.md, sql/, APPLY_LOG.md)
브라우저 검증(2단계 인증 필요)은 APPLY_LOG.md B1~B7 로 남겨둔다.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 13:58:58 +09:00
infraurp
f2029a00a0 개인정보보호 기능개선 2차 구현 — 접속기록 안정화·솔트 인증·관리자 화면 4종
접속기록(SFR-004/#33):
- AccessLogQueue 포화 방어. 종전 offer(timeout) 무한 반복은 컨슈머 정지 시
  요청 스레드가 영구 대기해 WAS 스레드 풀 고갈 → 사이트 전면 정지로 이어졌다.
  대기를 3회로 제한하고 포화 차단기(saturated)를 도입해 지속 포화 시 즉시 판정한다.
- 유실은 조용히 넘기지 않는다. recordDrop 이 누적 집계 + 초기 20건/이후 100건 표본
  ERROR 로그로 남긴다(법정 보관 대상이므로 사후 추적 가능해야 함).
- 컨슈머 루프가 Exception 이 아닌 Throwable 까지 흡수한다. Error 하나로 컨슈머가
  죽으면 running=true 인 채 이후 전 요청이 포화 대기에 빠졌다.
- 자체 데몬 워치독(30초) 추가 — 컨슈머 사망 시 재기동, 적체 경고, 차단기 자동 해제.
  task:annotation-driven 활성화 여부와 무관해야 하므로 @Scheduled 를 쓰지 않는다.
- 해시체인 순번 보장을 위한 단일 컨슈머 전제는 유지(병렬화 금지).

인증정보 보호(SER-001/SER-003/#27):
- EgovFileScrty 사용자별 랜덤 솔트(S1: 형식) 도입, matches() 로 검증 일원화 —
  기존 무솔트 계정과 공존한다.
- 비밀번호 변경 시 현재 비밀번호 검증 복구. 종전에는 DB 값을 자기 자신과 비교해
  항상 true 였고, 입력한 oldPassword 가 어디에도 쓰이지 않았다.
- 평문 비밀번호 println 제거.

관리자 화면: 접속기록 조회, 업무구분 매핑 관리, 권한변경 이력, 미사용계정 현황.
계정 파기(AccountDelete) 서비스 및 DDL/DML 추가.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 15:05:03 +09:00
infraurp
65bbe591d1 인증 실패 이력 IP 기록·보관기간·조회화면 구현 (#22-1)
All checks were successful
deploy-dev / deploy (push) Successful in 42s
#22(실패이력 활성 경로 이설)로 적재는 살아났으나 LOGIN_HISTORY가
ID/CREATE_DATE/GUBUN 3컬럼뿐이라 (1) 접속 IP 미기록 (2) 로그인 성공 시
당일 이력 DELETE로 무차별 대입 흔적 소멸 문제가 있었다.

- DDL: LOGIN_HISTORY에 CONECT_IP(45)/RESET_YN + 인덱스 2종,
  ACCOUNT_MNG_POLICY.LOGIN_HIST_KEEP_DAY(기본 730일) 추가
- 적재: insertFailHistory 컬럼 명시 전환 + ClientIpResolver IP 세팅
  (종전 무컬럼 VALUES(3값)은 컬럼 추가 시 ERROR 1136 — DDL과 한 쌍)
- 보존: 성공 시 DELETE -> RESET_YN='Y' 소프트 리셋.
  selectFailCount가 RESET_YN='N'만 세므로 계정잠금 동작은 종전과 동일
- 화면: /mnt/sec/loginFailHistory/listView.do (계정·구분·IP·기간·리셋여부
  검색 + 페이징), 메뉴 9100039 + left.jsp 분기
- 정책화면: 계정 관리 정책에 보관기간 입력 항목·검증 추가
- 배치: purgeExpiredLoginFailHistoryScheduler 매일 03:30, 1회 5,000건 상한
- Mysql/Oracle sqlmap 쌍 + sql-map-config 등록

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 14:48:24 +09:00
infraurp
e4973fb777 배포 파이프라인 결함 3건 수정
All checks were successful
deploy-dev / deploy (push) Successful in 39s
2026-07-30 나눔고딕 글꼴 배포 중 드러난 문제들이다.

1) build-and-upload.sh: 업로드 검증이 없어 잘린 WAR이 통과했다
   pscp가 대용량 전송 중 약 30초 지점에서 조용히 끊기며 exit 0을 반환해,
   194MB WAR이 66MB/84MB로 잘린 채 "업로드 완료"로 처리됐다. 그 WAR로
   배포가 돌아 실패했다. 30MB 조각 전송 + 조각별 크기 확인(3회 재시도) +
   서버 결합 후 size/md5 대조를 통과할 때만 arko.war 로 교체하도록 바꿨다.

2) build-and-upload.sh: mvn -ntp 는 Maven 3.6.1+ 전용
   PATH에 3.5.4가 잡히면 "Unrecognized option: -ntp"로 빌드가 즉시 죽는다.
   진행률 억제 옵션일 뿐이라 제거했다.

3) arko-dev-deploy.sh: WAR 검증이 파이프+pipefail 조합으로 취약
   정상 WAR인데 Actions 실행 중 "WEB-INF/web.xml 없음"으로 오판해 배포가
   멈췄다(서버에서 동일 명령 재실행 시 20/20 통과). unzip 목록을 한 번만
   읽어 변수에 담고 파이프 없이 검사한다.
   ※ 서버의 /opt/arko-dev/bin/ 사본은 워크플로가 갱신하지 않으므로 별도 반영 필요.

덧붙여 워크플로 주석의 "빈 커밋으로 재배포" 안내를 정정했다 —
paths-ignore 때문에 변경 경로가 없는 커밋은 워크플로가 실행되지 않는다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 13:44:50 +09:00
infraurp
10cb87ff42 재배포 트리거: 나눔고딕 글꼴 적용 WAR 전개
앞선 배포(task 14)가 WAR 검증 단계에서 실패했다.
서버의 arko.war 는 로컬과 size/md5 동일함을 확인했고(203413124,
b85bc6c25e3cb245c1718e68123e4b33), 동일 검증 명령을 서버에서 재실행하면
정상 통과한다. 러너 컨텍스트 일시 실패로 판단해 재전개만 트리거한다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 13:27:26 +09:00
infraurp
9684437374 관리자페이지 글꼴 나눔고딕 일괄 교체
Some checks failed
deploy-dev / deploy (push) Failing after 0s
개별 CSS에 맑은고딕/돋움/굴림/dotum/Tahoma/Arial 지정이 흩어져 있고,
나눔 @font-face 도 파일마다 4중(nanumttf/nanumeot/_r) 으로 중복 선언되어
화면마다 글꼴이 달라 보이던 것을 하나로 정리한다.

- css/site/mnt/nanumgothic.css 신규: "NanumGothic" 패밀리 단일 정의(400/700/800),
  local() 우선 + eot/woff/ttf fallback, 전역 적용 및 벤더 위젯 override
- head.jsp 에 마지막 스타일시트로 등록 → /mnt/include/head.do 를 가져가는
  관리자 화면 293개(egovframework.com.* 표준화면 포함)에 일괄 적용
- mnt CSS 11개 파일의 font-family 지정 39곳 교체, 레거시 @font-face 16줄 제거
- head.do 를 쓰지 않는 쪽지 팝업 4개는 개별 link 추가
- ckeditor/contents.css: "nanumttf_r" 이 @font-face 선언 없이 사용되어
  실제로는 적용되지 않던 상태를 정상화(관리자 21 / 프론트 26 화면 공용)
- NanumGothicBold.ttf 추가: 기존에 Regular/ExtraBold 만 있어
  font-weight:bold 가 ExtraBold 로 렌더링되던 것을 정상 Bold 로 교정

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 12:57:38 +09:00
URP2026
031f6b85e9 act_runner 폴링 정지 워치독 추가
All checks were successful
deploy-dev / deploy (push) Successful in 34s
러너가 작업 하나를 끝낸 뒤 폴링을 멈추는 문제가 있다. 프로세스는 살아 있고
Gitea로의 TCP 연결도 ESTABLISHED 인데 응답 없이 물려 있으며 CPU 사용량이 완전히
정지한다. nginx 경유 제거(직결 재등록)와 0.2.11->0.2.13 업그레이드로도 재현되어
근본 원인을 잡지 못했다.

arko-runner-watchdog.timer 가 1분마다 "90초 넘게 대기 중인 작업이 있는데
실행 중인 작업은 없는" 상태를 확인해 러너를 재기동한다. 실행 중인 작업이 있으면
건드리지 않으므로 배포 도중 끊길 위험은 없다.

검증: 대기 중이던 run 67을 워치독이 감지해 재기동했고 배포가 정상 완료됐다.
2026-07-29 18:45:25 +09:00
URP2026
afbdba5ba1 act_runner 0.2.11 -> 0.2.13 업그레이드 스크립트 추가
All checks were successful
deploy-dev / deploy (push) Successful in 28s
0.2.11은 기동 직후 대기 작업 하나를 처리한 뒤 폴링을 멈췄다.
프로세스는 살아 있는데 새 작업을 가져오지 않아 매번 재기동이 필요했고,
nginx 경유를 걷어내고 Gitea 직결로 바꾼 뒤에도 재현되어 러너 자체 문제로 판단했다.
2026-07-29 18:04:33 +09:00
URP2026
7d1182ecc3 배포 구조 문서화 및 runner 직결 재등록 스크립트 추가
All checks were successful
deploy-dev / deploy (push) Successful in 28s
runner를 nginx 경유(https://git.zioinfo.co.kr)로 등록하면 declare까지는 되는데
작업을 가져오지 않고 재기동해야만 처리하는 문제가 있었다. long-poll이 nginx의
proxy_buffering(기본 on)에 물리는 것으로 보인다. Gitea가 같은 서버에 있으므로
127.0.0.1:9003 직결로 재등록해 해결했고, 재발 시 쓰도록 스크립트로 남긴다.

deploy/README.md에 전체 구조(개발 WAS/DB 단일, 운영은 웹 티어 전용),
접속 방향이 양쪽으로 다른 이유(NAT), 키 제한 범위, 알려진 이슈를 정리했다.
2026-07-29 17:57:17 +09:00
URP2026
7376c99f17 운영 웹서버(csv.wise.ai.kr) 구축 및 개발→운영 자동 배포 연결
All checks were successful
deploy-dev / deploy (push) Successful in 36s
웹 티어(211.37.173.197 / Rocky 8):
- csv.wise.ai.kr nginx vhost + Let's Encrypt SSL
- WAS는 SSH 터널(arko-was-tunnel.service)로 연결 — 개발서버가 NAT 뒤라
  8088이 포워딩되지 않고 Tomcat도 127.0.0.1 바인딩이기 때문이다.
  키는 WAS에서 restrict,permitopen="127.0.0.1:8088" 로 묶어 셸 접근 불가.
- 정적 리소스는 운영 웹이 직접 서빙하고 없으면 @was 폴백 — 전환 중에도 깨지지 않는다.

파이프라인:
  git push -> 개발 WAS 배포 -> 개발 헬스체크 -> 운영 웹 정적 배포 -> 운영 검증
개발 헬스체크를 통과한 뒤에만 운영으로 넘어간다.
접속 방향은 개발->운영(개발서버는 NAT 뒤라 역방향 접속이 불가능하다).
2026-07-29 17:50:32 +09:00
URP2026
62ef19c78f Gitea 1.22 호환: 워크플로에서 workflow_dispatch 제거
All checks were successful
deploy-dev / deploy (push) Successful in 31s
Gitea 1.22.3은 workflow_dispatch(수동 실행)와 inputs 컨텍스트를 지원하지 않아
워크플로가 Actions 목록에 표시되지 않았다. 트리거를 push 하나로 단순화한다.
롤백은 서버에서 직접 수행하도록 README에 절차를 남긴다.

Tomcat 힙도 768m -> 448m로 낮춘다. 가용 메모리 1G 안팎인 서버에서
Tomcat 재기동 직후 서버 전체가 응답 불능이 된 사례가 두 번 있었다.
2026-07-29 17:03:55 +09:00
URP2026
7c574922d8 개발서버(csv.zioinfo.co.kr) 배포 구성 및 Gitea Actions 파이프라인 추가
- 00-server-setup.sh: JDK8(Temurin)·Tomcat9·systemd·nginx·act_runner 구축 (멱등)
- arko-dev-deploy.sh: WAR 검증→백업→ROOT 재전개→환경설정 주입→기동→헬스체크→실패 시 롤백
- build-and-upload.sh: 개발자 PC에서 JDK8 빌드 후 WAR 업로드 (서버 자원 보호)
- deploy-dev.yml: master push 시 자동 배포, 수동 재배포·롤백 지원

서버가 2코어/메모리 여유 1G에 40여 개 서비스가 동거하는 환경이라
Maven 빌드는 서버에서 돌리지 않고 개발자 PC에서 수행한다.
JSP가 리소스를 컨텍스트 경로 없이 하드코딩해 ROOT 전개만 가능하며,
globals-{dev,live}.properties는 .gitignore 대상이라 서버 config/에 두고 배포 시 주입한다.
2026-07-29 15:44:02 +09:00
infraurp
1288fc6396 다중 역할 계정의 좌측메뉴 조회 SQL 오류 수정 (SFR-001 후속)
권한 신청·승인 워크플로(N:신설=추가부여)로 사용자가 AUTHOR_CODE를 2개 이상
갖게 되면, 레거시 eGov 표준 메뉴 쿼리(selectMainMenuHead/Left/LastMenuNo(Cnt))의
"= (서브쿼리)"가 다중 행을 반환해 Subquery returns more than 1 row로 500 오류가
발생했다(2FA/OTP 등록 직후 /mnt/main.do 진입 시 재현). 서브쿼리를 IN으로,
상위 SELECT에 DISTINCT를 추가해 다중 역할을 지원하도록 수정.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 11:14:30 +09:00
infraurp
462e55bcd5 권한 신청·승인 워크플로 화면 및 2단계인증 UX 개선 (SFR-001)
관리자 메뉴에 권한 신청·승인 화면(#46)을 노출하고 신청/승인 처리 로직을 보강했으며,
2단계 인증(OTP) 등록·인증 화면의 사용성을 개선했다.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-27 14:52:16 +09:00
infraurp
2a2ab99d10 개인정보보호 기능개선 사업 구현 (SFR-001~004, 권한관리·인증체계·접속기록)
권한관리(SFR-001):
- getAuthorities() 구현(EgovUserAuthorityDAO), AuthorityInterceptor 역할별 URL 접근제어
  (COMTNMENUCREATDTLS×COMTNMENUINFO×COMTNPROGRMLIST 메뉴권한 기반, 캐시/TTL, ROLE_ADMIN 바이패스)
- 권한 신청·승인 워크플로 + AUTHOR_CHANGE_HISTORY 이력(3년 보관), 조회·다운로드
계정관리(SFR-002): 계정관리정책, 장기미사용(휴면) 확장(취급자 포함)·사전알림, 계정잠금 5회
인증체계(SFR-003): 로그인 통합 2단계 인증(SecondFactorInterceptor+SecondFactorController),
  OTP QR 등록(ZXing)·비밀키 DB 영속(OTP_DEVICE, AES-GCM), 세션재발급(고정공격 방지), 자동로그아웃 30분
접속기록(SFR-004): PERSONAL_DATA_ACCESS_LOG(월파티션), PersonalDataLogAspect 한정수집,
  SHA-256 해시체인 무결성, 업무유형매핑, IP 취득보정, 비정상접근 탐지, 정기점검 리포트
DB: privacy DDL 11종 + 설치용 통합 SQL(privacy.install_mysql.sql, DDL+시드 DML)
빌드복구: pom.xml 시스템 jar/JAXB 선언, iBatis2 SQL주석 '#'→'No.' 정정

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 18:03:02 +09:00
ythong
fde7598b48 Initial commit - ARKO (대용량 미디어 파일 제외)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 14:24:16 +09:00