λͺ¨λ“ˆ 별 Configuration

닷넷은 μ•±μ˜ μž¬μ‹œλ™λ§ŒμœΌλ‘œ 앱을 섀정을 λ³€κ²½ν•  수 μžˆλŠ” Configuration APIλ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€.

기본적으둜 ν™˜κ²½ λ³€μˆ˜μ™€, β€œappsettings.json” νŒŒμΌμ„ μΈμ‹ν•˜κ²Œλ” μ„€μ •λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

μ‹œμŠ€ν…œμ„ μ•„λž˜μ™€ 같이 관심사 λ³„λ‘œ λ‚˜λˆˆλ‹€κ³  ν•  λ•Œ,

  • WebApp
  • Infra.Database

각 관심사λ₯Ό μ±…μž„μ§€λŠ” νŒ€ λ³„λ‘œ 업무 λΆ„μž₯이 μ΄λ€„μ§ˆ κ²ƒμž…λ‹ˆλ‹€.
예λ₯Ό λ“€λ©΄, WebApp 은 μ›ΉνŒ€, Infra.Database λŠ” λ°μ΄ν„°λ² μ΄μŠ€ νŒ€ 처럼 말이죠.

μœ„μ™€ 같이 업무 λΆ„μž₯을 ν•˜μ§€ μ•Šλ”λΌλ„, 각 λͺ¨λ“ˆμ— κ΄€ν•œ 섀정은 각 λͺ¨λ“ˆμ— λ‘λŠ” 게, μ•„λ¬΄λž˜λ„ 관리 ν¬μΈνŠΈκ°€ λͺ…ν™•ν•˜κ²Œ λ©λ‹ˆλ‹€.

  • WebApp
    - appsettings.json
  • Infra.Database
    - dbsettings.json

λͺ¨λ“  μ„€μ • νŒŒμΌμ€ μ—”νŠΈλ¦¬ 포인트인 WebApp의 λΉŒλ“œ 결과물의 루트 폴더에 μ €μž₯λ©λ‹ˆλ‹€.

\bin\release\.net8.0\appsettings.json
\bin\release\.net8.0\dbsettings.json

이 경우, ν•˜μœ„ λͺ¨λ“ˆμ— μžˆλŠ” 섀정이 μ†ŒλΉ„λ˜λŠ” 방식은 두 κ°€μ§€μž…λ‹ˆλ‹€.

λ‚΄λΆ€ μ†ŒλΉ„

ν•˜μœ„ λͺ¨λ“ˆμ— κ΄€ν•œ 섀정이기 λ•Œλ¬Έμ—, λ‹€λ₯Έ λͺ¨λ“ˆμ— 이 섀정을 λ…ΈμΆœν•  ν•„μš”κ°€ μ—†λŠ” 게 일반적이라 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

이 경우, dbsettings.json μ—μ„œ 섀정을 κ°€μ Έ μ˜€λŠ” 건 μ˜ˆμƒ μ™Έλ‘œ μ‰½μŠ΅λ‹ˆλ‹€.

using Microsoft.Extensions.Configuration; // νŒ¨ν‚€μ§€ ν•„μš”.

//...

var localConfiguraiton = new Configuration()
   .AddJsonFile("dbsettings.json")
   .Build();

var subSectionValue = localConfiguraiton.GetRequiredSection("{TopSection}:{SubSection}")?.Value;

// subSectionValue  μ†ŒλΉ„ μ½”λ“œ.

μ£Όμ˜ν•  점은, new Configuration() λŠ” λ°˜λ“œμ‹œ ν•˜μœ„ λͺ¨λ“ˆμ—μ„œ μ‹€ν–‰λ˜μ–΄μ•Ό κ·Έ λͺ¨λ“ˆμ—μ„œ νŒŒμΌμ„ μ°ΎμŠ΅λ‹ˆλ‹€.

μ™ΈλΆ€ 곡개

μ™ΈλΆ€ κ³΅κ°œν•˜λŠ” 방법은 μ–΄λ”˜κ°€ 값을 λ…ΈμΆœν•˜μ—¬, 이 λͺ¨λ“ˆμ„ μ°Έμ‘°ν•˜λŠ” λ‹€λ₯Έ λͺ¨λ“ˆμ—μ„œ 읽어 κ°€κ²Œ λ§Œλ“€λ©΄ λ©λ‹ˆλ‹€.

namespace Infra.Database

public static class DbSettings
{
    public static string? Value { get; internal set; }
}
// μ„€μ •
var localConfiguraiton = new Configuration()
   .AddJsonFile("dbsettings.json")
   .Build();

DbSettings.Value = localConfiguraiton.GetRequiredSection("{TopSection}:{SubSection}")?.Value;

그런데, 이 λ°©λ²•μ˜ λ¬Έμ œλŠ” DbSettings.Value 에 μ ‘κ·Όν•˜λŠ” μ‹œμ μ— 따라, 섀정값을 받을 μˆ˜λ„ 있고 받지 λͺ»ν•  μˆ˜λ„ μžˆλ‹€(μ„€μ •ν•˜λŠ” μ½”λ“œλ³΄λ‹€ μ ‘κ·Όν•˜λŠ” μ½”λ“œκ°€ λ¨Όμ € μ‹€ν–‰λ˜λŠ” 경우)λŠ” μ μž…λ‹ˆλ‹€.

κ·Έλ ‡λ‹€κ³  μ•„λž˜μ™€ 같이 μ²˜λ¦¬ν•˜λ©΄, νŒŒμΌμ— μ ‘κ·Ό μ½”λ“œκ°€ 항상 μ‹€ν–‰λ˜κΈ° λ•Œλ¬Έμ—, μ„±λŠ₯ λ¬Έμ œκ°€ λ°œμƒν•©λ‹ˆλ‹€.
(κ·ΈλŸ¬λ‚˜, μ μ‹œμ„±μ€ μ’‹μ•„ μ§‘λ‹ˆλ‹€.)

namespace Infra.Database

public static class DbSettings
{
   private static IConfigurationRoot Config = new Configuration()
         .AddJsonFile("dbsettings.json")
         .Build();

   public static string? Value => Config      
         .GetSection("{TopSection}:{SubSection}").Value
}

Dependency Injection

섀정을 객체둜 μΊ‘μŠν™”ν•΄μ„œ, μ»¨ν…Œμ΄ν„°μ— λ“±λ‘ν•˜λ©΄, μ•± μ‹€ν–‰ μ΄ˆκΈ°μ— λ“±λ‘λ˜κΈ° λ•Œλ¬Έμ—, μ„±λŠ₯ λ¬Έμ œλ‚˜ μ ‘κ·Ό μ‹œμ°¨ 문제λ₯Ό ν•΄κ²°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μΊ‘μŠν™”

namespace Infra.Database.Contracts;

public class TopSection
{
   public string? SubSection { get; set; }
}

μ„œλΉ„μŠ€ 등둝

μƒμœ„ λͺ¨λ“ˆμ˜ DI에 μ„€μ • 객체λ₯Ό Singleton 으둜 λ“±λ‘ν•©λ‹ˆλ‹€.

using Microsoft.Extensions.Configuration; // νŒ¨ν‚€μ§€ ν•„μš”
using Microsoft.Extensions.DependencyInjection; // νŒ¨ν‚€μ§€ ν•„μš”
using Infra.Database.Contracts;

namespace Infra.Database;

public static class IServiceCollectonExtensions
{
   public static IServiceCollection AddInfraDatabaseServices(this IServiceCollection services)
   {
      var localConfiguraiton = new Configuration()
         .AddJsonFile("dbsettings.json")
         .Build();

      var topSection = new TopSection
      {
         SubSection = localConfiguraiton.GetRequiredSection("{TopSection}:SubSection}")?.Value,
      }

      service.AddSingleton(sp => topSection);

      // μΆ”κ°€ 등둝

      return services;
   }
}

μƒμœ„ λͺ¨λ“ˆ

// program.cs
using Infra.Database;
// ...
 builder.Services.AddInfraDatabaseServices();

// ...
// minimal api

app.MapGet("/my-page", (TopSection dbSetttings) => {
   // ...
});
@*MyPage.razor*@
@inject TopSection DbSettings

@*
....
*@
4개의 μ’‹μ•„μš”

κ΅¬μ„±μ˜ best practiceλŠ” μ˜΅μ…˜ νŒ¨ν„΄μ„ μ‚¬μš©ν•˜λŠ” κ±΄λ°μš”.

λŸ°νƒ€μž„μ— ꡬ성 값을 λ°”κΏ€ 수 μžˆμ„ μ •λ„λ‘œ κ°•λ ₯ν•œ κΈ°λŠ₯을 μ œκ³΅ν•©λ‹ˆλ‹€.

3개의 μ’‹μ•„μš”

λ‹€λ₯Έ λͺ¨λ“ˆμ˜ μ„€μ • 값을 μ˜΅μ…˜ νŒ¨ν„΄μœΌλ‘œ κ΅¬ν˜„ν•΄λ³΄μ‹  적이 μžˆμœΌμ‹ μ§€μš”?

예λ₯Ό λ“€λ©΄, 예제의 infra.Database λͺ¨λ“ˆμ˜ dbsettings.json 을 WebAppμ—μ„œ μ˜΅μ…˜ λ°”μΈλ”©ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.
해보셨닀면, μ½”λ“œ 곡유 λΆ€νƒλ“œλ¦½λ‹ˆλ‹€.

μ˜΅μ…˜ νŒ¨ν„΄ 적용 이전에, λ‹€λ₯Έ λͺ¨λ“ˆμ—μ„œ ꡬ성을 κ°€μ Έ μ˜¨λ‹€λŠ” 게 생각보닀 κ°„λ‹¨ν•˜μ§€ μ•Šμ•„, κ°„μ†Œν•œ 방식을 μ†Œκ°œν•œ κ²ƒμž…λ‹ˆλ‹€.

1개의 μ’‹μ•„μš”