ResiliencePipeline은 .NET 8에서 새롭게 도입된 고성능 탄력성 및 재시도(Retry) 패턴 제어 프레임워크입니다.
기존 .NET 생태계에서는 외부 장비 통신이나 네트워크 예외 처리를 위해 Polly라는 유명한 오픈소스 라이브러리를 개별적으로 가져다 썼습니다. 하지만 .NET 8에 이르러 Microsoft와 Polly 팀이 협력하여, 런타임 자체에 표준화된 고성능 엔진으로 내장시킨 것이 바로 이 ResiliencePipeline입니다.
통신 프로젝트처럼 "장치와 무선(BLE/Wi-Fi)으로 통신할 때 발생하는 패킷 유실, 일시적 타임아웃, 연결 끊김" 상황을 코드를 지저분하게 짜지 않고 우아하게 복구할 수 있도록 도와주는 핵심 기능입니다.
## 1. 왜 필요할까요? (MFC/레거시 방식과의 비교)
- 레거시 방식 (C++/MFC): BLE 패킷을 보냈는데 응답이 없으면, 개발자가 for 루프를 돌리고 내부에 try-catch를 넣은 뒤 수동으로 Sleep(500)을 걸어가며 재시도를 구현했습니다. 이 방식은 코드 가독성을 극도로 떨어뜨리고, UI 스레드를 쉽게 블로킹하며, 타임아웃 정책을 변경하기 어렵게 만듭니다.
- .NET 8 방식 (ResiliencePipeline): "예외가 발생하면 3번 재시도하되, 각 시도 사이에 1초씩 대기한다"라는 정책을 파이프라인으로 딱 한 번 정의해 두고, 통신 코드를 이 파이프라인 내부에서 실행(ExecuteAsync)시키기만 하면 프레임워크가 뒤에서 자동으로 복구 루프를 수행합니다.
## 2. 핵심 복구 전략 (Resilience Strategies)
파이프라인에는 여러 가지 강력한 탄력성 전략들을 단일 혹은 체인 형태로 엮어서 넣을 수 있습니다.
- Retry (재시도): 일시적인 오류(패킷 누락 등)가 발생했을 때 일정 횟수만큼 다시 시도합니다.
- Circuit Breaker (회로 차단기): 장치가 아예 꺼졌거나 통신이 완전히 불가능한 상태인데도 계속 재시도를 보내면 시스템 자원이 낭비됩니다. 오류율이 임계치를 넘으면 아예 통신 요청을 차단하고 즉시 에러를 반환하다가, 일정 시간이 지나면 다시 연결을 시도하는 스마트한 기능입니다.
- Timeout (타임아웃): 하드웨어나 네트워크 응답이 일정 시간 이상 걸리면 강제로 작업을 취소합니다.
## 3. 구현 샘플 코드 (BLE 통신 탄력성 적용)
HostApplicationBuilder 기반의 IServiceCollection 장부에 ResiliencePipeline을 등록하고, 실제 서비스에서 주입받아 사용하는 표준 아키텍처를 보여드리겠습니다.
### 1) 파이프라인 등록 및 정책 정의 (App.xaml.cs 또는 빌더 진입점)
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Polly;
using Polly.Retry;
var builder = Host.CreateApplicationBuilder(args);
// 'BleTimeoutPipeline'이라는 이름의 탄력성 파이프라인 구축
builder.Services.AddResiliencePipeline("BleTimeoutPipeline", pipelineBuilder =>
{
pipelineBuilder.AddRetry(new RetryStrategyOptions
{
// 1. 어떤 예외가 발생했을 때 재시도할 것인지 지정 (예: 통신 타임아웃 예외)
ShouldHandle = new PredicateBuilder().Handle<TimeoutException>(),
// 2. 최대 재시도 횟수
MaxRetryAttempts = 3,
// 3. 재시도 간격 패턴 (지수 백오프: 1초, 2초, 4초 순으로 늘려가며 대기)
BackoffType = DelayBackoffType.Exponential,
UseJitter = true, // 모바일 기기들이 동시에 재시도를 보내 무리가 가는 것을 방지하는 무작위 미세 지연 추가
Delay = TimeSpan.FromSeconds(1)
});
});
### 2) 서비스 부품에서 주입받아 사용하기
장부에 등록된 파이프라인은 ResiliencePipelineProvider<string>를 통해 원하는 클래스의 생성자로 주입받아 사용할 수 있습니다.
using Polly.Registry;
public class EntecCmrCommunicator
{
private readonly ResiliencePipeline _pipeline;
private readonly IBluetoothService _bleService;
// 프로바이더를 주입받아 이름으로 파이프라인을 획득합니다.
public EntecCmrCommunicator(ResiliencePipelineProvider<string> pipelineProvider, IBluetoothService bleService)
{
_pipeline = pipelineProvider.GetPipeline("BleTimeoutPipeline");
_bleService = bleService;
}
public async Task<byte[]> ReadCmrSettingsWithRetryAsync()
{
// 파이프라인 내부에서 실행(ExecuteAsync)하면,
// 팩토리나 장치에서 TimeoutException이 발생하더라도 자동으로 최대 3번 재시도 로직이 가동됩니다.
return await _pipeline.ExecuteAsync(async cancellationToken =>
{
// 실제 BLE 패킷 전송 및 수신 시도
byte[] requestPacket = new byte[] { 0x02, 0x01 }; // 예시 패킷
return await _bleService.SendAndReceiveAsync(requestPacket, cancellationToken);
});
}
}
## 4. 통신 안드로이드 APP(.NET MAUI) 환경에서의 시사점
통신 모바일 APP 개발을 하면서 안드로이드 환경에서의 업/다운로드 통신 속도 저하와 데이터 신뢰성 확보가 중요한 이슈로 다뤄지고 있습니다.
- 모바일 무선 환경의 불안정성 해결: 스마트폰 앱으로 장치를 검색하고 연결할 때, 주변 자계 노이즈나 거리 문제로 인해 블루투스 패킷이 순간적으로 유실될 수 있습니다.
- UI 얼어붙음(Freeze) 방지: 기존에는 재시도 루프를 돌릴 때 UI가 멈추는 현상을 막기 위해 복잡한 스레드 분리 처리를 해야 했지만, .NET 8의 ResiliencePipeline은 기본적으로 비동기(ExecuteAsync)로 완벽하게 동작하므로 모바일 화면이 멈추지 않고 매끄럽게 "재시도 중..." 상태를 유지할 수 있습니다.
- 보안 핸드셰이크의 견고함 확보: 보안 표준에 맞추어 AES-CTR 암호화 토큰이나 로그인 인증 패킷을 주고받을 때 , 일시적 통신 불량으로 세션이 깨지는 문제를 파이프라인 레이어에서 먼저 잡아주어 비즈니스 로직(로그인/설정 변경)의 안정성을 극대화합니다.
IServiceCollection 장부에 이 탄력성 파이프라인을 미리 전역적으로 세팅해 두시면, 통신 모듈 외에도 파일 입출력(XML/JSON 로드 시 락 걸림 현상 방지) 등 예외 처리가 필수적인 모든 구간을 매우 견고하게 방어할 수 있습니다.
'.NET' 카테고리의 다른 글
| C#의 public sealed record 이해하기 (0) | 2026.06.17 |
|---|---|
| C# 숫자 리터럴 중간에 들어간 언더바(_) 사용 (0) | 2026.06.16 |
| IServiceCollection를 확장하는 메서드 (0) | 2026.06.16 |
| MFC 개발자 대상 .NET 8 기반 IPC 샘플 코드 기반 교육 (0) | 2026.06.16 |
| .NET 8 개발 전환을 위한 핵심 개발자 패러다임 시프트 교육 로드맵 (0) | 2026.06.16 |