배경
배포는 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)
- 임대료 상세 조회 오류 — 세대 정보 조회에
del_yn필터가 없어서 삭제된 세대(청주지북 A4)가 세대 수와 등록률에 함께 잡혔음.del_yn필터를 추가해 해결함. - 기기제어분석에서 단지 조회 시 같은 그래프가 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}형태임. 공개노트/개발/시스템 구성
배포 시 확인할 것
| 모듈 | 개발 값이 운영에 섞이면 |
|---|---|
| MAW | LG 시뮬레이터 모드가 켜져 실제 가전이 안 움직임. 목업 URL이 인증 없이 열림 |
| APW | 푸시·SMS가 테스트 계정으로만 감. 홈넷 호출이 테스트 서버로 감 |
| SCW | Active WAS 지정이 어긋나면 스케줄러가 전부 꺼짐. 배포 1분 뒤 로그의 스케줄러 시작함 : [cron]으로 확인할 것 |
| 공통 | 로컬 프로필의 SSL 검증 해제가 켜짐. 로그에 ssl secure 모드가 해제 되었으니 주의필요 가 보이면 프로필 오류임 |
확인 필요
MAW의 Jenkins 잡이 따로 있는지, 아니면 다른 방식으로 배포하는지 확인 필요(2024-06 인수인계 문서에 MAW 잡 이름이 없음).
LMC 관리자 웹 빌드
서버 모듈과 프로필 방식이 다름. 백엔드와 프론트를 따로 빌드함. 화면·기능은 공개노트/개발/모듈/LMC 관리자 웹.
| 대상 | 명령 | 산출물 |
|---|---|---|
| 백엔드 | ./gradlew bootWar | lhmngr.war (Spring Boot 2.7.0, Java 8) |
| 백엔드 전체 | ./gradlew clean build | war + 테스트 |
| 백엔드 로컬 기동 | ./gradlew bootRun --args='--spring.profiles.active=prod' | - |
| 프론트 운영 | npm run build (--mode production) | LMC/frontend/dist |
| 프론트 개발 | npm run build-dev | 같음 |
| 프론트 로컬 | npm run serve | port 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) - 백엔드
WebConfig가classpath:/static/에서 못 찾은 경로를/static/index.html로 포워딩하므로 프론트 산출물을 백엔드 static에 넣어 war 하나로 배포하는 구성도 가능함. 현재vue.config.js의outputDir는 주석 처리돼 있음 - 운영 프론트 빌드는 파일명에 contenthash가 붙음. 배포 직후 기존 탭에서 ChunkLoadError가 나면 라우터가 한 번만 자동 새로고침함(10초 내 반복은 중단). “배포 후 화면이 안 뜬다”는 문의는 새로고침 1회로 대부분 해결됨
.env.production/.env.development의MNGEXP_FORM_FILE_SEQ·RFE_FORM_FILE_SEQ는 관리비·임대료 양식 파일의 첨부 일련번호 하드코딩임. 자료실에서 해당 첨부를 지우면 양식 다운로드가 깨짐- 역할·메뉴 권한을 DB에서 바꾼 뒤에는 애플리케이션 재기동이 필요함(기동 시 1회만 Security 매처로 등록됨)
- LMC에는 스케줄러·배치가 하나도 없음(
@Scheduled·Quartz·TaskScheduler0건,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 bootWar → sysmngr.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.sh | Google Play 내부 테스트 트랙 업로드. versionCode 중복 시 자동 증가 재시도 |
upload_testflight.sh | TestFlight 업로드 |
버전 관리
- 버전의 진실 소스는
config/release_versions.json임.pubspec.yaml의 버전이 아님. 이걸 모르고 pubspec만 고치면 반영되지 않음. - 도구가 로컬 기록과 스토어의 최신 빌드번호 중 큰 값 + 1을 계산하고, 빌드가 성공한 뒤에 json을 갱신함.
- iOS는 fastlane이 빌드 후 앱 본체와 원패스 위젯 익스텐션의 버전이 요청값과 같은지 검사하고, 다르면 실패시킴.
주의
- 서버 환경은 flavor가 아니라 소스 치환으로 갈림. 빌드 중 중단되면 소스에 개발 주소가 남을 수 있으므로 커밋 전 확인할 것.
- 인증서·스토어 API 키·Android 서명 키는 전부 저장소에 없음 → [REDACTED]. 담당자에게 문의함.
- 서버 인증서를 교체하기 전에 앱 인증서 피닝 갱신본이 먼저 배포돼야 함. 순서가 바뀌면 전 사용자가 앱을 못 씀. 공개노트/개발/모듈/앱 구조와 보안
- 릴리스 스크립트에는 테스트가 촘촘하지만 앱 화면·로직 테스트는 사실상 없음. 회귀는 수동 확인에 의존함.
확인 방법
- Jenkins 빌드 결과가
SUCCESS인지 봄.FAILURE면 서버에 반영되지 않은 것임. - 빌드 로그에서
error:또는BUILD FAILED를 검색함. - 배포 후 화면이 안 바뀌면 브라우저 캐시가 아니라 빌드 실패인지를 먼저 의심함.
Jenkins 주소와 계정은 담당자에게 문의함. 위키에 남기지 않음.