본문 바로가기
개발 노트/React Native

React Native 통합 앱 프로파일 회귀 테스트 설계 및 적용하기

by pposooj 2026. 5. 19.

React Native로 여러 개의 앱 프로파일을 하나의 코드베이스에서 관리하는 통합 앱 구조를 운영하다 보면, 꼭 예상치 못한 곳에서 버그가 터지곤 합니다.

공통 컴포넌트나 모듈 하나를 가볍게 수정했을 뿐인데, 엉뚱한 프로파일의 첫 화면이 깨지거나 뜬금없이 권한 요청 팝업이 튀어나오는 식입니다. 처음에는 "빌드만 통과하면 문제없겠지" 싶지만, 빌드는 문법 오류나 의존성 문제만 잡아줄 뿐 각 앱별 화면 정책까지 보장해주지 않습니다.

이럴 때 필요한 게 예전에 잘 되던 기능이 이번 수정 후에도 그대로 잘 도는지 확인하는 프로파일 회귀 테스트입니다. 매번 손으로 다 눌러볼 수는 없으니, 나중에 제가 다시 보면서 적용하려고 실무 기준을 정리해 둡니다.

회귀 테스트가 부족할 때 겪는 문제들

통합 앱 환경에서 프로파일별 검증을 소홀히 하면 운영 중에 꼭 이런 문제가 발생합니다.

  • 새로운 프로파일을 추가했는데, 기존에 잘 돌던 다른 앱의 첫 화면(라우팅)이 바뀜.
  • 지도가 필요 없는 특정 앱인데, 공통 모듈 수정 여파로 위치 권한 요청이나 지도 탭이 노출됨.
  • 빌드 스크립트(selectedProfiles) 상으로는 단일 빌드가 잘 붙은 것처럼 보이지만, 실제 연결된 UI 테스트 대상이 잘못 매칭됨.
  • 이미 안 쓰는 비활성 프로파일까지 테스트 대상에 섞여 들어와서 불필요한 실패 로그가 쌓임.
  • 특정 프로파일 딱 하나만 실패했는데, 로그가 사방으로 흩어져서 원인 파악이 늦어짐.
  • 테스트용 Fixture 데이터에 실제 운영 서버 URL이나 API 키, 관리자 경로가 노출되는 보안 위험 발생.

프로파일 회귀 테스트의 핵심 기준

모든 화면의 모든 동작을 다 자동화하는 것은 현실적으로 불가능합니다. 변경 영향도가 크고 치명적인 지점 위주로 검증 기준을 잡아야 합니다.

테스트 영역 확인할 내용 실패 시 영향
profile registry 필수 필드 누락 여부, 중복 profileId, 비활성 상태 분리 빌드 대상 해석 실패 (전체 빌드 마비)
selectedProfiles 선택된 프로파일만 정확히 빌드/테스트 대상으로 잡히는지 엉뚱한 앱 빌드 또는 배포 누락
initial route 앱 시작 시 첫 화면 정책이 올바르게 존재하는지 실행 직후 빈 화면 노출 또는 크래시
route guard 접근하면 안 되는 화면(타 앱 전용 메뉴)이 잘 막히는지 정책에 맞지 않는 잘못된 메뉴 노출
feature flag 지도, 검색, 결제 등 앱별 기능 노출 기준 검증 앱별 핵심 기능 작동 오류
permission flow 해당 프로파일에 꼭 필요한 권한만 요청하는지 불필요한 권한 요청으로 스토어 심사 리스크
connected UI 실제 기기/에뮬레이터 구동 시 기본 화면이 뜨는지 런타임 환경에서의 치명적 오류

💡 가성비 좋은 시작점

처음부터 다 하려면 지칩니다. profile registry 검증, selectedProfiles 대상 해석, 대표 프로파일 1~2개의 connected UI 테스트 이 세 가지부터 시작하는 걸 추천합니다. 가성비가 가장 좋고 실패 원인도 빨리 좁혀집니다.

효율적인 테스트 범위 쪼개기

프로파일 개수가 많아지면 CI/CD 돌릴 때 시간이 너무 오래 걸립니다. 상황에 맞게 범위를 나누어 효율적으로 돌려야 합니다.

  • 단일 프로파일 (--profile sampleTourBusan)
    • 추천 시점: 특정 앱의 전용 코드나 자산만 수정했을 때 로컬에서 빠르게 확인.
  • 같은 그룹 (--group tour-regional)
    • 추천 시점: 지역 관광 앱들이 공유하는 공통 데이터 로더나 템플릿을 수정했을 때.
  • 대표 프로파일
    • 추천 시점: 공통 네비게이션이나 코어 UI 라이브러리를 건드렸을 때, 각 도메인별 대표 앱 1~2개만 추려서 확인.
  • 전체 프로파일 (--all / 제외 목록 반영)
    • 추천 시점: 정기 배포 직전 최종 점검 단계. 단, 테스트가 불가능하거나 비활성화된 앱은 exclusion config로 명확히 제외 처리.

selectedProfiles 테스트 구현 예시

실제 프로젝트에서 사용하는 타겟 해석 로직을 단순화한 검증 스크립트입니다. 핵심은 파라미터를 받아 대상을 거르고, 해석된 타겟이 0개일 때 조용히 성공시키지 않고 에러를 터트리는 것입니다.

JavaScript
 
// profile-test-scope.mjs
const profiles = [
  {
    profileId: 'sampleTourBusan',
    applicationId: 'com.example.tour.busan',
    group: 'tour',
    enabled: true,
  },
  {
    profileId: 'sampleFileData',
    applicationId: 'com.example.filedata',
    group: 'filedata',
    enabled: true,
  },
  {
    profileId: 'sampleLegacy',
    applicationId: 'com.example.legacy',
    group: 'legacy',
    enabled: false, // 비활성 프로파일
  },
];

// 테스트에서 명시적으로 제외할 앱 ID 목록
const excludedApplicationIds = new Set(['com.example.legacy']);

function resolveTargets({profileId, group, all = false}) {
  const enabled = profiles.filter((profile) => profile.enabled);

  const selected = enabled.filter((profile) => {
    if (all) return true;
    if (profileId) return profile.profileId === profileId;
    if (group) return profile.group === group;
    return false;
  });

  // 제외 목록 필터링
  return selected.filter((profile) => !excludedApplicationIds.has(profile.applicationId));
}

function assertTargets(targets) {
  // [주의] 대상이 없는데 그냥 패스되면 CI에서 잡지 못하고 빈 테스트로 통과됨
  if (targets.length === 0) {
    throw new Error('No test targets resolved. Check profileId, group, or exclusion config.');
  }
}

// 환경변수로 프로파일 ID를 받아 실행한다고 가정
const targets = resolveTargets({profileId: process.env.PROFILE_ID});

assertTargets(targets);
console.table(targets);

실무에서 처음 스크립트를 짤 때 자주 하는 실수가 바로 이 부분입니다. 조건이 잘못되어서 아무것도 검증하지 않았는데, 에러가 안 나니 CI 결과는 초록색(성공)으로 뜹니다. 제대로 검증된 줄 알고 배포했다가 터지는 걸 막으려면 대상이 없을 땐 무조건 실패(Fail)로 처리해야 안전합니다.

Connected UI 테스트 시 실패 로그 분류하기

실제 기기나 에뮬레이터를 띄워 검증(Connected UI Test)하다 보면 실패 원인이 너무 다양합니다. 단순 UI 버그인지, 네트워크 타임아웃인지, 디바이스 연결이 끊긴 건지 명확히 분류해 두어야 헛걸음을 안 합니다.

실패 종류 발생 예시 대응 방법
build failure 컴파일 에러, Gradle 플레버(flavor) 설정 누락 registry 파일 구조 및 Gradle 환경 재확인
ui failure 진입 후 특정 버튼 미노출, 라우팅 깨짐 프로파일별 화면 조건 및 feature flag 로직 확인
permission failure 갑작스러운 시스템 권한 팝업으로 테스트 중단 권한 요청 시점 제어 및 테스트 환경 훅 확인
api/network failure API 응답 지연(Timeout), 주소 오류 Mock 데이터 활용 전환, 네트워크 분리 검증
device failure adb 연결 끊김, 에뮬레이터 먹통 테스트 러너 환경 및 디바이스 상태 점검

특히 외부 API를 바라보게 해두면 UI는 멀쩡한데 서버 상태 때문에 테스트가 실패하는 경우가 많습니다. 불필요하게 화면 코드를 수정하는 삽질을 줄이려면 로그 분류와 Mocking이 필수적입니다. 자동화가 부담스럽다면 실패 시점의 스크린샷 캡처와 프로파일 ID를 매칭해서 저장하는 것부터 시작해 보세요.

Fixture 데이터 관리 시 주의점 (민감 정보 제거)

테스트 코드는 생각보다 사내 문서나 오픈소스, 혹은 git 기록에 쉽게 노출됩니다. Fixture를 만들 때는 운영 환경의 진짜 정보를 철저히 걷어내야 합니다.

  • 넣어도 되는 안전한 값: profileId 예시, 테스트용 applicationId, 도메인 그룹명, 기능 플래그 온오프 값, 공개 가능한 샘플 앱 이름.
  • 절대 피해야 할 민감한 값: 실제 운영 서버의 관리자 URL, 광고 단위 ID(AdMob 등), Firebase 실서버 설정값, API 인증 키/토큰, 실제 키스토어(keystore) 비밀번호.

실무 추천 적용 순서

한 번에 완벽한 시스템을 구축하려 하지 말고 단계별로 살을 붙여 나가는 것이 좋습니다.

  1. 1단계: profile registry에 필수 필드가 다 들어가 있는지 체크하는 유닛 테스트 추가.
  2. 2단계: 위에서 구현한 selectedProfiles 대상 해석 로직 및 예외 처리 검증.
  3. 3단계: 앱별 권한이나 메뉴를 제어하는 route guard와 feature flag helper 단위 테스트 작성.
  4. 4단계: 메인 대표 프로파일 1~2개만 먼저 에뮬레이터 환경에서 기본 구동 화면(Connected UI) 테스트 연동.
  5. 5단계: 실패 로그를 프로파일별 JSON 리포트로 뽑아내기.
  6. 6단계: 정기 배포 전 단계에 그룹별/전체 프로파일 자동화 테스트 파이프라인 결합.

마치며

React Native 통합 앱 구조에서 프로파일 회귀 테스트는 쓰면 좋은 선택 사항이 아니라, 나중에 들어갈 유지보수 비용과 빡침을 줄여주는 핵심 안전장치입니다.

처음 세팅할 때 selectedProfiles 해석 로직이랑 가벼운 Registry 필드 검증만 꼼꼼히 묶어둬도 빌드가 엉뚱하게 꼬이는 배포 사고는 대부분 예방할 수 있습니다. 작은 검증부터 차근차근 얹어가며 안전한 코드베이스를 만들어 보시길 바랍니다.