Athena.Cache.SourceGenerator 1.0.4

There is a newer version of this package available.
See the version list below for details.
dotnet add package Athena.Cache.SourceGenerator --version 1.0.4
                    
NuGet\Install-Package Athena.Cache.SourceGenerator -Version 1.0.4
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Athena.Cache.SourceGenerator" Version="1.0.4">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Athena.Cache.SourceGenerator" Version="1.0.4" />
                    
Directory.Packages.props
<PackageReference Include="Athena.Cache.SourceGenerator">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Athena.Cache.SourceGenerator --version 1.0.4
                    
#r "nuget: Athena.Cache.SourceGenerator, 1.0.4"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Athena.Cache.SourceGenerator@1.0.4
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Athena.Cache.SourceGenerator&version=1.0.4
                    
Install as a Cake Addin
#tool nuget:?package=Athena.Cache.SourceGenerator&version=1.0.4
                    
Install as a Cake Tool

๐Ÿ›๏ธ Athena.Cache

CI NuGet Core Downloads NuGet Redis Downloads License: MIT

Smart caching library for ASP.NET Core with automatic query parameter key generation and table-based cache invalidation.

Athena.Cache๋Š” ASP.NET Core ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ„ํ•œ ์ง€๋Šฅํ˜• ์บ์‹ฑ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ ์บ์‹œ ํ‚ค๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ” ๋ณ€๊ฒฝ ์‹œ ๊ด€๋ จ ์บ์‹œ๋ฅผ ์ž๋™์œผ๋กœ ๋ฌดํšจํ™”ํ•ฉ๋‹ˆ๋‹ค.

โœจ ์ฃผ์š” ๊ธฐ๋Šฅ

  • ๐ŸŽฏ Source Generator: ์ปดํŒŒ์ผ ํƒ€์ž„์— ์บ์‹œ ์„ค์ • ์ž๋™ ์ƒ์„ฑ, AOT ํ˜ธํ™˜
  • ๐Ÿ”‘ ์ž๋™ ์บ์‹œ ํ‚ค ์ƒ์„ฑ: ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ โ†’ SHA256 ํ•ด์‹œ ํ‚ค ์ž๋™ ๋ณ€ํ™˜
  • ๐Ÿ—‚๏ธ ํ…Œ์ด๋ธ” ๊ธฐ๋ฐ˜ ๋ฌดํšจํ™”: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ” ๋ณ€๊ฒฝ ์‹œ ๊ด€๋ จ ์บ์‹œ ์ž๋™ ์‚ญ์ œ
  • ๐Ÿš€ ๋‹ค์ค‘ ๋ฐฑ์—”๋“œ ์ง€์›: MemoryCache, Redis, Valkey ์ง€์›
  • ๐ŸŽจ ์„ ์–ธ์  ์บ์‹ฑ: [AthenaCache], [CacheInvalidateOn] ์–ดํŠธ๋ฆฌ๋ทฐํŠธ
  • โšก ๊ณ ์„ฑ๋Šฅ: ๋Œ€์šฉ๋Ÿ‰ ํŠธ๋ž˜ํ”ฝ ํ™˜๊ฒฝ์— ์ตœ์ ํ™”, Primary Constructor ์‚ฌ์šฉ
  • ๐Ÿ”ง ์‰ฌ์šด ํ†ตํ•ฉ: ๋‹จ์ผ ํŒจํ‚ค์ง€ ์„ค์น˜๋กœ ๋ชจ๋“  ๊ธฐ๋Šฅ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • ๐Ÿงช ์™„์ „ํ•œ ํ…Œ์ŠคํŠธ: ํฌ๊ด„์ ์ธ ๋‹จ์œ„ ๋ฐ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ

๐Ÿš€ ๋น ๋ฅธ ์‹œ์ž‘

์„ค์น˜

# ๊ธฐ๋ณธ ํŒจํ‚ค์ง€ (MemoryCache + Source Generator ํฌํ•จ)
dotnet add package Athena.Cache.Core

# Redis ์ง€์› (์„ ํƒ์‚ฌํ•ญ)
dotnet add package Athena.Cache.Redis

๐ŸŽฏ ํ†ตํ•ฉ ํŒจํ‚ค์ง€: Athena.Cache.Core๋งŒ ์„ค์น˜ํ•˜๋ฉด Source Generator๊ฐ€ ์ž๋™์œผ๋กœ ํฌํ•จ๋˜์–ด ์ปดํŒŒ์ผ ํƒ€์ž„์— ์บ์‹œ ์„ค์ •์„ ์ž๋™ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ์„ค์ •

// Program.cs
using Athena.Cache.Core.Extensions;

var builder = WebApplication.CreateBuilder(args);

// ๊ฐœ๋ฐœ ํ™˜๊ฒฝ (MemoryCache)
builder.Services.AddAthenaCacheComplete(options => {
    options.Namespace = "MyApp_DEV";
    options.DefaultExpirationMinutes = 30;
    options.Logging.LogCacheHitMiss = true; // ์บ์‹œ ํžˆํŠธ/๋ฏธ์Šค ๋กœ๊น…
});

// ์šด์˜ ํ™˜๊ฒฝ (Redis)
builder.Services.AddAthenaCacheRedisComplete(
    athena => {
        athena.Namespace = "MyApp_PROD";
        athena.DefaultExpirationMinutes = 60;
    },
    redis => {
        redis.ConnectionString = "localhost:6379";
        redis.DatabaseId = 1;
    });

var app = builder.Build();

// ๐Ÿ”ง ๋ฏธ๋“ค์›จ์–ด ์ถ”๊ฐ€ (์ค‘์š”: ๋ผ์šฐํŒ… ํ›„, ์ปจํŠธ๋กค๋Ÿฌ ์ „์— ์ถ”๊ฐ€)
app.UseRouting();
app.UseAthenaCache();  // ๋ผ์šฐํŒ… ํ›„์— ์ถ”๊ฐ€
app.MapControllers();

app.Run();

์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์‚ฌ์šฉ

using Athena.Cache.Core.Attributes;
using Athena.Cache.Core.Enums;

[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    private readonly IUserService _userService;

    public UsersController(IUserService userService)
    {
        _userService = userService;
    }

    [HttpGet]
    [AthenaCache(ExpirationMinutes = 30)]
    [CacheInvalidateOn("Users")]
    public async Task<ActionResult<IEnumerable<UserDto>>> GetUsers(
        [FromQuery] string? search = null,
        [FromQuery] int page = 1)
    {
        // ๐Ÿš€ Source Generator๊ฐ€ ์ปดํŒŒ์ผ ํƒ€์ž„์— ์ด ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋ฅผ ์Šค์บ”ํ•˜์—ฌ
        // ์บ์‹œ ์„ค์ •์„ ์ž๋™ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋ณ„๋„ ์„ค์ • ๋ถˆํ•„์š”!
        var users = await _userService.GetUsersAsync(search, page);
        return Ok(users);
    }

    [HttpGet("{id}")]
    [AthenaCache(ExpirationMinutes = 60)]
    [CacheInvalidateOn("Users")]
    [CacheInvalidateOn("Orders", InvalidationType.Pattern, "User_*")]
    public async Task<ActionResult<UserDto>> GetUser(int id)
    {
        var user = await _userService.GetUserByIdAsync(id);
        if (user == null) return NotFound();
        return Ok(user);
    }

    [HttpPost]
    public async Task<ActionResult<UserDto>> CreateUser([FromBody] User user)
    {
        var createdUser = await _userService.CreateUserAsync(user);
        // Users ํ…Œ์ด๋ธ” ๊ด€๋ จ ์บ์‹œ๊ฐ€ ์ž๋™ ๋ฌดํšจํ™”๋จ
        return CreatedAtAction(nameof(GetUser), new { id = createdUser.Id }, createdUser);
    }

    // ์บ์‹œ ๋น„ํ™œ์„ฑํ™” ์˜ˆ์ œ
    [HttpGet("no-cache")]
    [NoCache]  // ์ด ์•ก์…˜์€ ์บ์‹ฑํ•˜์ง€ ์•Š์Œ
    public async Task<ActionResult<IEnumerable<UserDto>>> GetUsersWithoutCache()
    {
        var users = await _userService.GetUsersAsync();
        return Ok(users);
    }
}

๐Ÿ“Š ์บ์‹œ ์ƒํƒœ ํ™•์ธ

Athena.Cache๋Š” HTTP ํ—ค๋”๋ฅผ ํ†ตํ•ด ์บ์‹œ ์ƒํƒœ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

# ์ฒซ ๋ฒˆ์งธ ์š”์ฒญ (์บ์‹œ ๋ฏธ์Šค)
curl -v http://localhost:5000/api/users
# ์‘๋‹ต ํ—ค๋”: X-Athena-Cache: MISS

# ๋‘ ๋ฒˆ์งธ ์š”์ฒญ (์บ์‹œ ํžˆํŠธ)
curl -v http://localhost:5000/api/users  
# ์‘๋‹ต ํ—ค๋”: X-Athena-Cache: HIT

๐Ÿ› ๏ธ ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ

์ปค์Šคํ…€ ์บ์‹œ ํ‚ค

[AthenaCache(
    ExpirationMinutes = 45,
    CustomKeyPrefix = "UserStats",
    ExcludeParameters = new[] { "debug", "trace" }
)]
public async Task<IActionResult> GetUserStatistics(int userId, bool debug = false)
{
    // debug ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ์บ์‹œ ํ‚ค ์ƒ์„ฑ์—์„œ ์ œ์™ธ๋จ
    return Ok(stats);
}

ํŒจํ„ด ๊ธฐ๋ฐ˜ ๋ฌดํšจํ™”

[CacheInvalidateOn("Users", InvalidationType.All)]                      // ๋ชจ๋“  Users ๊ด€๋ จ ์บ์‹œ
[CacheInvalidateOn("Orders", InvalidationType.Pattern, "User_*")]       // User_* ํŒจํ„ด ์บ์‹œ
[CacheInvalidateOn("Products", InvalidationType.Related, "Categories")] // ์—ฐ๊ด€ ํ…Œ์ด๋ธ”๊นŒ์ง€
public async Task<IActionResult> GetUserOrders(int userId) { ... }

์ˆ˜๋™ ์บ์‹œ ๊ด€๋ฆฌ

public class UserService
{
    private readonly IAthenaCache _cache;
    private readonly ICacheInvalidator _invalidator;

    public UserService(IAthenaCache cache, ICacheInvalidator invalidator)
    {
        _cache = cache;
        _invalidator = invalidator;
    }

    public async Task InvalidateUserCaches(int userId)
    {
        // ํŠน์ • ์‚ฌ์šฉ์ž ๊ด€๋ จ ์บ์‹œ๋งŒ ์‚ญ์ œ
        await _invalidator.InvalidateByPatternAsync($"User_{userId}_*");
    }

    public async Task<CacheStatistics> GetCacheStats()
    {
        return await _cache.GetStatisticsAsync();
    }
}

๐Ÿ“Š ์„ฑ๋Šฅ

  • ๋†’์€ ์ฒ˜๋ฆฌ๋Ÿ‰: Redis ๊ธฐ์ค€ 10,000+ requests/second
  • ๋‚ฎ์€ ์ง€์—ฐ์‹œ๊ฐ„: ์บ์‹œ ํ‚ค ์ƒ์„ฑ 1ms ๋ฏธ๋งŒ
  • ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ: ์ตœ์ ํ™”๋œ ์ง๋ ฌํ™” ๋ฐ ์••์ถ•
  • ํ™•์žฅ ๊ฐ€๋Šฅ: ๋‹ค์ค‘ ์ธ์Šคํ„ด์Šค ๋ถ„์‚ฐ ๋ฌดํšจํ™” ์ง€์›

๐Ÿ”ง ์„ค์ • ์˜ต์…˜

์ „์—ญ ์„ค์ •

services.AddAthenaCacheComplete(options => {
    options.Namespace = "MyApp";              // ๋„ค์ž„์ŠคํŽ˜์ด์Šค (ํ™˜๊ฒฝ ๋ถ„๋ฆฌ)
    options.VersionKey = "v1.0";              // ๋ฒ„์ „ ํ‚ค (๋ฐฐํฌ ์‹œ ์บ์‹œ ๋ถ„๋ฆฌ)
    options.DefaultExpirationMinutes = 30;    // ๊ธฐ๋ณธ ๋งŒ๋ฃŒ ์‹œ๊ฐ„
    options.MaxRelatedDepth = 3;              // ์—ฐ์‡„ ๋ฌดํšจํ™” ์ตœ๋Œ€ ๊นŠ์ด
    options.StartupCacheCleanup = CleanupMode.ExpireShorten; // ์‹œ์ž‘ ์‹œ ์ •๋ฆฌ ๋ฐฉ์‹
    
    // ๋กœ๊น… ์„ค์ •
    options.Logging.LogCacheHitMiss = true;   // ํžˆํŠธ/๋ฏธ์Šค ๋กœ๊น…
    options.Logging.LogInvalidation = true;   // ๋ฌดํšจํ™” ๋กœ๊น…
    
    // ์—๋Ÿฌ ์ฒ˜๋ฆฌ
    options.ErrorHandling.SilentFallback = true; // ์กฐ์šฉํ•œ ํด๋ฐฑ
});

Redis ์„ค์ •

services.AddAthenaCacheRedisComplete(
    athena => { /* Athena ์„ค์ • */ },
    redis => {
        redis.ConnectionString = "localhost:6379";
        redis.DatabaseId = 1;
        redis.KeyPrefix = "MyApp";
        redis.BatchSize = 1000;
        redis.ConnectTimeoutSeconds = 5;
        redis.RetryCount = 3;
    });

๐Ÿงช ํ…Œ์ŠคํŠธ

# ๋ชจ๋“  ํ…Œ์ŠคํŠธ ์‹คํ–‰
dotnet test

# ์ปค๋ฒ„๋ฆฌ์ง€ ํฌํ•จ
dotnet test --collect:"XPlat Code Coverage"

# ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ (Redis ํ•„์š”)
docker run -d -p 6379:6379 redis:7-alpine
dotnet test --filter Category=Integration

๐Ÿ—๏ธ ์•„ํ‚คํ…์ฒ˜

ํ•ต์‹ฌ ์ปดํฌ๋„ŒํŠธ

  • ๐ŸŽฏ Source Generator: ์ปดํŒŒ์ผ ํƒ€์ž„์— Controller ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋ฅผ ์Šค์บ”ํ•˜์—ฌ ์บ์‹œ ์„ค์ • ์ž๋™ ์ƒ์„ฑ
  • ICacheConfigurationRegistry: ์ƒ์„ฑ๋œ ์บ์‹œ ์„ค์ •์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ
  • ICacheKeyGenerator: ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ โ†’ ์บ์‹œ ํ‚ค ๋ณ€ํ™˜
  • ICacheInvalidator: ํ…Œ์ด๋ธ” ๊ธฐ๋ฐ˜ ์บ์‹œ ๋ฌดํšจํ™” ๊ด€๋ฆฌ
  • IAthenaCache: ์บ์‹œ ์ œ๊ณต์ž ์ถ”์ƒํ™” (Memory/Redis/Valkey)
  • AthenaCacheMiddleware: HTTP ์š”์ฒญ ๊ฐ€๋กœ์ฑ„๊ธฐ ๋ฐ ์บ์‹ฑ (Primary Constructor ์‚ฌ์šฉ)

๋™์ž‘ ์›๋ฆฌ

  1. ๐Ÿ”ง ์ปดํŒŒ์ผ ํƒ€์ž„: Source Generator๊ฐ€ Controller๋ฅผ ์Šค์บ”ํ•˜์—ฌ ์บ์‹œ ์„ค์ • ํด๋ž˜์Šค ์ž๋™ ์ƒ์„ฑ
  2. ๐Ÿš€ ๋Ÿฐํƒ€์ž„ ์ดˆ๊ธฐํ™”: ์ƒ์„ฑ๋œ ์„ค์ •์ด ์žˆ์œผ๋ฉด ์‚ฌ์šฉ, ์—†์œผ๋ฉด Reflection ๋ฐฑ์—… ์‚ฌ์šฉ
  3. ๐Ÿ“ก ์š”์ฒญ ๊ฐ€๋กœ์ฑ„๊ธฐ: ๋ฏธ๋“ค์›จ์–ด๊ฐ€ GET ์š”์ฒญ์„ ๋ผ์šฐํŒ… ์ •๋ณด์™€ ํ•จ๊ป˜ ๊ฐ€๋กœ์ฑ”
  4. ๐Ÿ”‘ ํ‚ค ์ƒ์„ฑ: ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ •๋ ฌํ•˜์—ฌ SHA256 ํ•ด์‹œ ์ƒ์„ฑ
  5. ๐Ÿ’พ ์บ์‹œ ํ™•์ธ: ์ƒ์„ฑ๋œ ํ‚ค๋กœ ์บ์‹œ์—์„œ ์‘๋‹ต ์กฐํšŒ
  6. ๐Ÿ“ฆ ์‘๋‹ต ์บ์‹ฑ: ์บ์‹œ ๋ฏธ์Šค ์‹œ ์‘๋‹ต์„ ์บ์‹œ์— ์ €์žฅ ํ›„ ํ…Œ์ด๋ธ” ์ถ”์  ๋“ฑ๋ก
  7. ๐Ÿ”„ ๋ฌดํšจํ™”: ํ…Œ์ด๋ธ” ๋ณ€๊ฒฝ ์‹œ ๊ด€๋ จ ์บ์‹œ ์ž๋™ ์‚ญ์ œ

๐ŸŽฏ Source Generator ์žฅ์ 

  • โšก ์„ฑ๋Šฅ: ๋Ÿฐํƒ€์ž„ Reflection ๋ถˆํ•„์š”, ์ปดํŒŒ์ผ ํƒ€์ž„ ์ตœ์ ํ™”
  • ๐Ÿ›ก๏ธ ํƒ€์ž… ์•ˆ์ „์„ฑ: ์ปดํŒŒ์ผ ํƒ€์ž„์— ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ๊ฒ€์ฆ
  • ๐Ÿš€ AOT ํ˜ธํ™˜: Native AOT ๋ฐฐํฌ ์ง€์›
  • ๐Ÿ”ง ์ž๋™ ๊ด€๋ฆฌ: ๋ณ„๋„ ์„ค์ • ํŒŒ์ผ ๋ถˆํ•„์š”, ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋งŒ์œผ๋กœ ์™„์„ฑ

๐Ÿ”„ ์บ์‹œ ๋ฌดํšจํ™” ์ „๋žต

1. ์ฆ‰์‹œ ๋ฌดํšจํ™” (Immediate)

[CacheInvalidateOn("Users", InvalidationType.All)]

2. ํŒจํ„ด ๋ฌดํšจํ™” (Pattern-based)

[CacheInvalidateOn("Users", InvalidationType.Pattern, "User_*")]
[CacheInvalidateOn("Users", InvalidationType.Related, "Orders", "Profiles")]

๐Ÿ“ฆ ์ถ”๊ฐ€ ํŒจํ‚ค์ง€

# Source Generator (์„ ํƒ์  - Core์— ํฌํ•จ๋˜์ง€๋งŒ ๋…๋ฆฝ ์„ค์น˜ ๊ฐ€๋Šฅ)
dotnet add package Athena.Cache.SourceGenerator

# ๋ถ„์„ ๋ฐ ๋ชจ๋‹ˆํ„ฐ๋ง (์„ ํƒ์ )
dotnet add package Athena.Cache.Analytics

๐Ÿ“‹ ๋ฆด๋ฆฌ์ฆˆ ์ •๋ณด: ์ž์„ธํ•œ ๋ฆด๋ฆฌ์ฆˆ ํ”„๋กœ์„ธ์Šค์™€ ๋ฒ„์ „ ๊ด€๋ฆฌ ์ „๋žต์€ RELEASE.md๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

๐Ÿค ๊ธฐ์—ฌํ•˜๊ธฐ

  1. ์ €์žฅ์†Œ ํฌํฌ
  2. ๊ธฐ๋Šฅ ๋ธŒ๋žœ์น˜ ์ƒ์„ฑ (git checkout -b feature/amazing-feature)
  3. ๋ณ€๊ฒฝ์‚ฌํ•ญ ์ปค๋ฐ‹ (git commit -m 'Add amazing feature')
  4. ๋ธŒ๋žœ์น˜์— ํ‘ธ์‹œ (git push origin feature/amazing-feature)
  5. Pull Request ์˜คํ”ˆ

๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์„ค์ •

git clone https://github.com/jhbrunoK/Athena.Cache.git
cd Athena.Cache
dotnet restore
dotnet build
dotnet test

๐Ÿ“ ๋ผ์ด์„ผ์Šค

์ด ํ”„๋กœ์ ํŠธ๋Š” MIT ๋ผ์ด์„ผ์Šค ํ•˜์— ๋ฐฐํฌ๋ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ LICENSE ํŒŒ์ผ์„ ์ฐธ์กฐํ•˜์„ธ์š”.

๐Ÿ™ ๊ฐ์‚ฌ์˜ ๋ง

  • ์ „๋žต๊ณผ ์ง€ํ˜œ์˜ ์—ฌ์‹  ์•„ํ…Œ๋‚˜์—์„œ ์˜๊ฐ์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค
  • ASP.NET Core ์ปค๋ฎค๋‹ˆํ‹ฐ๋ฅผ ์œ„ํ•ด ์ œ์ž‘๋˜์—ˆ์Šต๋‹ˆ๋‹ค
  • ๋ชจ๋“  ๊ธฐ์—ฌ์ž๋ถ„๋“ค๊ป˜ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค

๐Ÿ“ž ์ง€์› ๋ฐ ๋ฌธ์˜

  • ๐Ÿ› ๋ฒ„๊ทธ ๋ฆฌํฌํŠธ: GitHub Issues
  • ๐Ÿ’ก ๊ธฐ๋Šฅ ์š”์ฒญ: GitHub Discussions
  • ๐Ÿ“ง ์ด๋ฉ”์ผ: bobhappy2000@gmail.com

โค๏ธ ๊ณ ์„ฑ๋Šฅ ASP.NET Core ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ„ํ•ด ์ œ์ž‘๋˜์—ˆ์Šต๋‹ˆ๋‹ค

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.9 68 8/2/2025
1.1.6 107 7/27/2025
1.1.5 107 7/27/2025
1.1.3 105 7/27/2025
1.0.4 119 7/27/2025

v1.0.4: Source Generator for compile-time cache configuration