다음을 통해 공유


App Center 충돌(macOS)

중요합니다

Visual Studio App Center는 2026년 6월 30일까지 계속 지원되는 분석 및 진단 기능을 제외하고 2025년 3월 31일에 사용 중지되었습니다. 자세히 알아보기.

App Center 크래시는 앱이 크래시할 때마다 자동으로 크래시 로그를 생성합니다. 로그는 먼저 디바이스의 스토리지에 기록되며 사용자가 앱을 다시 시작하면 크래시 보고서가 App Center로 전송됩니다. 크래시 수집은 베타 및 라이브 앱( 즉, App Store에 제출된 앱)에서 모두 작동합니다. 크래시 로그에는 충돌을 해결하는 데 도움이 되는 중요한 정보가 포함되어 있습니다.

애플리케이션에서 SDK를 아직 설정하지 않은 경우 시작 섹션을 따릅니다.

또한 macOS의 충돌 로그에는 기호화가 필요하며 앱에 기호를 제공하는 방법을 설명하는 App Center 진단 설명서를 확인하세요.

비고

4.0.0 버전의 App Center에서 중대한 변경 사항이 도입되었습니다. App Center SDK 4.0.0 이상으로 마이그레이션 섹션에 따라 이전 버전에서 App Center를 마이그레이션합니다.

확장의 충돌 보고서

App Center는 macOS 확장에서 크래시 보고를 지원합니다. 사용량은 컨테이너 애플리케이션에서와 동일합니다.

테스트 크래시 생성

App Center Crashes 기능은 SDK를 쉽게 테스트할 수 있도록 테스트 크래시를 생성하는 API를 제공합니다. 이 API는 테스트/베타 앱에서만 사용할 수 있으며 프로덕션 앱에서는 아무 작업도 수행하지 않습니다.

[MSACCrashes generateTestCrash];
Crashes.generateTestCrash()

이전 충돌에 대한 자세한 정보 가져오기

App Center 크래시에는 앱이 충돌하는 경우에 더 많은 정보를 제공하는 두 개의 API가 있습니다.

앱이 이전 세션에서 메모리 부족 경고를 받았나요?

SDK를 시작한 후 언제든지 앱이 이전 세션에서 메모리 경고를 받았는지 확인할 수 있습니다.

[MSACCrashes hasReceivedMemoryWarningInLastSession];
Crashes.hasReceivedMemoryWarningInLastSession

비고

이 메서드는 시작된 후에 Crashes 만 사용해야 하며, 항상 반환 NO 되거나 false 시작되기 전에 사용해야 합니다.

비고

경우에 따라 메모리가 낮은 디바이스는 이벤트를 보낼 수 없습니다.

이전 세션에서 앱이 충돌했나요?

SDK를 시작한 후 언제든지 이전 시작에서 앱이 충돌했는지 확인할 수 있습니다.

[MSACCrashes hasCrashedInLastSession];
Crashes.hasCrashedInLastSession

이는 크래시가 발생한 후 앱의 동작 또는 UI를 조정하려는 경우에 유용합니다.

비고

이 메서드는 시작된 후에 MSACCrashes 만 사용해야 하며, 항상 반환 NO 되거나 false 시작되기 전에 사용해야 합니다.

마지막 충돌에 대한 세부 정보

앱이 이전에 충돌한 경우 마지막 충돌에 대한 세부 정보를 얻을 수 있습니다.

MSACErrorReport *crashReport = [MSACCrashes lastSessionCrashReport];
var crashReport = Crashes.lastSessionCrashReport

비고

이 메서드는 Crashes가 시작된 후에만 사용해야 합니다. 시작하기 전에 항상 nil을 반환합니다.

이 API에는 다양한 사용 사례가 있으며, 가장 일반적인 사례는 이 API를 호출하고 사용자 지정 CrashesDelegate를 구현하는 사용자입니다.

App Center 크래시에 대한 사용을 맞춤 설정하기

App Center 충돌 관리 시스템은 개발자가 크래시 로그를 App Center로 보내기 전에 또는 보낼 때 추가 작업을 수행할 수 있는 콜백을 제공합니다.

사용자 지정 동작을 추가하려면 -protocol을 CrashesDelegate채택해야 합니다. 모든 메서드는 선택 사항입니다.

대리자로 등록

[MSACCrashes setDelegate:self];
Crashes.delegate = self

비고

App Center가 시작 직후에 크래시 처리를 시작하기 때문에 호출AppCenter.start 대리자를 설정해야 합니다.

크래시가 처리되어야 하나요?

crashes:shouldProcessErrorReport:-메서드를 구현하려면, 특정 크래시가 처리되어야 하는지 결정하고자 할 때, CrashesDelegate-프로토콜을 채택하는 클래스에 구현하십시오. 예를 들어, 무시하고 App Center로 보내지 않으려는 시스템 수준의 충돌이 있을 수 있습니다.

- (BOOL)crashes:(MSACCrashes *)crashes shouldProcessErrorReport:(MSACErrorReport *)errorReport {
  return YES; // return YES if the crash report should be processed, otherwise NO.
}
func crashes(_ crashes: Crashes, shouldProcess errorReport: ErrorReport) -> Bool {
  return true; // return true if the crash report should be processed, otherwise false.
}

처리된 오류

App Center를 사용하면 trackError 메서드를 통해 처리된 예외를 사용하여 오류를 추적할 수도 있습니다. 앱은 필요에 따라 속성 또는/및 첨부 파일을 처리된 오류 보고서에 첨부하여 추가 컨텍스트를 제공할 수 있습니다.

@try {
  // Throw error.
} @catch (NSError *error) {

  // Init attachments.
  NSArray<MSACErrorAttachmentLog *> attachments = @[ MSACErrorAttachmentLog attachmentWithText:@"Hello world!" filename:@"hello.txt"] ]

  // Init properties.
  NSDictionary *properties = @{ "Category" : "Music", "Wifi" : "On" };

  // Track errors.
  [MSACCrashes trackError:error withProperties:properties attachments:attachments];
  [MSACCrashes trackError:error withProperties:properties attachments:nil];
  [MSACCrashes trackError:error withProperties:nil attachments:attachments];
  [MSACCrashes trackError:error withProperties:nil attachments:nil];
}
do {
  // Throw error.
} catch {

  // Init attachments.
  let attachments = [ErrorAttachmentLog.attachment(withText: "Hello world!", filename: "hello.txt")]

  // Init properties.
  let properties:Dictionary<String, String> = ["Category" : "Music", "Wifi" : "On"]

  // Track errors.
  Crashes.trackError(error, properties: properties, attachments: attachments)
  Crashes.trackError(error, properties: properties, attachments: nil)
  Crashes.trackError(error, properties: nil, attachments: attachments)
  Crashes.trackError(error, properties: nil, attachments: nil)
}

예외를 추적하기 위해 trackException 메서드를 사용할 수 있습니다.

@try {
  // Throw exceptions.
} @catch (NSException *exception) {

  // Init exceptions.
  MSACExceptionModel *customException1 = [MSACExceptionModel initWithType:@"Custom exception" exceptionMessage:"Track custom exception.", stackTrace:exception.callStackSymbols];
  MSACExceptionModel *customException2 = [MSACExceptionModel initWithException:exception];

  // Track exceptions.
  [MSACCrashes trackException:customException1 withProperties:properties attachments:nil];
  [MSACCrashes trackException:customException2 withProperties:properties attachments:nil];
}
do {
  // Throw exception.
} catch {

  // Init exception.
  let exception = ExceptionModel(withType: "Custom exception", exceptionMessage: "Track custom exception.", stackTrace: Thread.callStackSymbols)

  // Track exception.
  Crashes.trackException(exception, properties: properties, attachments: nil)
}

사용자 개인 정보가 중요한 경우 App Center에 크래시 보고서를 보내기 전에 사용자 확인을 받을 수 있습니다. SDK는 충돌 보고서를 보내기 전에 사용자 확인을 기다리도록 App Center Crashs에 지시하는 콜백을 노출합니다.

이렇게 하려면 사용자의 확인(예: 항상 보내기, 보내기보내지 않음) 옵션 중 하나가 포함된 대화 상자 프롬프트를 통해 사용자의 확인을 받을 책임이 있습니다. 입력에 따라 App Center에 수행할 작업을 알려 주며 그에 따라 크래시가 처리됩니다.

비고

SDK는 이에 대한 대화 상자를 표시하지 않습니다. 앱은 사용자 동의를 요청하는 자체 UI를 제공해야 합니다.

다음 메서드는 사용자 확인 처리기를 설정하는 방법을 보여줍니다.

[MSACCrashes setUserConfirmationHandler:(^(NSArray<MSACErrorReport *> *errorReports) {

  // Your code to present your UI to the user, e.g. an NSAlert.
  NSAlert *alert = [[NSAlert alloc] init];
  [alert setMessageText:@"Sorry about that!"];
  [alert setInformativeText:@"Do you want to send an anonymous crash report so we can fix the issue?"];
  [alert addButtonWithTitle:@"Always send"];
  [alert addButtonWithTitle:@"Send"];
  [alert addButtonWithTitle:@"Don't send"];
  [alert setAlertStyle:NSWarningAlertStyle];

  switch ([alert runModal]) {
  case NSAlertFirstButtonReturn:
    [MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationAlways];
    break;
  case NSAlertSecondButtonReturn:
    [MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationSend];
    break;
  case NSAlertThirdButtonReturn:
    [MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationDontSend];
    break;
  default:
    break;
  }

  return YES; // Return YES if the SDK should await user confirmation, otherwise NO.
})];
Crashes.setUserConfirmationHandler({ (errorReports: [ErrorReport]) in

  // Your code to present your UI to the user, e.g. an NSAlert.
  let alert: NSAlert = NSAlert()
  alert.messageText = "Sorry about that!"
  alert.informativeText = "Do you want to send an anonymous crash report so we can fix the issue?"
  alert.addButton(withTitle: "Always send")
  alert.addButton(withTitle: "Send")
  alert.addButton(withTitle: "Don't send")
  alert.alertStyle = NSWarningAlertStyle

  switch (alert.runModal()) {
  case NSAlertFirstButtonReturn:
    Crashes.notify(with: .always)
    break;
  case NSAlertSecondButtonReturn:
    Crashes.notify(with: .send)
    break;
  case NSAlertThirdButtonReturn:
    Crashes.notify(with: .dontSend)
    break;
  default:
    break;
  }

  return true // Return true if the SDK should await user confirmation, otherwise return false.
})

위의 처리기 블록에서 반환 YES/true 하는 경우 앱은 다음 API를 사용하여 사용자 권한을 얻고 결과와 함께 SDK에 메시지를 보내야 합니다. 위의 샘플에서와 같이 이에 대한 경고를 사용하는 경우 호출 결과(ModalResponse) runModal 를 기반으로 호출합니다.

// Depending on the user's choice, call notifyWithUserConfirmation: with the right value.
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationDontSend];
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationSend];
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationAlways];
// Depending on the user's choice, call notify(with:) with the right value.
Crashes.notify(with: .dontSend)
Crashes.notify(with: .send)
Crashes.notify(with: .always)

주 스레드에서 발생한 처리되지 않은 예외를 포착하도록 설정합니다.

AppKit은 주 스레드에서 throw된 예외를 catch하여 애플리케이션이 macOS에서 충돌하는 것을 방지하므로 SDK는 이러한 충돌을 catch할 수 없습니다. SDK를 초기화하기 전에 iOS 동작을 모방하기 위해 NSApplicationCrashOnExceptions 플래그를 설정하십시오. 이 플래그를 설정하면 애플리케이션이 잡히지 않은 예외로 인해 충돌할 수 있으며, SDK는 이를 보고할 수 있습니다.

[[NSUserDefaults standardUserDefaults] registerDefaults:@{ @"NSApplicationCrashOnExceptions" : @YES }];
UserDefaults.standard.register(defaults: ["NSApplicationCrashOnExceptions": true])

비고

App Center SDK는 버전 1.10.0 이하에서 플래그를 자동으로 설정합니다. 버전 1.11.0부터 이 플래그는 더 이상 자동으로 설정되지 않습니다.

App Center 크래시로 애플리케이션 주 클래스의 메서드 호출 전달 사용 안 함

App Center 크래시 SDK는 스위즐링을 사용하여 애플리케이션 기본 클래스의 메서드 호출 중 일부를 전달하여 통합을 개선합니다. 메서드 스위즐링은 런타임에 메서드의 구현을 변경하는 방법입니다. 어떤 이유로든 스위즐링을 사용하지 않으려는 경우(예: 특정 정책으로 인해), 주 스레드에서 발생한 예외를 올바르게 보고할 수 있도록 해야 하며, 이를 위해서는 애플리케이션의 reportException:sendEvent: 메서드를 직접 재정의해야 합니다.

  1. ReportExceptionApplication.m 파일을 만들고 다음 구현을 추가합니다.

    @import Cocoa;
    @import AppCenterCrashes;
    
    @interface ReportExceptionApplication : NSApplication
    @end
    
    @implementation ReportExceptionApplication
    
    - (void)reportException:(NSException *)exception {
      [MSACCrashes applicationDidReportException:exception];
      [super reportException:exception];
    }
    
    - (void)sendEvent:(NSEvent *)theEvent {
      @try {
        [super sendEvent:theEvent];
      } @catch (NSException *exception) {
        [self reportException:exception];
      }
    }
    
    @end
    

    비고

    Swift는 try/catch와 함께 작동하지 않습니다 NSException. 이러한 예외는 Objective-C에서만 처리할 수 있습니다.

  2. Info.plist 파일을 열고 보안 주체 클래스 필드의 NSApplication을 애플리케이션 클래스 이름인 ReportExceptionApplication으로 바꿉니다.

  3. App Center SDK에서 스위즐링을 사용하지 않도록 설정하려면 AppCenterApplicationForwarderEnabled 파일에 키를 추가하고 값을 0.로 설정합니다.

크래시 로그의 전송 상태에 대한 정보 가져오기

때때로 앱 크래시 상태를 알고 싶을 수 있습니다. 일반적인 사용 사례는 앱이 크래시 보고서를 제출하고 있음을 사용자에게 알리는 UI를 표시하거나, 앱이 출시 후 빠르게 충돌하는 경우 크래시 로그를 제출할 수 있도록 앱의 동작을 조정하려고 할 수 있습니다. CrashesDelegate 프로토콜은 앱에서 어떤 일이 일어나고 있는지 알림을 받을 수 있도록 사용할 수 있는 세 가지 콜백을 정의합니다.

다음 콜백은 SDK가 크래시 로그를 보내기 전에 호출됩니다.

- (void)crashes:(MSACCrashes *)crashes willSendErrorReport:(MSACErrorReport *)errorReport {
  // Your code, e.g. to present a custom UI.
}
func crashes(_ crashes: Crashes, willSend errorReport: ErrorReport) {
  // Your code, e.g. to present a custom UI.
}

엔드포인트에 네트워크 문제나 장애가 발생하여 앱을 willSendErrorReport 재시작하면, 프로세스가 다시 시작될 때 willSendErrorReport가 다시 트리거됩니다.

다음 콜백은 SDK가 크래시 로그를 성공적으로 보낸 후에 호출됩니다.

- (void)crashes:(MSACCrashes *)crashes didSucceedSendingErrorReport:(MSACErrorReport *)errorReport {
  // Your code, e.g. to hide the custom UI.
}
func crashes(_ crashes: Crashes, didSucceedSending errorReport: ErrorReport) {
  // Your code goes here.
}

SDK에서 크래시 로그를 보내지 못한 경우 다음 콜백이 호출됩니다.

- (void)crashes:(MSACCrashes *)crashes didFailSendingErrorReport:(MSACErrorReport *)errorReport withError:(NSError *)error {
  // Your code goes here.
}
func crashes(_ crashes: Crashes, didFailSending errorReport: ErrorReport, withError error: Error) {
  // Your code goes here.
}

수신은 didFailSendingErrorReport4xx 코드와 같은 복구할 수 없는 오류가 발생했음을 의미합니다. 예를 들어 401 은 잘못된 것을 의미합니다 appSecret .

이 콜백은 네트워크 문제인 경우 트리거되지 않습니다. 이 경우 SDK는 계속 다시 시도하며 네트워크 연결이 중단되는 동안 다시 시도를 일시 중지합니다.

크래시 보고서에 첨부 파일 추가

크래시 보고서에 이진 및 텍스트 첨부 파일을 추가할 수 있습니다. SDK는 크래시와 함께 보내므로 App Center 포털에서 볼 수 있습니다. 다음 콜백은 이전 애플리케이션 시작에서 저장된 크래시 보내기 직전에 호출됩니다. 충돌이 발생하면 호출되지 않습니다. 다음은 충돌 발생에 텍스트와 이미지를 연결하는 방법의 예입니다.

- (NSArray<MSACErrorAttachmentLog *> *)attachmentsWithCrashes:(MSACCrashes *)crashes
                                             forErrorReport:(MSACErrorReport *)errorReport {
  MSACErrorAttachmentLog *attachment1 = [MSACErrorAttachmentLog attachmentWithText:@"Hello world!" filename:@"hello.txt"];
  MSACErrorAttachmentLog *attachment2 = [MSACErrorAttachmentLog attachmentWithBinary:[@"Fake image" dataUsingEncoding:NSUTF8StringEncoding] filename:@"fake_image.jpeg" contentType:@"image/jpeg"];
  return @[ attachment1, attachment2 ];
}
func attachments(with crashes: Crashes, for errorReport: ErrorReport) -> [ErrorAttachmentLog]? {
  let attachment1 = ErrorAttachmentLog.attachment(withText: "Hello world!", filename: "hello.txt")
  let attachment2 = ErrorAttachmentLog.attachment(withBinary: "Fake image".data(using: String.Encoding.utf8), filename: nil, contentType: "image/jpeg")
  return [attachment1!, attachment2!]
}

비고

크기 제한은 현재 7MB입니다. 더 큰 첨부 파일을 보내려고 하면 오류가 트리거됩니다.

런타임에 App Center 충돌 사용 또는 사용 안 함

런타임에 App Center 크래시 기능을 사용하거나 사용하지 않도록 설정할 수 있습니다. 사용하지 않도록 설정하면 SDK에서 앱에 대한 크래시 보고를 수행하지 않습니다.

[MSACCrashes setEnabled:NO];
Crashes.enabled = false

App Center 크래시를 다시 사용하도록 설정하려면 동일한 API를 사용하고 YES/true를 매개 변수로 전달하세요.

[MSACCrashes setEnabled:YES];
Crashes.enabled = true

상태는 애플리케이션 시작 시 디바이스의 스토리지에 유지됩니다.

비고

이 메서드는 Crashes가 시작된 후에만 사용해야 합니다.

App Center 크래시가 사용하도록 설정되어 있는지 확인

App Center Crashes가 사용 설정되어 있는지 여부를 확인할 수 있습니다.

BOOL enabled = [MSACCrashes isEnabled];
var enabled = Crashes.enabled

비고

이 메서드는 Crashes가 시작된 후에만 사용해야 합니다. 시작하기 전에 항상 false을 반환합니다.

Mach 예외 처리 사용 안 림

기본적으로 App Center 크래시는 마하 예외 처리기를 사용하여 마하 예외 서버를 통해 치명적인 예외 신호(예: 스택 오버플로)를 처리합니다.

disableMachExceptionHandler-방법은 Mach 예외 서버를 통해 치명적인 신호를 포착하는 기능을 비활성화할 옵션을 제공합니다. Mach 예외 처리기를 사용하지 않도록 설정하려면 SDK를 시작하기 전에 이 메서드를 호출해야 합니다. 일반적인 설치 코드는 다음과 같습니다.

[MSACCrashes disableMachExceptionHandler];
[MSACAppCenter start:@"{Your App Secret}" withServices:@[[MSACAnalytics class], [MSACCrashes class]]];
Crashes.disableMachExceptionHandler()
AppCenter.start(withAppSecret: "{Your App Secret}", services: [Analytics.self, Crashes.self])