특수 폴더와 스크립트 컴파일 순서
관리되는 코드 스트리핑

어셈블리 정의

프로젝트의 스크립트를 어셈블리에 정리하기 위해 어셈블리 정의를 만듭니다. 폴더에 어셈블리 정의 에셋을 만들면 Unity는 폴더의 모든 스크립트를 이용하여 별도의 관리되는 어셈블리를 컴파일합니다. 이때 하위 폴더의 스크립트는 자체적인 어셈블리 정의가 없는 경우 함께 포함됩니다. 이러한 관리되는 어셈블리는 Unity 프로젝트 내의 개별 라이브러리로 볼 수 있습니다.

어셈블리 정의 에셋은 파일 확장자가 “.asmdef”인 텍스트 파일로, Assembly Definition 프로퍼티를 정의하는 JSON 스트링을 포함합니다. 에셋 파일을 선택하여 Unity 인스펙터(Inspector) 창에서 해당 프로퍼티를 설정할 수 있습니다. 외부 에디터를 사용하면 JSON을 직접 편집할 수도 있습니다. JSON 구문에 대한 자세한 내용은 어셈블리 정의 파일 포맷을 참조하십시오.

어셈블리 정의를 사용해야 하는 이유

코드를 잘 정의된 종속 관계가 있는 어셈블리로 분리하면 Unity는 스크립트 변경 시 종속된 어셈블리만 재빌드하여 컴파일 시간을 단축합니다. 어셈블리 정의는 플랫폼과 Unity 버전별 코드가 포함된 프로젝트의 종속성을 관리하는 데에도 유용합니다.

어셈블리 정의가 없으면 Unity는 프로젝트의 모든 C# 스크립트를 사전 정의된 관리되는 어셈블리 중 하나에 컴파일합니다. 스크립트를 변경하면 Unity는 프로젝트 전체의 모든 스크립트를 다시 컴파일해야 합니다. 즉, 프로젝트에 스크립트를 추가할수록 코드를 변경한 후 변경 내용이 실행될 때까지 소요되는 시간이 증가합니다.

참고: 필수 사항은 아니지만, Unity는 프로젝트에서 어셈블리 정의를 사용하는 경우 프로젝트의 모든 코드에 대해 사용할 것을 권장합니다. 그렇지 않으면 사전 정의된 어셈블리 하나의 스크립트를 변경할 때마다 Unity가 프로젝트의 모든 코드를 다시 컴파일해야 합니다. 이는 사전 정의된 어셈블리가 어셈블리 정의를 사용하여 생성한 어셈블리에 자동으로 종속되기 때문입니다.

다음 그림은 여러 개의 어셈블리로 분할된 프로젝트를 나타냅니다.

사전 정의된 어셈블리 vs 수동으로 정의된 어셈블리
사전 정의된 어셈블리 vs 수동으로 정의된 어셈블리

Unity는 기본적으로 거의 모든 프로젝트 스크립트를 Assembly-CSharp.dll 관리되는 어셈블리로 컴파일합니다. 위의 예시는 대신 5개의 어셈블리로 나뉜 프로젝트를 나타냅니다. Main.dll 어셈블리는 Stuff.dll과 ThirdParty.dll에 종속되며, Stuff.dll은 Library.dll에 종속됩니다. 결과적으로 Unity는 Main.dll의 코드 변화로 인해 다른 어셈블리를 재컴파일할 필요가 없습니다. 또한 Main.dll은 포함된 스크립트 수가 더 적으므로 Asmbly-CSharp.dll보다 빠르게 컴파일됩니다. 마찬가지로 Stuff.dll의 코드가 변경되면 Unity는 Main.dll과 Stuff.dll만 재컴파일하면 되며, ThirdParty.dll이나 Library.dll은 재컴파일할 필요가 없습니다.

참고: 프로젝트(Project) 창에서 스크립트 파일을 선택하고 인스펙터의 Assembly Information 목록을 확인하면 Unity가 특정 C# 파일을 어디에 컴파일하는지 알 수 있습니다.

Assembly-CSharp-Editor.dll 사전 정의된 어셈블리의 스크립트
Assembly-CSharp-Editor.dll 사전 정의된 어셈블리의 스크립트

어셈블리 정의를 사용하는 방법

Unity 프로젝트의 폴더에 어셈블리 정의 에셋을 추가하여 어셈블리를 정의합니다. 컴파일 후 어셈블리는 폴더와 하위 폴더(하위 폴더에 자체적인 어셈블리 정의가 있는 경우 제외)의 모든 스크립트를 포함합니다. 인스펙터에서 어셈블리의 이름을 설정합니다.

어셈블리 정의는 Unity 에셋의 한 가지 타입입니다. 프로젝트 창에서 기존의 어셈블리 정의를 선택하여 프로퍼티를 보거나 변경할 수 있습니다. 어셈블리 정의 에셋 파일 포맷에 관한 내용은 파일 포맷을 참조하십시오.

어셈블리 정의 에셋을 만들려면 다음 단계를 따르십시오.

프로젝트 창에서 어셈블리 정의를 추가할 폴더를 선택합니다.

  1. Assets > Create > Assembly Definition 메뉴로 이동하여 어셈블리 정의 에셋을 생성합니다.
  2. 새로 생성한 어셈블리 정의를 선택합니다.
  3. 필요한 경우 인스펙터 창에서 프로퍼티를 설정합니다.

폴더 하나당 어셈블리 정의를 하나만 생성할 수 있습니다. 이미 어셈블리 정의가 있는 폴더의 하위 폴더에 어셈블리 정의를 만들면 Unity는 하위 폴더에 있는 모든 스크립트와 그 자식을 부모 폴더에 정의된 어셈블리가 아닌 하위 폴더에 정의된 어셈블리로 컴파일합니다.

버전 정의

버전 정의를 사용하면 현재 프로젝트에 포함된 다양한 리소스 및 패키지 간의 종속성을 효과적으로 처리할 수 있습니다. 패키지 관리자 패키지 또는 에셋 스토어 패키지를 통해 프로젝트를 공유할 때 유용합니다.

버전을 설정하려면 더하기 기호(+)를 클릭하십시오. 원하는 만큼 많은 버전 정의를 어셈블리 정의에 추가할 수 있습니다. 정의를 삭제하려면 리스트에서 선택한 후 빼기 기호(-)를 클릭하십시오.

버전 정의에서 추가하는 경우 다음 프로퍼티가 나타납니다.

인스펙터에 나타나는 버전 정의의 모습입니다. 이 예시에는 두 개의 활성 버전 정의가 있습니다.
인스펙터에 나타나는 버전 정의의 모습입니다. 이 예시에는 두 개의 활성 버전 정의가 있습니다.
프로퍼티 설명
Resource 이 드롭다운 리스트를 사용하여 정의를 설정할 패키지나 모듈을 선택합니다. 이 리스트에는 프로젝트의 모든 활성 패키지와 모듈이 나와 있습니다.
Define 이 정의에 지정할 이름입니다. 이 정의는 아래의 표현식이 true를 반환할 때에만 설정됩니다.
Expression 선택한 모듈 또는 패키지의 시맨틱 버전 범위입니다. 수학적인 간격 표기법을 사용해야 합니다. 와일드카드는 지원되지 않습니다. 이 프로퍼티는 Microsoft의 .NET 패키지 관리자, NuGet과 동일한 버전 범위를 사용합니다.
Expression outcome 표현식이 나타내는 수학적 등식을 표시합니다.

어셈블리 정의 프로퍼티

인스펙터 창에서 어셈블리의 프로퍼티를 설정하려면 해당 어셈블리 정의 에셋을 클릭합니다.

어셈블리 정의 인스펙터
어셈블리 정의 인스펙터

Name

어셈블리의 이름(파일 확장자 없음)입니다. 어셈블리 이름은 프로젝트 전체에 걸쳐 고유해야 합니다. 특히 어셈블리가 두 개 이상의 프로젝트에서 사용될 가능성이 있는 경우, 리버스 dns 방식으로 이름을 지정하는 것을 고려하십시오. Unity는 어셈블리 정의 에셋에 할당된 이름을 Name 필드의 기본값으로 사용합니다. 원하는 경우 이 이름을 변경할 수 있습니다.

General

Allow ‘unsafe’ Code

어셈블리 내 스크립트에서 C# unsafe 키워드를 사용하는 경우 Allow ‘unsafe’ Code 를 활성화합니다. 이 옵션이 선택되면 Unity는 어셈블리를 컴파일할 때 C# 컴파일러에 /unsafe 옵션을 전달합니다.

Auto Referenced

사전 정의된 어셈블리가 모두 이 프로젝트 어셈블리를 참조해야 할지 지정합니다. 이 옵션을 선택하면 사전 정의된 어셈블리가 프로젝트에 정의된 모든 어셈블리를 참조합니다. 이는 사전 컴파일된 어셈블리(플러그인)가 사전 정의된 어셈블리에 의해 참조되는 방식과 일치합니다.

Override References

이 어셈블리가 종속되는 사전 컴파일된 어셈블리를 수동으로 지정하려면 Override References 옵션을 활성화합니다. Override References 를 활성화하면 인스펙터가 Assembly References 섹션을 표시합니다. 이 섹션에서 레퍼런스를 지정할 수 있습니다.

사전 컴파일된 어셈블리는 Unity 프로젝트 외에서 컴파일된 라이브러리입니다. 기본적으로 프로젝트에 정의된 어셈블리는 프로젝트에 추가한 모든 사전 컴파일된 어셈블리를 참조합니다. 이는 사전 정의된 어셈블리가 모든 사전 컴파일된 어셈블리를 참조하는 방식과 일치합니다. Override References 를 활성화하면 해당 어셈블리는 Assembly References 에 추가한 사전 컴파일된 어셈블리만 참조합니다.

사전 컴파일된 어셈블리가 프로젝트 어셈블리에 의해 자동으로 참조되지 않게 하려면 Auto Referenced 옵션을 비활성화하십시오. 자세한 내용은 플러그인 인스펙터를 참조하십시오.

Define Constraints

어셈블리가 컴파일되거나 참조되려면 필수적으로 정의해야 하는 컴파일러 #define 지시문을 지정합니다.

Unity는 모든 Define Constraints 가 충족되어야만 프로젝트 어셈블리를 컴파일하고 참조합니다. 제약은 C#의 #if 전처리기 지시문처럼 작동하되, 스크립트 레벨이 아닌 어셈블리 레벨에서 작동합니다. Define Constraints 설정의 모든 기호를 정의해야 제약이 충족됩니다. 취소를 의미하는 !(느낌표) 기호를 앞부분에 붙여 기호가 정의되지 않아야 한다고 지정할 수도 있습니다. 예를 들어, 다음 기호를 Define Constraints 로 지정하는 경우를 살펴보겠습니다.

!ENABLE_IL2CPP 
UNITY_2018_3_OR_NEWER

기호 ENABLE_IL2CPP가 지정되지 않고 기호 UNITY_2018_3_OR_NEWER가 지정되는 경우 제약이 충족됩니다. 즉, 이 어셈블리는 Unity 2018.3 이상을 위한 비 IL2CPP 스크립팅 런타임에서만 컴파일 및 참조됩니다.

Unity의 빌트인 #define 지시문을 사용하거나, 프로젝트의 Scripting Define Symbols 플레이어 설정에 정의된 모든 기호를 사용할 수 있습니다. 빌트인 기호의 목록을 비롯한 자세한 내용은 플랫폼별 컴파일을 참조하십시오. Scripting Define Symbols 설정은 플랫폼별로 다릅니다. 이 설정을 통해 어셈블리 사용 여부를 정의하는 경우 반드시 해당하는 모든 플랫폼에서 필수 기호를 정의하십시오.

Assembly Definition References

어셈블리 정의 에셋을 사용하여 생성한 다른 어셈블리에 대한 레퍼런스를 지정합니다.

Unity는 이러한 레퍼런스를 사용하여 어셈블리를 컴파일하고 어셈블리 간 종속성을 정의합니다.

Use GUIDs 옵션은 Unity가 다른 어셈블리 정의 에셋에 대한 레퍼런스를 직렬화하는 방식을 제어합니다. Use GUIDs 가 활성화되면 Unity는 레퍼런스를 어셈블리 정의 이름이 아니라 에셋의 GUID로 저장합니다. 이름 대신 GUID를 사용하는 것은 항상 바람직합니다. 이렇게 하면 참조하는 다른 어셈블리 정의 파일을 업데이트하지 않고도 어셈블리 정의 에셋의 이름에 변경 사항을 적용할 수 있습니다.

Assembly References

이 어셈블리가 종속된 사전 컴파일된 어셈블리에 대한 레퍼런스를 지정합니다. 사전 컴파일된 어셈블리에 대한 레퍼런스를 수동으로 지정하려면 General 섹션의 Override References 옵션을 선택해야 합니다.

Unity References

어셈블리를 테스트 어셈블리로 표시하려면 인스펙터의 Test Assemblies 옵션을 활성화합니다. Test Assemblies 를 활성화하면 어셈블리 정의에 unit.framework.dll과 UnityEngine.TestRunner.dll 라이브러리에 대한 레퍼런스가 추가됩니다.

어셈블리를 테스트 어셈블리로 표시하면 사전 정의된 어셈블리(예: Assembly-CSharp.dll)가 해당 어셈블리를 자동으로 참조하지 않으며, 어셈블리가 빌드에 포함되지 않습니다.

테스트 어셈블리를 플레이어 빌드에 포함하려면 빌드 스크립트에서 BuildOption.IncludeTestAssemblies를 사용하십시오.

참고: 이 옵션은 빌드의 어셈블리만 포함하며 테스트를 실행하지 않습니다.

Platforms

어셈블리의 플랫폼 호환성을 설정합니다. Unity는 포함된(혹은 포함되지 않은) 플랫폼에서만 해당 어셈블리를 컴파일하거나 참조합니다.

이전 버전과의 호환성 및 암시적 종속 관계

사전 정의된 어셈블리는 Unity의 기존 사전 정의된 컴파일 시스템과의 호환성을 유지하기 위해 어셈블리 정의 에셋으로 생성한 모든 어셈블리를 참조합니다. 이는 사전 정의된 어셈블리가 활성 빌드 타겟과 호환되는 프로젝트의 모든 사전 컴파일된 어셈블리(plugins / .dlls)를 참조하는 방식과 유사합니다.

다음 다이어그램은 사전 정의된 어셈블리, 어셈블리 정의 에셋으로 생성된 어셈블리와 사전 컴파일된 어셈블리 간의 기본 종속 관계를 나타냅니다.

그림 3 - 어셈블리 종속성
그림 3 - 어셈블리 종속성

다이어그램의 숫자는 어셈블리 간 레퍼런스를 나타냅니다. 이는 다음과 같이 제어할 수 있습니다.

  1. 기본적으로 어셈블리 정의 에셋을 이용하여 생성된 어셈블리는 사전 정의된 어셈블리에 의해 참조됩니다. 이 옵션은 인스펙터에서 Auto Referenced 옵션을 선택 해제하여 어셈블리 정의 에셋에 대해 끌 수 있습니다. Assembly Definition 프로퍼티를 참조하십시오.

  2. 마찬가지로 사전 컴파일된 어셈블리(플러그인)는 사전 정의된 어셈블리와 어셈블리 정의 에셋을 이용하여 생성된 어셈블리에 의해 자동으로 참조됩니다. 이 기본 동작은 인스펙터에서 해당 플러그인에 대해 Auto Referenced 옵션을 선택 해제하여 끌 수 있습니다. 플러그인 인스펙터를 참조하십시오.

  3. 플러그인에 대해 Auto Referenced 를 해제하면 인스펙터에서 어셈블리 정의 에셋에 대해 명시적으로 레퍼런스를 설정할 수 있습니다. 에셋의 Override References 옵션을 활성화하고 플러그인에 대한 레퍼런스를 추가합니다. Assembly Definition 프로퍼티를 참조하십시오.

참고: 사전 컴파일된 어셈블리나 어셈블리 정의 에셋으로 생성된 어셈블리에 대해 Auto Referenced 옵션을 해제하면 사전 컴파일된 어셈블리의 클래스가 더 이상 해당 어셈블리의 클래스를 참조하거나 사용할 수 없습니다. 또한 사전 컴파일된 어셈블리를 위한 명시적 레퍼런스를 선언할 수 없습니다.

특수 폴더

Unity는 폴더 내에서 특정한 특수 이름이 지정된 스크립트를 다른 폴더의 스크립트와 다르게 취급합니다. 단, 이러한 폴더는 해당 폴더 내 또는 상위 폴더에 어셈블리 정의 에셋을 생성하면 더 이상 다르게 취급되지 않습니다. 이와 같은 특수 취급의 변화는 Editor 폴더를 사용할 때 가장 잘 알아볼 수 있는데, 이러한 Editor 폴더는 보통 코드 정리 방식과 사용하는 에셋 패키지에 따라 프로젝트 전체에 걸쳐 분산되어 있습니다.

보통 Unity는 이름이 “Editor”인 폴더의 모든 스크립트를 이러한 스크립트의 위치와는 상관없이 사전 정의된 Assembly-CSharp-Editor 어셈블리에 컴파일합니다. 단, 하위 폴더 중 Editor 폴더가 있는 폴더에 어셈블리 정의 에셋을 생성하면 해당 에디터 스크립트가 사전 정의된 에디터 어셈블리가 아닌 어셈블리 정의에 의해 생성된 새로운 어셈블리로 전송됩니다. 이 위치는 잘못된 위치입니다. 다음 방법 중 한 가지를 통해 Editor 폴더를 처리하십시오.

  • 해당하는 각 Editor 폴더에 어셈블리 정의 에셋을 추가하고 해당 어셈블리의 Platform 프로퍼티를 Editor Platform 에만 사용되도록 설정합니다.
  • 어셈블리 정의에 의해 처리되지 않는 중앙 위치로 모든 에디터별 코드를 이동합니다.

테스트 어셈블리

테스트 어셈블리는 프로젝트의 다른 코드를 테스트하는 코드를 포함합니다. 따라서 이러한 어셈블리는 프로젝트의 릴리스 빌드에 포함될 필요가 없으며, 테스트 어셈블리가 아닌 다른 어셈블리는 테스트 어셈블리에 종속되면 안 됩니다. Assembly Definition Asset 프로퍼티에서 Test Assemblies 옵션을 선택하여 Unity 빌드에 테스트 어셈블리를 지정할 수 있습니다. 이 프로퍼티를 설정하면 다음이 가능합니다.

  • 사전 정의된 어셈블리가 테스트 어셈블리를 참조하지 못하도록 방지
  • 테스트 어셈블리를 빌드에서 제외
  • NUnit 어셈블리에 대한 레퍼런스 추가

참고: 릴리스 빌드나 개발용 빌드에 테스트 어셈블리를 포함하려면 빌딩 스크립트에서 BuildOption.IncludeTestAssemblies를 사용하십시오. 이는 빌드의 어셈블리만 포함하며 테스트는 실행하지 않습니다.

API

UnityEditor.Compilation 네임스페이스에서 CompilationPipeline 클래스를 사용하면 Unity가 프로젝트를 위해 빌드한 모든 어셈블리에 대한 정보를 검색해서 가져올 수 있습니다. 여기에는 어셈블리 정의 에셋에 기반하여 생성된 어셈블리도 포함됩니다.

예를 들어 다음 스크립트는 CompilationPipeline을 사용하여 프로젝트의 모든 현재 플레이어 어셈블리를 나열합니다.

using UnityEditor;
using UnityEditor.Compilation;

public static class AssemblyLister
{

    [MenuItem("Tools/List Player Assemblies in Console")]
    public static void PrintAssemblyNames()

    {
        UnityEngine.Debug.Log("== Player Assemblies ==");
        Assembly[] playerAssemblies = 
            CompilationPipeline.GetAssemblies(AssembliesType.Player);

        foreach (var assembly in playerAssemblies)
        {
            UnityEngine.Debug.Log(assembly.name);
        }
    }
}

어셈블리 정의 파일 포맷

어셈블리 정의 에셋은 JSON 파일입니다. 외부 툴을 이용하여 Unity 에디터 내의 에셋을 편집하거나 JSON 콘텐츠를 수정할 수 있습니다. 어셈블리 정의는 다음 필드가 포함된 JSON 객체입니다.

필드 타입
name 문자열
references (optional) 문자열 배열
includePlatforms (optional) 문자열 배열
excludePlatforms (optional) 문자열 배열
allowUnsafeCode(optional) bool
autoReferenced(optional) bool
overrideReferences(optional) bool
precompiledReferences(optional) 문자열 배열
defineConstraints(optional) 문자열 배열
optionalUnityReferences(optional) 문자열 배열

includePlatformsexcludePlatforms 필드는 같은 어셈블리 정의 파일에서 함께 사용될 수 없습니다.

어셈블리의 이름이나 에셋의 GUID를 사용하여 references 필드에 어셈블리 정의 에셋을 지정할 수 있습니다. 에셋 GUID를 사용하려면 값은 GUID:Asset GUID 와 같은 형태여야 합니다. 예를 들어 “GUID:0ec2b662ccc592241854c1b507df8a89” 를 사용할 수 있습니다. AssetDatabase.AssetPathToGUID는 에셋의 GUID를 검색해서 가져옵니다.

CompilationPipeline.GetAssemblyDefinitionPlatforms() 함수로 플랫폼 이름 스트링을 검색하여 가져올 수 있습니다(현재 에디터에 플랫폼 지원 설치 필요).

예시 어셈블리 정의 JSON

MyLibrary.asmdef

{
    "name": "MyLibrary",
    "references": [ "Utility" ],
    "includePlatforms": ["Android", "iOS"]
}

MyLibrary2.asmdef

{
    "name": "MyLibrary2",
    "references": [ "GUID:0ec2b662ccc592241854c1b507df8a89" ],
     "excludePlatforms": ["WebGL"]
}

  • 2019–03–07 편집 리뷰를 거쳐 페이지 수정됨

  • Unity 2017.3의 새로운 기능 NewIn20173

  • Unity 2018.1에서 커스텀 스크립트 어셈블리가 업데이트됨

  • 2019.1에서 프로퍼티 추가됨

특수 폴더와 스크립트 컴파일 순서
관리되는 코드 스트리핑