Unity·Unreal 실전

Unity AssetPostprocessor로 임포트 설정 자동화하기 — 팀 전체의 텍스처 실수를 코드로 막는 법

kr-gamedev 2026. 5. 28. 09:01

프로젝트가 커지면 가장 조용히 쌓이는 부채가 바로 에셋 임포트 설정이다. 누군가 텍스처를 드래그해서 넣는다. 기본값 그대로 들어간다. 압축은 엉뚱하게 잡히고, mipmap 은 켜진 채로 UI 텍스처에 들어가고, sRGB 플래그는 노멀맵에 잘못 박힌다. 빌드 직전에야 "이거 왜 이렇게 무겁지"를 깨닫고 수백 장을 하나하나 클릭하며 고치는 경험, 한 번쯤 해봤을 것이다.

이 문제의 본질은 "사람이 매번 옳은 설정을 기억해야 한다"는 데 있다. 규칙이 머릿속에만 있으면 신규 입사자나 외주 작업자는 그 규칙을 모른다. 결국 컨벤션 문서를 아무리 잘 써놔도 임포트 시점에 강제되지 않으면 무너진다.

해법은 의외로 단순하다. 임포트라는 행위 자체에 코드를 끼워 넣으면 된다. Unity 의 AssetPostprocessor 는 에셋이 임포트되는 바로 그 순간에 콜백을 주는 클래스다. 사람이 기억할 필요 없이, 폴더에 파일이 들어오는 순간 규칙이 자동으로 적용되게 만들 수 있다.

AssetPostprocessor 가 동작하는 시점

AssetPostprocessor 는 Editor 전용 클래스로 Editor 폴더 안에 두기만 하면 별도 등록 없이 Unity 가 자동으로 인식한다. 핵심은 콜백이 두 단계로 나뉜다는 점이다.

OnPreprocessTexture 는 임포트가 실제로 일어나기 전에 호출된다. 여기서 assetImporter 를 만지면 그 설정으로 임포트가 진행된다. 즉 결과물을 바꾸려면 여기서 손대야 한다. 반대로 OnPostprocessTexture 는 임포트가 끝난 픽셀 데이터를 받는 단계라, 메타 설정 변경이 아니라 결과 검사·후처리에 쓴다.

이 구분을 헷갈리면 "코드를 분명히 넣었는데 설정이 안 바뀐다"는 함정에 빠진다. 압축이나 sRGB 같은 임포트 옵션은 반드시 Pre 단계에서 잡아야 한다.

경로 기반 규칙으로 텍스처 분류하기

가장 실용적인 패턴은 폴더 경로로 텍스처의 용도를 판별해 설정을 분기하는 것이다. UI 폴더에 들어온 텍스처는 mipmap 을 끄고, 노멀맵 폴더는 Normal map 타입으로 강제하는 식이다.

using UnityEditor;
using UnityEngine;

public sealed class TextureImportRules : AssetPostprocessor
{
    void OnPreprocessTexture()
    {
        var importer = (TextureImporter)assetImporter;
        string path = assetPath.ToLowerInvariant();

        if (path.Contains("/ui/"))
        {
            importer.textureType = TextureImporterType.Sprite;
            importer.mipmapEnabled = false;
            importer.alphaIsTransparency = true;
        }
        else if (path.Contains("_normal") || path.Contains("/normals/"))
        {
            importer.textureType = TextureImporterType.NormalMap;
            importer.sRGBTexture = false;
        }

        // 모든 텍스처 공통 규칙: 최초 임포트일 때만 적용
        if (importer.importSettingsMissing)
            importer.maxTextureSize = 2048;
    }
}

여기서 한 가지 결정적인 디테일이 importSettingsMissing 프로퍼티다. 이 값이 true 면 아직 한 번도 사람이 만진 적 없는 신규 임포트라는 뜻이다. 무조건 덮어쓰면 아티스트가 의도적으로 바꿔둔 설정까지 매번 리셋되어 원성을 산다. 신규 에셋에만 기본값을 강제하고, 한 번 손댄 에셋은 존중하는 것이 협업에서 훨씬 안전하다.

플랫폼별 압축 오버라이드 자동화

모바일과 PC 의 텍스처 압축 포맷은 다르다. 이걸 손으로 일일이 잡는 건 가장 흔한 누락 지점이다. SetPlatformTextureSettings 로 플랫폼별 오버라이드를 코드에서 박아버릴 수 있다.

void OnPreprocessTexture()
{
    var importer = (TextureImporter)assetImporter;

    var android = new TextureImporterPlatformSettings
    {
        name = "Android",
        overridden = true,
        maxTextureSize = 1024,
        format = TextureImporterFormat.ASTC_6x6,
        compressionQuality = 50,
    };
    importer.SetPlatformTextureSettings(android);
}

이렇게 해두면 안드로이드 빌드 타깃에서 ASTC 압축이 자동으로 걸린다. 아티스트가 압축 탭을 열어볼 필요조차 없다. 같은 방식으로 iOS, Standalone 을 추가하면 플랫폼 분기 전체를 코드 한 곳에서 관리하게 된다.

잘못된 에셋을 임포트 단계에서 거르기

자동화의 진짜 가치는 "막는 것"에 있다. 예를 들어 텍스처 해상도가 2의 거듭제곱(POT)이 아니면 모바일 압축 효율이 급격히 떨어진다. OnPostprocessTexture 에서 결과를 검사해 경고를 띄우면, 문제 에셋이 들어온 즉시 콘솔에 빨간 줄이 뜬다.

void OnPostprocessTexture(Texture2D texture)
{
    bool IsPot(int v) => (v & (v - 1)) == 0;

    if (!IsPot(texture.width) || !IsPot(texture.height))
    {
        Debug.LogWarning(
            $"[ImportRule] Non-POT 텍스처: {assetPath} " +
            $"({texture.width}x{texture.height}) — 압축 효율 저하 위험");
    }
}

Debug.LogWarning 의 두 번째 인자로 에셋 오브젝트를 넘기면 콘솔의 경고를 클릭했을 때 프로젝트 창에서 해당 에셋이 하이라이트된다. 수백 개 중 어느 파일이 문제인지 바로 찾을 수 있어 실무에서 체감 차이가 크다.

정리

AssetPostprocessor 는 "컨벤션을 문서가 아니라 코드로 강제한다"는 발상의 핵심 도구다. 임포트 직전(OnPreprocessTexture)에서 설정을 바꾸고, 임포트 직후(OnPostprocessTexture)에서 결과를 검증한다는 두 단계 구조만 기억하면 된다.

실무 적용 시 챙길 포인트는 세 가지다. 첫째, importSettingsMissing 으로 신규 에셋과 사람이 손댄 에셋을 구분해 아티스트의 의도를 존중할 것. 둘째, 압축처럼 결과물을 바꾸는 설정은 반드시 Pre 단계에서 잡을 것. 셋째, 경고 로그에 에셋 참조를 넘겨 클릭 한 번으로 문제 파일을 찾을 수 있게 할 것. 이 세 가지만 지켜도 팀 전체의 텍스처 실수가 코드 한 파일로 사라진다.