-
[ASP.NET Core] AddSingleton(), AddScoped(), AddTransient() 차이점 - 1.NET/ASP.NET Core 2021. 9. 12. 22:54반응형
ASP.NET Core에서 의존성 주입에 의해 추가되는 Service는 크게 3가지 생명주기를 지닌다.
- AddSingleton
- AddScoped
- AddTransient
AddSingleton의 경우는 클라이언트(보통 웹브라우저)의 접속상태에 관계없이, 웹 서비스 시작 때 생성되서, 웹 서비스가 종료될때까지 유지된다. Singleton이란 이름에 걸맞게, 클라이언트가 아무리 많이 붙어도 오직 1개의 서비스만 존재하게 된다.
AddScoped는 클라이언트의 Request 시작부터, Response 종료까지 유지된다. 각 클라이언트마다 존재하므로, 연결되는 클라이언트 수 만큼 존재하게 될 수 있다.
AddTransient는 의존성 주입한 객체마다 독립적인데, 그냥 간단한 교육용 예제 서비스에선 AddScoped와 구분이 잘 안갈 수 있을 것이다.
말로 설명하는 것보단 예제가 와닿을 수 있으므로 ASP.NET MVC 프로젝트를 생성하고 실습해보자.
(아니면 소스코드를 직접 받아봐도 된다.)
https://github.com/ddochea0314/DotNETExamples/tree/main/Web/ServiceLifeCycle
1. GuidService 추가
프로젝트에 Services 폴더를 추가하고 아래 소스를 추가하자.
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace ServiceLifeCycle.Serivces { public class GuidService { private Guid _guid; public GuidService() { _guid = System.Guid.NewGuid(); } public Guid GetGuid() { return _guid; } } }
2. Startup에 AddSingleton(), AddScoped(), AddTransient() 추가
Startup.cs 에 3가지 함수를 모두 추가하되, AddSingleton을 제외하고 나머지는 주석처리한다. 해당 함수들을 번갈아가며 주석해제 하여 생명주기에 어떤 차이가 있는지 살펴볼 것이다.
public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); services.AddSingleton<GuidService>(); //services.AddScoped<GuidService>(); //services.AddTransient<GuidService>(); }
3. HomeController 변경
프로젝트에 기본 생성된 HomeController에 `GuidService` 소스 추가한다. 이때 GuidService 객체를 2개 주입시킨다.
public class HomeController : Controller { private readonly ILogger<HomeController> _logger; private readonly GuidService _service1; private readonly GuidService _service2; public HomeController(ILogger<HomeController> logger, GuidService service1, GuidService service2) { _logger = logger; _service1 = service1; _service2 = service2; } public IActionResult Index() { ViewBag.Guid1 = _service1.GetGuid(); ViewBag.Guid2 = _service2.GetGuid(); return View(); } public IActionResult Privacy() { return View(); } [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } }
4. View 변경
Views/Home 폴더에 있는 Index.cshtml 을 아래와 같이 수정한다.
@{ ViewData["Title"] = "Home Page"; } <div class="text-center"> <h1 class="display-4">Welcome</h1> <p> 1번째 : @ViewBag.Guid1 </p> <p> 2번째 : @ViewBag.Guid2 </p> <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p> </div>
5. 실행
AddSingleton 함수만 주석해제된 상태인지 Startup.cs에서 확인 한 후, F5 키를 눌러 실행해보자. 아래 스크린샷과는 다른 값이겠지만, 1번째 Guid와 2번째 Guid가 같다는 점은 동일할 것이다.
해당 값은 웹페이지를 새로고침해도 바뀌지 않는다.
실행 종료 후 AddSingleton 을 주석처리 한 뒤, AddScope를 주석해제 하고 재실행해보자. 이미지상에선 Singleton과 차이가 없어보이겠지만, 웹페이지를 새로고침하면 값이 변하는 걸 확인할 수 있다.
마지막으로, AddScope 주석 처리 후 AddTransient 를 주석해제 한 뒤 재실행 해보자.
이번엔 1번째 GUID와 2번째 GUID가 다른 것을 확인할 수 있으며, 새로고침시에도 각기 다른 값이 새로 출력되는 것을 확인할 수 있다.
앞서 설명했듯이 Scoped는 Request 시작부터 Response 완료시까지의 생명주기를 갖는다고 하였다. 따라서 Scoped로 생성된 서비스객체는 "Home" 이라는 웹페이지가 요청된 순간 부터 초기 생성됨과 동시에 초기화된 Guid 값이 페이지 응답이 모두 완료된 순간까지 계속 유지되었으므로, 객체가 아무리 많이 주입(Injection)되었어도 1개의 객체처럼 존재하게 된 것이다.
반면, Transient는 요청,응답 관계없이 사용순간마다 생성되므로, 주입된 2개의 GuidService가 각각 다른 객체로 사용될 수 있었던 것이다.
Singleton은 이름에서 알 수 있듯, 1개만 존재하게 되며 웹서비스 종료순간까지 유지되는 서비스이므로 값이 변하지 않는 것이다.
이것으로 ASP.NET Core의 3가지 서비스 생명주기를 확인하였다.
[2023.03.15] 추가사항
AddScope과 AddTransient 에 대한 차이점을 좀 더 확인할 수 있는 후속 포스트를 작성했습니다.
[ASP.NET Core] AddSingleton(), AddScoped(), AddTransient() 차이점 - 2 :: 또치의 삽질 보관함 (tistory.com)
반응형'.NET > ASP.NET Core' 카테고리의 다른 글
[ASP.NET Core] Serilog 에서 미들웨어를 이용한 모든 Request 로그 기록 설정 (0) 2021.10.12 [ASP.NET Core] 기본 로그를 지우고 Serilog만 나오도록 수정하는 방법 (0) 2021.09.22 [ASP.NET Core] AddController(), AddMvc(), AddControllersWithViews(), AddRazorPages() 차이점 (0) 2021.06.26 [ASP.NET Core] 세상 간편해진 Video/Audio Streaming (0) 2021.04.21 [ASP.NET Core] 개선된 다운로드 예제(feat. ASP.NET을 쓰지 말아야할 이유 1 Stack 추가) (0) 2021.04.15