재우니의 블로그

 

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