using System.Text; using Microsoft.AspNetCore.Mvc; using economy.Controllers.Price.Global; namespace economy.Controllers { // sitemap.xml 생성 // // 기존에는 wwwroot/sitemap.xml 정적 파일을 외부 생성기로 만들어 두었는데, // 같은 페이지의 쿼리스트링 변형(페이지네이션 41개, 조회기간/코드 파라미터 등)이 대부분을 차지해 // 98건 중 실제 고유 페이지는 20여 개뿐이었고 lastmod 도 2025-08-10 에 고정되어 있었다. // 여기서는 정규 URL 만 내보낸다. public class SitemapController : Controller { // 리버스 프록시 뒤에서는 Request.Scheme 이 http 로 들어올 수 있어 설정값을 우선 사용한다. private const string DefaultBaseUrl = "https://economy.web.or.kr"; // 파라미터가 없는 정규 경로만 담는다. // 제외 대상: // - Business/Search, Whois/Search : [HttpPost] 전용이라 GET 은 405 // - Home/Error : 오류 페이지 // - Price/Domestic/Item/Detail/{item} : 품목 코드가 외부 API 응답에서 오므로 목록을 고정할 수 없다. // Item/List 페이지의 링크를 통해 크롤링된다. private static readonly string[] StaticPaths = { "/", "/Home/Privacy", "/Business/Number", "/Days/Anniversary", "/Days/Holiday", "/Days/Seasonal", "/Days/Sundry", "/FIFA", "/Financial/Exchange", "/Financial/Interest", "/Financial/International", "/Lotto", "/Whois", "/Price/Domestic/Emission", "/Price/Domestic/Flower", "/Price/Domestic/Gold", "/Price/Domestic/Oil", "/Price/Domestic/Item/List.cshtml", "/Price/Global/NaturalGas" }; private readonly IConfiguration _configuration; public SitemapController(IConfiguration configuration) { _configuration = configuration; } [HttpGet("/sitemap.xml")] [HttpHead("/sitemap.xml")] [ResponseCache(Duration = 3600, Location = ResponseCacheLocation.Any)] public IActionResult Index() { var baseUrl = (_configuration["Site:BaseUrl"] ?? DefaultBaseUrl).TrimEnd('/'); // 시세 페이지는 매일 갱신되므로 날짜 단위로만 표기한다. var today = DateTime.UtcNow.ToString("yyyy-MM-dd"); var builder = new StringBuilder(); builder.AppendLine(@""); builder.AppendLine(@""); foreach (var path in StaticPaths) { AppendUrl(builder, baseUrl + path, today, "daily", path == "/" ? "1.0" : "0.8"); } // 국제 원자재 시세. 품목 목록은 GlobalController.CommodityMap 을 그대로 읽어 // 라우트가 실제로 처리하는 값과 어긋나지 않게 한다. foreach (var commodity in GlobalController.CommodityMap.Keys.OrderBy(key => key, StringComparer.OrdinalIgnoreCase)) { AppendUrl(builder, $"{baseUrl}/Price/Global/{commodity}", today, "daily", "0.8"); } builder.AppendLine(""); return Content(builder.ToString(), "application/xml", Encoding.UTF8); } private static void AppendUrl(StringBuilder builder, string location, string lastModified, string changeFrequency, string priority) { builder.AppendLine(" "); builder.AppendLine($" {location}"); builder.AppendLine($" {lastModified}"); builder.AppendLine($" {changeFrequency}"); builder.AppendLine($" {priority}"); builder.AppendLine(" "); } } }