빠른 흐름
[System.Diagnostics.Conditional("ENABLE_LOG")]
public static void Log(object message)
{
Debug.Log(message);
}기본 흐름
Debug.Log의 런타임 비용
Unity 공식 가이드는 특히 Update, LateUpdate, FixedUpdate 안에 Debug.Log를 두면 매 프레임 호출이 누적되어 성능을 크게 떨어뜨릴 수 있다고 설명합니다. 에디터에서는 Console 창 출력이 느리지 않아 체감이 어렵지만, 빌드에서는 문자열 생성과 스택 트레이스 수집이 실제 프레임 시간에 반영됩니다. 릴리스 빌드에서 로그를 조건부로 제거하거나 끄는 이유가 여기에 있습니다.
조건부 래퍼로 빌드별 제어
System.Diagnostics.Conditional 속성을 사용하면, 지정한 심볼이 정의되지 않은 빌드에서는 해당 메서드의 호출 자체가 컴파일러 수준에서 제거됩니다. 아래처럼 래퍼 클래스를 만들어 두면 로그 정책을 한 곳에서 관리하기 쉽습니다.
public static class GameLog
{
[System.Diagnostics.Conditional("ENABLE_LOG")]
public static void Info(object message)
{
Debug.Log(message);
}
}ENABLE_LOG 심볼은 Player Settings의 Scripting Define Symbols에 개발 빌드용으로 추가하고, 릴리스 빌드에서는 제거하면 됩니다. 직접 Debug.Log를 쓰는 대신 GameLog.Info처럼 래퍼를 쓰면, 빌드 타입에 따라 로그 전체를 일괄 제어할 수 있습니다.
Stack Trace와 운영 로그 분리
Stack Trace 옵션도 필요 이상으로 켜 두면 성능과 로그량에 영향을 줍니다. Project Settings > Player에서 로그 타입별로 Stack Trace 수준을 조정할 수 있습니다. 한편, 운영 빌드에서도 오류나 중요 이벤트를 추적해야 하는 경우가 있으므로, 디버깅용 상세 로그와 운영 진단용 최소 로그는 목적을 나눠 두는 것이 좋습니다. 모든 로그를 일괄 삭제하면 나중에 문제가 생겼을 때 진단 수단이 없어질 수 있습니다.
체크포인트
| 상황 | 적합한 선택 |
|---|---|
| 개발 중 상세 로그, 릴리스에서 제거 | [Conditional("ENABLE_LOG")] 래퍼 |
Update 안 로그가 프레임 드랍 원인 | 조건부로 제거 또는 빈도 제한 |
| Stack Trace 줄이기 | Project Settings > Player > Stack Trace 설정 |
| 운영 진단용 최소 로그 유지 | 오류 로그는 별도 래퍼로 분리 보존 |
| 로그 종류 | 더 잘 맞는 처리 | 이유 |
|---|---|---|
| 개발용 흐름 추적 로그 | 조건부 래퍼로 제거 가능 | 빌드에서 비용 없이 꺼낼 수 있음 |
| 오류·예외 로그 | 릴리스에도 유지 | 운영 진단 수단이 필요함 |
| 고빈도 상태 로그 | 샘플링 또는 빈도 제한 | 로그 자체가 병목이 될 수 있음 |
| 사용자 이벤트 감사 로그 | 별도 운영 로깅 체계 검토 | Debug.Log와 목적이 다름 |
주의할 점
모든 로그를 제거하면 운영 중 문제 진단 수단이 없어집니다. 디버그용과 운영 진단용 로그를 목적에 따라 분리하세요.
// ❌ 모든 Debug.Log를 삭제 — 운영 중 오류 추적 불가
// Debug.Log("플레이어 사망"); 전부 제거
// ✅ 빌드 타입별 조건부 제어
public static class GameLog
{
[System.Diagnostics.Conditional("ENABLE_LOG")]
public static void Debug(object msg) => UnityEngine.Debug.Log(msg);
// 오류 로그는 릴리스에서도 유지
public static void Error(object msg) => UnityEngine.Debug.LogError(msg);
}
// Player Settings > Scripting Define Symbols:
// 개발 빌드: ENABLE_LOG 추가
// 릴리스 빌드: ENABLE_LOG 제거 → Debug 메서드 호출 자체가 컴파일에서 제거조건부 래퍼를 만들었어도, 메시지 문자열을 미리 만들어 넘기는 위치가 잘못되면 호출부에서 할당이 먼저 발생할 수 있습니다. 고빈도 경로에서는 로그 호출 자체를 분기 밖으로 빼는 편이 더 안전합니다.
// ❌ 매 프레임 문자열 보간 먼저 수행
GameLog.Debug($"Player Pos: {transform.position}");
// ENABLE_LOG가 꺼져 있어도 호출부 비용을 완전히 무시하기 어렵다
// ✅ 고빈도 경로는 빈도 제한 또는 조건 분기
if (frameCount % 30 == 0)
{
GameLog.Debug($"Player Pos: {transform.position}");
}참고 링크
2 sources