배경

배포는 Jenkins가 Gradle 빌드를 돌린 뒤 SSH로 서버에 올리는 순서임. 빌드가 실패하면 SSH 단계는 실행되지 않으므로(SSH: Current build result is [FAILURE], not going to run.) 서버에는 아무것도 올라가지 않음. 배포가 안 됐다는 문의가 오면 먼저 빌드 결과부터 봄.

변경 내용

웹 취약점 조치 (2026-08-08, 9월 배포 전)

감사 보안취약점 점검에서 지적됨. 브라우저 세션 스토리지에 토큰 전체를 저장하던 구조를 바꿈.

  • 클라이언트는 access token만 가짐.
  • 갱신 정보(refresh)는 Redis로 옮기고, 필요할 때 서버에서 다시 조회해서 씀.

2026-09-17 기준 아직 미조치. 9월 점검 후 배포 예정.

웹 오류 수정 (2026-09-03)

  1. 임대료 상세 조회 오류 — 세대 정보 조회에 del_yn 필터가 없어서 삭제된 세대(청주지북 A4)가 세대 수와 등록률에 함께 잡혔음. del_yn 필터를 추가해 해결함.
  2. 기기제어분석에서 단지 조회 시 같은 그래프가 2번 나옴 — API가 2번 호출되고 있었음. 수정 완료(2026-09-17 확인).

WAS 빌드 (MAW·APW·SCW·OAW 공통)

서버 모듈은 전부 Gradle로 war를 만들어 외부 Tomcat에 올리는 방식임. 모듈별 상세는 공개노트/개발/모듈/MAW 앱 API 서버, 공개노트/개발/모듈/APW 연계 서버, 공개노트/개발/모듈/SCW 스케줄러 서버, 공개노트/개발/모듈/OAW 인증 서버.

  • 빌드 명령은 ./gradlew bootWar -Pprofile={local|dev|prod} 형태임. 프로필을 지정하지 않으면 local로 빌드됨
  • 프로필에 따라 설정 리소스 디렉터리 자체가 갈림(src/main/resources-{프로필}). 같은 키라도 값이 다르고, 개발 프로필에만 있는 키(목업 허용 URL, 프록시 설정 등)가 있음
  • 산출물은 maw.war, apw.war, scw.war, oaw.war임. 배포 경로는 /usr/local/tomcat-{모듈}/
  • 기동 스크립트는 외부로 나가는 호출이 있는 모듈(MAW·APW·SCW)이 startup_proxy.sh, 수신 전용인 OAW만 startup.sh임. war로 구동하면 설정 파일의 프록시 값이 안 먹고 catalina.sh에 있어야 함
  • Jenkins 잡 이름은 (DEV|PROD)-lh-smah-server-{apw|scw|oaw} 형태임. 공개노트/개발/시스템 구성

배포 시 확인할 것

모듈개발 값이 운영에 섞이면
MAWLG 시뮬레이터 모드가 켜져 실제 가전이 안 움직임. 목업 URL이 인증 없이 열림
APW푸시·SMS가 테스트 계정으로만 감. 홈넷 호출이 테스트 서버로 감
SCWActive WAS 지정이 어긋나면 스케줄러가 전부 꺼짐. 배포 1분 뒤 로그의 스케줄러 시작함 : [cron]으로 확인할 것
공통로컬 프로필의 SSL 검증 해제가 켜짐. 로그에 ssl secure 모드가 해제 되었으니 주의필요 가 보이면 프로필 오류임

확인 필요

MAW의 Jenkins 잡이 따로 있는지, 아니면 다른 방식으로 배포하는지 확인 필요(2024-06 인수인계 문서에 MAW 잡 이름이 없음).

LMC 관리자 웹 빌드

서버 모듈과 프로필 방식이 다름. 백엔드와 프론트를 따로 빌드함. 화면·기능은 공개노트/개발/모듈/LMC 관리자 웹.

대상명령산출물
백엔드./gradlew bootWarlhmngr.war (Spring Boot 2.7.0, Java 8)
백엔드 전체./gradlew clean buildwar + 테스트
백엔드 로컬 기동./gradlew bootRun --args='--spring.profiles.active=prod'-
프론트 운영npm run build (--mode production)LMC/frontend/dist
프론트 개발npm run build-dev같음
프론트 로컬npm run serveport 9091
  • 포트는 8085, 컨텍스트 경로 없음, API 접두사 /api/v1/...
  • 프로필은 -Pprofile이 아니라 spring.profiles.active(local / dev / prod) 로 지정함. 프로필별로 리소스 폴더(src/main/resources-{프로필})가 갈리고, 프로필을 지정하지 않으면 기동되지 않음
  • 프로필이 섞이면 CORS 허용 도메인과 APW 호출 대상이 어긋남(dev는 homezdev.lh.or.kr, prod는 homez.lh.or.kr / homez-api.lh.or.kr:8094)
  • 백엔드 WebConfigclasspath:/static/에서 못 찾은 경로를 /static/index.html로 포워딩하므로 프론트 산출물을 백엔드 static에 넣어 war 하나로 배포하는 구성도 가능함. 현재 vue.config.jsoutputDir는 주석 처리돼 있음
  • 운영 프론트 빌드는 파일명에 contenthash가 붙음. 배포 직후 기존 탭에서 ChunkLoadError가 나면 라우터가 한 번만 자동 새로고침함(10초 내 반복은 중단). “배포 후 화면이 안 뜬다”는 문의는 새로고침 1회로 대부분 해결됨
  • .env.production / .env.developmentMNGEXP_FORM_FILE_SEQ·RFE_FORM_FILE_SEQ관리비·임대료 양식 파일의 첨부 일련번호 하드코딩임. 자료실에서 해당 첨부를 지우면 양식 다운로드가 깨짐
  • 역할·메뉴 권한을 DB에서 바꾼 뒤에는 애플리케이션 재기동이 필요함(기동 시 1회만 Security 매처로 등록됨)
  • LMC에는 스케줄러·배치가 하나도 없음(@Scheduled·Quartz·TaskScheduler 0건, build.gradle에 스케줄러 의존성 없음). 재기동해도 배치가 같이 뜨지 않으므로 대시보드·보고서 숫자가 멈춘 문제는 LMC 재기동으로 해결되지 않음공개노트/개발/모듈/통계 배치 서버, 공개노트/개발/모듈/LMC 기능 상세

확인 필요

LMC의 Jenkins 잡 이름과 war 배포 경로(/usr/local/tomcat-*)가 서버 모듈과 같은 규칙인지 확인 필요. 코드 분석 원본에는 빌드 명령만 있고 배포 경로·잡 이름이 없음.

SMC 통합운영시스템 빌드

프론트·백엔드가 한 저장소(lh-home-2022-web/SMC)에 있음. 상세는 공개노트/개발/모듈/SMC 통합운영시스템.

항목
프론트Vue 2 SPA. build(production), build-dev 스크립트
백엔드Gradle bootWarsysmngr.war. ServletInitializer가 있어 외부 톰캣 배포 가능
프로필`-Pprofile=local
포트8086(세 프로필 공통)

프론트 빌드 시 NODE_ENV가 production이 아니면 SMS 2차 인증이 빠진 산출물이 나옴. 운영 배포본은 반드시 build로 만들 것.

입주민 앱 빌드·배포

서버와 경로가 완전히 다름. Jenkins가 아니라 저장소의 셸 스크립트 + fastlane으로 나감. 앱 구조 자체는 공개노트/개발/모듈/앱 구조와 보안.

스크립트하는 일
build_android.sh <prod|dev|aab>서버 주소 치환 → 릴리스 빌드 → lhsmarthome_prod.apk / lhsmarthome_dev.apk / AAB 생성 → 소스 원복
run_android.sh, run_ios.sh로컬 실행
upload_play_internal.shGoogle Play 내부 테스트 트랙 업로드. versionCode 중복 시 자동 증가 재시도
upload_testflight.shTestFlight 업로드

버전 관리

  • 버전의 진실 소스는 config/release_versions.json임. pubspec.yaml의 버전이 아님. 이걸 모르고 pubspec만 고치면 반영되지 않음.
  • 도구가 로컬 기록과 스토어의 최신 빌드번호 중 큰 값 + 1을 계산하고, 빌드가 성공한 뒤에 json을 갱신함.
  • iOS는 fastlane이 빌드 후 앱 본체와 원패스 위젯 익스텐션의 버전이 요청값과 같은지 검사하고, 다르면 실패시킴.

주의

  • 서버 환경은 flavor가 아니라 소스 치환으로 갈림. 빌드 중 중단되면 소스에 개발 주소가 남을 수 있으므로 커밋 전 확인할 것.
  • 인증서·스토어 API 키·Android 서명 키는 전부 저장소에 없음 → [REDACTED]. 담당자에게 문의함.
  • 서버 인증서를 교체하기 전에 앱 인증서 피닝 갱신본이 먼저 배포돼야 함. 순서가 바뀌면 전 사용자가 앱을 못 씀. 공개노트/개발/모듈/앱 구조와 보안
  • 릴리스 스크립트에는 테스트가 촘촘하지만 앱 화면·로직 테스트는 사실상 없음. 회귀는 수동 확인에 의존함.

확인 방법

  1. Jenkins 빌드 결과가 SUCCESS인지 봄. FAILURE면 서버에 반영되지 않은 것임.
  2. 빌드 로그에서 error: 또는 BUILD FAILED를 검색함.
  3. 배포 후 화면이 안 바뀌면 브라우저 캐시가 아니라 빌드 실패인지를 먼저 의심함.

Jenkins 주소와 계정은 담당자에게 문의함. 위키에 남기지 않음.

관련