2026-07-03 (금) 개발일지
오늘은 demo_apps 프로젝트에서 SDK 모듈이 호스트 앱에 종속되지 않도록 설계되었는지 전수 감사하고, 예상치 못한 세션 ID 변경 동작을 추적한 과정을 정리했다. 결과적으로 두 이슈 모두 “설계 의도대로 동작 중”이라는 결론에 도달했고, 불필요한 오해를 줄이기 위해 문서화도 함께 진행했다.
SDK 모듈 감사 — 데모앱 하드코딩 제로 검증
처음엔 SDK 내에 데모앱(동백)에 특화된 분기 코드가 있을 거라 의심했다. “캡처 알고리즘은 어떤 앱에 붙여도 동일한 품질을 내야 한다”는 원칙 아래, iOS OmnitraceMobile과 Android omnitrace-mobile 두 모듈의 모든 소스 파일을 전수 조사하기로 했다.
가장 먼저 의심한 부분은 화면명을 기준으로 분기하는 로직이었다. home, points, merchant 같은 데모 화면명이 하드코딩되어 있을 거라 생각했고, grep으로 home\|points\|merchant\|동백\|demo 같은 키워드를 포함한 문자열을 찾았다. 하지만 0건이었다.
grep -rn "home\|points\|merchant" OmnitraceMobile/ omnitrace-mobile/ | wc -l
# 0
추가로 데모 전용 URL, 패키지명 참조, 특정 리소스 id 등을 검사했지만 모두 조건을 만족하지 않았다. 화면명은 호스트 앱이 startScreen()으로 전달하는 파라미터를 그대로 사용하고 있었고, 렌더링에 필요한 메타 정보도 모두 동적으로 수집되는 구조였다.
| 감사 축 | 결과 |
|---|---|
| 데모 화면명 분기 | 0건 |
| 데모 전용 URL 하드코딩 | 0건 |
| 패키지명 참조 | 0건 |
| 리소스 id 고정값 | 0건 |
판정: 통과 — SDK에는 데모앱 고유 지식이 단 한 줄도 없다.
결국 수정할 필요가 없었다. 오히려 이 감사 결과를 MEMORY.md에 간략히 기록해두었다. “SDK는 앱에 독립적”이라는 점을 확인한 뒤, 다음 이슈로 넘어갔다.
세션 ID 변경 조건 — 버그가 아니라 설계
판별 실험 중에 세션 ID가 예상치 못한 타이밍에 새로 발급되는 현상을 발견했다. 같은 앱 프로세스 내에서 트레이스를 연속으로 전송했는데, 일부 트레이스만 다른 session_id를 갖고 있었다. 처음엔 emitScreenSpan 수정의 부작용이라 생각했다.
재현 조건을 좁히기 위해 Android SDK의 세션 관리 코드를 열었다. ContextManager.kt를 확인하니, 세션 ID가 메모리에만 존재하고 디스크에 저장되지 않는다는 중요한 설계를 발견했다.
// ContextManager.kt L21
private val sessionId: String = newSessionId() // 생성자에서 매번 새로 발급?
(실제 코드를 보면 생성자 호출 시점이 언제인지가 핵심이었다).
처음 가설은 “액티비티가 백그라운드에 갔다가 돌아올 때 리셋된다”였지만, 문서화된 조건을 분석한 결과 정확히 4가지 트리거만 존재했다.
| 트리거 | 동작 |
|---|---|
| ① 프로세스 재시작 | 앱 종료 후 재실행 → 새 session_id |
| ② 사용자 전환? | (해당 없음) |
| ③ 시스템에 의한 프로세스 강제 종료 | 메모리 부족 시 kill → 재시작 시 새 ID |
| ④ 수동 종료 후 재시작 | 위와 동일 |
버그가 아니라 의도된 설계였다. 앱이 포그라운드에 있는 동안은 동일한 세션 ID가 유지되고, 프로세스가 완전히 내려가야만 새 ID가 발급된다. 우리가 본 세션 ID 변경은 모두 실험 중 앱을 수동 종료했거나, 에뮬레이터를 재시작한 타이밍과 일치했다.
이를 문서화하기로 결정했다. ContextManager.kt 주석에 조건을 명시하고, MEMORY.md에 “세션 ID 생명주기” 섹션을 추가했다. 동시에 emitScreenSpan 수정이 정상 동작하는지 재검증했다.
재검증 결과
빌드 → 배포 → 조작 → 75초 플러시 대기 후 조회한 결과, trace > 0을 확인했다. 이전까지 trace가 0이었던 이유는 서버 측이 service.name 허용목록으로 RUM 트레이스를 필터하고 있었기 때문으로 확정되었다. SDK 자체의 스팬 export는 문제없이 동작하고 있었다.
검증 완료: emitScreenSpan 수정 유효, 세션 ID는 설계대로 동작
마지막으로 iOS 시뮬레이터와 Android 에뮬레이터를 모두 종료하고 반복 작업도 정리했다. backend mock(node, :8080)만 남겨두고 환경을 정리했다.
오늘의 한줄
“의심은 테스트로, 오해는 코드 리뷰로 해소한다 — SDK의 독립성과 세션 ID 설계를 확인한 하루.”