배경
입주민 앱 homez(스토어 표시명 LH 스마트홈)의 구조를 한 장으로 봄. “앱이 켜지자마자 꺼진다”, “우리집 제어 탭이 없다”, “보안 연결 오류가 뜬다” 같은 문의의 근거가 여기 있음. 기능별 내용은 공개노트/기능/우리집제어, 공개노트/기능/스마트원패스, 공개노트/기능/로그인과 세대 승인에 있음. 서버 쪽 전체 구성은 공개노트/개발/시스템 구성.
앱은 MAW 한 곳에만 REST로 요청하고, MAW가 홈넷서버·에너지플랫폼·가전사·FCM으로 중계함. 예외 셋임.
- 스마트 원패스 문열기 — 서버를 안 거치고 단말이 직접 BLE 신호를 쏨. 서버 호출은 사용 로그용임
- 본인인증(NICE)·하자보수(바로처리)·파트너 가전 OAuth — 앱 내 웹뷰로 외부 URL 열림
- 홈 화면 위젯(Android AppWidget / iOS WidgetKit) — 문열기를 딥링크로 호출함
기술 스택
| 항목 | 값 |
|---|---|
| 프레임워크 | Flutter, Dart SDK 3 계열 |
| 상태관리 / 라우팅 / 통신 | Riverpod / GoRouter / Dio + Retrofit |
| Android | minSdk 27, targetSdk 35, applicationId homez.lh.or.kr |
| iOS | 최소 13, 위젯 익스텐션 homez.lh.or.kr.OnePassWidget |
| 로컬 저장 | flutter_secure_storage(토큰·설정), SQLCipher(알림함 DB) |
| 푸시·통계 | Firebase Messaging / Analytics / Crashlytics (Crashlytics는 릴리즈 빌드만 수집) |
- Dart 소스 약 9만 줄임.
third_party/에 로컬 참조 패키지 3개(스켈레톤 UI, 루팅 탐지, 홈 위젯)가 있어 이 디렉터리가 없으면pub get이 실패함. - 라우트는 107개임(로그인 후 88개 + 로그인 전·공통 19개). 존재하지 않는 경로면
RedirectScreen이 세션을 확인해 메인 또는 로그인으로 보냄. - 화면 전환마다 Analytics
screenEnter이벤트가 기록됨. 같은 화면 연속 진입은 중복 제거됨.
개발·운영 서버 전환
- flavor가 없음. 빌드 스크립트가 소스의 서버 주소 한 줄을 치환하고 빌드 후 원복하는 방식임.
- 운영은
homez-m.lh.or.kr/maw/v1, 개발은homezdev-m.lh.or.kr/maw/v1임. - 개발 빌드는 FCM 토픽
DEV, 운영 빌드는PRD를 구독함. - 앱 화면에 환경 표시가 없음. APK 파일명(
lhsmarthome_prod.apk/lhsmarthome_dev.apk)으로만 구분 가능함. “푸시가 안 온다” 문의에서 개발 빌드를 깔고 있는 경우가 있으므로 확인할 것.
앱 시작 흐름
- Firebase 초기화 → 로컬 알림 채널 생성 → FCM 백그라운드 핸들러 등록 → 환경에 맞는 토픽(
PRD/DEV) 구독 - 로컬 DB(SQLCipher) 초기화
- Android는 알림·위젯으로 눌린 “문열기” 대기 플래그가 있으면 즉시 문열기 실행
/splash진입- 루팅·탈옥·에뮬레이터 검사 → 걸리면 종료 팝업(아래 “보안 차단” 참조)
- 첫 실행이면 인트로 화면 → 확인 시 플래그 저장
- 필수 권한(Android 전화·카메라 / iOS 사진·카메라) 미허용이면 권한 화면
- 세션 조회 → 유효하면 즐겨찾기 탭, 무효면 로그인, 통신 실패면 재시도 다이얼로그
네트워크 또는 서버 상태가 원활하지 않습니다.\n다시 시도해주세요. - 안전장치: 6초가 지나도 아무 데로도 이동하지 않으면 무조건 로그인 화면으로 보냄
운영 시 알아둘 점
- 스플래시에서 오래 멈췄다가 로그인 화면으로 튕기면 회원 상세 조회(
member/findUserDetailInfo)가 느리거나 실패한 것임. - 스플래시 배경은 파란 단색(
#004EBE)이고 같은 화면을 새로고침·리다이렉트 화면도 씀. “파란 화면에서 멈춤”은 셋 중 하나임.
버전 체크
- 상단 날씨바가 그려질 때
common/applicationVersion으로 최신 버전을 받아 설치 버전과 비교함. 20초 캐시를 거침. - 구버전이면 팝업
앱 업데이트가 있습니다.\n업데이트 후 이용해주세요.버튼확인(스토어 이동) /종료(앱 종료). - 그 전에 신규 약관(
common/agreementStatus)이 있으면 약관 동의 화면으로 먼저 보냄.
주의
- 강제 업데이트(하드 블로킹)가 없음. 팝업은 날씨바가 있는 화면에서만 뜨고, 무시하고 계속 쓸 수 있음.
- 버전 비교가 문자열 비교라
1.10.0을1.9.0보다 낮게 판정함. 마이너 버전이 두 자리가 되는 순간 오판함. 배포 전 반드시 확인할 것.
하단 탭과 화면 노출 조건
메인 탭 화면은 하나이고 인덱스로 갈림. 가운데 큰 원형 버튼은 항상 즐겨찾기이고 앱 기본 진입 화면도 즐겨찾기임.
| 인덱스 | 화면 |
|---|---|
| 0 | 우리집 제어 |
| 1 | 아파트관리 |
| 2 | 즐겨찾기(기본 진입) |
| 3 | 헬스케어 |
| 4 | 에너지관리 |
| 5 | 전체메뉴 |
| 8 | 내 정보 |
탭 구성은 회원의 menuType(서버가 내려줌)에 따라 4종임. menuType이 type2인데 homenetServerYn이 Y면 앱이 type4로 강제 변경함.
| menuType | 탭 |
|---|---|
| type1 | 아파트관리 / 즐겨찾기 / 헬스케어 |
| type2 | 우리집 제어 / 아파트관리 / 즐겨찾기 / 헬스케어 / 내 정보 |
| type3 | 아파트관리 / 헬스케어 / 즐겨찾기 / 에너지관리 / 내 정보 |
| type4 | 우리집 제어 / 아파트관리 / 즐겨찾기 / 헬스케어 / 에너지관리 |
운영 시 알아둘 점 “우리집 제어 탭이 안 보인다”, “에너지 탭이 없다”는 거의 전부 menuType·homenetServerYn·energyPlatformYn 값 문제임. 앱 버그가 아니라 회원·단지 설정을 볼 것.
기능 노출을 좌우하는 회원 플래그
전부 서버가 내려주는 값임. 문의 응대 시 이 값부터 확인함.
| 필드 | 뜻 |
|---|---|
rolId | 역할. VSTR이면 방문자(미인증) |
menuType | 하단 탭 구성 |
cogoSsCd | 입주민 인증 상태. 공개노트/기능/로그인과 세대 승인 |
homenetServerYn | 홈넷서버 연동 여부(우리집 제어 노출) |
energyPlatformYn | 에너지플랫폼 연동 여부 |
elvPlatformYn / elrContYn | 승강기 플랫폼 연동 / 엘리베이터 계약. 공개노트/기능/승강기 호출 |
onePassYn, onePassLhCodeList | 원패스 사용 여부·LH 코드. 공개노트/기능/스마트원패스 |
hmappContYn | 홈넷앱 계약 여부 |
sftSvcHshYn | 안전지원(살피미) 세대 여부 |
floorNoiseYn | 층간소음 서비스 여부 |
flwPrcYn | 하자보수 바로처리 가능 여부 |
maintenanceLeaseType | 01이면 관리비·임대료 위젯 노출 |
지원하지 않는 단지 기능을 누르면 해당 기능을 지원하지 않는 단지입니다. 가 뜸.
보안 차단
인증서 피닝
- 대상 호스트는 운영 도메인 하나뿐임. 개발 도메인은 피닝하지 않음.
- SPKI SHA-256 핀 2개(현재·백업)가 앱 소스에 박혀 있음 → [REDACTED]
- 실패하면 앱 전체가 보안 연결 오류 화면으로 강제 이동하고 이후 요청이 사전 차단됨. 뒤로가기 불가임.
- 화면 문구: 제목
보안 연결 오류, 본문보안 연결을 확인할 수 없어 서비스를 이용할 수 없습니다.\n네트워크 환경을 확인한 후 다시 시도해주세요., 버튼재시도.
서버 인증서를 교체하기 전에 반드시 앱 핀 업데이트 배포가 먼저 나가야 함. 순서가 바뀌면 전 사용자가 동시에 앱을 못 씀.
TLS 검사
- Android만 응답마다 네이티브 채널로 TLS 버전을 확인하고, 결과를 2분간 캐시함.
- Android 네트워크 설정은 운영 도메인에 평문 차단 + TLS 1.2 이상 강제임. iOS ATS도 예외 도메인만 허용함.
루팅·탈옥·에뮬레이터
- 스플래시와 메인 탭 두 곳에서 검사함. 걸리면 버튼
종료하나짜리 팝업을 띄우고 앱이 꺼짐. - 에뮬레이터 차단만 빌드 플래그로 끌 수 있음.
| 팝업 문구 | 원인 |
|---|---|
에뮬레이터 환경에서는 앱을 사용할 수 없습니다. | 에뮬레이터로 판정 |
루팅된 기기에서는 사용이 불가능합니다. | 루팅·탈옥 탐지 |
보안 환경을 확인할 수 없어 앱을 사용할 수 없습니다. | 검사 자체 실패. 실제 루팅이 아니라 기기 호환성 문제일 수 있음 |
운영 시 알아둘 점
- “앱이 켜지자마자 종료된다”는 위 3개 팝업 중 하나임. 어떤 문구가 떴는지 물어보면 원인이 바로 갈림.
- “보안 연결 오류”는 사내 프록시·공공 와이파이의 SSL 검사 장비, 또는 서버 인증서 교체 후 앱 핀 미갱신일 때 뜸. 여러 사용자가 동시에 신고하면 인증서 쪽부터 볼 것.
백그라운드 작업
background_fetch로 최소 15분 간격(OS가 실제 주기를 정함), 부팅 후 시작, 앱 종료 후에도 유지되도록 등록됨. 하는 일은 살피미 체크(healthCare/healthCheck) 한 건뿐임.- Android 원패스는 이와 별개로 네이티브 포그라운드 서비스가 상시 동작함. 공개노트/기능/스마트원패스
권한
Android
| 권한 | 용도 |
|---|---|
| BLUETOOTH_SCAN / _CONNECT / _ADVERTISE | 원패스 비콘 탐지·상태 조회·문열기 신호 송신 |
| ACCESS_FINE/COARSE_LOCATION | BLE 스캔 전제 조건 |
| ACCESS_BACKGROUND_LOCATION | 앱이 백그라운드일 때도 원패스 동작(“항상 허용”) |
| FOREGROUND_SERVICE 계열 | 원패스 포그라운드 서비스 |
| POST_NOTIFICATIONS | Android 13 이상 알림 표시 |
| CALL_PHONE | 비상호출·고객센터 전화 연결 |
| CAMERA / 저장소 | 주차 등록 등 사진 촬영·업로드 |
| RECORD_AUDIO | 음성 명령 |
| RECEIVE_BOOT_COMPLETED | 부팅 후 원패스 서비스·예약 알림 재등록 |
| SCHEDULE_EXACT_ALARM | 복약 등 정시 알림 |
| REQUEST_IGNORE_BATTERY_OPTIMIZATIONS | 배터리 최적화 예외 요청 |
iOS
- 블루투스·위치·카메라·앨범·마이크·음성인식 설명 문구가 등록돼 있음.
- 백그라운드 모드는
fetch,processing,remote-notification뿐임. BLE 백그라운드 모드가 없음 → 공개노트/기능/스마트원패스의 iOS 제약 원인임.
최초 권한 안내 화면
- 필수는 전화·카메라, 선택은 저장공간·위치·마이크임. 거부해도 막지 않고 그대로 진행함.
- 원패스용 “항상 허용” 위치 권한은 여기서 안 받고 원패스를 켤 때 따로 요청함.
- 화면 하단 안내에 치환되지 않은
App Title문자열이 그대로 노출됨(앱 수정 필요).
공통 코드표
응답 코드
모든 API 응답은 {resCd, resMsg, traceId, resData} 형태임.
| resCd | 뜻 |
|---|---|
SQI0000 | 정상. 코드 전반에서 이 값만 성공으로 봄 |
2000, 0000 | 정상(일부 화면에서만 허용) |
SQI2010 | 파트너 가전 인증 만료 → 재인증 유도 |
SQI4010~SQI4013, 401, 403 | 세션 무효 → 토큰 삭제 후 로그인 화면 |
E4001~E4004 | 긴급연락처 OTP 실패 |
캐시 TTL
“방금 바꿨는데 앱에 안 보인다”는 문의의 상당수가 이 캐시임.
| 대상 | TTL |
|---|---|
| 회원 정보 | 10초 |
| IoT 기기 목록 | 30초 |
| 앱 버전 정보 | 20초 |
| TLS 검사 결과 | 2분 |
| 헬스케어 데이터 | 30초 |
| 에너지 데이터 | 5분 |
통신 타임아웃은 연결·수신 모두 10초임.
단말 저장 항목
토큰(ACCESS_TOKEN, REFRESH_TOKEN), 사용자 ID, 인트로 플래그, 직전 승인 상태, 즐겨찾기 목록, 구독 토픽 목록, 원패스 사용 여부·LH 코드, 위젯 순서, 각종 캐시가 secure storage에 들어감. 로그아웃 시 전체 삭제됨. 공개노트/기능/로그인과 세대 승인
외부 연동 (앱이 직접 여는 것)
| 대상 | 방식 |
|---|---|
| NICE 본인인증 | 웹뷰 |
| 하자보수(바로처리) | 웹뷰. 단지·동·호를 쿼리로 전달 |
| 파트너 가전 OAuth | 웹뷰. 서버가 내려준 로그인 URL |
| PASS 본인인증 앱 | URL scheme으로 외부 앱 호출(SKT·KT·LGU+) |
| 건강보험 앱 | 딥링크, 실패 시 스토어 이동 |
| 앱 스토어 | 버전 업데이트 안내에서 호출 |
| 공동현관 리더기 | BLE 직접 송신(서버 미경유) |
알려진 문제
| 항목 | 영향 |
|---|---|
| 버전 비교가 문자열 비교 | 1.10.0을 구버전으로 오판. 마이너 두 자리 배포 전 수정 필요 |
| 강제 업데이트 없음 | 구버전 사용자를 막을 수단이 없음 |
| 로그아웃이 전체 삭제 | 즐겨찾기·인트로·원패스 설정까지 초기화됨 |
| 루팅 검사 코드가 두 곳에 중복 | 한 곳만 고치면 다른 쪽이 남음 |
권한 안내 화면의 App Title 미치환 | 사용자에게 그대로 노출됨 |
| 앱 화면·로직 단위 테스트가 사실상 없음 | 릴리스 스크립트만 테스트가 촘촘함 |
| 화면 문구 오탈자 | 채중관리, 예방를, 안정 경보, 공백 2칸 등이 그대로 노출됨 |
확인 필요
확인 필요
- iOS ATS 예외 도메인과
data.dart의 개발 서버 도메인이 서로 다름. iOS 개발 빌드가 ATS에 막히는지 단말 확인 필요.- Android 네트워크 보안 설정에 운영 도메인만 있고 개발 도메인이 없음. 개발 빌드의 TLS 정책 적용 방식 확인 필요.
third_party/패키지 3개를 왜 로컬로 포크해 뒀는지 코드만으로 알 수 없음. 원본 대비 수정 내역 확인 필요.- 긴급연락처 OTP 실패 코드
E4001~E4004의 서버 측 정확한 의미는 MAW 문서 확인 필요.- 앱 저장소 README가 가리키는
docs/디렉터리가 실제로 없음. 기능·구조 문서의 별도 위치 확인 필요.
관련
공개노트/개발/시스템 구성 공개노트/개발/배포와 빌드 공개노트/개발/push 알림 공개노트/기능/로그인과 세대 승인 공개노트/기능/우리집제어 공개노트/기능/스마트원패스 공개노트/기능/승강기 호출