역할

SCW(Scheduler WAS)는 시간이 되면 알아서 도는 일을 맡는 서버임. 원래 APW에 있던 스케줄 기능을 2023-08-31에 떼어내 만듦. 전체 그림은 공개노트/개발/시스템 구성.

  • 컨트롤러가 사실상 없음. 스케줄러 → 서비스 → DB 구조임(예외: 스케줄러 제어 API 1개)
  • 아무도 SCW를 호출하지 않음. 자기 시계로 돎
  • 부르는 쪽: 홈넷서버, 공공데이터포털, 이음(에너지플랫폼), LG ThinQ, APW
  • SMS·푸시를 직접 보내지 않고 APW에 요청함. 공개노트/개발/모듈/APW 연계 서버

기술 스택

APW에서 떼어냈기 때문에 구성이 거의 같음.

항목
프레임워크Spring Boot 2.7.0, Java 8, Gradle, war 패키징(scw.war)
영속성JPA + MyBatis 혼용
DBPostgreSQL smahdb
포트운영 WAS 8083
스케줄링ThreadPoolTaskScheduler + CronTrigger를 직접 제어함. @Scheduled를 쓰지 않음
HTTP 클라이언트WebClient(홈넷용·LG용 유틸 분리). 외부 호출 타임아웃 20초
톰캣/usr/local/tomcat-scw/. 기동은 startup_proxy.sh(Squid 프록시 경유)
로그/app/logs/was/tomcat-scw/scw.log, scw_error.log (일별 롤링, 30일 보관)
로그 패턴[traceId=...] 포함. 스케줄 실행 단위로 traceId가 붙음
Jenkins 잡(DEV/PROD)-lh-smah-server-scw

설정 주소가 DB에 있음

smah.api.url, to.eepapi.api.url 같은 설정값은 주소가 아니라 cmn.tb_cstt_m의 상수 ID임. 런타임에 DB에서 실제 값을 꺼내 씀.

APW 주소나 에너지플랫폼 주소를 바꾸려면 설정 파일이 아니라 DB의 cmn.tb_cstt_m을 고쳐야 함. 재배포가 필요 없는 대신, 소스만 봐서는 실제 호출 대상을 알 수 없음.

스케줄러 공통 동작 (가장 중요)

기동 순서

  1. 서버가 뜨면 각 스케줄러가 기본 주기 1분으로 먼저 시작함
  2. 1분 뒤 첫 실행에서 cmn.tb_proc_m을 읽음(proc_nm = 스케줄러 이름, us_yn = 'Y')
  3. Active WAS인지 판정함. 아니면 스스로 종료함
  4. 맞으면 DB의 cron 값으로 주기를 바꾸고 스케줄러를 재시작함
  5. 이후부터는 DB에 적힌 주기로 돎

cron 표현식은 소스에 없음. 전부 cmn.tb_proc_m.cron_xprssn_vl에 들어 있음. 현재 주기를 보려면 cmn.tb_proc_m에서 proc_nmSCW_로 시작하는 행의 cron_xprssn_vl, pod_cd, pod_hr, us_yn, actv_trg_svr_id, actv_trg_svr_ip, proc_desc를 조회할 것.

같은 테이블을 통계 배치도 씀. SCW는 cron_xprssn_vl이 있는 행, 배치는 cron_schdl_yn='N'인 행을 담당함. 공개노트/개발/모듈/통계 배치 서버

Active WAS 판정 (이중화)

  • tb_proc_m의 Active 서버 IP와 호스트명을 읽어 현재 서버와 비교함. 둘 다 맞아야 Active로 봄
  • Active가 아니면 스케줄러를 완전히 끄고 Active 대상 WAS 가 아닙니다...스케줄러 종료됨 로그를 남김
  • 한 번 꺼지면 WAS를 재시작할 때까지 다시 돌지 않음

확인 필요

WAS 2대에 SCW를 모두 띄우면 Active가 아닌 쪽은 기동 1분 뒤 스케줄러가 전부 꺼짐. 자동 failover가 없음. Active 서버를 교체하려면 tb_proc_m의 Active 서버 IP·호스트명을 바꾸고 새 Active WAS를 재시작해야 함. 이 절차가 운영 매뉴얼에 있는지 확인 필요. Active 호스트명은 서버가 스스로 읽는 호스트명과 정확히 같아야 하므로(DNS 설정에 따라 FQDN이 될 수 있음) 운영값 확인도 필요함.

실행 주기와 데이터 조회 범위 (pod_hr)

예약 기반 스케줄(이벤트 전달, IoT 예약 제어, AutoDR 제어)은 cron 주기와 별개로 얼마나 넓은 시간 범위의 데이터를 가져올지tb_proc_m.pod_hr(분)로 정함.

  • 과거 조회형(이벤트 전달): 지금 - pod_hr분 ~ 지금에 생긴 데이터를 전달함
  • 미래 예약형(IoT·AutoDR 제어): 지금 ~ 지금 + pod_hr분 예약을 가져와 스케줄러 안에서 시간 맞춰 실행함

cron 주기와 pod_hr은 항상 같게 맞춰야 함. pod_hr이 작으면 그만큼 데이터가 누락되고, 크면 중복 발송됨.

실행 이력

실행할 때마다 cmn.tb_proc_run_h에 결과를 남김. 장애 진단은 여기부터 봄.

결과값이 통일되어 있지 않음 — COMPLETE, COMPLITE(오타), FAIL이 섞여 있고, DB 배치 쪽은 같은 테이블에 0(실행중)/1(성공)/2(오류) 체계로 씀. 모니터링 쿼리를 짤 때 주의할 것. 배치 쪽 체계는 공개노트/개발/모듈/통계 배치 서버.

스케줄러 제어 API

SCW에 있는 유일한 컨트롤러임. POST /api/smh/schedulerExecuteAction(헤더 ApiKey)으로 시스템관리자 화면(SMW)에서 시작·중지·주기 변경을 함. 스스로 꺼진 스케줄러를 다시 켜는 방법은 WAS 재기동 또는 이 API뿐임.

스케줄 목록

주기는 전부 DB에 있으므로 아래 “주기”는 소스 주석 기준 추정임.

동작 중 (15개)

proc_nm하는 일주기(추정)상세
SCW_SCHEDULER_GET_HOUSEHOLD_TERMINAL홈넷서버에서 단지별 세대단말기(월패드) 목록·상태 수집매일아래
SCW_SCHEDULER_CONTROL_AUTODR_DEVICEAutoDR 발령에 따라 홈넷 기기 제어분 단위공개노트/기능/AutoDR
SCW_SCHEDULER_CONTROL_USER_IOT_DEVICE입주민이 예약한 IoT 기기 제어 실행분 단위공개노트/기능/우리집제어
SCW_SCHEDULER_EVENT_SMARTHOME_NOTIFICATION_HOUSEHOLD세대별 이벤트를 홈넷서버로 전달분 단위공개노트/기능/홈넷 이벤트 알림
SCW_SCHEDULER_EVENT_SMARTHOME_NOTIFICATION_SUBDIVISION단지별 이벤트를 홈넷서버로 전달분 단위공개노트/기능/홈넷 이벤트 알림
SCW_SCHEDULER_CANCEL_SUBSCRIBE_DEVICE_EVENT리프레시 토큰이 만료된 사용자의 기기 이벤트 구독 해지공개노트/기능/홈넷 이벤트 알림
SCW_SCHEDULER_EVENT_VACANT_HOUSEHOLD_MOVE_OUT공가세대에 남은 입주확정 사용자를 전출 처리아래
SCW_SCHEDULER_GET_AIR_QUALITY공공데이터포털 대기질 조회아래
SCW_SCHEDULER_GET_SHORTERM_FORECAST공공데이터포털 단기예보 조회아래
SCW_SCHEDULER_GET_WEATHER_CONDITION공공데이터포털 기상개황 조회아래
SCW_SCHEDULER_GET_WEATHER_WARNING공공데이터포털 기상특보 조회아래
SCW_SCHEDULER_GET_AUTODR_EXA_DTLS에너지플랫폼에서 AutoDR 정산내역 조회·적재매달공개노트/기능/AutoDR
SCW_SCHEDULER_GET_LHECR_NCLH살피미 임계치 초과 확인 → SMS 발송 요청1시간마다아래
SCW_SCHEDULER_GET_TKMDCN_NC복약 대상자에게 복약 푸시 알림아래
SCW_SCHEDULER_REFRESH_LG_TOKENLG ThinQ API 토큰 갱신공개노트/기능/우리집제어

비활성 (4개, 주석 처리됨)

홈넷서버 정보·상태 동기화, 주거약자(안전서비스) 세대 동기화, 구 버전 날씨 수집, 구 버전 복약 알림 클래스 4개가 주석 처리된 채 남아 있음. 이관하면서 옮기지 않은 기능이라 proc_nm도 아직 APW_SCHEDULER_*임.

홈넷서버 정보·상태 동기화와 주거약자 세대 동기화는 현재 아무도 자동으로 하지 않음. 세대단말기 스케줄러가 대신하거나 수동 처리하는 것으로 보임(추정).

기능 상세

세대단말기 정보 수집

각 단지 홈넷서버에 세대 월패드 목록을 물어 cmn.tb_hsh_ter_m을 통째로 현행화함. 관리자 화면의 단말기 조회가 이 데이터를 봄.

  • 홈넷서버 GET /api/lh2hn/gateways를 페이징으로 반복 호출함
  • 응답을 세션 기반 임시테이블에 넣고 중복 제거 → 동·호로 세대ID 매핑 → 이력 이관 후 갱신·삽입·삭제 처리함
  • 임시테이블을 쓰는 이유는 PostgreSQL Vacuum 지연을 피하기 위함임. 세션 기반이라 외부에서 진행 상황을 볼 수 없음

운영 시 알아둘 점

  • 한 단지가 실패하면 전체가 롤백됨(메서드 전체가 하나의 트랜잭션임). 인수인계 문서에도 개선 과제로 적혀 있음
  • “단말기 목록이 어제 것이다” → 이 스케줄러가 어젯밤에 실패한 것임. cmn.tb_proc_run_h에서 마지막 결과를 볼 것
  • 동·호가 세대 테이블에 없는 단말기는 unknown으로 걸러짐. 신규 입주 단지에서 세대 등록이 안 된 경우 여기 걸림. 기본매뉴얼/관리사무소/새로 연동한 단지의 단말기 조회가 안 돼요

공가세대 전출 처리

세대가 공가인데 입주확정 사용자가 남아 있으면 APW POST /api/smh/cogo/move-out으로 전출 처리를 요청함. 데이터 정합성 보정용임.

이 처리가 돌면 파트너 가전 연동 해지·홈넷 전출 이벤트 전달까지 연쇄로 일어남. 대량 처리 시 부하에 주의. 전출 처리 내용은 공개노트/기능/로그인과 세대 승인.

날씨·대기질 수집 (공공데이터포털 4종)

대상저장 테이블
대기질hc.tb_arqlt_l
단기예보hc.tb_strm_frcst_l
기상개황hc.tb_wthrcnd_frcst_l
기상특보hc.tb_wthrwrn_l
  • 주소와 인증키는 전부 cmn.tb_cstt_m에 있고 인증키(SCW_DATA_API_KEY)는 4종 공통
  • 주소나 키가 비어 있으면 호출하지 않고 조용히 넘어감
  • 조회 기준은 단지별 격자좌표(단기예보), 측정소 정보(대기질), 지점코드(기상개황), 전국 일괄(기상특보)임

운영 시 알아둘 점

  • 공공데이터포털 인증키는 만료됨. 만료되면 cmn.tb_cstt_m의 키를 갱신해야 함
  • 저장이 덮어쓰기 방식이라 수집이 멈춰도 데이터가 지워지지 않고 오래된 값으로 남음. 위 테이블의 최종 갱신 시각으로 진단할 것
  • 앱·월패드가 보는 날씨는 이 테이블을 읽는 DB 함수(sf_*_wthr_*_for_usr)가 만듦. 공개노트/개발/모듈/통계 집계 DB 함수, 공개노트/개발/모듈/MAW 앱 API 서버
  • 수집이 밀리면 일 3시 프로시저 sp_ev_if_gdata가 수신율 50% 미만을 감지해 SE004 이벤트를 띄움. 공개노트/개발/모듈/통계 집계 DB 함수
  • 구 버전 날씨 테이블(cmn.tb_sbd_wthr_m, cmn.tb_sbd_arqlt_m)이 아직 남아 있어 두 세대의 날씨 테이블이 공존함

LH살피미 알림

LH살피미(독거 어르신 안전확인 센서)가 일정 시간 이상 반응이 없으면 보호자에게 SMS를 보냄. 발송은 APW POST /api/smh/sms에 요청함. 공개노트/개발/모듈/SMS 발송

  • 임계치는 세대별 안전서비스 설정값(시간 단위)임
  • 발송 후 이벤트 발생 내역을 갱신해 중복 발송을 막음
  • 1시간 주기이므로 최대 1시간 늦게 감. “왜 늦게 왔냐”는 문의의 답임
  • APW가 죽어 있으면 SMS가 나가지 않음

복약 알림

복약 시간이 된 대상자와 그 가족에게 푸시를 보냄. 발송은 APW POST /api/smh/push에 요청함. 공개노트/개발/push 알림

구 버전 클래스(비활성)와 현재 클래스가 같은 proc_nm을 씀. 둘 다 켜면 중복 발송됨. 클래스 이름도 Taking/Talking으로 혼동됨.

앱 서버(MAW)에는 스케줄러가 없음. @Scheduled·@EnableScheduling·cron 표현식이 MAW 전 소스에 0건임(2026-09-18 확인). MAW는 약 등록·복약 기록·기기 예약을 저장만 하고, 시간이 되어 실행하는 일은 전부 SCW 몫임. 그래서 “복약 알림이 안 온다”, “예약이 실행되지 않는다”, “전출이 반영 안 된다”는 MAW 로그로 추적할 수 없고 여기 실행 이력을 봐야 함. 공개노트/기능/헬스케어

외부 연동

대상인증실패 시
홈넷서버Authorization: Bearer (토큰은 APW에서 받아옴)건별 로그 + tb_proc_run_h. 세대단말기 수집만 전체 롤백
APWApiKey 헤더(cmn.tb_cstt_m)APW가 멈추면 SMS·푸시·홈넷 제어가 전부 멈춤
에너지플랫폼(이음)auth 헤더 + vendor-id정산 데이터 미적재
공공데이터포털serviceKey 파라미터날씨가 오래된 값으로 고정됨
LG ThinQ파트너 API 키·시크릿단지별 건별 실패 허용
  • 모든 외부 호출이 Squid 프록시를 탐. war로 구동하므로 프록시 설정은 catalina.sh에 있어야 하고, 그래서 기동 스크립트가 startup_proxy.sh
  • 홈넷서버 SSL은 LH가 배포한 사설 인증서임. 공개노트/기능/홈넷 서버 연동
  • API 송수신 이력은 APW와 같은 alog 스키마 테이블에 남음

데이터

스케줄 제어

테이블용도
cmn.tb_proc_m스케줄 설정. 아래 컬럼 표 참고
cmn.tb_proc_run_h스케줄 실행 이력. 장애 진단은 여기부터
cmn.tb_cstt_m상수(외부 주소, API 키)

tb_proc_m 주요 컬럼

컬럼의미
proc_nm스케줄러 식별자(SCW_SCHEDULER_*). 소스의 이름과 정확히 같아야 함
cron_xprssn_vlcron 표현식(초 포함 6자리)
us_ynY가 아니면 설정을 못 읽고 그냥 넘어감
actv_trg_svr_id / actv_trg_svr_ipActive WAS 호스트명 / IP. 둘 다 현재 서버와 같아야 함
pod_cd / pod_hr주기 코드(m=분) / 데이터 조회 범위(분). cron 주기와 같게 맞출 것
proc_desc설명. 인수인계 문서가 “기능 목록은 이 컬럼을 보라”고 안내함

업무 테이블

  • 홈넷·단지: cmn.tb_smah_sbd_d, cmn.tb_hnsvr_m, cmn.tb_hnsvr_tkn_d, cmn.tb_hsh_m, cmn.tb_usr_m, cmn.tb_hsh_ter_m, smah.tb_hsh_ter_ss_l, cmn.tb_cogo_h, cmn.tb_oauth_m, cmn.tb_ptnr_m, cmn.tb_ptnr_sbd_d
  • 업무: smah.tb_dr_goo_l(DR 발령), smah.tb_atdr_cont_l(AutoDR 제어 결과), smah.tb_dr_ctctr_m, smah.tb_dr_exa_l(정산), smah.tb_cont_schdl_m·_h·_fil_l(IoT 예약·이력·실패), smah.tb_hsh_mngexp_m, smah.tb_hsh_rfe_m, smah.tb_elc_vt_m, cmn.tb_rsd_annc_fcts_l, cmn.tb_evn_occ_l
  • 날씨·헬스케어(hc): 위 날씨 4종, hc.tb_arqlt_msrsttn_m, hc.tb_lhecr_pod_brf_l(살피미 주기보고), hc.tb_tkmdcn_*(복약)

알려진 이슈

  1. 세대단말기 스케줄러가 전 단지를 하나의 트랜잭션으로 묶음. 한 단지 홈넷서버가 응답을 안 주면 그날 전 단지 갱신이 무효가 됨
  2. 관리비·임대료 푸시가 세대별 토픽 발송이라 느림. 단지별 1회 발송으로 바꾸면 개선됨(우선순위 낮음)
  3. Active WAS 자동 failover 없음. tb_proc_m 수정 + WAS 재시작이 수동으로 필요함
  4. 스케줄러가 스스로 꺼진 뒤 다시 켜지지 않음
  5. 비활성 스케줄러 4개가 남아 있음. 홈넷서버 상태·주거약자 세대 동기화가 현재 자동으로 돌지 않음
  6. 복약 알림 클래스 2개가 같은 proc_nm을 씀. 둘 다 켜면 중복 발송됨
  7. 홈넷 호출 포트 8094가 하드코딩됨. APW는 DB에 포트가 있으면 그걸 쓰는데 SCW는 무조건 8094를 붙임. 홈넷사가 다른 포트를 쓰면 SCW 쪽만 실패함
  8. 기기 이벤트 구독 해지가 JWT 검증 예외를 전부 “만료”로 간주함. 서명키를 바꾸면 전 사용자 구독이 해지될 수 있음
  9. tb_proc_run_h 결과 코드가 통일되지 않음(COMPLETE/COMPLITE/FAIL + 배치의 0/1/2)
  10. 전입·전출 이벤트가 신·구 코드로 중복 발송됨(연동규격 V1.0 → V1.1 전환 중). 홈넷사가 둘 다 처리하면 이중 처리될 수 있음
  11. 로컬 SSL 검증 해제 코드가 여러 서비스에 복사되어 있음. 프로필이 잘못 들어가면 운영에서 인증서 검증이 꺼짐. 로그에 ssl secure 모드가 해제 되었으니 주의필요 가 보이면 프로필 오류임
  12. jasypt·ARIA·JWT 키가 설정 파일에 평문임(APW와 같은 문제)
  13. 설정 주소가 DB에 있어 소스만으로는 실제 호출 대상을 알 수 없음

확인 필요

확인 필요

  • 운영 cmn.tb_proc_m의 실제 등록 내역을 확인해야 함. 이 페이지의 주기는 전부 추정임
  • 각 스케줄러의 cron 주기와 pod_hr이 일치하는지. 불일치하면 이벤트 누락 또는 중복 발송이 생김
  • LG 토큰 갱신 주기가 LG 토큰 유효기간보다 짧은지. 길면 중간에 만료 구간이 생김
  • 주거약자 세대 정보와 홈넷서버 상태를 현재 무엇이 갱신하는지. 스케줄러가 비활성인데 데이터는 최신인지
  • 복약 알림 구 클래스를 지워도 되는지
  • 배포 후 스케줄러가 정상 기동했는지 확인하는 절차가 있는지(기동 1분 뒤 로그의 스케줄러 시작함 : [cron]으로 확인 가능)
  • 공공데이터포털 인증키의 만료일과 갱신 담당자

관련

공개노트/개발/시스템 구성 공개노트/개발/모듈/APW 연계 서버 공개노트/개발/모듈/MAW 앱 API 서버 공개노트/개발/모듈/OAW 인증 서버 공개노트/개발/모듈/통계 배치 서버 공개노트/개발/모듈/통계 집계 DB 함수 공개노트/기능/AutoDR 공개노트/기능/홈넷 이벤트 알림 공개노트/기능/우리집제어 공개노트/개발/모듈/SMS 발송 공개노트/개발/push 알림 기본매뉴얼/운영/tomcat과 배치 기동 기본매뉴얼/운영/WAS 로그 확인