컨테이너를 사용하여... 크리스마스 선물 가격을 추적하시나요?
크리스마스가 코앞으로 다가왔습니다. 사랑하는 사람을 위한 완벽한 선물을 찾는 즐거운 일이 다가오고 있습니다. 저와 같은 사람이라면 좋은 상품을 구매하는 것을 좋아할 것입니다. 하지만 연휴 동안 치솟는 인기 품목 가격을 탐색하는 것은 실제 썰매를 타는 것처럼 느껴질 수 있습니다. 흥미롭지만 약간 부담스럽습니다! 올해는 매일 가격을 확인하느라 정신없게 지내는 대신 기술 능력을 잘 활용하고 프로세스를 자동화하기로 결정했습니다.

소프트웨어 개발자이자 기술을 활용하여 일상적인 문제를 해결하는 데 열정을 갖고 있는 사람으로서 저는 가격 확인 프로세스를 자동화하는 방법을 찾았습니다. 매일 수동으로 여러 온라인 매장을 방문하여 가격을 비교하는 대신, 이를 대신해 줄 수 있는 시스템을 만들기로 결정했습니다. 이를 통해 시간을 절약할 수 있을 뿐만 아니라 매일 확인하는 스트레스 없이 최고의 거래를 얻을 수 있습니다.
가격 모니터링을 자동화하는 이유는 무엇입니까?
가격 모니터링을 자동화하는 것은 손가락 하나 까딱하지 않고도 최고의 거래를 얻을 수 있도록 24시간 내내 일하는 산타의 요정 팀을 갖는 것과 같습니다. 당신이 그것을 좋아할 이유는 다음과 같습니다:
- 비싼 품목: 우리 모두는 크리스마스 선물이 상당히 비쌀 수 있다는 것을 알고 있습니다. 특히 장치와 장난감이 목록에 있을 때 더욱 그렇습니다. 이것에 대한 비용을 절약하는 것은 재고에서 마지막 나무 꼭대기를 찾는 것만큼 만족스러울 수 있습니다.
- 일일 확인: 매일 가격을 확인할 시간(또는 인내심)이 있는 사람은 누구입니까? 나 말고!
- 자동화: 나눔이라는 명절 정신을 받아들이고 자신에게 효율성을 선물하세요.
- 정확성: 자동화는 루돌프의 코처럼 정확한 가격 확인을 보장합니다.
핵심 기술
나만의 산타 도우미를 만들기 위해 저는 몇 가지 핵심 기술을 사용하기로 결정했습니다.
컨테이너
컨테이너는 소프트웨어의 크리스마스 포장과 같습니다. 애플리케이션을 모든 기능(종속성)과 함께 묶어 신선한 눈 속에서 썰매를 타는 것처럼 모든 것이 원활하게 실행되도록 합니다. Docker는 이러한 컨테이너를 만드는 데 사용되는 도구입니다.
블레이저
Blazor는 .NET을 사용하여 대화형 웹 애플리케이션을 구축하기 위한 멋진 프레임워크입니다. 일반적인 크리스마스 캐롤을 맞춤화되고 효율적이며 재미있는 나만의 휴일 재생목록으로 바꾸는 것과 같습니다.
Docker-작성
Docker-Compose는 North Pole 운영의 관리자입니다. 이는 API 및 Blazor 프런트 엔드와 같은 모든 서비스가 완벽한 조화를 이루며 함께 실행되는 데 도움이 됩니다. 그를 우리 명절 교향곡의 지휘자로 생각해보세요.
단계별 가이드
이제 산타의 작업장에 들어가 이 프로젝트에 생기를 불어넣어 보세요!
1단계: API 생성
1.1 프로젝트 설정
코딩 산타 모자를 쓰고 새로운 ASP.NET Core Web API 프로젝트를 설정하세요. 터미널을 열고(강림절 달력을 여는 것과 약간 비슷함) 다음을 실행합니다.
dotnet new webapi -o PriceMonitorApi
cd PriceMonitorApi
이 명령은 PriceMonitorApi라는 새 디렉터리를 생성하고 기본 웹 API 프로젝트를 설정합니다. 진저브레드 하우스를 위한 견고한 기반을 만드는 것과 같다고 상상해 보세요.
1.2 HttpClient 추가 및 라이브러리 스크랩다음으로 HttpClient 및 라이브러리를 추가하여 HTML을 구문 분석합니다. 이는 가격 데이터를 가져오고 읽는 데 있어 신뢰할 수 있는 썰매가 될 것입니다.
dotnet add package HtmlAgilityPack
HtmlAgilityPack은 HTML 문서를 구문 분석하는 데 도움이 되는 엘프입니다.
1.3 모델 생성
모델은 장난감의 청사진과 같습니다. 제품 정보를 나타내는 모델을 만들어 보겠습니다.
namespace PriceMonitorApi.Models
{
public class ProductInfo
{
public string Title { get; set; }
public decimal Price { get; set; }
public DateTime Date { get; set; }
}
}
우리는 데이터에 딱 맞는 템플릿을 만들었습니다.
1.4 스크레이퍼 서비스 구현
우리의 스크레이퍼 서비스는 산타의 작은 도우미와 같습니다. 우리를 위해 정보를 가져오고 처리합니다.
using HtmlAgilityPack;
using PriceMonitorApi.Models;
using System.Globalization;
namespace PriceMonitorApi.Services
{
public class ScraperService
{
private readonly HttpClient _httpClient;
public ScraperService(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<ProductInfo> ScrapeProductInfoAsync(string url)
{
var response = await _httpClient.GetStringAsync(url);
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(response);
var title = htmlDoc.DocumentNode.SelectSingleNode("//h1[@class='product-title']").InnerText.Trim();
var priceString = htmlDoc.DocumentNode.SelectSingleNode("//span[@class='product-price']").InnerText.Trim();
if (decimal.TryParse(priceString, NumberStyles.Currency, CultureInfo.InvariantCulture, out var price))
{
return new ProductInfo
{
Title = title,
Price = price,
Date = DateTime.UtcNow
};
}
throw new Exception("Unable to parse price");
}
}
}
이 스니펫은 HtmlAgilityPack를 휴일 마술 지팡이로 바꿔줍니다.
1.5 API 컨트롤러 생성
데이터의 게이트키퍼 역할을 하는 컨트롤러를 만들어 보겠습니다.
using Microsoft.AspNetCore.Mvc;
using PriceMonitorApi.Models;
using PriceMonitorApi.Services;
namespace PriceMonitorApi.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class ScraperController : ControllerBase
{
private readonly ScraperService _scraperService;
public ScraperController(ScraperService scraperService)
{
_scraperService = scraperService;
}
[HttpGet("productinfo")]
public async Task<ActionResult<ProductInfo>> GetProductInfo(string url)
{
try
{
var productInfo = await _scraperService.ScrapeProductInfoAsync(url);
return Ok(productInfo);
}
catch (Exception ex)
{
return BadRequest(new { Message = ex.Message });
}
}
}
}
우리 컨트롤러는 굴뚝 아래로 산타보다 데이터가 더 빨리 전달되도록 보장합니다.
1.6 DI 컨테이너에 서비스 등록
마지막으로 ScraperService를 등록하여 필요할 때 사용할 수 있는지 확인하세요.
services.AddHttpClient<ScraperService>();
이제 크리스마스 이브의 산타 썰매처럼 API가 준비되었습니다!
2단계: Blazor 애플리케이션 만들기
Blazor를 사용하면 프로젝트를 크리스마스 트리처럼 장식하여 시각적으로 매력적이고 대화형으로 만들 수 있습니다.
2.1 Blazor 프로젝트 설정
다음으로 가격 모니터링 썰매 타기를 위한 인터페이스 역할을 하는 Blazor 프로젝트를 만듭니다.
dotnet new blazor -o PriceMonitorBlazor
cd PriceMonitorBlazor
이 명령은 기본 Blazor WebAssembly 프로젝트를 설정하기 위해 몇 가지 휴일 마법을 뿌립니다.
2.2 모델 추가
장식품 설정과 마찬가지로 Blazor 프로젝트에 ProductInfo 모델을 추가합니다.
namespace PriceMonitorBlazor.Models
{
public class ProductInfo
{
public string Title { get; set; }
public decimal Price { get; set; }
public DateTime Date { get; set; }
}
}
2.3 API 호출을 위한 서비스 생성
API에서 데이터를 가져오는 서비스를 만듭니다. 온라인 쇼핑 친구라고 생각하세요.
using PriceMonitorBlazor.Models;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;
namespace PriceMonitorBlazor.Services
{
public class ScraperService
{
private readonly HttpClient _httpClient;
public ScraperService(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<ProductInfo> GetProductInfoAsync(string url)
{
var response = await _httpClient.GetFromJsonAsync<ProductInfo>($"https://localhost:5001/api/scraper/productinfo?url={url}");
return response;
}
}
}
2.4 DI 컨테이너에 서비스 등록
구성요소에 주입할 수 있도록 ScraperService가 등록되어 있는지 확인하세요.
builder.Services.AddScoped<ScraperService>();
2.5 Blazor 구성 요소 만들기
재미있고 대화형 인터페이스를 포함하도록 Pages/Index.razor를 업데이트하세요.
@page "/"
@using PriceMonitorBlazor.Models
@using PriceMonitorBlazor.Services
@inject ScraperService ScraperService
<h3>Price Monitor</h3>
<p>
<label for="urlInput">Product URL:</label>
<input id="urlInput" @bind="productUrl" />
<button @onclick="FetchProductInfo">Fetch Price</button>
</p>
@if (productInfos.Any())
{
<table class="table">
<thead>
<tr>
<th>Title</th>
<th>Price</th>
<th>Date</th>
</tr>
</thead>
<tbody>
@foreach (var product in productInfos)
{
<tr>
<td>@product.Title</td>
<td>@product.Price</td>
<td>@product.Date</td>
</tr>
}
</tbody>
</table>
}
@code {
private string productUrl;
private List<ProductInfo> productInfos = new List<ProductInfo>();
private async Task FetchProductInfo()
{
if (!string.IsNullOrEmpty(productUrl))
{
var productInfo = await ScraperService.GetProductInfoAsync(productUrl);
productInfos.Add(productInfo);
}
}
}
이는 축제의 휴일 디스플레이를 설정하여 앱을 대화형이고 즐겁게 만드는 것과 같습니다.
3단계: Docker-Compose를 사용하여 모든 항목 연결
이제 Docker-Compose를 사용하여 모든 것을 연결하여 프로젝트를 기름진 썰매 타기로 바꿔 보겠습니다.
3.1 Dockerfile 만들기
API 및 Blazor 프로젝트 모두에 대한 Dockerfile을 만듭니다.
PriceMonitorApi/Dockerfile:
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["PriceMonitorApi/PriceMonitorApi.csproj", "PriceMonitorApi/"]
RUN dotnet restore "PriceMonitorApi/PriceMonitorApi.csproj"
COPY . .
WORKDIR "/src/PriceMonitorApi"
RUN dotnet build "PriceMonitorApi.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "PriceMonitorApi.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "PriceMonitorApi.dll"]
PriceMonitorBlazor/Dockerfile:
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["PriceMonitorBlazor/PriceMonitorBlazor.csproj", "PriceMonitorBlazor/"]
RUN dotnet restore "PriceMonitorBlazor/PriceMonitorBlazor.csproj"
COPY . .
WORKDIR "/src/PriceMonitorBlazor"
RUN dotnet build "PriceMonitorBlazor.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "PriceMonitorBlazor.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "PriceMonitorBlazor.dll"]
3.2 docker-compose.yml 만들기
단일 docker-compose.yml 파일로 모든 점(크리스마스 조명)을 연결합니다.
version: '3.4'
services:
api:
image: pricemonitorapi
build:
context: ./PriceMonitorApi
dockerfile: Dockerfile
ports:
- "5000:80"
networks:
- price-monitor-network
blazor:
image: pricemonitorblazor
build:
context: ./PriceMonitorBlazor
dockerfile: Dockerfile
ports:
- "5001:80"
depends_on:
- api
networks:
- price-monitor-network
networks:
price-monitor-network:
driver: bridge
다이어그램
다음은 다양한 구성 요소와 데이터 흐름을 시각화하는 데 도움이 되는 다이어그램입니다. 이는 산타 세계에서 실제로 무슨 일이 일어나고 있는지 이해하는 데 도움이 됩니다.
시스템 아키텍처 다이어그램

데이터 흐름 다이어그램

시퀀스 다이어그램

Docker 설정을 위한 구성 요소 다이어그램

4단계: URL 관리, 새로 고침 및 자동 주기적 새로 고침이 데모에서는 이를 메모리에 저장하지만 실제 애플리케이션에서는 데이터베이스를 사용합니다. 이 재미있는 프로젝트에서는 메모리 내 저장소를 고수하겠습니다.
4.1 URL 관리를 위한 서비스 수정
먼저, 우리 서비스가 URL 추가 및 검색은 물론 제품 정보 가져오기도 처리할 수 있는지 확인하겠습니다.
Services/ScraperService.cs 업데이트:
using PriceMonitorBlazor.Models;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;
namespace PriceMonitorBlazor.Services
{
public class ScraperService
{
private readonly HttpClient _httpClient;
private List<string> urls = new List<string>();
public ScraperService(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<ProductInfo> GetProductInfoAsync(string url)
{
var response = await _httpClient.GetFromJsonAsync<ProductInfo>($"http://localhost:5000/api/scraper/productinfo?url={url}");
return response;
}
public void AddUrl(string url)
{
if (!urls.Contains(url))
{
urls.Add(url);
}
}
public List<string> GetUrls()
{
return urls;
}
public void ClearUrls()
{
urls.Clear();
}
}
}
4.2 URL 관리 및 새로 고침을 위한 Blazor 구성 요소 업데이트
다음으로 Pages/Index.razor를 업데이트하여 URL 관리, 새로 고침 및 자동 주기적 새로 고침을 추가합니다.
@page "/"
@using PriceMonitorBlazor.Models
@using PriceMonitorBlazor.Services
@inject ScraperService ScraperService
<h3>Price Monitor</h3>
<p>
<label for="urlInput">Product URL:</label>
<input id="urlInput" @bind="productUrl" />
<button @onclick="AddUrl">Add URL</button>
</p>
<p>
<button @onclick="RefreshPrices">Refresh All Prices</button>
</p>
@if (productInfos.Any())
{
<table class="table">
<thead>
<tr>
<th>Title</th>
<th>Price</th>
<th>Date</th>
</tr>
</thead>
<tbody>
@foreach (var product in productInfos)
{
<tr>
<td>@product.Title</td>
<td>@product.Price</td>
<td>@product.Date</td>
</tr>
}
</tbody>
</table>
}
@code {
private string productUrl;
private List<ProductInfo> productInfos = new List<ProductInfo>();
private Timer _timer;
protected override void OnInitialized()
{
StartTimer();
}
private void StartTimer()
{
// Set up the timer to call RefreshPrices every minute (60000 ms)
_timer = new Timer(async _ => await InvokeAsync(RefreshPrices), null, TimeSpan.Zero, TimeSpan.FromMinutes(1));
}
private void AddUrl()
{
if (!string.IsNullOrEmpty(productUrl))
{
ScraperService.AddUrl(productUrl);
productUrl = string.Empty;
}
}
private async Task RefreshPrices()
{
productInfos.Clear();
var urls = ScraperService.GetUrls();
foreach (var url in urls)
{
var productInfo = await ScraperService.GetProductInfoAsync(url);
productInfos.Add(productInfo);
}
StateHasChanged();
}
}
이 업데이트된 구성 요소에서는 다음을 수행합니다.
Timer를 사용하여 1분마다RefreshPrices메서드를 주기적으로 호출합니다.StartTimer메소드는 타이머를 초기화하여 즉시 시작하고 60초마다 트리거합니다.OnInitialized수명 주기 메서드는 구성 요소가 초기화되어 주기적 새로 고침을 시작할 때StartTimer를 호출합니다.
4.3 솔루션 실행
새로운 기능으로 업데이트된 Blazor 애플리케이션을 실행하려면 Docker 컨테이너를 다시 빌드하고 다시 시작하세요.
docker-compose build
docker-compose up
브라우저에 http://localhost:5001를 로드한 후 Blazor 앱은 수동 새로 고침 및 URL 관리를 허용하는 것 외에도 매분 자동으로 제품 가격을 새로 고쳐야 합니다.
결론
이 가격 모니터링 시스템을 구축하는 것은 정말 즐거운 일이었습니다! 매일 가격을 확인하는 스트레스에서 벗어날 수 있었을 뿐만 아니라 현대 웹 기술의 마법도 보여주었습니다.
축제 기술 달력 2024

저는 기술 애호가, 혁신가, 디지털 몽상가들이 함께 모여 지식을 공유하고 축제 정신과 기술의 경이로움의 융합을 축하하는 Festive Tech Calendar 2024 이벤트의 일환으로 이 게시물을 작성했습니다. 이 이니셔티브는 학습과 연결뿐만 아니라 환원에 관한 것입니다.
Festive Tech Calendar 2024는 올해 Beatson Cancer Charity를 지원합니다. Beatson Cancer Charity는 암으로 고통받는 사람들과 그 가족, 그들을 돌보는 의료 전문가를 지원하는 데 최선을 다하고 있습니다. 그들의 놀라운 작업에 대한 자세한 내용은 https://www.beatsoncancercharity.org/에서 확인할 수 있습니다.
자주 묻는 질문과 이벤트에 대한 자세한 내용은 Festive Tech Calendar 웹사이트 https://festivetechcalendar.com에서 확인하세요.
호호호!
이 프로젝트를 만드는 것은 축제 기술 커뮤니티에 기여하고 동시에 훌륭한 목적을 지원할 수 있는 훌륭한 방법이었습니다.
이 가이드가 도움이 되기를 바라며 기술을 사용하여 일상적인 작업을 단순화하는 더 많은 방법을 탐색하는 데 영감을 주기를 바랍니다.
궁금한 점이 있거나 추가 지원이 필요한 경우 언제든지 문의해 주세요.
즐거운 코딩하세요!