콘텐츠 대표 이미지 - Xamarin과 .NET MAUI를 활용한크로스플랫폼 하이브리드 앱 개발 전략
📱 모바일/앱 개발 · 프로그램개발

Xamarin과 .NET MAUI를 활용한
크로스플랫폼 하이브리드 앱 개발 전략

하나의 코드로 iOS·Android·Windows를 동시에 정복하는 실전 가이드 🚀

Xamarin .NET MAUI 크로스플랫폼 C# 하이브리드 앱
.NET MAUI 공유 코드베이스 C# / XAML 🍎 iOS iPhone / iPad 🤖 Android 스마트폰 / 태블릿 🪟 Windows 데스크탑 / 태블릿 💻 macOS Mac Catalyst 🌐 Blazor Hybrid 웹 통합 하나의 C# 코드베이스 → 5개 플랫폼 동시 배포 가능 ✨
🤔 잠깐, 크로스플랫폼이 뭔데요?

앱 개발하려고 마음먹으면 제일 먼저 맞닥뜨리는 고민이 있잖아요ㅋㅋ
"iOS용으로 Swift 써야 해? Android는 Kotlin? 아니면 둘 다 따로 만들어야 해??"

이 고민을 해결해주는 게 바로 크로스플랫폼 개발이에요. 쉽게 말하면 코드 한 번 짜서 여러 플랫폼에 동시에 올리는 방식이죠. 그리고 그 대표 주자가 바로 Xamarin과 그 후계자 .NET MAUI입니다!

📌 핵심 개념 정리 Xamarin Microsoft가 2011년 인수한 크로스플랫폼 프레임워크. C#으로 iOS/Android 앱 개발 가능.

.NET MAUI Multi-platform App UI의 약자. Xamarin의 진화형으로 2022년 정식 출시. iOS, Android, Windows, macOS 모두 지원.

하이브리드 앱 네이티브 앱 껍데기 안에 웹 기술(HTML/CSS/JS)을 결합한 형태. MAUI에서는 BlazorWebView로 구현.

근데 솔직히 말하면 Xamarin이랑 MAUI가 뭐가 다른지 헷갈리는 분들 많을 거예요ㅋㅋ 걱정 마세요, 지금부터 차근차근 다 풀어드릴게요! 🎯

📜 Xamarin의 역사와 현재 위치

Xamarin은 2011년 Nat Friedman과 Miguel de Icaza가 설립한 회사에서 시작됐어요. 그러다가 2016년에 Microsoft가 인수하면서 .NET 생태계의 핵심 멤버가 됐죠.

Xamarin의 두 가지 접근법
Xamarin.Android
🤖
Android SDK를 C#으로 직접 바인딩.
네이티브 UI 컨트롤 사용.
Xamarin.iOS
🍎
iOS SDK를 C#으로 바인딩.
Objective-C/Swift API 접근 가능.
Xamarin.Forms
🎨
공유 UI 레이어 추가.
XAML로 한 번에 여러 플랫폼 UI 작성.

Xamarin.Forms가 나오면서 진짜 "코드 한 번 짜서 여러 플랫폼에 올리기"가 가능해졌는데요, 근데 여기서 문제가 생겼어요. 성능이 좀 아쉽고, 플랫폼별 커스터마이징이 복잡하고, 아키텍처 자체가 좀 낡아서 유지보수가 힘들다는 피드백이 쏟아진 거죠ㅋㅋ

💡 알아두면 좋은 사실! Xamarin은 2024년 5월 1일부로 공식 지원이 종료됐어요. 즉, 지금 새 프로젝트를 시작한다면 무조건 .NET MAUI로 가야 한다는 뜻! 기존 Xamarin 프로젝트도 MAUI로 마이그레이션을 권장하고 있어요.
2011 Xamarin 설립 2016 MS 인수 2018 Xamarin.Forms 3.0 2022 .NET MAUI 정식 출시 2024.05 Xamarin 지원 종료 Xamarin → .NET MAUI 진화의 여정 🚀
🚀 .NET MAUI가 뭐가 그렇게 대단해?

.NET MAUI는 그냥 Xamarin 업그레이드 버전이 아니에요. 아키텍처 자체를 갈아엎은 수준이라고 보면 돼요ㅋㅋ 뭐가 달라졌는지 핵심만 짚어볼게요!

🏗️ 단일 프로젝트 구조 (Single Project)

Xamarin.Forms 시절에는 iOS 프로젝트, Android 프로젝트, 공유 프로젝트를 따로따로 관리해야 했어요. 솔루션 파일 열면 프로젝트가 3~4개씩 있어서 처음 보는 사람은 멘붕 오기 딱 좋았죠ㅋㅋㅋ

MAUI는 이걸 하나의 프로젝트로 통합했어요. 플랫폼별 코드는 Platforms/ 폴더 안에 깔끔하게 분리되고, 공유 코드는 루트에 바로 있어요.

MyMauiApp/
├── Platforms/
│   ├── Android/
│   │   └── MainActivity.cs
│   ├── iOS/
│   │   └── AppDelegate.cs
│   ├── Windows/
│   │   └── App.xaml
│   └── MacCatalyst/
├── Resources/
│   ├── Images/        ← 이미지 한 번만 넣으면 자동 리사이징!
│   ├── Fonts/
│   └── Styles/
├── App.xaml           ← 공유 앱 진입점
├── MainPage.xaml      ← 공유 UI
└── MauiProgram.cs     ← 앱 설정 (DI 컨테이너 등)
⚡ 성능 개선: 핸들러 아키텍처

Xamarin.Forms의 가장 큰 단점 중 하나가 렌더러(Renderer) 패턴이었어요. UI 컨트롤 하나 커스터마이징하려면 플랫폼별 렌더러 클래스를 각각 만들어야 해서 코드가 엄청 복잡해졌거든요.

MAUI는 이걸 핸들러(Handler) 패턴으로 교체했어요. 핸들러는 렌더러보다 훨씬 가볍고, 인터셉트 포인트가 명확해서 커스터마이징이 훨씬 쉬워졌어요!

// MAUI 핸들러 커스터마이징 예시
// Entry 컨트롤의 밑줄 제거 (Android)
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping(
    "NoUnderline", (handler, view) =>
    {
#if ANDROID
        handler.PlatformView.BackgroundTintList =
            Android.Content.Res.ColorStateList.ValueOf(
                Android.Graphics.Color.Transparent);
#endif
    });
🎨 새로운 컨트롤들
🗺️
Map
지도 통합
📷
MediaPicker
카메라/갤러리
🔔
Notifications
로컬 알림
📡
Connectivity
네트워크 상태
🌐
BlazorWebView
웹 통합

특히 BlazorWebView가 진짜 게임체인저예요! 이게 바로 "하이브리드 앱"의 핵심인데, 기존 Blazor 웹 앱을 네이티브 앱 안에 그대로 임베드할 수 있거든요. 웹 개발자들이 모바일 앱 개발에 진입하기 훨씬 쉬워진 거죠!

🔥 하이브리드 앱 개발 전략: BlazorWebView 활용

자, 이제 진짜 핵심인 하이브리드 앱 얘기를 해볼게요. MAUI에서 하이브리드 앱을 만드는 방법은 크게 두 가지예요.

방법 1: .NET MAUI + BlazorWebView (권장 ⭐)

Blazor 컴포넌트를 네이티브 앱 안에서 실행하는 방식이에요. HTML/CSS/C#으로 UI를 만들고, 네이티브 기능(카메라, GPS 등)은 C# 코드로 접근하는 구조죠.

<!-- MainPage.xaml -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:b="clr-namespace:Microsoft.AspNetCore.Components.WebView.Maui;assembly=Microsoft.AspNetCore.Components.WebView.Maui">
    <b:BlazorWebView HostPage="wwwroot/index.html">
        <b:BlazorWebView.RootComponents>
            <b:RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
        </b:BlazorWebView.RootComponents>
    </b:BlazorWebView>
</ContentPage>
// MauiProgram.cs - DI 설정
public static MauiApp CreateMauiApp()
{
    var builder = MauiApp.CreateBuilder();
    builder
        .UseMauiApp<App>()
        .ConfigureFonts(fonts =>
        {
            fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
        });

    // Blazor 서비스 등록
    builder.Services.AddMauiBlazorWebView();

    // 네이티브 서비스 등록 (DI 활용)
    builder.Services.AddSingleton<IDeviceService, DeviceService>();
    builder.Services.AddSingleton<ILocationService, LocationService>();

#if DEBUG
    builder.Services.AddBlazorWebViewDeveloperTools();
#endif

    return builder.Build();
}
방법 2: MAUI + WebView (기존 웹앱 래핑)

이미 만들어진 웹사이트나 웹앱을 네이티브 앱으로 감싸는 방식이에요. 빠르게 앱 스토어에 올려야 할 때 쓰는 방법인데, 솔직히 이건 진정한 하이브리드라기보다는 웹뷰 래퍼에 가깝죠ㅋㅋ

<!-- 기존 웹앱 래핑 -->
<WebView Source="https://yourwebapp.com"
         HorizontalOptions="FillAndExpand"
         VerticalOptions="FillAndExpand" />
💡 어떤 방법을 선택해야 할까요? 새 프로젝트라면 BlazorWebView 방식을 강력 추천해요. 네이티브 기능 접근이 훨씬 자연스럽고, 코드 공유율도 높고, 성능도 더 좋거든요. 기존 웹앱이 있고 빠르게 앱화만 하고 싶다면 WebView 래핑도 나쁘지 않아요.
🏛️ MAUI 앱 아키텍처 설계 전략

좋은 앱은 좋은 아키텍처에서 나온다는 말, 들어봤죠? MAUI에서 많이 쓰이는 패턴들을 알아볼게요!

MVVM 패턴 (Model-View-ViewModel)

MAUI에서 가장 권장되는 아키텍처 패턴이에요. Microsoft가 공식적으로 밀어주는 패턴이기도 하고, XAML 데이터 바인딩과 찰떡궁합이에요.

// ViewModel 예시 (CommunityToolkit.Mvvm 활용)
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

public partial class MainViewModel : ObservableObject
{
    [ObservableProperty]
    private string _userName = string.Empty;

    [ObservableProperty]
    private bool _isLoading;

    [ObservableProperty]
    private ObservableCollection<Product> _products = new();

    [RelayCommand]
    private async Task LoadProductsAsync()
    {
        IsLoading = true;
        try
        {
            var result = await _productService.GetProductsAsync();
            Products = new ObservableCollection<Product>(result);
        }
        finally
        {
            IsLoading = false;
        }
    }
}

CommunityToolkit.Mvvm 라이브러리를 쓰면 소스 제너레이터 덕분에 보일러플레이트 코드가 엄청 줄어요. [ObservableProperty] 어트리뷰트 하나로 INotifyPropertyChanged 구현이 자동으로 되거든요. 진짜 편해요ㅋㅋ

의존성 주입 (Dependency Injection)

MAUI는 .NET의 기본 DI 컨테이너를 그대로 사용해요. 서비스 등록하고 생성자 주입으로 쓰는 방식이 ASP.NET Core랑 완전히 동일해서, 백엔드 개발자들이 모바일로 넘어오기 정말 편해요!

// 서비스 인터페이스 정의
public interface IWeatherService
{
    Task<WeatherData> GetCurrentWeatherAsync(double lat, double lon);
}

// 플랫폼별 구현 (필요한 경우)
public class WeatherService : IWeatherService
{
    private readonly HttpClient _httpClient;

    public WeatherService(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    public async Task<WeatherData> GetCurrentWeatherAsync(double lat, double lon)
    {
        var response = await _httpClient.GetFromJsonAsync<WeatherData>(
            $"api/weather?lat={lat}&lon={lon}");
        return response ?? new WeatherData();
    }
}

// MauiProgram.cs에서 등록
builder.Services.AddHttpClient<IWeatherService, WeatherService>(client =>
{
    client.BaseAddress = new Uri("https://api.yourweather.com/");
});
Shell 네비게이션

MAUI Shell은 앱의 전체 구조를 선언적으로 정의하는 방법이에요. 탭바, 플라이아웃 메뉴, 딥링크까지 한 번에 처리할 수 있어요!

<!-- AppShell.xaml -->
<Shell xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       xmlns:views="clr-namespace:MyApp.Views">

    <TabBar>
        <Tab Title="홈" Icon="home.png">
            <ShellContent ContentTemplate="{DataTemplate views:HomePage}" Route="home"/>
        </Tab>
        <Tab Title="검색" Icon="search.png">
            <ShellContent ContentTemplate="{DataTemplate views:SearchPage}" Route="search"/>
        </Tab>
        <Tab Title="프로필" Icon="profile.png">
            <ShellContent ContentTemplate="{DataTemplate views:ProfilePage}" Route="profile"/>
        </Tab>
    </TabBar>
</Shell>
MAUI MVVM 아키텍처 구조 View (XAML) ContentPage CollectionView Entry / Button Label / Image 데이터 바인딩 ({Binding}) 커맨드 바인딩 ViewModel ObservableObject [ObservableProperty] [RelayCommand] INotifyPropertyChanged 비즈니스 로직 처리 서비스 호출 Model / Service 데이터 모델 (POCO) Repository 패턴 API 서비스 로컬 DB (SQLite) 데이터 접근 레이어 외부 API 통신 View ↔ ViewModel: 데이터 바인딩 / ViewModel ↔ Model: 서비스 호출 CommunityToolkit.Mvvm 라이브러리로 보일러플레이트 코드 최소화
📊 Xamarin vs .NET MAUI 비교 분석

마이그레이션을 고민 중이거나, 둘 중 어떤 걸 배워야 할지 고민하는 분들을 위해 핵심 비교표를 만들어봤어요!

항목 Xamarin.Forms .NET MAUI
지원 플랫폼 iOS, Android, UWP iOS, Android, Windows, macOS
프로젝트 구조 멀티 프로젝트 단일 프로젝트 ⭐
UI 렌더링 렌더러(Renderer) 패턴 핸들러(Handler) 패턴 ⭐
.NET 버전 .NET Standard 2.0/2.1 .NET 6+ (최신 .NET) ⭐
핫 리로드 제한적 XAML/C# 핫 리로드 ⭐
Blazor 통합 미지원 BlazorWebView 지원 ⭐
성능 보통 개선됨 ⭐
공식 지원 2024년 5월 종료 ❌ 활발히 지원 중 ✅
학습 곡선 중간 중간 (Xamarin 경험자는 쉬움)

표만 봐도 답이 나오죠?ㅋㅋ 새 프로젝트는 무조건 MAUI예요. 기존 Xamarin 프로젝트도 마이그레이션 가이드 따라서 MAUI로 옮기는 게 장기적으로 훨씬 이득이에요.

🛠️ 실전 개발 팁: 자주 쓰는 패턴들
1. 플랫폼별 코드 분기

아무리 크로스플랫폼이라도 플랫폼별로 다르게 동작해야 할 때가 있어요. MAUI에서는 세 가지 방법을 제공해요.

// 방법 1: 컴파일러 지시문 (#if)
public void ConfigurePlatform()
{
#if ANDROID
    // Android 전용 코드
    Android.App.Application.Context.GetSystemService(...);
#elif IOS
    // iOS 전용 코드
    UIKit.UIApplication.SharedApplication.StatusBarStyle = ...;
#elif WINDOWS
    // Windows 전용 코드
#endif
}

// 방법 2: DeviceInfo 런타임 체크
if (DeviceInfo.Platform == DevicePlatform.iOS)
{
    // iOS에서만 실행
}

// 방법 3: 부분 클래스 (Partial Class) - 권장
// Platforms/Android/MyService.cs
public partial class MyService
{
    public partial void DoAndroidThing()
    {
        // Android 구현
    }
}

// Platforms/iOS/MyService.cs
public partial class MyService
{
    public partial void DoAndroidThing()
    {
        // iOS 구현 (같은 메서드명, 다른 구현)
    }
}
2. 로컬 데이터베이스 (SQLite)

오프라인 지원이 필요한 앱이라면 SQLite는 필수예요. sqlite-net-pcl 패키지가 MAUI에서도 잘 동작해요!

// 모델 정의
public class TodoItem
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }
    public string Title { get; set; } = string.Empty;
    public bool IsCompleted { get; set; }
    public DateTime CreatedAt { get; set; } = DateTime.Now;
}

// 데이터베이스 서비스
public class TodoDatabase
{
    private SQLiteAsyncConnection? _database;

    private async Task InitAsync()
    {
        if (_database is not null) return;

        var dbPath = Path.Combine(
            FileSystem.AppDataDirectory, "todo.db3");
        _database = new SQLiteAsyncConnection(dbPath,
            SQLiteOpenFlags.ReadWrite |
            SQLiteOpenFlags.Create |
            SQLiteOpenFlags.SharedCache);

        await _database.CreateTableAsync<TodoItem>();
    }

    public async Task<List<TodoItem>> GetItemsAsync()
    {
        await InitAsync();
        return await _database!.Table<TodoItem>().ToListAsync();
    }

    public async Task<int> SaveItemAsync(TodoItem item)
    {
        await InitAsync();
        return item.Id != 0
            ? await _database!.UpdateAsync(item)
            : await _database!.InsertAsync(item);
    }
}
3. 네이티브 기능 접근 (Essentials)

MAUI Essentials는 Xamarin.Essentials의 후계자로, 네이티브 기능을 크로스플랫폼으로 쉽게 쓸 수 있게 해줘요.

// GPS 위치 가져오기
public async Task<Location?> GetCurrentLocationAsync()
{
    try
    {
        var request = new GeolocationRequest(
            GeolocationAccuracy.Medium,
            TimeSpan.FromSeconds(10));
        return await Geolocation.Default.GetLocationAsync(request);
    }
    catch (FeatureNotSupportedException)
    {
        // GPS 미지원 기기
        return null;
    }
    catch (PermissionException)
    {
        // 권한 없음 - 권한 요청 필요
        await RequestLocationPermission();
        return null;
    }
}

// 카메라로 사진 찍기
public async Task<FileResult?> TakePhotoAsync()
{
    if (MediaPicker.Default.IsCaptureSupported)
    {
        return await MediaPicker.Default.CapturePhotoAsync();
    }
    return null;
}

// 클립보드 복사
await Clipboard.Default.SetTextAsync("복사할 텍스트");

// 진동
Vibration.Default.Vibrate(TimeSpan.FromMilliseconds(500));
🎯 Xamarin → .NET MAUI 마이그레이션 전략

기존에 Xamarin 프로젝트를 운영 중이라면 마이그레이션이 필수예요. 근데 겁먹지 마세요! 생각보다 체계적으로 접근하면 할 만해요ㅋㅋ

마이그레이션 단계별 접근법
1
사전 준비 및 분석
현재 프로젝트의 NuGet 패키지 목록 확인. MAUI 호환 여부 체크. .NET Upgrade Assistant 도구 활용 (Microsoft 공식 제공).
2
프로젝트 파일 변환
.csproj 파일을 SDK 스타일로 변환. 플랫폼별 프로젝트를 단일 프로젝트로 통합. Platforms/ 폴더 구조로 재편.
3
네임스페이스 업데이트
Xamarin.Forms → Microsoft.Maui
Xamarin.Essentials → Microsoft.Maui.Essentials
대부분 Find & Replace로 처리 가능!
4
커스텀 렌더러 → 핸들러 변환
가장 손이 많이 가는 부분. 렌더러 패턴을 핸들러 패턴으로 재작성. 공식 마이그레이션 가이드 참고 필수.
5
테스트 및 검증
각 플랫폼별 빌드 및 실행 테스트. UI 렌더링 차이 확인. 성능 프로파일링.
⚠️ 마이그레이션 주의사항 • Effects는 MAUI에서 핸들러로 대체됨
• MessagingCenter는 WeakReferenceMessenger로 교체 권장
• Device.BeginInvokeOnMainThread → MainThread.BeginInvokeOnMainThread
• Application.Current.MainPage 접근 방식 변경됨
• 일부 서드파티 라이브러리는 MAUI 버전 별도 확인 필요
📦 꼭 알아야 할 MAUI 생태계 라이브러리

혼자 다 만들 필요 없어요! 이미 검증된 라이브러리들이 많거든요ㅋㅋ

라이브러리 용도 특징
CommunityToolkit.Mvvm MVVM 패턴 소스 제너레이터, 보일러플레이트 최소화
CommunityToolkit.Maui 추가 컨트롤/기능 Popup, Toast, MediaElement 등
sqlite-net-pcl 로컬 DB 경량 SQLite ORM
Refit REST API 클라이언트 인터페이스 기반 HTTP 클라이언트
Prism.Maui 고급 MVVM 프레임워크 DI, 네비게이션, 모듈화
SkiaSharp 2D 그래픽 크로스플랫폼 캔버스 드로잉
LiveCharts2 차트/그래프 애니메이션 지원 차트
Plugin.Firebase Firebase 연동 푸시 알림, 분석, 인증
💡 재능넷 팁! MAUI 개발을 배우고 싶은데 혼자 하기 막막하다면, 재능넷에서 .NET/MAUI 전문 개발자에게 1:1 멘토링을 받아보는 것도 좋은 방법이에요. 실무 경험이 있는 분들한테 직접 배우면 학습 속도가 훨씬 빨라지거든요!
MAUI 하이브리드 앱 개발 플로우 📋 요구사항 분석 플랫폼 결정 🏗️ 아키텍처 설계 MVVM / DI 설정 🎨 UI 개발 XAML / Blazor ⚙️ 비즈니스 로직 서비스 / API 🧪 테스트 단위 / UI 테스트 🔧 플랫폼 최적화 핸들러 커스터마이징 📦 빌드 & 패키징 서명 / 배포 준비 🚀 스토어 배포 App Store / Play Store 🛠️ 필수 개발 도구 Visual Studio 2022 VS Code + C# Dev Kit .NET 8 SDK Android Studio Xcode (macOS) Windows에서 iOS 빌드는 Mac Build Host 연결 필요 (네트워크로 Mac 연결) 또는 GitHub Actions / Azure DevOps CI/CD 파이프라인 활용 권장
⚡ 성능 최적화 전략

앱 만들었는데 느리면 사용자들 바로 삭제해버리죠ㅋㅋ MAUI 앱 성능 최적화에서 꼭 챙겨야 할 포인트들을 알아볼게요!

1. CollectionView 최적화

리스트 렌더링은 앱 성능에 가장 큰 영향을 미치는 요소 중 하나예요.

<!-- 가상화 활성화 (기본값이지만 명시적으로) -->
<CollectionView ItemsSource="{Binding Products}"
                RemainingItemsThreshold="5"
                RemainingItemsThresholdReachedCommand="{Binding LoadMoreCommand}">
    <CollectionView.ItemTemplate>
        <DataTemplate x:DataType="models:Product">
            <!-- x:DataType으로 컴파일 타임 바인딩 활성화 -->
            <Grid Padding="10">
                <Label Text="{Binding Name}" />
                <Label Text="{Binding Price, StringFormat='{0:C}'}" />
            </Grid>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>
2. 이미지 최적화
// 이미지 캐싱 (FFImageLoading 또는 기본 캐싱 활용)
<Image Source="{Binding ImageUrl}"
       Aspect="AspectFill"
       CachingStrategy="RecycleElement" />

// 코드에서 이미지 다운샘플링
var imageSource = ImageSource.FromUri(new Uri(imageUrl));
// 큰 이미지는 표시 크기에 맞게 리사이징 필요
3. 앱 시작 시간 최적화
✅ 시작 시간 줄이는 방법들

• AOT 컴파일 활성화:
<RunAOTCompilation>true</RunAOTCompilation>

• 링커(Linker) 활용: 사용하지 않는 코드 제거
• 지연 초기화(Lazy Initialization): 필요할 때만 서비스 초기화
• Splash Screen 최적화: 네이티브 스플래시 스크린 활용
• 앱 번들 크기 최소화: 불필요한 리소스 제거
4. 메모리 관리
// WeakReference 활용으로 메모리 누수 방지
public class MyViewModel : ObservableObject, IDisposable
{
    private readonly IDisposable _subscription;

    public MyViewModel(IEventAggregator eventAggregator)
    {
        // WeakReferenceMessenger 사용 (CommunityToolkit)
        WeakReferenceMessenger.Default
            .Register<ProductUpdatedMessage>(this, (r, m) =>
            {
                // 메시지 처리
            });
    }

    public void Dispose()
    {
        // 구독 해제 - 메모리 누수 방지
        WeakReferenceMessenger.Default.UnregisterAll(this);
        _subscription?.Dispose();
    }
}
🌐 CI/CD 파이프라인 구축

앱 개발만큼 중요한 게 자동화된 빌드/배포 파이프라인이에요. 특히 MAUI는 여러 플랫폼을 동시에 빌드해야 하니까 CI/CD가 더더욱 중요해요!

GitHub Actions 활용 예시
# .github/workflows/maui-build.yml
name: MAUI Build & Deploy

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build-android:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '8.0.x'
      - name: Install MAUI workload
        run: dotnet workload install maui-android
      - name: Build Android
        run: dotnet build -f net8.0-android -c Release
      - name: Sign APK
        # 서명 단계 (keystore 파일 필요)
        run: |
          echo "${{ secrets.KEYSTORE_FILE }}" | base64 -d > keystore.jks
          # apksigner 명령어로 서명

  build-ios:
    runs-on: macos-latest  # iOS 빌드는 macOS 필수!
    steps:
      - uses: actions/checkout@v4
      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '8.0.x'
      - name: Install MAUI workload
        run: dotnet workload install maui-ios
      - name: Build iOS
        run: dotnet build -f net8.0-ios -c Release
💡 배포 자동화 팁! App Center(현재는 Visual Studio App Center → Appcenter.ms)나 Fastlane을 활용하면 스토어 배포까지 완전 자동화할 수 있어요. 특히 Fastlane의 deliver(iOS)와 supply(Android) 플러그인이 강력해요. 재능넷에서 DevOps 전문가를 찾아 파이프라인 구축을 맡기는 것도 효율적인 방법이에요!
🔮 .NET MAUI의 미래와 로드맵

MAUI는 계속 발전 중이에요. 앞으로 어떤 방향으로 가는지 알아두면 기술 선택에 도움이 돼요!

현재 주요 업데이트 트렌드 (.NET 8/9 기준)
🆕 .NET 9 MAUI 주요 변경사항 • HybridWebView 정식 추가: 네이티브 ↔ 웹 양방향 통신 강화
• Android API 35 타겟 지원
• iOS 18 지원 및 새 API 바인딩
• 성능 개선: 앱 시작 시간 및 메모리 사용량 최적화
• Xcode 16 지원
HybridWebView - 새로운 하이브리드 접근법

.NET 9에서 추가된 HybridWebView는 BlazorWebView와 다르게 어떤 웹 프레임워크든 사용할 수 있어요. React, Vue, Angular 등 기존 웹 앱을 MAUI 앱 안에 임베드하고, JavaScript ↔ C# 양방향 통신이 가능해요!

// HybridWebView 사용 예시 (.NET 9)
<HybridWebView x:Name="hybridWebView"
               HybridRoot="hybrid_root"
               DefaultFile="index.html"
               RawMessageReceived="OnRawMessageReceived" />

// C#에서 JavaScript 호출
await hybridWebView.InvokeJavaScriptAsync(
    "updateUserData",
    HybridWebViewJsonSerializerContext.Default.UserData,
    new[] { userData });

// JavaScript에서 C# 호출 (JS 코드)
// window.HybridWebView.SendRawMessage('{"action":"getLocation"}');
🎯 MAUI를 선택해야 하는 이유 요약 • Microsoft의 강력한 지원과 활발한 커뮤니티
• C# 하나로 iOS, Android, Windows, macOS 모두 커버
• .NET 생태계의 방대한 라이브러리 활용 가능
• ASP.NET Core 개발자라면 진입 장벽이 매우 낮음
• Blazor 통합으로 웹 개발자도 쉽게 접근 가능
• 엔터프라이즈 환경에서 검증된 기술 스택
📝 마무리: 어떤 선택을 해야 할까?

자, 이제 정리해볼게요! 상황별로 어떤 선택이 맞는지 딱 정리해드릴게요ㅋㅋ

🆕 새 프로젝트 시작

무조건 .NET MAUI
Xamarin은 지원 종료됨.
MAUI + CommunityToolkit
조합이 현재 최선.
🔄 기존 Xamarin 프로젝트

단계적 마이그레이션 계획 수립.
.NET Upgrade Assistant 활용.
2024년 5월 이후 보안 패치 없음.
🌐 웹 개발자 전향

MAUI + Blazor Hybrid
기존 Blazor 지식 활용.
HTML/CSS/C# 그대로 사용 가능.

크로스플랫폼 앱 개발은 이제 선택이 아닌 필수가 되어가고 있어요. 개발 비용과 시간을 절약하면서도 품질 높은 앱을 만들 수 있는 .NET MAUI는 앞으로도 계속 성장할 기술이에요. 지금 시작해도 절대 늦지 않았어요! 🚀

특히 C# 백엔드 개발자라면 MAUI는 진짜 진입 장벽이 낮아요. 이미 알고 있는 언어와 패턴을 그대로 모바일에 적용할 수 있으니까요. 오늘 당장 Visual Studio 2022 설치하고 MAUI 워크로드 추가해서 Hello World부터 시작해보세요! 💪


댓글 작성

이 글에 대한 여러분의 생각을 들려주세요

댓글 0
댓글을 불러오는 중입니다.

아직 댓글이 없습니다.