컨트롤러: 영역

등록일시: 2016-11-14 08:00,  수정일시: 2016-11-14 11:50
조회수: 5,289
이 문서는 ASP.NET Core MVC 기술을 널리 알리고자 하는 개인적인 취지로 제공되는 번역문서입니다. 이 문서에 대한 모든 저작권은 마이크로소프트에 있으며 요청이 있을 경우 언제라도 게시가 중단될 수 있습니다. 번역 내용에 오역이 존재할 수 있고 주석은 번역자 개인의 의견일 뿐이며 마이크로소프트는 이에 관한 어떠한 보장도 하지 않습니다. 번역이 완료된 이후에도 대상 제품 및 기술이 개선되거나 변경됨에 따라 원문의 내용도 변경되거나 보완되었을 수 있으므로 주의하시기 바랍니다.
본문에서는 관련된 기능들을 분리된 이름공간과 폴더 구조의 그룹으로 분할 구성할 수 있게 해주는 영역(Areas) 기능을 살펴봅니다.

영역(Areas)은 관련된 기능들을 분리된 이름공간(라우팅)과 폴더 구조(뷰)의 그룹으로 분할 구성하는 용도로 사용되는 ASP.NET MVC의 기능입니다. 영역을 사용하면 controlleraction에 더하여 area라는 또 다른 라우트 매개변수가 추가됨으로써, 라우팅에 대한 계층구조가 만들어집니다.

영역을 사용하면 규모가 큰 ASP.NET Core MVC 응용 프로그램을 보다 작은 여러 개의 기능적 그룹으로 분할할 수 있습니다. 영역은 응용 프로그램 내부의 MVC 구조에 효과적입니다. MVC 프로젝트에서 모델, 컨트롤러, 뷰 같은 논리적 구성 요소들은 각기 다른 폴더에 위치하며, MVC는 명명 규칙을 통해서 이런 구성 요소들 간의 관계를 수립합니다. 규모가 큰 응용 프로그램에서는 응용 프로그램을 서로 분리된 고수준의 기능적 영역으로 분할하는 편이 유리합니다. 한 가지 예로, 지불, 결제, 검색 등과 같은 여러가지 업무 단위로 구상된 전자상거래 응용 프로그램을 들 수 있습니다. 이런 각각의 업무 단위들은 자체적인 논리적 구성 요소들, 즉 뷰, 컨트롤러, 모델을 갖습니다. 이런 시나리오에서 영역을 사용하면 동일한 프로젝트 내의 업무 구성 요소들을 물리적으로 분리할 수 있습니다.

영역은 자체적인 컨트롤러, 뷰, 모델들의 모음을 갖고 있는 ASP.NET Core MVC 프로젝트 내부의 보다 작은 기능적 단위라고 정의할 수 있습니다.

다음과 같은 경우, MVC 프로젝트에서 영역을 사용할 것을 고려해보시기 바랍니다:

  • 응용 프로그램이 논리적으로 분리 가능한 여러 개의 고수준 기능적 구성 요소들로 구성된 경우
  • 내부적으로 MVC 프로젝트를 분리해서 각 기능적 영역들이 독립적으로 동작할 수 있게 만들고자 하는 경우

영역의 기능:

  • ASP.NET Core MVC 응용 프로그램은 필요한 만큼 얼마든지 영역을 가질 수 있습니다.
  • 각 영역은 자체적으로 컨트롤러, 모델, 뷰를 갖습니다.
  • 큰 규모의 MVC 프로젝트를 독립적으로 동작할 수 있는 여러 개의 고수준 구성 요소들로 구성할 수 있습니다.
  • 서로 다른 영역에 존재하는, 동일한 이름을 가진 여러 개의 컨트롤러들을 지원합니다.

간단한 예제를 통해서 영역을 생성하고 사용하는 방법을 살펴보도록 하겠습니다. Products와 Services라는 개별적인 두 그룹의 컨트롤러 및 뷰들이 존재하는 상점 응용 프로그램을 가정해봅니다. 영역 기능을 사용하는 MVC 프로젝트의 일반적인 폴더 구조는 다음과 같습니다:

  • 프로젝트명
    • Areas
      • Products
        • Controllers
          • HomeController.cs
          • ManageController.cs
        • Views
          • Home
            • Index.cshtml
          • Manage
            • Index.cshtml
      • Services
        • Controllers
          • HomeController.cs
        • Views
          • Home
            • Index.cshtml

영역 기능을 사용하는 경우, MVC는 뷰를 렌더하기 위해서 기본적으로 다음과 같은 경로들을 검색합니다:

/Areas/<Area-Name>/Views/<Controller-Name>/<Action-Name>.cshtml
/Areas/<Area-Name>/Views/Shared/<Action-Name>.cshtml
/Views/Shared/<Action-Name>.cshtml

이 경로들은 기본 위치로, Microsoft.AspNetCore.Mvc.Razor.RazorViewEngineOptions 클래스의 AreaViewLocationFormats 속성을 이용해서 변경할 수 있습니다.

가령, 다음 예제 코드는 'Areas'라는 폴더명 대신, 'Categories' 라는 폴더명을 사용하도록 구성합니다.

services.Configure<RazorViewEngineOptions>(options =>
{
    options.AreaViewLocationFormats.Clear();
    options.AreaViewLocationFormats.Add("/Categories/{2}/Views/{1}/{0}.cshtml");
    options.AreaViewLocationFormats.Add("/Categories/{2}/Views/Shared/{0}.cshtml");
    options.AreaViewLocationFormats.Add("/Views/Shared/{0}.cshtml");
});

여기서 한 가지 유의해야 할 점은, 이 중 Views 폴더의 구조만 유의해서 관리하면 되며, Controllers 폴더나 Models 폴더 같은 나머지 폴더들의 내용은 별다른 문제가 되지 않는다는 것입니다. 단적으로 Controllers 폴더나 Models 폴더는 아예 존재하지 않아도 무방합니다. 그 이유는 Controllers 폴더와 Models 폴더의 내용들은 그저 .dll 파일로 컴파일되는 코드인 반면, Views 폴더의 내용들은 해당 뷰가 요청되기 전까지는 컴파일되지 않기 때문입니다.

폴더의 계층 구조를 정의한 다음에는, MVC에게 각 영역에 속한 컨트롤러들을 알려줘야 합니다. 이 작업은 컨트롤러에 [Area] 어트리뷰트를 적용해서 처리할 수 있습니다.

...
namespace MyStore.Areas.Products.Controllers
{
    [Area("Products")]
    public class HomeController : Controller
    {
        // GET: /Products/Home/Index
        public IActionResult Index()
        {
            return View();
        }

        // GET: /Products/Home/Create
        public IActionResult Create()
        {
            return View();
        }
    }
}

계속해서 이번에는 새로 생성한 영역에 적용할 라우트 정의를 설정합니다. 컨트롤러 액션으로 라우팅하기 문서에서는 기본 라우트 및 어트리뷰트 라우트의 이용해서 라우트 정의를 생성하는 방법을 자세하게 설명합니다. 본문의 예제에서는 기본 라우트 방식을 사용합니다. 따라서, Startup.cs 파일을 열고 다음 코드에 강조된 라우트 정의를 추가합니다.

...
app.UseMvc(routes =>
{
    routes.MapRoute(name: "areaRoute",
        template: "{area:exists}/{controller=Home}/{action=Index}");

    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}");
});

이제 http://<yourApp>/products 로 이동해보면, Products 영역에 위치한 HomeControllerIndex 액션 메서드가 호출될 것입니다.

영역 게시하기

영역 폴더의 모든 뷰들을 게시하려면, project.json 파일에서 publishOptions 하위의 include 노드에 다음과 같은 항목을 추가합니다:

"publishOptions": {
  "include": [
    "Areas/**/*.cshtml",
    ....
    ....
  ]