빌드 프로파일
고친 사람 github-actions[bot]
빌드 프로파일은 이름 하나만 고르면 빌드 설정 여러 개를 한꺼번에 바꿔 줍니다. 게임 개발에서는 같은 게임을 컴퓨터용과 휴대폰용으로, 시험용과 출시용으로 갈라 만들 때 씁니다. 손으로 설정을 하나씩 바꾸다 빠뜨리는 일이 사라집니다. 자바 빌드 도구 같은 다른 분야도 같은 이름을 씁니다.
쉽고 빠른 이해
빌드 프로파일은 「이 게임을 이렇게 만들어라」를 이름 하나로 불러냅니다. 「휴대폰 출시용」을 고르면 휴대폰에 맞는 설정과 출시에 맞는 설정이 한 번에 걸립니다.
이게 없으면 빌드할 때마다 설정 여러 개를 손으로 바꿔야 합니다. 하나만 빠뜨려도 시험용 메뉴가 든 게임이 출시되거나, 휴대폰이 못 읽는 그림이 담깁니다.
- 기기와 용도마다 프로파일을 하나씩 만들어 둡니다
- 빌드할 때 프로파일 이름 하나를 고릅니다
- 빌드 도구가 그 안의 설정을 적용해 결과물을 만듭니다
대가도 있습니다. 프로파일이 늘어날수록 어느 하나에서만 깨지는 문제가 생깁니다. 그것을 다 시험하는 데 시간이 듭니다.
가를 기기나 용도가 없으면 프로파일도 필요 없습니다. 한 기기에만 내고 시험용과 출시용을 나눌 일도 없는 작은 프로그램이 그렇습니다.
상세
카메라에는 촬영 모드가 있습니다. 「야경」을 고르면 셔터 속도와 감도와 플래시가 한꺼번에 밤에 맞게 바뀝니다. 찍는 사람은 다이얼 여러 개를 돌리는 대신 모드 이름 하나만 고릅니다.
빌드 프로파일은 빌드에 이 일을 해 줍니다. 빌드는 소스 코드와 데이터를 실행할 수 있는 결과물로 바꾸는 일입니다. 빌드 프로파일은 이 빌드에 거는 설정 여러 개를 이름 하나로 묶어 둡니다. 빌드할 때 이름을 고르면 그 안의 설정이 한꺼번에 적용됩니다.
게임 하나에 프로파일 둘을 둔 경우를 떠올려 봅니다. 「개발용」은 오류를 찾기 쉽게 디버그 정보를 넣습니다. 디버그 정보는 기계어가 소스의 몇째 줄에서 왔는지 적어 둔 정보입니다. 시험용 메뉴도 켭니다.
「출시용」은 그 둘을 빼고 실행 속도를 높이는 최적화를 켭니다. 소스는 하나입니다. 어느 이름을 골랐느냐에 따라 결과물이 둘로 갈립니다.
이 절은 게임 개발의 빌드 프로파일을 중심으로 봅니다. 프로파일이 없을 때 무엇이 곤란한지에서 시작합니다. 이어서 프로파일 하나에 무엇이 묶이는지, 어떻게 골라 쓰는지, 프로파일이 늘면 무엇이 어려워지는지를 따라갑니다. 끝에서는 같은 이름을 쓰는 다른 분야와 견줍니다.
프로파일 없이 빌드할 때의 문제
게임은 흔히 여러 기기에 함께 나옵니다. PC(Personal Computer, 개인용 컴퓨터)와 게임 콘솔과 휴대폰에 같은 게임을 내는 식입니다. 이렇게 여러 기기에 내는 것을 멀티 플랫폼 출시라고 부릅니다. 기기마다 실행 파일의 꼴도, 그림 데이터를 담는 방식도 다릅니다.
프로파일이 없으면 기기를 바꿀 때마다 빌드 설정을 손으로 고칩니다. 고칠 항목이 열 개면 하나쯤은 빠뜨립니다. 휴대폰용 빌드에 컴퓨터용 그림 설정이 남으면 휴대폰이 그 그림을 제대로 못 읽습니다.
용도가 갈리는 것도 같은 문제를 부릅니다. 개발 중에는 시험용 빌드를 하루에도 여러 번 만듭니다. 출시할 때만 출시용 설정으로 바꿨다가 되돌립니다. 바꾸기를 깜빡하면 시험용 메뉴가 든 채로 출시됩니다. 되돌리기를 깜빡하면 다음 시험용 빌드에서 오류 위치를 못 찾습니다.
설정이 한 사람의 컴퓨터에만 있는 것도 문제입니다. 다른 사람이나 빌드 서버는 같은 결과물을 만들 수 없습니다. 빌드 서버는 코드가 바뀔 때마다 빌드와 시험을 자동으로 돌리는 컴퓨터입니다.
프로파일은 대개 파일로 저장해 소스와 함께 버전 관리에 올립니다. 그러면 누구든 같은 이름을 골라 같은 빌드를 만듭니다.
프로파일 하나에 묶이는 설정
프로파일에 무엇을 넣을지는 「기기나 용도에 따라 달라지는 설정」이 기준입니다. 어느 빌드에서나 같은 설정은 프로파일에 넣을 까닭이 없습니다. 게임 개발에서 흔히 묶는 설정은 아래와 같습니다.
| 설정 | 예 | 프로파일마다 다른 까닭 |
|---|---|---|
| 대상 플랫폼 | PC · 게임 콘솔 · 휴대폰 | 기기마다 실행 파일의 꼴이 다르다 |
| 최적화 수준 | 개발용은 낮게 · 출시용은 높게 | 높이면 빠르지만 빌드가 오래 걸리고 오류를 따라가기 어렵다 |
| 디버그 정보 | 넣는다 · 뺀다 | 넣으면 오류 위치를 찾기 쉽지만 파일이 커진다 |
| 담을 장면 | 시험 장면까지 · 출시 장면만 | 시험용 장면이 출시본에 들어가면 안 된다 |
| 컴파일 기호 | 시험용 메뉴를 켜는 기호 | 코드 일부를 빌드에 넣거나 뺀다 |
| 그림 압축 방식 | PC용 포맷 · 휴대폰용 포맷 | 기기의 그래픽 칩이 읽는 포맷이 다르다 |
표의 위쪽 셋은 어느 프로그램 빌드에나 있는 설정입니다. 최적화 수준은 컴파일러가 코드를 얼마나 손봐 빠르게 만들지를 정합니다. 디버그 정보는 앞에서 본 대로 기계어와 소스 줄을 잇는 정보입니다. 이 정보가 있어야 프로그램이 멈췄을 때 소스의 어느 줄인지 알 수 있습니다.
「담을 장면」은 게임에서 두드러지는 설정입니다. 게임은 메뉴 화면, 지역 하나하나 같은 장면 단위로 데이터를 나눠 만듭니다. 개발 중에는 기능 하나만 시험하는 장면을 따로 만들어 둡니다. 출시용 프로파일은 이런 장면을 빼고 플레이어가 볼 장면만 담습니다.
컴파일 기호로 코드를 넣고 빼기
컴파일 기호는 코드의 한 부분을 빌드에 넣을지 뺄지 정하는 이름표입니다. 소스에 「이 기호가 켜져 있을 때만 이 코드를 넣어라」라고 적어 둡니다. 이렇게 빌드할 때 코드를 고르는 일을 조건부 컴파일이라고 부릅니다.
아래 코드는 시험용 메뉴를 기호 하나로 감싼 모습입니다. 개발용 프로파일은 CHEATS 기호를 켠다고 해 봅니다. 출시용 프로파일은 이 기호를 끕니다.
#if CHEATS
show_cheat_menu(); // 개발용: 들어감
#endif // 출시용: 빠짐
출시용 빌드에서는 가운데 줄이 아예 컴파일되지 않습니다. 실행할 때 기호를 확인해 메뉴를 숨기는 것과 다릅니다. 코드가 결과물에 없으니 플레이어가 파일을 뜯어봐도 시험용 메뉴를 찾을 수 없습니다.
그림 압축 방식이 기기마다 다른 까닭
게임 속 그림은 그래픽 칩이 바로 읽는 전용 압축 포맷으로 줄여 담습니다. 그래픽 칩은 GPU(Graphics Processing Unit, 그래픽 처리 장치)라고도 합니다. 텍스처 압축은 이렇게 그림을 GPU 전용 포맷으로 줄이는 일입니다.
문제는 GPU 종류마다 읽을 수 있는 압축 포맷이 다르다는 것입니다. 컴퓨터용 GPU는 대개 BC(Block Compression, 블록 압축) 계열 포맷을 읽습니다. 휴대폰용 GPU는 대개 ASTC(Adaptive Scalable Texture Compression)나 ETC2(Ericsson Texture Compression 2) 포맷을 읽습니다.
그래서 그림 원본은 하나만 둡니다. 빌드할 때 기기에 맞는 포맷으로 바꿉니다. 어느 포맷으로 바꿀지가 프로파일에 들어갑니다. 휴대폰용 프로파일을 고르면 그림이 휴대폰 GPU의 포맷으로 바뀌어 담깁니다.
에셋 파이프라인은 게임에 들어갈 그림이나 소리 같은 데이터를 출시용 꼴로 바꾸는 과정 전체입니다. 그림 포맷을 바꾸는 일은 그 과정의 한 단계입니다.
프로파일을 골라 빌드하는 흐름
소스와 그림 원본은 하나입니다. 빌드할 때 프로파일 이름을 하나 고르면, 빌드 도구가 그 프로파일의 설정으로 컴파일과 그림 변환과 패키징을 차례로 돌립니다. 패키징은 컴파일한 코드와 바꾼 그림을 기기에 설치할 수 있는 파일로 묶는 일입니다. 아래 그림은 같은 소스가 프로파일에 따라 결과물 셋으로 갈리는 모습입니다.
flowchart TD
S["소스 코드 · 그림 원본"]
S --> A["PC 개발용 프로파일"]
S --> B["PC 출시용 프로파일"]
S --> C["휴대폰 출시용 프로파일"]
A --> RA["디버그 정보와 시험용 메뉴가 든 PC 빌드"]
B --> RB["최적화한 PC 빌드"]
C --> RC["휴대폰 포맷 그림을 담은 최적화 빌드"]
프로파일 이름은 사람이 고르기도 하고 앞에서 본 빌드 서버가 고르기도 합니다. 지속적 통합은 코드가 바뀔 때마다 빌드 서버가 빌드와 시험을 자동으로 돌리게 하는 운영 방식입니다.
빌드 서버는 흔히 모든 프로파일로 한 번씩 빌드합니다. 개발자가 자기 컴퓨터에서 PC 개발용만 빌드해 보고 코드를 올렸다고 해 봅니다. 그 코드가 휴대폰 출시용에서만 깨져도 빌드 서버가 바로 알려 줍니다.
공통 설정과 덮어쓰기
프로파일끼리는 겹치는 설정이 많습니다. PC 개발용과 PC 출시용은 대상 플랫폼이 같습니다. 다른 것은 최적화 수준과 디버그 정보, 시험용 메뉴 정도입니다. 모든 프로파일에 같은 설정을 하나씩 적으면 고칠 때 여러 군데를 고쳐야 합니다.
그래서 흔히 공통 설정을 한 곳에 둡니다. 프로파일은 다른 부분만 덮어씁니다. 「PC 출시용은 PC 공통에서 최적화만 높인다」처럼 적는 식입니다. 공통 설정을 고치면 그것을 물려받은 프로파일이 모두 따라 바뀝니다.
프로파일이 늘어날 때의 대가
프로파일 수는 곱으로 늡니다. 기기가 셋이고 용도가 셋이면 프로파일이 아홉 개가 됩니다. 아홉 개를 다 빌드하고 시험하는 시간이 그만큼 듭니다.
더 까다로운 것은 한 프로파일에서만 나는 버그입니다. 개발용에서 잘 돌던 게임이 출시용에서만 멈출 수 있습니다. 원인은 크게 둘입니다.
하나는 최적화입니다. 값을 넣지 않은 변수를 읽는 코드는 개발용에서 우연히 맞는 값을 읽어 잘 돌 수 있습니다. 최적화를 켜면 컴파일러가 코드를 다르게 손보면서 그 변수가 다른 값을 읽을 수 있습니다.
다른 하나는 조건부 컴파일입니다. 앞의 #if CHEATS 안 코드가 시험용 메뉴를 띄우면서 게임에 필요한 다른 값까지 초기화하던 경우가 그렇습니다. 출시용에서는 그 줄이 통째로 빠지므로 그 값도 초기화되지 않습니다.
그래서 출시 직전에만 출시용으로 빌드하면 늦습니다. 출시용 프로파일로도 평소에 자주 빌드하고 시험해야 이런 버그를 일찍 찾습니다. 프로파일은 설정을 손으로 바꾸는 실수를 없애 줍니다. 대신 시험할 빌드의 가짓수를 늘립니다.
가를 것이 없으면 프로파일도 필요 없습니다. 한 기기에만 내고 시험용과 출시용을 나눌 일도 없는 작은 프로그램이라면 프로파일을 따로 둘 까닭이 적습니다.
같은 이름을 쓰는 다른 분야
「빌드 프로파일」은 게임 밖에서도 씁니다. 같은 소스로 빌드할 때 설정을 이름 하나로 갈아 끼운다는 생각은 같습니다. 묶는 설정이 분야마다 다릅니다.
| 분야 | 프로파일이 바꾸는 것 | 고르는 때 |
|---|---|---|
| 게임 개발 | 대상 플랫폼 · 출시용 여부 · 담을 장면 · 그림 압축 방식 | 빌드할 때 |
| 자바 빌드 도구 | 넣을 의존성 · 돌릴 플러그인 · 설정 값 | 빌드할 때 |
| 백엔드 프레임워크의 실행 프로파일 | 접속할 데이터베이스 주소 같은 설정 값 | 실행할 때 |
자바 빌드 도구인 Maven은 프로젝트 설정 파일 pom.xml 안에 프로파일을 여럿 적어 둡니다. 빌드할 때는 mvn -P <이름> 처럼 명령에 이름을 붙여 고릅니다. 운영 환경용 프로파일에서만 특정 의존성을 넣거나 시험 단계를 건너뛰게 할 수 있습니다. 게임 개발의 빌드 프로파일과 하는 일이 같습니다.
셋째 줄은 이름이 비슷해 헷갈리기 쉽습니다. 백엔드 개발자에게 익숙한 Spring의 프로파일은 결과물을 바꾸지 않습니다. 같은 실행 파일을 띄울 때 spring.profiles.active 값으로 「dev」나 「prod」를 골라 설정 값만 바꿉니다. 빌드 프로파일은 빌드할 때 골라서 결과물 자체가 달라집니다.
관련 항목
빌드 프로파일이 설정을 거는 빌드 단계
빌드 · 컴파일 · 링크 · 에셋 파이프라인 · 쿠킹 · 텍스처 압축 · 청킹 · 패키징
빌드 프로파일 하나에 묶이는 설정
대상 플랫폼 · 최적화 · 디버그 정보 · 조건부 컴파일 · 컴파일 기호 · 전처리기 · GPU 텍스처 포맷 · 장면
빌드 프로파일이 갈라 만드는 결과물
디버그 빌드 · 릴리스 빌드 · 개발 빌드 · 멀티 플랫폼 · 크로스 컴파일 · 아티팩트
빌드 프로파일을 골라 돌리는 도구와 운영
빌드 도구 · Maven · Gradle · 빌드 서버 · 지속적 통합 · 빌드 파이프라인 · 버전 관리 · 재현 가능한 빌드
빌드 프로파일과 헷갈리는 이웃
빌드 구성 · Spring 프로파일 · 환경 변수 · 기능 플래그 · 프로파일러 · 프로파일링
빌드 프로파일이 속하는 상위 분류
다른 이름: build profile