-
Assert 없애기JDTuner/개발기록 2026. 3. 3. 20:12
앱 빌드하면 처음에 항상 CoreMidi 관련 Assert가 나왔다.
너무 불편. 이 현상을 없애기 위해 했던 기록이다.
카테고리로 어느 정도 스포가 됐는데 개발 환경 설정 문제가 아니라 코드 안쪽 내용이었다!!
문제점
JUCE Assertion failure in juce_CoreMidi_mac.mm:529 JUCE Assertion failure in juce_CoreMidi_mac.mm:1078 JUCE Assertion failure in juce_MidiDeviceListConnectionBroadcaster.cpp:222앱 빌드하면 항상 이 Assert가 나오면서 멈췄다.
앱 구동과 기능에 문제 없어 보이지만 빌드하자마자 확인해야할거도 있는데 불편했었다.
원인

juce_CoreMidi_mac.mm의 529 줄 코드 스레드 문제였다!!
JUCE는 오디오 스레드와 메세지 스레드가 있는데
오디오 스레드는 iOS에서 UI 담당하는것과 같이 최대한 오디오 코드만 들어가야 한다.

Wrapper를 주석처리하니 나오지 않는 Assert Wrapper의 init에 engine 초기화 코드가 있다.
이 engine 객체를 메세지 스레드가 아닌곳에서 생성하고 있는게 문제였다.
engine에서 AudioDeviceManager를 사용하고 있어 메세지 루프를 사용해야한다.
해결방식
- (instancetype)init { self = [super init]; // 인스턴스 초기화 확인 방어코드 if (self) { // 엔진 객체를 생성합니다. static juce::ScopedJuceInitialiser_GUI guiInitialiser; engine = std::make_unique<JDTunerEngine>(); } return self; }Wrapper의 초기화 코드를 수정했다.
juce::ScopedJuceInitialiser_GUI가 생성되면 메세지 스레드를 사용하기 위한 환경이 세팅이 된다.
따라서 juce::ScopedJuceInitialiser_GUI의 생성으로 스레드 문제가 해결됐다.
static인 이유는 MIDI assert는 사라졌지만 asyncupdater assert는 계속 나왔다.
juce::ScopedJuceInitialiser_GUI를 static으로 만들어 메세지 스레드 환경이 유지될 수 있도록 했다.
정리
JUCE의 AudioDeviceManager나 AsyncUpdater 같은 컴포넌트는
내부적으로 Message Manager(메시지 루프)에 의존하며, 반드시 이 루프가 활성화된 스레드에서 생성 및 관리되어야 한다.
juce::ScopedJuceInitialiser_GUI를 생성함으로써 iOS 환경 내에 JUCE 전용 메시지 스레드 인프라를 구축해 문제를 해결했다.
특히 이를 **static**으로 선언한 이유는,
초기화 객체가 함수 스코프를 벗어나 소멸될 경우 메시지 루프가 즉시 종료되어 AsyncUpdater 관련 Assert가 재발하기 때문으로
이를 정적으로 유지함으로써 앱의 생명 주기 동안 메시지 스레드 환경이 영구적으로 보존되도록 조치했다.
'JDTuner > 개발기록' 카테고리의 다른 글
튜너 UI 구현 (0) 2026.03.08 Cents 계산 (0) 2026.03.04 주파수 검출 구현하기 2. (1) 2026.02.24 주파수 검출 구현하기 1. (0) 2026.02.20 디바이스 삭제와 마이크 입력 확인 (0) 2026.02.20