unity , c# , 

using System;
using System.Threading;
using System.Threading.Tasks;


namespace Ncroquis.Backend
{

    /// ADX 라이브러리가 지원하는 광고 형식에 기반한 광고 기능 인터페이스입니다.

    public interface IBackendAds
    {



        /// 배너 광고를 로드합니다.      
        Task LoadBannerAsync(string adUnitId, CancellationToken cancellationToken = default);

        /// 로드된 배너 광고를 표시합니다.
        void ShowBannerAd();

        /// 표시된 배너 광고를 숨깁니다.
        void HideBannerAd();



        /// 전면 광고를 로드합니다.
        Task LoadInterstitialAsync(string adUnitId, CancellationToken cancellationToken = default);

        /// 로드된 전면 광고를 표시합니다.
        void ShowInterstitialAd();

        /// 전면 광고가 로드되어 표시 준비가 되었는지 확인합니다.        
        bool IsInterstitialAdReady();



        /// 보상형 광고를 로드합니다.
        /// <param name="adUnitId">광고 단위 ID</param>
        Task LoadRewardedAsync(string adUnitId , CancellationToken cancellationToken = default);

        /// 로드된 보상형 광고를 표시합니다.
        void ShowRewardedAd();

        /// 보상형 광고가 로드되어 표시 준비가 되었는지 확인합니다.        
        /// <returns>광고 준비 여부</returns>
        bool IsRewardedAdReady();




        /// 광고 로드 또는 표시 중 오류가 발생할 때 발생하는 이벤트입니다.                
        event Action OnAdError;


        /// 광고로부터 수익이 발생했을 때 발생하는 이벤트입니다.        
        /// <param name="adUnitId">수익이 발생한 광고 단위 ID</param>
        /// <param name="revenueAmount">발생한 수익 금액</param>        
        event Action<string, double> OnAdRevenue;
    }
}



using System;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using VContainer;
using AdxUnityPlugin;
using R3;




namespace Ncroquis.Backend
{
    
    

    /// ADX 라이브러리의 광고 기능 인터페이스(IBackendAds) 구현체    
    public class AdxBackendAds : IBackendAds, IDisposable
    {

        private readonly AdxBackendProvider _adxProvider;
        private readonly CompositeDisposable _disposables = new();
        private CancellationTokenSource _cts = new();




        // ADX 광고 인스턴스
        private AdxBannerAd _bannerAd;
        private AdxInterstitialAd _interstitialAd;
        private AdxRewardedAd _rewardedAd;


        public string bannerAdUnitId;
        public string interstitialAdUnitId;
        public string rewardedAdUnitId;


        // IBackendAds 인터페이스 이벤트 [17, 18]
        public event Action OnAdError;
        public event Action<string, double> OnAdRevenue; // 소스 설명을 반영하여 Action<string, double>으로 변경 [18]



        [Inject]
        public AdxBackendAds(AdxBackendProvider provider)
        {
            _adxProvider = provider;

            // ProviderAds만 초기화되면 광고 로드
            _adxProvider.IsInitialized
                .Where(isInitialized => isInitialized)
                .Subscribe(async _ => await LoadAllAdsAsync(_cts.Token))
                .AddTo(_disposables);
        }

        public void Dispose()
        {
            _cts?.Cancel();
            _cts?.Dispose();
            _disposables?.Dispose();

            Debug.Log("Ads disposed and resources released.");
        }




        private async Task LoadAllAdsAsync(CancellationToken cancellationToken = default)
        {
            Debug.Log("ProviderAds is initialized. Loading all ads...");

            try
            {
                await Task.WhenAll(
                    LoadBannerAsync(bannerAdUnitId, cancellationToken),
                    LoadInterstitialAsync(interstitialAdUnitId, cancellationToken),
                    LoadRewardedAsync(rewardedAdUnitId, cancellationToken)
                );

                Debug.Log("All ads loaded successfully!");
            }
            catch (OperationCanceledException)
            {
                Debug.Log("Ad loading was cancelled");
            }
            catch (Exception ex)
            {
                Debug.LogError($"Failed to load ads: {ex.Message}");
            }
        }






        ///
        /// 배너 광고를 로드합니다.
        /// ADX 배너 광고는 크기와 위치를 생성자에 명시해야 합니다.
        /// IBackendAds 인터페이스는 이러한 파라미터를 제공하지 않으므로, 기본값(320x50, 상단)을 사용합니다.
        ///
        /// 광고 단위 ID
        public async Task LoadBannerAsync(string adUnitId, CancellationToken cancellationToken = default)
        {
            if (!_adxProvider.IsInitialized.CurrentValue)
            {
                Debug.LogError("[ADX Backend Ads] ADX SDK가 초기화되지 않았습니다. 배너 광고를 로드할 수 없습니다."); // [8]
                OnAdError?.Invoke(); // 오류 이벤트 트리거
                return;
            }

            // 기존 배너 광고가 있다면 파괴하고 다시 생성합니다.
            if (_bannerAd != null)
            {
                _bannerAd.Destroy();
                _bannerAd = null;
                Debug.Log("[ADX Backend Ads] 기존 배너 광고를 파괴하고 다시 로드합니다."); // [20]
            }

            // 배너 광고 인스턴스 생성 (기본 크기 및 위치 사용)
            _bannerAd = new AdxBannerAd(adUnitId, AdxBannerAd.AD_SIZE_320x50, AdxBannerAd.POSITION_TOP); // [20]

            // 이벤트 핸들러 등록
            _bannerAd.OnAdLoaded += () =>
            {
                Debug.Log("[ADX Backend Ads] 배너 광고 로드 성공."); // [20]
            };

            _bannerAd.OnAdFailedToLoad += (error) =>
            {
                Debug.LogError($"[ADX Backend Ads] 배너 광고 로드 실패: {error}"); // [20]
                OnAdError?.Invoke(); // 오류 이벤트 트리거
            };

            _bannerAd.OnAdClicked += () =>
            {
                Debug.Log("[ADX Backend Ads] 배너 광고 클릭됨."); // [20]
            };

            _bannerAd.OnPaidEvent += (ecpm) =>
            {
                // 예상 광고 수익 계산
                double revenue = ecpm / 1000f; // [20]
                Debug.Log($"[ADX Backend Ads] 배너 광고 수익 발생: {revenue} USD (eCPM: {ecpm})"); // [10]
                OnAdRevenue?.Invoke("ADX Banner Ad", revenue); // 수익 이벤트 트리거
            };

            _bannerAd.Load(); // 광고 로드 요청. ADX 배너 광고는 Load() 시 자동으로 표시됩니다. [10]
            Debug.Log($"[ADX Backend Ads] 배너 광고 로드 요청: {adUnitId}");
        }

        ///
        /// 로드된 배너 광고를 표시합니다.
        /// ADX 배너 광고는 Load() 시 자동으로 표시되므로, 이 메서드는 단순히 광고가 로드되었는지 확인하는 역할을 합니다.
        ///
        public void ShowBannerAd()
        {
            if (!_adxProvider.IsInitialized.CurrentValue)
            {
                Debug.LogError("[ADX Backend Ads] ADX SDK가 초기화되지 않았습니다. 배너 광고를 표시할 수 없습니다."); // [10]
                OnAdError?.Invoke(); // [21]
                return;
            }

            if (_bannerAd != null)
            {
                Debug.Log("[ADX Backend Ads] 배너 광고가 이미 로드되어 있거나 로드 요청되었습니다. (ADX 배너 광고는 Load() 시 표시됩니다.)"); // [21]
            }
            else
            {
                Debug.LogWarning("[ADX Backend Ads] 표시할 배너 광고 인스턴스가 없습니다. LoadBannerAd를 먼저 호출해야 합니다."); // [21]
                OnAdError?.Invoke();
            }
        }

        ///
        /// 표시된 배너 광고를 숨깁니다.
        /// ADX SDK에서는 배너 광고 인스턴스를 파괴함으로써 숨기는 효과를 냅니다.
        ///
        public void HideBannerAd()
        {
            if (_bannerAd != null) // [11]
            {
                _bannerAd.Destroy(); // 광고 인스턴스 파괴
                _bannerAd = null;
                Debug.Log("[ADX Backend Ads] 배너 광고를 숨기고 파괴했습니다."); // [11]
            }
            else
            {
                Debug.LogWarning("[ADX Backend Ads] 파괴할 배너 광고 인스턴스가 없습니다."); // [11]
            }
        }

        ///
        /// 전면 광고를 로드합니다.
        ///
        /// 광고 단위 ID
        public async Task LoadInterstitialAsync(string adUnitId, CancellationToken cancellationToken = default)
        {
            if (!_adxProvider.IsInitialized.CurrentValue)
            {
                Debug.LogError("[ADX Backend Ads] ADX SDK가 초기화되지 않았습니다. 전면 광고를 로드할 수 없습니다."); // [11]
                OnAdError?.Invoke(); // 오류 이벤트 트리거
                return;
            }

            if (_interstitialAd == null)
            {
                _interstitialAd = new AdxInterstitialAd(adUnitId); // [11]

                // 이벤트 핸들러 등록
                _interstitialAd.OnAdLoaded += () =>
                {
                    Debug.Log("[ADX Backend Ads] 전면 광고 로드 성공."); // [22]
                };

                _interstitialAd.OnAdFailedToLoad += (error) =>
                {
                    Debug.LogError($"[ADX Backend Ads] 전면 광고 로드 실패: {error}"); // [22]
                    OnAdError?.Invoke(); // 오류 이벤트 트리거
                };

                _interstitialAd.OnAdClicked += () =>
                {
                    Debug.Log("[ADX Backend Ads] 전면 광고 클릭됨."); // [22]
                };

                _interstitialAd.OnAdShown += () =>
                {
                    Debug.Log("[ADX Backend Ads] 전면 광고 표시됨."); // [22]
                };

                _interstitialAd.OnAdClosed += () =>
                {
                    Debug.Log("[ADX Backend Ads] 전면 광고 닫힘."); // [22]
                };

                _interstitialAd.OnAdFailedToShow += () =>
                {
                    Debug.LogError($"[ADX Backend Ads] 전면 광고 표시 실패"); // [12]
                    OnAdError?.Invoke(); // 오류 이벤트 트리거
                };

                _interstitialAd.OnPaidEvent += (ecpm) =>
                {
                    // 예상 광고 수익 계산
                    double revenue = ecpm / 1000f; // [12]
                    Debug.Log($"[ADX Backend Ads] 전면 광고 수익 발생: {revenue} USD (eCPM: {ecpm})"); // [12]
                    OnAdRevenue?.Invoke("ADX Interstitial Ad", revenue); // 수익 이벤트 트리거
                };
            }

            _interstitialAd.Load(); // 광고 로드 요청 [12]
            Debug.Log($"[ADX Backend Ads] 전면 광고 로드 요청: {adUnitId}");
        }

        ///
        /// 로드된 전면 광고를 표시합니다.
        ///
        public void ShowInterstitialAd()
        {
            if (!_adxProvider.IsInitialized.CurrentValue)
            {
                Debug.LogError("[ADX Backend Ads] ADX SDK가 초기화되지 않았습니다. 전면 광고를 표시할 수 없습니다."); // [23]
                OnAdError?.Invoke();
                return;
            }

            if (_interstitialAd != null && _interstitialAd.IsLoaded()) // 광고가 로드되어 준비되었는지 확인 [24]
            {
                _interstitialAd.Show(); // 광고 표시 [23]
                Debug.Log("[ADX Backend Ads] 전면 광고 표시 요청.");
            }
            else
            {
                Debug.LogWarning("[ADX Backend Ads] 전면 광고가 로드되지 않았거나 아직 준비되지 않았습니다."); // [23]
                OnAdError?.Invoke(); // 오류 이벤트 트리거
            }
        }

        ///
        /// 전면 광고가 로드되어 표시 준비가 되었는지 확인합니다.
        ///
        /// 광고 준비 여부
        public bool IsInterstitialAdReady()
        {
            return _interstitialAd != null && _interstitialAd.IsLoaded(); // [13]
        }



        /// 보상형 광고를 로드합니다.                
        public async Task LoadRewardedAsync(string adUnitId, CancellationToken cancellationToken = default)
        {
            if (!_adxProvider.IsInitialized.CurrentValue)
            {
                Debug.LogError("[ADX Backend Ads] ADX SDK가 초기화되지 않았습니다. 보상형 광고를 로드할 수 없습니다."); // [13]
                OnAdError?.Invoke(); // 오류 이벤트 트리거
                return;
            }

            if (_rewardedAd == null)
            {
                _rewardedAd = new AdxRewardedAd(adUnitId);

                // 이벤트 핸들러 등록
                _rewardedAd.OnRewardedAdLoaded += () =>
                {
                    Debug.Log("[ADX Backend Ads] 보상형 광고 로드 성공."); // [13]
                };

                _rewardedAd.OnRewardedAdFailedToLoad += (error) =>
                {
                    Debug.LogError($"[ADX Backend Ads] 보상형 광고 로드 실패: {error}"); // [25]
                    OnAdError?.Invoke(); // 오류 이벤트 트리거
                };

                _rewardedAd.OnRewardedAdShown += () =>
                {
                    Debug.Log("[ADX Backend Ads] 보상형 광고 표시됨."); // [25]
                };

                _rewardedAd.OnRewardedAdClicked += () =>
                {
                    Debug.Log("[ADX Backend Ads] 보상형 광고 클릭됨."); // [25]
                };

                _rewardedAd.OnRewardedAdFailedToShow += () =>
                {
                    Debug.LogError($"[ADX Backend Ads] 보상형 광고 표시 실패"); // [25]
                    OnAdError?.Invoke(); // 오류 이벤트 트리거
                };

                _rewardedAd.OnRewardedAdEarnedReward += () =>
                {
                    Debug.Log("[ADX Backend Ads] 보상형 광고 보상 획득 이벤트 발생."); // [25]
                };

                _rewardedAd.OnRewardedAdClosed += () =>
                {
                    Debug.Log("[ADX Backend Ads] 보상형 광고 닫힘."); // [14]
                };

                _rewardedAd.OnPaidEvent += (ecpm) =>
                {
                    // 예상 광고 수익 계산
                    double revenue = ecpm / 1000f; // [14]
                    Debug.Log($"[ADX Backend Ads] 보상형 광고 수익 발생: {revenue} USD (eCPM: {ecpm})"); // [14]
                    OnAdRevenue?.Invoke("ADX Rewarded Ad", revenue); // 수익 이벤트 트리거
                };
            }

            _rewardedAd.Load(); // 광고 로드 요청 [14]
            Debug.Log($"[ADX Backend Ads] 보상형 광고 로드 요청: {adUnitId}");
        }

        ///
        /// 로드된 보상형 광고를 표시합니다.
        ///
        public void ShowRewardedAd()
        {
            if (!_adxProvider.IsInitialized.CurrentValue)
            {
                Debug.LogError("[ADX Backend Ads] ADX SDK가 초기화되지 않았습니다. 보상형 광고를 표시할 수 없습니다."); // [14]
                OnAdError?.Invoke();
                return;
            }

            if (_rewardedAd != null && _rewardedAd.IsLoaded()) // 광고가 로드되어 준비되었는지 확인 [26]
            {
                _rewardedAd.Show(); // 광고 표시 [26]
                Debug.Log("[ADX Backend Ads] 보상형 광고 표시 요청.");
            }
            else
            {
                Debug.LogWarning("[ADX Backend Ads] 보상형 광고가 로드되지 않았거나 아직 준비되지 않았습니다."); // [26]
                OnAdError?.Invoke(); // 오류 이벤트 트리거
            }
        }

        ///
        /// 보상형 광고가 로드되어 표시 준비가 되었는지 확인합니다.
        ///
        /// 광고 준비 여부
        public bool IsRewardedAdReady()
        {
            return _rewardedAd != null && _rewardedAd.IsLoaded(); // [26]
        }


    }
}

오류가 안나도록 

Async 코드를 수정해줘