# Android 앱 설치/실행 재발 방지 정책 작성일: 2026-07-06 상태: v1.4 목적: Windows Android Studio emulator + WSL/Docker Flutter 환경과 Android 공기계 USB 연결 환경에서 `tdc114plus` 앱을 테스트할 때, 환경값 누락과 ADB 연결 장애로 같은 문제를 반복하지 않도록 설치/실행 정책을 고정한다. 관련 문서: - `docs/policy_android_studio_wsl_adb_2026-07-03.md` - `docs/scenario_android_emulator_device_integration_test_2026-07-03.md` - `scripts/README.md` ## 1. 이번 장애 요약 2026-07-06에 아래 문제가 재현되었다. - 최신 코드를 빌드한 뒤 `adb install`로 debug APK만 직접 설치했다. - 그러나 이 앱은 `TDC114_API_BASE` 같은 runtime 값을 `--dart-define`으로 받는다. - APK 직접 설치 방식은 이 값을 전달하지 못한다. - 결과적으로 앱은 기본값 `https://sso.example.invalid`를 바라보게 되었고, 직원 목록 API가 실패했다. - 사용자는 코드가 반영되지 않았거나 필터 버그가 남아 있다고 오해할 수 있었다. 핵심 원인: - 문제는 코드 수정 자체가 아니라 `설치 방식이 앱의 runtime config 구조와 맞지 않은 것`이었다. ## 2. 필수 원칙 - `tdc114plus` Android 수동 검증 기본 경로는 `flutter run`이다. - `TDC114_API_BASE`가 필요한 앱 실행은 반드시 `dart-define` 포함 경로로 띄운다. - `adb install` 또는 APK 파일 직접 설치는 기본 검증 경로로 사용하지 않는다. - local Baron SSO 검증은 emulator 기준 `http://10.0.2.2:5000`을 사용한다. - 앱/API 버그 판단 전에는 먼저 `./scripts/api-smoke.sh`로 backend 상태를 확인한다. - Windows `adb.exe devices`에서 대상 emulator가 `device` 상태로 안정화되기 전에는 WSL/Docker Android 스크립트를 실행하지 않는다. - 2026-07-08 기준 Windows Android Studio emulator + Docker Flutter 표준 연결 방식은 `ADB_SERVER_SOCKET=tcp::5037`이다. - `TDC114_ADB_CONNECT_ADDRESS=:` 직접 연결 방식은 Windows ADB 서버 공유 방식이 실패하거나 integration test의 VM service port forwarding 이슈가 확인된 경우에만 보조 경로로 사용한다. - 2026-07-08 이후 신규 수동 기능점검의 기본 target은 가능하면 Android 공기계 USB 연결 방식으로 전환한다. - emulator 경로는 보조/fallback으로 보존하되, 물리 키보드 한글 입력이나 emulator portproxy 문제를 해결하기 위해 emulator 설정을 반복하지 않는다. - 공기계에서는 `10.0.2.2`를 사용할 수 없으므로 `adb reverse tcp:5000 tcp:5000` + `TDC114_API_BASE=http://127.0.0.1:5000`을 우선 사용한다. - USB 없는 독립형 실기기 검증에서는 `TDC114_API_BASE=https://`를 사용하고 `TDC114_SKIP_SESSION_BOOTSTRAP=true`로 로컬 bootstrap/mocking을 끈다. - 2026-07-08 이후 로그인과 데이터 소스를 분리해야 하면 `TDC114_AUTH_API_BASE`, `TDC114_DIRECTORY_API_BASE`, `TDC114_ORGANIZATION_API_BASE`를 별도로 지정할 수 있다. 값을 지정하지 않으면 모두 `TDC114_API_BASE`를 사용한다. ## 3. 허용 경로와 금지 경로 ### 3.1 기본 허용 경로 공기계 USB 수동 기능점검을 우선한다. ```bash ADB_SERVER_SOCKET=tcp::5037 \ TDC114_SMOKE_ENV_FILE=scripts/.env.android-device.local \ TDC114_FLUTTER_DEVICE_ID= \ ./scripts/manual-postlogin-run.sh ``` 사전 조건: - Windows PowerShell `adb.exe devices`에서 공기계가 `device` 상태다. - `adb reverse tcp:5000 tcp:5000`이 적용되어 있다. - `scripts/.env.android-device.local`의 `TDC114_API_BASE`는 `http://127.0.0.1:5000`이다. ### 3.1-B USB 없는 독립형 실기기 허용 경로 staging 또는 production 공개 API에 직접 붙는 실기기 검증은 아래 경로를 사용한다. ```bash ADB_SERVER_SOCKET=tcp::5037 \ TDC114_SMOKE_ENV_FILE=scripts/.env.android-device.staging.local \ TDC114_FLUTTER_DEVICE_ID= \ ./scripts/manual-postlogin-run.sh ``` 사전 조건: - `TDC114_API_BASE`는 `https://...` 공개 HTTPS Baron API 주소다. - 필요 시 로그인은 staging, 직원/조직 데이터는 production으로 분리 주입할 수 있다. - `TDC114_SKIP_SESSION_BOOTSTRAP=true`가 설정되어 있다. - 로그인은 앱의 `Baron SSO로 로그인` 버튼에서 Hosted Login을 열고, App Link callback과 PKCE token 교환으로 완료한다. - USB는 최초 설치/실행 후 분리 가능해야 한다. ### 3.1-A emulator fallback 허용 경로 emulator를 쓸 경우 아래 경로만 허용한다. ```bash ADB_SERVER_SOCKET=tcp::5037 \ TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local \ ./scripts/manual-postlogin-run.sh ``` 용도: - post-login 상태 수동 기능 점검 - local API base URL 포함 실행 - 실제 phone-login bootstrap 또는 mock fallback 포함 실행 실제 로그인 화면 검증이 필요하면 RP issuer/client/callback 값이 맞는지 확인한 뒤 `Baron SSO로 로그인` 버튼에서 외부 Hosted Login을 연다. ### 3.2 조건부 허용 경로 ```bash ADB_SERVER_SOCKET=tcp::5037 \ TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local \ ./scripts/integration_tests.sh ``` 용도: - integration smoke - post-login 가정 자동 검증 ### 3.3 금지 경로 아래 방식은 정책상 기본 검증 경로로 금지한다. ```bash adb install app-debug.apk ``` 금지 이유: - `TDC114_API_BASE` - `TDC114_PREAUTH_*` - `TDC114_SMOKE_USE_MOCK_DIRECTORY` 같은 runtime define 값이 전달되지 않는다. 예외: - 단순 설치 가능 여부 확인 - 패키지명 확인 - manifest 수준 점검 이 경우에도 `기능 검증용 실행`으로 간주하지 않는다. ## 3-A. 직원검색 초기 기본값 정책 직원검색 첫 진입 시 기본값은 아래처럼 고정한다. - 초기 조회 범위: 로그인 사용자의 회사급 범위 - 상단 기본 노출 칩: 회사급 칩 + 본인팀 칩 - 금지 동작: 앱 시작 직후 phone/name 재조회로 본인 1명 결과에 맞춰 초기 범위를 다시 팀 또는 개인 단위로 축소하는 로직 정책 이유: - 첫 진입에서 사용자가 자기 자신만 보이면 디렉터리 앱 기본 UX와 맞지 않는다. - 조직/회사 단위 탐색이 시작점이어야 하고, 본인팀은 빠른 재선택용 칩으로 유지하면 충분하다. - `회사급 범위 조회`와 `본인팀 칩 고정 노출`은 서로 다른 정책이므로 둘 다 함께 유지해야 한다. ## 4. 실행 전 체크 순서 Android 기능점검 전에는 아래 순서를 고정한다. ### 4.1 공기계 USB 기본 순서 1. Windows PowerShell에서 `adb.exe devices` 확인 2. 공기계가 `device` 상태인지 확인 3. `./scripts/api-smoke.sh` 통과 확인 4. `adb reverse tcp:5000 tcp:5000` 적용 5. `scripts/check-android-device-env.sh` 통과 확인 6. `manual-postlogin-run.sh` 실행 중단 기준: - Windows `adb.exe devices`에서 공기계가 `unauthorized`이면 단말 RSA 승인 전까지 진행하지 않는다. - `adb reverse`가 실패하면 LAN IP 방식으로 바꾸기 전에는 `127.0.0.1:5000` 기준 앱 실행을 하지 않는다. - 앱에서 HTTP API가 차단되면 debug 전용 cleartext 허용 설정을 먼저 검토한다. ### 4.1-B USB 없는 독립형 실기기 순서 1. Windows PowerShell에서 `adb.exe devices` 확인 2. 공기계 또는 실사용 폰이 `device` 상태인지 확인 3. `TDC114_API_BASE=https://`로 env를 준비 4. `TDC114_SKIP_SESSION_BOOTSTRAP=true` 상태로 `manual-postlogin-run.sh` 실행 5. 앱 첫 화면에서 `Baron SSO로 로그인` 수행 6. 문자 또는 메일의 링크 승인 완료 7. `직원검색`, `organization/tenants`, `organization/orgchart` 화면 동작 확인 8. 앱이 열린 뒤 USB를 분리하고 같은 동작이 유지되는지 재확인 중단 기준: - 공개 HTTPS base URL이 확정되지 않았으면 진행하지 않는다. - Hosted Login, App Link callback, PKCE token 교환이 staging/production 환경에서 준비되지 않았으면 local mode로 되돌리지 않고 RP 설정과 서버 준비 상태를 먼저 맞춘다. - 승인 링크 수신 채널이 준비되지 않았으면 USB 없는 독립 검증 완료로 간주하지 않는다. ### 4.2 emulator fallback 순서 1. Windows PowerShell에서 `adb.exe devices` 확인 2. 대상 emulator가 `device` 상태인지 확인 3. `./scripts/api-smoke.sh` 통과 확인 4. Windows ADB server `5037 -> 127.0.0.1:5037` portproxy와 방화벽 rule 확인 5. 그 다음 `manual-postlogin-run.sh` 또는 `integration_tests.sh` 실행 중단 기준: - Windows `adb.exe devices`에서 대상 emulator가 `offline`이면 WSL/Docker 스크립트를 실행하지 않는다. - Windows `adb.exe devices`가 `device`인데 Docker local ADB 직접 연결이 `offline`이면, 직접 emulator port 연결을 반복하지 않고 `ADB_SERVER_SOCKET=tcp::5037` 방식으로 전환한다. - Android Studio Device Manager의 표시 이름과 실제 AVD 폴더 이름이 달라도, `C:\Users\user\.android\avd`에 저장된 AVD 수와 Windows `adb.exe devices` 상태를 우선 기준으로 삼는다. - AVD 프로세스가 `terminated`되거나 Android Studio가 `failed to connect within 5 minutes`를 표시하면 WSL/Docker 확인으로 넘어가지 않고 Windows 단독 emulator 부팅 안정화부터 처리한다. 완료 기준: - 앱이 local API 기준으로 실행된다 - 직원검색 또는 로그인 화면이 기대한 경로로 열린다 ## 5. 포트가 왜 바뀌는가 질문: 코드 수정이 생길 때마다 포트가 바뀌는가? 답: 아니다. `코드 수정 때문에 포트가 바뀌는 것이 아니다.` 포트가 바뀌는 이유는 보통 아래 중 하나다. - 새 emulator 인스턴스를 띄웠다 - 기존 emulator를 끄고 다른 emulator 번호로 다시 띄웠다 - `emulator-5554`, `5556`, `5558`처럼 여러 인스턴스가 섞였다 - Windows `portproxy`가 그 emulator의 adbd port와 맞지 않았다 즉: - 코드 변경 - Flutter rebuild - hot reload 이 자체는 emulator port를 바꾸지 않는다. ## 6. 반복 절차를 줄이는 고정 운영안 반복을 줄이기 위해 아래 운영안을 기본값으로 사용한다. ### 6.1 1대 고정 원칙 - 수동 검증용 emulator는 한 번에 1대만 켠다. - 기본 장비는 당일 Windows `adb.exe devices`에서 `device`로 확인된 emulator 1대다. - 다른 emulator가 `offline`으로 남아 있거나 여러 인스턴스가 섞이면 Android Studio/ADB 상태를 먼저 정리한다. 효과: - 어떤 emulator가 현재 대상인지 혼선이 줄어든다. - `offline`/`refused` 원인 추적이 쉬워진다. ### 6.2 Windows ADB 서버 공유 원칙 - Docker/WSL Flutter는 기본적으로 Windows ADB server를 공유한다. - 표준 환경변수는 `ADB_SERVER_SOCKET=tcp::5037`이다. - Windows 관리자 PowerShell에서 `0.0.0.0:5037 -> 127.0.0.1:5037` portproxy와 방화벽 rule을 유지한다. - Windows `adb.exe devices`에서 `emulator-5562 device`처럼 정상으로 보이면, Docker Flutter도 같은 Windows ADB server를 통해 장치를 인식해야 한다. - 직접 emulator adbd port 연결이 `offline`으로 반복되면 해당 방식은 중단하고 Windows ADB server 공유 방식만 사용한다. 효과: - Docker container 내부 ADB key 불일치로 인한 `offline`/`unauthorized` 반복을 줄인다. - Windows에서 이미 정상 승인된 ADB 세션을 그대로 사용한다. ### 6.3 명시 emulator portproxy 원칙 - 수동 검증 포트는 Windows `adb.exe devices`에서 확인한 emulator port에 맞춘다. - 예: Windows 대상이 `emulator-5562`이면 `5562 -> 127.0.0.1:5562` portproxy와 방화벽 규칙을 확인한다. - `TDC114_ADB_CONNECT_ADDRESS=:`는 보조 경로로만 명시한다. - shutdown/startup 스크립트는 과거 고정 포트를 임의로 disconnect하지 않는다. 효과: - 실제 대상 포트와 스크립트 포트가 어긋나는 일을 줄인다. ### 6.4 APK 직접 설치 금지 - 코드 수정 후 수동 검증은 항상 `flutter run` 또는 `manual-postlogin-run.sh` - APK 직접 설치는 설치 확인용 보조 수단으로만 사용 효과: - runtime define 누락 사고를 막는다. ### 6.5 같은 세션 재사용 - emulator를 켠 뒤 가능한 한 끄지 않는다. - `flutter run` 세션이 살아 있을 때는 hot reload/hot restart를 우선한다. - 큰 설정 변경이 아닐 때는 재설치보다 같은 세션 재사용을 우선한다. 효과: - rebuild/install 시간과 ADB 재연결 횟수가 줄어든다. ## 7. 표준 명령 ### 7.1 post-login 수동 기능점검 ```bash TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local \ ADB_SERVER_SOCKET=tcp::5037 \ ./scripts/manual-postlogin-run.sh ``` ### 7.2 integration smoke ```bash TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local \ ADB_SERVER_SOCKET=tcp::5037 \ ./scripts/integration_tests.sh ``` ### 7.3 backend 상태 확인 ```bash ./scripts/api-smoke.sh ``` ## 8. 내일부터의 운영 기준 - Android 수동 검증 기본 target은 USB 연결 공기계다. - Android emulator는 fallback target으로 보존한다. - Docker/WSL 기본 연결은 `ADB_SERVER_SOCKET=tcp::5037`로 명시한다. - `TDC114_ADB_CONNECT_ADDRESS=:`는 직접 emulator port 연결이 필요한 예외 상황에만 사용 - 실행 스크립트 기본값은 `manual-postlogin-run.sh` - `adb install`은 기능검증용 실행으로 인정하지 않음 이 기준을 어기면 다시 아래 오판이 발생할 수 있다. - 코드 미반영으로 오해 - API 장애로 오해 - 필터 버그 미수정으로 오해