컨트롤러: 영역
- 본 번역문서의 원문은 Areas docs.asp.net 입니다.
- 본 번역문서는 MVC : Controller - 영역(Areas) www.taeyo.net 에서도 함께 제공됩니다.
영역(Areas)은 관련된 기능들을 분리된 이름공간(라우팅)과 폴더 구조(뷰)의 그룹으로 분할 구성하는 용도로 사용되는 ASP.NET MVC의 기능입니다.
영역을 사용하면 controller
와 action
에 더하여 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
-
Home
-
Controllers
-
Services
-
Controllers
- HomeController.cs
-
Views
-
Home
- Index.cshtml
-
Home
-
Controllers
-
Products
-
Areas
영역 기능을 사용하는 경우, 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
영역에 위치한 HomeController
의 Index
액션 메서드가 호출될 것입니다.
링크 생성
-
영역 기반 컨트롤러에 존재하는 액션에서 동일한 컨트롤러의 다른 액션을 가리키는 링크 생성하기
현재 요청의 경로는
/Products/Home/Create
라고 가정합니다.HtmlHelper 구문:
@Html.ActionLink("Go to Product's Home Page", "Index")
TagHelper 구문:
<a asp-action="Index">Go to Product's Home Page</a>
이 경우, 'area' 값과 'controller' 값은 현재 요청의 컨텍스트를 통해서 이미 사용 가능하기 때문에 명시적으로 제공할 필요가 없다는 점에 주목하시기 바랍니다. 이런 유형의 값을 주변값(Ambient Values)이라고 합니다.
-
영역 기반 컨트롤러에 존재하는 액션에서 다른 컨트롤러의 특정 액션을 가리키는 링크 생성하기
현재 요청의 경로는
/Products/Home/Create
라고 가정합니다.HtmlHelper 구문:
@Html.ActionLink("Go to Manage Products' Home Page", "Index", "Manage")
TagHelper 구문:
<a asp-controller="Manage" asp-action="Index">Go to Manage Products' Home Page</a>
이번에는 'area' 값은 주변값이 사용됐지만, 'controller' 값은 명시적으로 지정되었다는 점에 유의하시기 바랍니다.
-
영역 기반 컨트롤러에 존재하는 액션에서 다른 영역의 다른 컨트롤러의 특정 액션을 가리키는 링크 생성하기
현재 요청의 경로는
/Products/Home/Create
라고 가정합니다.HtmlHelper 구문:
@Html.ActionLink("Go to Services' Home Page", "Index", "Home", new { area = "Services" })
TagHelper 구문:
<a asp-area="Services" asp-controller="Home" asp-action="Index">Go to Services' Home Page</a>
이번에는 주변값이 전혀 사용되지 않았습니다.
-
영역 기반 컨트롤러에 존재하는 액션에서 영역에 속하지 않은 다른 컨트롤러의 특정 액션을 가리키는 링크 생성하기
HtmlHelper 구문:
@Html.ActionLink("Go to Manage Products' Home Page", "Index", "Home", new { area = "" })
TagHelper 구문:
<a asp-area="" asp-controller="Manage" asp-action="Index">Go to Manage Products' Home Page</a>
이처럼 영역에 속하지 않은 컨트롤러의 액션을 가리키는 링크를 생성할 때는 빈 문자로 'area'의 주변값을 비워줘야 합니다.
영역 게시하기
영역 폴더의 모든 뷰들을 게시하려면, project.json
파일에서 publishOptions
하위의 include
노드에 다음과 같은 항목을 추가합니다:
"publishOptions": {
"include": [
"Areas/**/*.cshtml",
....
....
]
- 컨트롤러: 컨트롤러, 액션 및 액션 결과 2016-10-24 08:00
- 컨트롤러: 필터 2016-10-31 08:00
- 컨트롤러: 의존성 주입과 컨트롤러 2016-11-07 08:00
- 컨트롤러: 영역 2016-11-14 08:00
- 컨트롤러: 컨트롤러 액션으로 라우팅하기 2016-11-21 08:00
- 컨트롤러: 컨트롤러 로직 테스트하기 2016-11-28 08:00