Program.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. using Application;
  2. using Application.Abstractions.Chat;
  3. using Infrastructure;
  4. using SharedKernel;
  5. using System.Reflection;
  6. using Microsoft.Extensions.Hosting.WindowsServices;
  7. using Serilog;
  8. using Web.Api;
  9. using Web.Api.Extensions;
  10. using Web.Api.Hubs;
  11. using Web.Api.Services;
  12. using Infrastructure.Hubs;
  13. var builder = WebApplication.CreateBuilder(args);
  14. var settings = builder.Configuration.Get<AppSettings>()!;
  15. if (!WindowsServiceHelpers.IsWindowsService())
  16. {
  17. Console.Title = settings.App.Name;
  18. }
  19. Console.WriteLine($"ENV={builder.Environment.EnvironmentName}");
  20. Console.WriteLine($"현재 시간: {DateTime.Now} / {TimeZoneInfo.Local.Id}");
  21. builder.Host.UseWindowsService();
  22. // Serilog — Production에서만 파일 로그
  23. if (builder.Environment.IsProduction())
  24. {
  25. Log.Logger = new LoggerConfiguration()
  26. .ReadFrom.Configuration(builder.Configuration)
  27. .WriteTo.File("logs/webapi-.log",
  28. rollingInterval: RollingInterval.Day,
  29. retainedFileCountLimit: 30,
  30. outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {Message:lj}{NewLine}{Exception}")
  31. .CreateLogger();
  32. builder.Host.UseSerilog();
  33. }
  34. builder.Services.Configure<AppSettings>(builder.Configuration);
  35. builder.Services
  36. .AddApplication()
  37. .AddPresentation()
  38. .AddApiInfrastructure(builder.Configuration);
  39. // CORS
  40. builder.Services.AddCors(options =>
  41. {
  42. options.AddPolicy(settings.CorsPolicy.Name, policy =>
  43. {
  44. policy
  45. .WithOrigins(settings.CorsPolicy.AllowedOrigins.ToArray())
  46. .AllowAnyHeader()
  47. .AllowAnyMethod()
  48. .AllowCredentials()
  49. .SetPreflightMaxAge(TimeSpan.FromSeconds(settings.CorsPolicy.PreflightMaxAgeSeconds));
  50. });
  51. });
  52. // SignalR
  53. builder.Services.AddSignalR();
  54. // Chat
  55. builder.Services.AddSingleton<IChatHubService, ChatHubService>();
  56. builder.Services.AddHostedService<KickSubscriberService>();
  57. // Endpoints
  58. builder.Services.AddEndpoints(Assembly.GetExecutingAssembly());
  59. builder.Logging.AddConsole();
  60. /**
  61. * =======================================================================================================================================================
  62. */
  63. var app = builder.Build();
  64. /**
  65. * =======================================================================================================================================================
  66. */
  67. if (app.Environment.IsDevelopment())
  68. {
  69. app.UseSwagger();
  70. app.UseSwaggerUI();
  71. }
  72. // 상태 확인\
  73. app.MapHealthChecks("/health");
  74. app.UseExceptionHandler();
  75. app.UseCors(settings.CorsPolicy.Name);
  76. app.UseStaticFiles();
  77. app.UseAuthentication();
  78. app.UseAuthorization();
  79. app.MapEndpoints();
  80. app.MapHub<ChatHub>("/hubs/chat");
  81. app.MapHub<AppHub>("/hubs/app");
  82. app.MapHub<DonationHub>("/hubs/donation");
  83. // 서버 시작 시 이전 채팅 접속자 정보 초기화 (stale 연결 제거)
  84. using (var scope = app.Services.CreateScope())
  85. {
  86. await scope.ServiceProvider.GetRequiredService<IChatConnectionTracker>().ClearAllAsync();
  87. }
  88. app.Run();