Cheondi
개발 · Unity

빌드 전처리기가 기능을 숨기고 있었다

플랫폼별 전처리 분기 때문에 특정 빌드에서만 기능이 빠진 문제를 빌드 조합별로 추적한 기록입니다.

  • #unity
  • #build
  • #preprocessor

에디터와 Android 개발 빌드에서는 보이던 메뉴가 배포용 빌드에서 사라졌다. 서버 권한과 설정을 확인했지만 값은 같았다. 코드를 더 따라가니 컴파일 전처리 조건 안에서 해당 기능 등록 자체가 제외되고 있었다. 플랫폼 조건과 개발 빌드 조건이 겹쳐 의도보다 좁은 조합에서만 코드가 들어갔다.

실행 중 if와 달리 전처리 분기는 빌드 결과에서 코드가 아예 사라질 수 있었다.

조건식을 실제 빌드 조합으로 펼쳤다

긴 전처리 식을 눈으로만 읽지 않고 표로 만들었다.

#if UNITY_ANDROID && DEVELOPMENT_BUILD || UNITY_EDITOR
RegisterFeature();
#endif

연산 우선순위와 의도를 명확히 하도록 괄호를 사용하고, 정말 플랫폼 제약인지 개발 편의 조건인지 분리했다.

Editor / Dev / Release
Android Dev / Android Release
WebGL Dev / WebGL Release

각 조합에서 기능 포함 여부를 예상하고 빌드 로그와 비교했다.

플랫폼 차이는 어댑터 안으로 모았다

기능 전체를 전처리기로 감싸면 등록 누락을 발견하기 어려웠다. 공통 기능은 항상 등록하고 플랫폼에서 지원하지 않는 작은 연결 부분만 분기했다.

IShareBridge bridge = PlatformBridgeFactory.CreateShareBridge();
featureRegistry.Register(new ShareFeature(bridge));

지원하지 않는 구현은 명확한 NotSupported 결과를 반환해 UI가 상태를 설명할 수 있게 했다.

빌드 결과에 포함 여부를 남겼다

앱 시작 로그에 공개 가능한 빌드 채널, 플랫폼, 기능 플래그 목록을 남겼다. 사용자 정보나 비밀 설정은 포함하지 않았다. 특정 빌드에서 기능이 빠졌을 때 서버와 클라이언트 설정을 빠르게 구분할 수 있었다.

릴리스에 가까운 설정의 빌드를 자동 또는 정기적으로 만들어 개발 빌드만 성공하는 상황도 줄였다.

컴파일 조건도 테스트 대상이었다

전처리기는 편리했지만 보이지 않는 제품 변형을 만들었다. 코드 리뷰에서 한 경로를 읽는 것만으로 모든 빌드를 확신할 수 없었다.

이 경험 뒤 전처리 조건을 추가할 때 지원 조합과 제외 이유를 적고, 핵심 기능은 가능한 한 런타임 추상화로 옮긴다. 빌드 성공뿐 아니라 필요한 기능이 실제 산출물에 들어갔는지도 확인하게 됐다.