이번 포스트에서는 Visual Studio에서 빌드를 하면서 생성되는 폴더와 파일들에 대해서 알아보고자 합니다.
모든 프로젝트에는 아래의 그림과 같이 Configuration과 Platform이 있습니다.


=> Configuration은 Debug, Release를 기본값으로 해서 사용자가 정의할 수도 있습니다. Platform은 x86, x64, Any CPU 등등이 있습니다.

일단 윈폼 프로젝트를 하나 생성하고 빌드를 해본 이후에 Platform을 윈폼 프로젝트의 기본값(x86)이 아닌 다른 값으로 복사를 하고 빌드를 해봅니다. 그렇다면 아래와 같은 구조로 폴더가 생성된다는 것을 확인하실 수 있습니다.

일단 
obj폴더와 bin폴더가 만들어지며 Platform이 Any CPU일 경우에는 obj와 bin폴더 바로 하위에 Debug, Release폴더가 만들어지는 것을 확인할 수 있습니다. 만약 다른 Platform을 지정하신 후 빌드하신 다면 해당 Platform폴더가 먼저 만들어지고 Debug, Release폴더가 만들어지는 것도 확인하실 수 있습니다. 확인만 안해봤을 뿐 이해가 되는 구조로 폴더가 만들어지고 있습니다. ^^

그럼 이제 obj폴더와 bin폴더 하위에 어떤 파일들이 생성되는지를 알아보겠습니다.
먼저 다음과 같은 사전 작업을 합니다.
  1. 클래스 라이브러리 프로젝트를 하나 추가한 이후에 윈폼 프로젝트에서 해당 클래스 라이브러리 프로젝트를 참조
  2. 윈폼 프로젝트의 Form1.cs파일을 클릭하면 디자이너 화면을 로드
  3. 빌드

먼저 obj\Debug 폴더 안에 파일을 분석해보고 bin\Debug을 살펴보도록 하겠습니다.
 =>  리소스 관련 파일 3개와 절대 경로 파일 목록 텍스트 파일이 있습니다. 그리고 빌드 완료된 어셈블리와 pdb파일이 보입니다. 그 외에 3가지 파일에 대해서 살펴보도록 하겠습니다.

DesignTimeResolveAssemblyReferenceInput.cache
 => Visual Studio(IDE)에서도 내부적으로 당연히(!) 리플렉션을 사용합니다. 해당 파일은 테스트 결과 참조를 추가/삭제하던지 *.resx나 *.settings파일을 클릭할 경우에 생성됩니다. 해당 파일을 열어보면 Microsoft.VisualStudio.CommonIDE 어셈블리를 로드하는 것을 확인할 수 있습니다. 따라서 Visual Studio 전반적으로 리플렉션을 사용하는 곳에서 해당 파일이 생성되는 것을 알 수 있습니다.

DesignTimeResolveAssemblyReference.cache
 => 해당 파일은 윈폼 프로젝트에서 Form1.cs파일을 클릭하여 디자인 화면에 폼이 보여질 경우에 생기는 파일입니다.

ResolveAssemblyReference.cache
 => 위의 사전 작업에서 윔폼 프로젝트에서 클래스 라이브러리 프로젝트를 참조 후 빌드하였습니다. 바로 이 파일음 참조된 어셈블리와 관련되어 빌드시에 생성되는 파일입니다.

이전 포스트인 '프로젝트 참조 VS 어셈블리 참조' 에서 참조한 어셈블리를 어떠한 우선 순위 경로로 찾는지에 대해서 잠깐 언급을 했었습니다. 위의 3가지 파일 중에 ResolveAssemblyReference.cache가 바로 이러한 결과 값이라고 할 수 있습니다. 만약 클래스 라이브러리 프로젝트를 참조하지 않았다면 해당 파일은 생기지 않습니다.
그렇다면 Visual Studio는 어디서 이러한 정보를 가져오는 걸까요? 이 정보를 변경할 수는 없을까요?
%windir%\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets 파일에 이러한 정보가 있습니다.
줄 1410
<ProjectDesignTimeAssemblyResolutionSearchPaths 
   
Condition=" '$(ProjectDesignTimeAssemblyResolutionSearchPaths)' == '' "
    {CandidateAssemblyFiles}; 
    $(ReferencePath); 
    {HintPathFromItem};
    {TargetFrameworkDirectory};                
    {Registry:$(FrameworkRegistryBase),$(TargetFrameworkVersion),
  $(AssemblyFoldersSuffix)$(AssemblyFoldersExConditions)};
    {RawFileName}; 
    $(TargetDir) 
</ProjectDesignTimeAssemblyResolutionSearchPaths

줄 1461

<
DesignTimeAssemblySearchPaths Condition=" '$(DesignTimeAssemblySearchPaths)' == '' ">
    {CandidateAssemblyFiles};
    $(ReferencePath);
    {HintPathFromItem};
    {TargetFrameworkDirectory};
    {Registry:$(FrameworkRegistryBase),$(TargetFrameworkVersion),
  $(AssemblyFoldersSuffix)$(AssemblyFoldersExConditions)};
    {RawFileName};
    $(OutDir)
</DesignTimeAssemblySearchPaths>

줄 418
<AssemblySearchPaths Condition=" '$(AssemblySearchPaths)' == ''">
    {CandidateAssemblyFiles};
    $(ReferencePath);
    {HintPathFromItem};
    {TargetFrameworkDirectory};
    {Registry:$(FrameworkRegistryBase),$(TargetFrameworkVersion),
  $(AssemblyFoldersSuffix)$(AssemblyFoldersExConditions)};
    {AssemblyFolders};
    {GAC};
    {RawFileName};
    $(OutDir)
</AssemblySearchPaths>


 => 각각의 경로는 *.cache 파일과 매칭됩니다. (디자인 타임과 관련된 사항은 시간이 지나 헷갈리네요. 순서가 매칭 순서가 맞지 않을 수도 있습니다. ^^;)
이전에 .NET 1.1를 Target Framework로 하고 개발 툴을 VS2010에서 사용하려고 할 때 위의 설정을 변경해준 적이 있습니다. 빌드와 디자인 타임에 해당 폼을 보는 것 까지는 성공을 했었는데 도구 상자(ToolBox)가 최소 .NET 2.0으로 설정이 되는 문제와 기타 잠재된 문제도 있을 것으로 예상되어 포기 했었습니다.
여튼 이제 bin\Debug 폴더에 생기는 파일을 보면 최종 결과물인 어셈블리와 pdb파일 그리고 vshost파일이 있는 것을 알 수 있습니다. 빌드시에 필요한 정보인 리소스, 로그, 툴에서 사용하는 정보 등을 obj 폴더 하위에 만들어 사용하고 최종 결과물은 bin폴더 하위에 만드는 구조입니다. 디버깅시에 사용하는 vshost파일의 경우 obj에 있으면 어떨가 잠시 생각을 해봤지만 obj 폴더 하위에는 해당 프로젝트의 결과물만 가지고 있을 뿐 참조하고 있는 어셈블리가 복사되는 것은 아닙니다. bin 폴더에는 참조하고 있는 어셈블리의 Copy Local속성이 True일 경우에는 bin폴더로 복사가 됩니다.
실제 개발과는 별로 상관없는 내용이였지만 Visual Studio를 사용하면서 만들어지는 폴더와 파일에 대한 내용이 궁금해져 한 번 정리를 해보았답니다. ^^
Posted by resisa