Project
SBI Cosmoney
한국 거주 외국인이 11개 언어로 본국에 송금하는 글로벌 송금 앱 'SBI Cosmoney'의 안드로이드 앱 개발 프로젝트입니다.
Java·XML로 된 오래된 단일 구조였고, 금융 보안 취약점과 느린 시작 속도를 안고 있었습니다. 저는 쓰던 기능이 하나도 달라지면 안 된다는 조건 아래, 구조와 보안과 속도를 지금 기준으로 끌어올리는 작업을 맡아 진행했습니다.
디자인 시스템·네트워크·SQLCipher Room을 모듈로 나누고, 화면 로직을 UiState와 순수 Reducer 구조로 바꿨습니다.
- 구조 전면 개편: 멀티 모듈 & UiState·순수 Reducer
- 성과: 오래된 코드 47,356줄을 걷어내고 그 자리를 Kotlin 88,137줄로 채웠습니다. 로직이 입력과 출력만 가지게 되면서 8개월간 76,243줄의 테스트 코드를 확보했습니다.
- 기존 동작 그대로 옮기기: 옛 코드의 판정 기준과 서버 규격을 먼저 분석
- 성과: 송금 금액·한도·수수료 계산과 요청 암호화·서명 순서를 옛 코드와 똑같은 값이 나오도록 맞춰, 국내·해외송금과 네트워크를 동작 변화 없이 옮겼습니다.
금융결제원 보안 기준에 맞춰 인증 방식과 저장소, 로그 기록을 다시 만들었습니다.
- 보안 키패드·PIN 인증 Compose 재구축, SecureRandom 교체, TLS 검증 우회 제거
- 성과: 여기저기 흩어져 있던 인증 토큰 저장을 암호화 저장소 한 곳으로 모았고, 앱이 변조되면 들어올 수 없도록 막는 검사를 모든 진입 경로에 적용했습니다.
- 앱에 남던 로그 정리: 오래된 LOG 코드 880건을 Timber로 교체
- 성과: 네트워크 응답과 개인정보가 출시 버전 로그로 새어 나가던 것을 막고, 대신 경고와 오류만 수집해 운영 중 문제를 바로 확인할 수 있게 했습니다.
- 접근 권한 분리 안내: 필수(전화·설치된 앱) / 선택(카메라·사진·알림)
- 성과: 금융 사고를 막는 데 꼭 필요한 권한만 필수로 두어, 선택 권한을 거부해도 송금 기능을 그대로 쓸 수 있게 했습니다.
Macrobenchmark로 느린 구간을 직접 재서 앱 시작 속도를 개선했습니다.
- 어디가 느린지 먼저 측정: 시작 구간별 기록과 StartupBenchmark 도입
- 성과: 짐작으로 고치지 않고 구간별로 시간을 재서, 범인으로 의심받던 보안 모듈이 각 3ms뿐이라는 걸 확인하고 진짜 원인이던 GMS 로딩을 찾아냈습니다.
- 보안 모듈 설치와 SharedPreferences 생성을 백그라운드·Lazy로 분리
- 성과: 앱 시작 때 화면을 붙잡고 있던 시간을 268ms에서 54ms로 줄였습니다(약 80% 단축). 시작 중 Keystore 호출도 48회에서 5회로 줄었습니다.
사용자에게 실제로 발생하던 오류를 찾아 원인을 막고, 같은 문제가 다시 생기지 않게 테스트로 고정했습니다.
- 운영 중 발생하던 앱 꺼짐 문제와 구형 기기 대응
- 성과: 암호 키를 못 읽거나 송금 화면에서 앱이 꺼지는 등 실제 사용자에게 발생하던 오류 7건의 원인을 없앴고, 안드로이드 23~25 버전에서 거래내역에 들어가면 앱이 꺼지던 문제도 해결했습니다.
- 일부러 고장 내서 확인하는 테스트 방식
- 성과: 고치기 전 코드에서 테스트가 실패하는지 먼저 확인한 뒤 통과시켜, 그 테스트가 정말 그 버그를 잡는지 검증했습니다. 다시 생기기 쉬운 부분에는 따로 잠금장치를 걸어뒀습니다.
언어별 문구를 번역 정의서와 하나하나 대조해 맞추고, 언어 때문에 화면이 깨지는 경우를 구조적으로 막았습니다.
- 새로 추가된 5개 언어(몽골어·우즈베크어·벵골어·네팔어·싱할라어) 대응
- 성과: 문구에 잘못 섞여 들어간 형식 기호 때문에 해당 언어 사용자만 앱이 꺼지던 문제를 없앴고, 쓰이지 않거나 번역과 다른 문구 수백 건을 정리했습니다.
- 금액·날짜 표기를 한 가지로 통일
- 성과: 베트남어·인도네시아어 등에서 천 단위가 마침표로 보이던 금액 표기를 쉼표로 맞추고, 잘못된 표기가 다시 들어오면 빌드가 실패하도록 검사를 넣었습니다.
빌드와 배포에서 사람이 손으로 하던 일을 자동으로 돌렸습니다.
- 유료 도구 Allatori를 R8 난독화·리소스 축소로 대체
- 성과: 유료 난독화 도구를 쓰지 않게 되었고 앱 용량도 104.1MB에서 100.4MB로 줄었습니다. 오류 분석에 필요한 정보는 오히려 더 정확해졌습니다.
- 릴리즈 노트 자동 발행과 운영 배포 자동화
- 성과: 배포할 때마다 사람이 하던 Confluence·Teams 공유 작업을 없앴습니다. 배포 기록을 기준으로 변경 범위를 계산하도록 바꿔, 빌드가 한 번 실패하면 그 사이 작업 내역이 통째로 사라지던 문제도 함께 해결했습니다.
SBI Cosmoney 아키텍처 다이어그램
- ViewModel은 Intent를 받아 부수효과만 실행하고, 상태 전이는 순수 Reducer가 전담합니다.
- Reducer는 이전 UiState와 Intent만 받아 새 UiState를 돌려주므로 안드로이드 프레임워크 없이 검증할 수 있고, 8개월간 확보한 테스트 코드 대부분이 여기에서 나왔습니다.



공개용으로 내부 식별자를 일반화한 다이어그램