ASP.NET Core 의 AddScoped AddTransient AddSingleton 생명주기 알아보기


ASP.NET Core 의 AddScoped AddTransient AddSingleton 생명주기 알아보기


Transient

Transient  의 Lifetime services  는 매번 인터페이스가 요청될 때마다 새로운 객체를 생성합니다.이는 비유지(stateless)  서비스에 가장 적합합니다.

Scoped

Scoped 의 Lifetime services 경우, 각 HTTP 요청 당 하나의 인스턴스를 생성하며, 동일한 주소의 웹화면내서 여러번 이를 사용할 경우 동일한 인스턴스를 재사용합니다.

Singleton

Singleton Lifetime services 는 딱 한번 처음으로 인스턴스를 생성하고, 모든 호출에서 동일한 오브젝트를 재사용합니다. 따라서 결과값을 전체 모든 호출하는 사람들과 공유하는 효과를 얻습니다. 보통 누적된 방문자 수를 보여줄 때 사용하면 되겠습니다.


위의 3가지를 사용하는 방법은 아래와 같습니다. 위치는 Startup.cs 파일에 존재합니다.


public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<ICharacterRepository, CharacterRepository>();
services.AddTransient<IOperationTransient, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
}



위의 3가지 중 유난히 Transient 와 Scoped 의 차이점을 정확히 이해하기 어려운데요. 여기서 예제를 들어볼 까 합니다.

먼저 DI 를 구성하기 위해 인터페이스와 구현체를 만들어 봅시다.


[IRepositoy] 인터페이스

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Core1.Models
{
public interface IRepository
{
int GetnUpdateCounter();
}
}


[Repositoy] 구현체 클래스
: 여기서 자동증가 값을 구현했습니다. 동일한 인스턴스라면 계속 누적되어 +1 씩 증가되겠죠...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Core1.Models
{
public class MyRepository : IRepository
{
private int i;
public int GetnUpdateCounter()
{
return i++;
}
}
}


Startup.cs 에서 AddScoped 생명주기를 테스트 하기 위해 인스턴스와 구현클래스를 매칭했습니다.

public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IRepository, MyRepository>();
services.AddMvc();
}


호출하는 샘플을 보여주기 위해서 TagHelper 를 만들어 봤습니다.

: View 단에서 <test message="test"></test> 이런식으로 구현할 예정입니다. 실행하면 h5 태그로 구성되며 내용은 message : 증가값 이 출력됩니다.


using Core1.Models;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Core1.TagHelpers
{
public class TestTagHelper : TagHelper
{

private readonly IRepository _myRepository;

public TestTagHelper(IRepository myRepository)
{
_myRepository = myRepository;
}

public string Message { get; set; }

public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "h5";
output.Content.SetContent(Message + " : " + _myRepository.GetnUpdateCounter().ToString());
}
}
}


home 컨트롤러를 구현합니다. DI 를 위해 생성자를 작성하였고 +1 씩 추가하는 메소드 GetnUpdateCounter() 함수를 호출했습니다.

Transient 은 항상 인스턴스를 생성하므로 0 값만 들어가 있을 것이며, Scoped 는 처음 컨트롤러 REQUEST 받았으므로 0 값이 할당되어 있습니다. Singleton 은 동일한 인스턴스를 재사용하므로 매번 REQUEST 할 때마다 +1씩 증가되어 결과값을 보여줍니다.


using Core1.Models;
using Microsoft.AspNetCore.Mvc;

namespace Core1.Controllers
{
public class HomeController : Controller
{
private readonly IRepository _myRepository;

public HomeController(IRepository myRepository)
{
_myRepository = myRepository;
}

public IActionResult Index()
{
ViewBag.Counter = _myRepository.GetnUpdateCounter();

return View();
}
}
}

태그를 사용하기 위해 _ViewImports.cshtml 에 기재 합니다. 네임스페이스 제일 앞 부분만 기재합니다. (Core1.TagHelpers 에서 Core1 만...)

@using Core1
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Core1

Home 의 index.cshtml 에 할당합니다.

<p>
@ViewBag.Counter
<test message="aspdotnet"></test>
<test message="심재운"></test>
</p>


AddScoped 생명주기는 처음 컨트롤러에서 호출하여 인스턴스를 생성 해서 우선 viewbag 에는 0 값이 할당되었고, view 에서 aspdotnet 의 taghelper 에서 인스턴스를 재사용하여 +1 되었습니다. 심재운 이라는 taghelper 를 호출해서 다시 재활용하여 +1 되어 2가 되었습니다. 다시 페이지를 새로고침하면 인스턴스를 다시 재생성하므로 아래와 동일한 결과가 나옵니다.

AddTransient 인 생명주기를 사용해 볼게요. 호출할때 마다 매번 인스턴스를 생성하니 초기값인 0이 출력되죠.


public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IRepository, MyRepository>();
services.AddMvc();
}

AddSingleton  은 인스턴스르 하나로 지속적으로 재활용하므로 누적되는 것을 보실 수 있습니다.


public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IRepository, MyRepository>();
services.AddMvc();
}

해당 페이지 한번 호출했을때,

해당 페이지 두번 호출했을때...


계속 누적되죠??? 하나의 인스턴스를 계속 재활용하므로 누적된다는 점만 알아두시면 됩니다.


감사합니다.


참고 사이트 : 

https://docs.microsoft.com/ko-kr/aspnet/core/mvc/views/tag-helpers/authoring

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection#resolve-a-scoped-service-within-the-application-scope


Comments 0