올리브영 테크블로그 포스팅 한 기기에 개발·운영 앱을 동시에 설치하는 방법: 올리브영 DEV/PROD 환경 분리
Tech

한 기기에 개발·운영 앱을 동시에 설치하는 방법: 올리브영 DEV/PROD 환경 분리

Android Product Flavor와 iOS xcconfig로 안전한 배포 만들기

2025.12.24

안녕하세요. 올리브영의 앱 개발을 맡고 있는 Hz, 송편입니다.

이번 글에서는 개발용 앱(이하 ‘개발 앱’) 과 실제 운영용 앱(이하 ‘운영 앱’)을 완전히 분리해 관리하게 된 과정을 공유합니다. 특히 Android(Product Flavor)와 iOS(xcconfig)에서 환경을 코드 밖 설정으로 고정하고, CI/CD까지 연결해 운영 배포 리스크를 줄인 방법을 정리했습니다.


왜 환경을 분리해야 했는가

① 커뮤니케이션 비용을 줄이고 싶어요

프로덕트팀 🍊 오후 2:34
안녕하세요! 이번 업데이트 화면 확인하려고 하는데, 지금 제 폰에 깔려있는 앱이 개발용인가요 아니면 운영용인가요?
디자인팀 🐰 오후 3:15
새로운 이벤트 페이지 확인하고 싶은데 개발 서버로 바꾸려면 어떻게 해야 하나요? 앱을 삭제하고 다시 깔아야 하나요?
QA팀 🦫 오후 4:22
지금 운영앱으로 보고 있는데 개발중인 기능이 안보이네요. 혹시 제가 잘못 보고 있는 건가요?
아, 개발앱을 봐야 하는군요. 운영앱 지우고 개발앱 다시 설치할게요...
환경 분리 전, 반복되던 문의들

이런 상황은 왜 발생했을까요?

올리브영 앱은 개발용 앱과 운영용 앱이 같은 앱 식별자(설치 단위) 를 사용하고 있었습니다. (iOS는 Bundle Identifier, Android는 applicationId가 설치 단위를 구분합니다.)

모바일 OS의 샌드박스 정책상 식별자가 같으면 동일한 앱으로 구분하기 때문에, 한 기기에 두 가지 버전을 동시에 설치하는 것은 불가능했습니다. 이로 인해 환경을 전환하려면 반드시 기존 앱을 삭제하거나 덮어씌워야 했습니다. 이 과정에서 로그인 세션, 로컬 DB, 캐시 데이터가 초기화되다 보니, QA나 개발 과정에서 연속적인 테스트를 수행하는 데 큰 걸림돌이 되었습니다. 또한, 시각적으로 두 앱이 구분되지 않아 비개발 직군의 동료들은 지금 보고 있는 앱이 어떤 환경인지 몰라 혼란을 겪는 일도 빈번했습니다.

② 휴먼 에러를 방지하고 싶어요

개발 앱과 운영 앱이 같은 앱 식별자를 공유하면, 실수로 개발 앱을 스토어에 배포하는 사고가 발생할 수 있습니다. 특히 QA·개발·운영이 동시에 진행되는 바쁜 시기에는 사람이 수동으로 설정을 바꾸는 과정에서 실수로 테스트용 푸시 알림이 실제 고객에게 발송되거나, 운영 DB에 테스트용 데이터가 쌓이는 등의 문제가 발생할 수 있습니다.

이러한 이유로 많은 테크 기업들은 배포 파이프라인에서 환경 변수가 맞지 않으면 빌드 단계에서 실패하도록 가드레일을 둡니다. 또한 실리콘밸리의 여러 기업들은 dogfooding 문화의 일환으로, 내부 테스트 전용 빌드나 사내 배포용 앱을 운영하며 운영용 앱과 명확히 구분된 환경에서 검증을 진행합니다.

저희 역시 사람이 조심하는 것에는 한계가 있다고 판단했고, 이를 앱 레벨(xcconfig / Product Flavor)에서 강제함으로써 배포 담당자가 실수하고 싶어도 구조적으로 환경이 섞일 수 없는 상태를 목표로 환경 분리를 설계했습니다.




환경 분리 전략

그래서 올리브영 앱을 두 가지로 분리했습니다.

구분 운영 앱 개발 앱
대상 실제 고객 내부 구성원(QA·개발·기획·디자인·마케팅 등)
목적 검증이 완료된 기능을 스토어를 통해 안정적으로 제공 QA 검증, 개발 및 테스트 수행
서버 환경 운영 서버 고정 운영 / STG / QA 등 서버 전환 가능
특징 운영 키·설정 고정, 스토어 배포 기준에 따른 품질·안정성 검증, 불필요한 로그 제거 디버깅에 도움이 되는 개발자 모드 제공

이러한 분리를 위해 iOS와 Android는 각각의 플랫폼 특성이 있지만, 완전히 별도의 앱으로 구분하는 것을 원칙으로 개발환경 분리 작업을 진행했습니다.



Android 프로젝트에서 환경 분리하기

1. Build Variant로 환경 분리

Android는 Gradle의 빌드 구성 시스템인 Build Variant를 통해 다른 버전의 앱을 만들어낼 수 있습니다. 하나의 코드베이스에서 BuildType과 ProductFlavor를 조합하여 다양한 앱 버전을 만들 수 있게 해줍니다. 올리브영 프로젝트에서의 BuildType은 debug/release로, ProductFlavor는 production/develop으로 구성되어 있습니다. 앱 버전은 아래처럼 총 4가지입니다. 이 중에서 협업 동료들에게 배포되는 버전은 developRelease(개발 앱)와 productionRelease(운영 앱)입니다.

  • developDebug - 개발 환경 디버그
    • Android 개발자들이 로컬 환경에서 개발할 때 사용하는 앱
  • developRelease - 개발 환경 릴리즈
    • QA 기간 동안 협업 동료들이 설치하여 확인할 때 사용하는 앱
  • productionDebug - 운영 환경 디버그
    • 운영 환경과 동일한 설정을 로컬에서 빠르게 확인할 때 사용하는 디버그용 앱(개발자용)
  • productionRelease - 운영 환경 릴리즈
    • 협업 동료들이 설치하여 스토어 배포 전 확인할 때 사용하는 앱
    • 스토어 배포용(운영) 빌드. 사내 배포 채널을 통해 검증 후 스토어에 게시

개발 앱과 운영 앱이 별도로 설치되게 하기 위해서는 추가적으로 해줘야 하는 작업이 있습니다. 각 앱에게 별도의 패키지명을 지정하는 일입니다. 개발과 운영을 구분하기 위해 기존 운영 패키지명 뒤에 dev를 추가적으로 붙여주었습니다.

  • 운영(production)
    • applicationId : com.oliveyoung
  • 개발(develop)
    • applicationId: com.oliveyoung.dev

패키지명이 달라지면 OS가 두 앱을 서로 다른 앱으로 인식하기 때문에, 한 기기에 개발 앱과 운영 앱을 동시에 설치할 수 있습니다.

// build.gradle
flavorDimensions += "version"

  productFlavors {
      create("develop") {
          dimension = "version"
          applicationIdSuffix = ".dev"
      }

      create("production") {
          dimension = "version"
      }
  }

2. 운영과 개발 환경으로 소스셋 나누기

ProductFlavor를 통해 flavor를 나누어놓으면 지정한 이름 별로 소스셋을 관리할 수 있습니다. 아직 개발 중인 코드나 디버깅용으로 확인하기 위한 기능들은 개발(develop) 디렉토리에, 상용에 출시할 기능들은 운영(production) 디렉토리에 두어 환경별로 소스 분리를 했습니다. 예를 들어 앱 아이콘과 앱 이름을 각각 리소스에 분리하여 처리해주고 있습니다.

   app/src/
    ├── main/                # 공통 소스
    ├── develop/             # 개발 환경 전용
    │  ├── java/
    │  ├── res/
    │  │   ├── mipmap/      # 개발용 앱 아이콘
    │  │   │   └── ic_launcher.png
    │  │   └── values/
    │  │       └── strings.xml  # 앱 이름: "올디브영"
    │  └── AndroidManifest.xml
    └── production/           # 운영 환경 전용 (production)
       ├── java/
       ├── res/
       │   ├── mipmap/      # 운영용 앱 아이콘
       │   │   └── ic_launcher.xml
       │   └── values/
       │       └── strings.xml  # 앱 이름: "올리브영"
       └── AndroidManifest.xml

각 모듈들을 운영/개발 flavor로 나눈 결과의 프로젝트 구조는 아래와 같습니다.

올리브영 Android 앱 구조에서의 환경별(PROD/DEV) 소스셋 분리 구조

올리브영 Android 앱 구조


iOS 프로젝트에서 환경 분리하기

iOS에서는 빌드 설정과 설정 파일(xcconfig, Info.plist)을 중심으로 환경을 분리했습니다.

용어를 간단히 정리하면 다음과 같습니다.

  • Scheme: “어떤 앱을 어떻게 빌드/실행할지”를 고르는 레시피
  • Build Configuration: DEV/PROD처럼 빌드 설정 묶음(값의 집합)
  • xcconfig: 위 설정값을 코드 밖 파일로 분리해 관리하는 설정 파일

1. Build Configuration과 Scheme로 환경 정의하기

기존에는 Debug / Release 두 가지 설정만 두고, 코드 안에서 #if DEBUG 전처리로 개발/운영 동작을 나누는 방식이 섞여 있었습니다. 이 구조에서는 어느 빌드가 어떤 키와 엔드포인트를 쓰는지 한눈에 파악하기 어려웠습니다. 환경을 명확히 나누기 위해 아래와 같이 빌드 설정과 Scheme을 재구성했습니다.

Build Configuration 예시

Debug-DEV
Release-PROD

각 Configuration에 대응하는 Scheme 구성

OliveYoung-DEV
OliveYoung-PROD

이렇게 해 두면 Xcode에서 Scheme만 바꿔도 "지금 이 빌드는 어느 환경용인지"를 바로 알 수 있고, CI에서도 동일한 Scheme 이름을 사용해 환경별 빌드를 자동화할 수 있습니다.

2. xcconfig로 환경별 설정 분리하기

다음 단계는 환경별 설정을 코드에서 빼서 xcconfig로 옮기는 작업이었습니다.

환경별 설정

  • Dev.xcconfig, Prod.xcconfig를 분리
  • 각 파일에서만 달라지는 값들만 관리
  • (예: 서버 베이스 URL, 서드파티 ‘앱 등록 ID’, API 키 등)

예를 들어 아래와 같은 값들을 xcconfig에서 관리하도록 변경했습니다.

  • API 서버 주소: API_BASE_URL
  • 서드파티 API Key

3. Bundle Identifier, App Group, 딥링크 설정까지 분리

환경을 완전히 분리하려면 UI만 다르게 보는 것만으로는 부족하고, 시스템 레벨 식별자들도 분리해야 합니다. iOS에서는 다음 항목들을 환경별로 각각 갖도록 정리했습니다.

  • Bundle Identifier
    • 앱을 구분하기 위해 사용하는 고유 식별자
  • App Group / Keychain Group
    • Extension과 데이터를 공유할 때 환경이 섞이지 않도록 분리
  • Associated Domains (Universal Links)
    • 운영/개발용 도메인을 나누고, 각 환경 앱에서 바라볼 수 있도록 설정

이렇게 정리하여, 식별자들도 서로 다른 환경별로 겹치지 않도록 설정했습니다. 각 패키지별로 설정파일을 바라보게 되며 분리되는 프로젝트 구조는 다음과 같습니다.

올리브영 iOS 앱 구조(환경별 xcconfig/식별자 분리)

iOS에서의 Build Configuration 및 식별자(Identifier) 격리 구조




서드파티 SDK와 분석 도구 설정 통합

AppsFlyer, Firebase, Braze 같은 서드파티 SDK는 환경별로 다른 앱 ID나 프로젝트를 바라봐야 합니다.
환경 분리 이후에는 아래의 작업을 했습니다.

  • 각 SDK에서 참조하는 앱 등록 ID / API Key를 전부 환경 설정 파일(xcconfig 등)로 이관
  • 운영/개발용 앱 ID를 명확히 분리

작업 후에는 특정 빌드가 어떤 환경의 데이터 소스로 연결되는지가 설정 파일만 봐도 명확해졌고, 마케팅/데이터 팀과의 커뮤니케이션도 수월해졌습니다.


CI/CD 구축

마지막으로, GitHub Actions 기반 CI/CD에서 환경별로 다른 빌드를 생성하고 다른 채널로 배포하도록 워크플로우를 정리했습니다.

DEV 빌드

  • 개발용 Scheme을 사용해 빌드
  • Firebase App Distribution 등 내부 테스트 채널로 배포

PROD 빌드

  • 운영 Scheme으로 빌드
  • TestFlight 및 App Store용 아카이브 생성

추가로, 환경 혼선을 줄이기 위해 CI에서 다음 가드레일을 적용했습니다.

  • DEV 워크플로우는 DEV Scheme만 허용
  • PROD 워크플로우는 PROD Scheme만 허용

워크플로우 분리를 통해 환경 설정이 잘못된 상태로 운영 빌드가 스토어에 배포되는 리스크를 줄였습니다.
하지만 자동화만으로는 충분하지 않았습니다. 정말로 개발 환경과 운영 환경이 섞이지 않는지를 반복적으로 확인할 수 있는 기준이 필요했습니다.

환경이 섞이지 않도록 확인하는 기준

그래서 우리는 다음 기준으로 확인했습니다. 환경 분리는 “분리했다”에서 끝나지 않고, 정말로 섞이지 않는지를 반복 검증할 수 있어야 합니다.

  • 설치 확인: 한 기기에 DEV/PROD 앱이 동시에 설치되는지(아이콘/앱명으로 즉시 구분)
  • 엔드포인트 확인: 앱 실행 후 네트워크 로그에서 DEV 빌드가 DEV 서버(API_BASE_URL)를 바라보는지
  • 서드파티 프로젝트 확인: AppsFlyer/Firebase/Braze에서 DEV 이벤트가 DEV 프로젝트로만 수집되는지
  • 딥링크 확인: DEV/PROD 도메인이 각 앱으로 올바르게 라우팅되는지(Universal Links/App Links)

위 항목 중 하나라도 어긋나면, 설정 파일(xcconfig)과 식별자(Bundle Identifier/App Group/Associated Domains)를 우선 점검하도록 팀 내의 컨벤션을 정리했습니다.

마무리: 개발환경분리를 통해 얻은 구조적 안정성

개발용 앱(올디브영)과 운영용 앱(올리브영) 아이콘 비교

시각적 인지 편의성을 극대화한 개발용(올디브영) 및 운영용(올리브영) 앱 아이콘/명칭 분리

개발 환경과 운영 환경을 완전히 분리한 후, 다음과 같은 긍정적인 변화를 경험했습니다.

  • 협업 부서 간 커뮤니케이션 비용 감소

    • 개발 앱과 운영 앱이 동시에 설치 가능해지면서, "지금 보고 있는 앱이 어떤 환경인가요?"라는 질문이 사라졌습니다.
    • 앱 아이콘과 이름만으로도 환경을 구분할 수 있게 되어, 비개발부서와의 소통이 훨씬 명확해졌습니다.
  • 배포 과정에서의 안정성 향상

    • CI/CD 파이프라인에서도 환경별로 명확히 분리된 워크플로우가 각각의 빌드를 처리하기 때문에, 배포 과정에서의 안정성이 크게 향상되었습니다.
  • 개발 생산성 향상

    • 개발자들은 더 이상 환경 전환을 위해 설정을 바꾸거나 앱을 재설치할 필요가 없어졌습니다.
    • 두 앱을 동시에 띄워놓고 비교 테스트를 진행할 수 있게 되어, 디버깅과 검증 작업이 훨씬 수월해졌습니다.
  • 안정적인 앱 운영

    • 서드파티 SDK와 분석 도구들이 환경별로 명확히 분리되어, 개발 중인 기능이 운영 데이터에 영향을 주는 일이 없어졌습니다.
동료 A 👱‍♀️ 오후 12:25
올디브영 있어서 너무 좋아요🥰 스토어버전 앱과 개발중인 앱 따로 볼 수 있어서 너무 편합니다!!
동료 B 👨‍🍳 오후 2:28
올디브영 없을때 어떻게 개발 했나 싶네요. 상용앱 깔았다가 개발 앱 깔았다가… 이제 개발 앱을 따로 깔 수 있어서 헷갈리는 일이 없어요! 너무 좋습니다.
동료 C 👩‍🦱 오후 3:35
예전처럼 서버 설정 바꿀 필요 없이 앱만 전환하면 되니까 확인이 너무 수월합니다. 가이드도 꼼꼼해서 좋네요. 잘 쓰겠습니다!
동료 D 🧑‍🎨 오후 5:30
올디브영이 생겨서 개발, 상용 돌아가면서 설치하지 않아도 되서 너무 좋아요
올디브영(개발앱)에 대한 동료들의 긍정적인 피드백

환경 분리는 단순히 기술적인 개선이 아니라, 개발조직 전체의 협업 방식과 개발 문화를 개선하는 계기가 되었습니다.

기술적인 개선을 통해, 전체적인 커뮤니케이션 비용을 줄이고, 배포 안정성을 높일 수 있었습니다.

올리브영의 개발자들은 앞으로도 더 나은 개발 경험과 안정적인 서비스 제공을 위해 지속적으로 개선해 나갈 것입니다.


올리브영 네이티브 앱 개발 더 알아보기

DEV/PROD 환경 분리부터 앱 구조 개선, 생산성 도구까지— 아래 글들을 함께 보시면 올리브영 앱 개발자들이 실제로 어떤 문제를 풀고 있는지를 더 입체적으로 살펴볼 수 있습니다. ☺️

앱 구조·운영 안정성·성능 개선기

개발 생산성·문서화

개발자 행사·커뮤니티

iOSAndroidApp
올리브영 테크 블로그 작성 한 기기에 개발·운영 앱을 동시에 설치하는 방법: 올리브영 DEV/PROD 환경 분리
🐠
Hz |
Android App Engineer
물을 사랑하는 안드로이드 개발자