현재 프로젝트에서 참조를 어떻게 하고 계십니까? 아마도 대부분 이렇게 구성하고 계실 것입니다.
1. 프로젝트 사이에 참조가 필요한 경우에는 프로젝트 참조를 한다.
2. 3Party DLL 등등은 어셈블리 참조를 한다.
2번에서 3Party DLL의 소스가 있을 경우에 소스의 수정 여부에 따라서 프로젝트 참조를 할 것입니다.
이렇게만 구성을 하여도 충분히 훌륭한 솔루션(.sln)을 구성한 것입니다.
2. 3Party DLL 등등은 어셈블리 참조를 한다.
2번에서 3Party DLL의 소스가 있을 경우에 소스의 수정 여부에 따라서 프로젝트 참조를 할 것입니다.
이렇게만 구성을 하여도 충분히 훌륭한 솔루션(.sln)을 구성한 것입니다.
그렇다면 혹시 프로젝트 참조와 어셈블리 참조의 차이점은 알고 계십니까?
참조의 관점에서 본다면 차이점이 없습니다. 어셈블리 참조는 해당 위치(Path)에 있는 어셈블리를 참조하는 것이고 프로젝트 참조는 프로젝트의 출력 경로의 어셈블리를 참조하게 해주는 것 뿐입니다.
빌드의 관점에서 본다면 차이점이 존재합니다. 먼저 어셈블리 참조는 단순히 참조만 합니다. 하지만 프로젝트 참조를 하면 참조된 프로젝트의 출력 경로로 빌드된 어셈블리가 생성되고 참조됩니다.
이 차이점을 가지고 참조된 어셈블리의 Properties에 대해서도 살펴보겠습니다. 차이점이 보이실 겁니다. 바로 Specific Version 프로퍼티입니다. 이 프로퍼티는 어셈블리 참조에는 존재하고 프로젝트 참조에는 존재하지 않습니다. 그렇다면 빌드의 관점 뿐만이 아니라 프로퍼티에 대해서도 뭔가 차이점이 존재하는 것 아니냐고 생각하실 수 있습니다. 하지만 명백하게(?!) 빌드의 관점을 제외하고는 차이점이 없습니다.
이 차이점을 가지고 참조된 어셈블리의 Properties에 대해서도 살펴보겠습니다. 차이점이 보이실 겁니다. 바로 Specific Version 프로퍼티입니다. 이 프로퍼티는 어셈블리 참조에는 존재하고 프로젝트 참조에는 존재하지 않습니다. 그렇다면 빌드의 관점 뿐만이 아니라 프로퍼티에 대해서도 뭔가 차이점이 존재하는 것 아니냐고 생각하실 수 있습니다. 하지만 명백하게(?!) 빌드의 관점을 제외하고는 차이점이 없습니다.
Specific Version 프로퍼티는 그 이름대로 GAC(Global Assembly Cache)에 등록되어 있는 어셈블리 중에 특정 버전를 참조할 것인지의 여부를 설정하는 것입니다. 프로젝트 참조에서는 위에서 말했듯이 빌드가 된 어셈블리를 참조하기 때문에 특정 버전의 여부가 의미가 없어지는 것입니다. 참고적으로 어셈블리 참조시에 Local Copy는 GAC에 등록여부에 따라서 해당 값이 결정되기 때문에 닷넷 프레임워크에서 제공해주는 System 등등은 false가 됩니다. 프로젝트 참조에서는 Local Copy는 Default로 True 값을 가집니다.
지금까지 차이점에 대해서 이야기를 해보았습니다. 어셈블리 참조를 프로젝트 참조와 동일하게 만들어보도록 하겠습니다.
참조를 하는 프로젝트에서 오른쪽 버튼을 눌러 아래와 같이 Project Dependencies를 선택합니다.
=> Depends on 메뉴에서 어셈블리 참조를 한 ClassLibrary1에 체크 표시를 하고 'OK'버튼을 클릭합니다. Build Order탭을 살펴보면 해당 빌드 순서도 확인하실 수 있습니다. 이렇게 설정을 하고 참조를 하고 있는 프로젝트에서 '빌드'를 실행하면 어셈블리 참조를 한 어셈블리도 빌드가 되는 것을 확인하실 수 있습니다.(물론 어셈블리 참조를 하였더라도 해당 어셈블리로 출력되는 프로젝트는 솔루션에 로드되어 있어야 합니다.) 이러한 정보를 어디서 가지고 있을까요? 바로 솔루션 파일(.sln)에 있습니다.
=> 노란색으로 표시한 부분 아래에 나와있는 Guid가 바로 ClassLibrary1의 Guid입니다. 프로젝트 참조시에는 솔루션 파일에 이러한 정보는 보이지 않습니다. 하지만 Project Dependencies 속성을 확인해보면 자동으로 체크표시가 되어 있는 것을 확인할 수 있는데 해당 정보는 프로젝트 파일(.csproj)에서 얻을 수 있습니다. 어쨌든 Visual Stuido에서는 솔루션 파일과 프로젝트 파일에 있는 정보를 사용하여 빌드 순서를 정해주게 됩니다.
마지막으로 빌드시에 참조되는 어셈블리를 어떠한 경로를 통해서 찾는지 알아보겠습니다.
(여기서는 VS2010기준입니다.)
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsFormsApplication5", "WindowsFormsApplication5\WindowsFormsApplication5.csproj", "{DA5C04D8-F654-49FF-BBEB-CD6BE17AD952}"
ProjectSection(ProjectDependencies) = postProject {9526A004-DF09-4C1E-9BB2-A1B31B37A716} = {9526A004-DF09-4C1E-9BB2-A1B31B37A716} EndProjectSection EndProject |
마지막으로 빌드시에 참조되는 어셈블리를 어떠한 경로를 통해서 찾는지 알아보겠습니다.
(여기서는 VS2010기준입니다.)
단순히 나열을 해보도록 하겠습니다.
{HintPathFromItem}
{TargetFrameworkDirectory}
{Registry:Software\Microsoft\.NETFramework,v4.0,AssemblyFoldersEx}
{AssemblyFolders}
{GAC}
{RawFileName}
bin\Debug\
{TargetFrameworkDirectory}
{Registry:Software\Microsoft\.NETFramework,v4.0,AssemblyFoldersEx}
{AssemblyFolders}
{GAC}
{RawFileName}
bin\Debug\
위의 항목 중에는 단순히 하나의 경로도 있지만 컴퓨터 환경에 따라서 수십개의 경로를 탐색하기도 합니다. 또한 .exe .dll를 모두 찾습니다. 만약에 위의 항목이 실질적으로 경로를 탐색하는 순서라면 bin\Debug\가 제일 마지막에 있는 것이 의외(?)네요. 이러한 정보는 모두 MsBuild를 통해서 얻을 수 있는데 VS에서도 MsBuild에서와 마찬가지로 위의 경로를 탐색합니다.
<2010-06-23>
결정적인 차이점이 존재하네요. 바로 Go To Defenition(정의로 이동?)입니다. 어셈블리 참조를 하면 해당 코드로 이동할 수가 없지만 프로젝트 참조를 하면 해당 코드로 이동이 가능합니다. +_+;;