Coordinator

낯선 언어를 매일 학습하며 몰입과 성장을 기록하는 일지

  ·  2 min read

구현 기능 사항 #

  • QR 코드 View 파일 생성

문제 상황 #

  • View에서 카메라를 사용하기 위해서는 UIViewcontrollerRepresentable의 필요 발생
  • UIKit의 Context를 매개변수로 받아 이용하는데 Context의 학습
  • SwiftUI에서 카메라 기능을 넣기 위해 살펴보니 UIKit 델리게이트 패턴에 대한 내용 발견
  • struct에서 class인 deligator를 쓰기 위해 Coordinator 패턴을 적용할 필요가 발생
  • Gemini, Claude를 통해 일단 템플릿 코드들을 보면서 대화식 학습 진행

개념 학습 #

UIViewControllerRepresentable #

  • 일종의 어댑터 패턴
  • SwiftUI와 UIKit(Camera) 사이의 어댑터 역할
  • 해당 프로토콜을 통해 Class를 Struct처럼 사용 가능

참고 #

  • SwiftUI는 무엇을 그릴지 선언하는 방식
  • 카메라는 어떻게 하드웨어를 단계벌로 제어할지의 명령형 방식 UIViewControllerRepresentable이 두 패러다임의 불일치를 해결해주는 가교 역할

Context #

Context는 SwiftUI 시스템이 UIKit(카메라)에게 전달하는 전체 정보

  • Context안에는 Coordinator와 Environment 들어있음
    • Context안의 Coordinator를 카메라의 Delegate로 임명
    • Context가 없다면 Coordinator에 접근할 방법이 없음
    • Environment는 시스템정보(다크 모드, 폰트 사이즈)와 같이 UIKit뷰가 SwiftUI 환경 설정을 읽어야 할 때 해당 정보를 사용

NSObject #

  • Swift는 struct기반, AVFoundation은 class기반
  • AVFoundation의 뿌리는 Objective-C(NSObject)
  • struct는 가볍지만 생성 후 사라지기를 반복
  • 카메라는 QR코드 촬영 후 해당 신호를 누구에게 전달해야 될지를 모르는 상황
  • SwiftUI 뷰는 계속 주소값이 바뀌거나 사라지므로 신호를 받을 수 없음
  • 따라서 SwiftUI안에 Coordinator(통역사)가 필요
  • Coordinator 클래스를 생성하며 이 클래스는 NSObject를 상속받아 안정적으로 카메라 신호를 수신

AVCaptureMetadataOutputObjectsDelegat #

  • AVCapture: 카메라와 상호작용
  • MetadataOutput: 영상 안에 숨겨진 정보 (QR 바코드) 결과
  • 카메라가 영상을 찍으면서 QR을 발견할 때마다 Delegate에게 알림

weak #

  • 약한 참조를 만드는데 사용
  • Swift는 ARC(Automatic Reference Counting)로 메모리 관리
  • 객체 참조할 때마다 참조 카운트 증가, 카운트가 0이 되면 메모리에서 해제
  • 강한 순환 참조를 방지하기 위해 사용
  • weak 참조는 항상 Optional이어야 함
  • 참조하던 객체가 해제되면 자동으로 nil 할당
  • delegate패턴이나 클로저에서 주로 사용됨
  • Java의 GC와 달리 개발자가 직접 명시적으로 관리해야 하는 부분이 낯섦

개발 과정 #

문제 상황 #

  1. QR코드 스캔 시 3 게임인 경우 2 게임은 [0,0,0,0,0,0]으로 출력되는 문제 발견

원인 #

  • 유효한 게임 데이터 뒤에 000으로 이루어진 더미 데이터나 체크섬이 붙어있는 경우 존재
  • 단순히 숫자만 추출하여 12자리씩 끊는 로직으로는 더미 데이터까지 모두 숫자 공으로 만드는 문제
  • 구분자가 q, n 그리고 m이 혼용되어 사용됨

n이 섞인 경우
q만 있는 경우

해결 과정 #

  • 유효성 검사 도입
    • 숫자가 정확히 6개인지 확인
    • 모든 숫자가 범위 내에 있는지 확인
    • 중복된 숫자가 없는 지 확인
  • 구분자 삭제 후 게임 데이터에 맞는 숫자들만 사용
    • 0으로만 이루어진 숫자 제거
    • 5게임 이후들의 숫자는 모두 무시
    • 한 게임당 12자리의 숫자(2자리씩 6개)만 사용

부가적 문제들 #

  • 테스트 시 와이파이 연결은 디버깅이 유실되는 문제 발생
    • QR코드를 촬영할 때는 후면 카메라가 필수이므로 시뮬레이터 사용 불가
    • 항상 유선 연결로 전환하여 사용해야 될 필요 느낌

배운 점과 인사이트 #

  • SwiftUI의 Context가 UIKit의 Delegate 패턴을 어떻게 연결해주는지 구조적으로 이해
  • 클라이언트는 언제나 더미가 섞인 데이터를 받을 수 있으므로 파싱 로직은 최대한 방어적으로 구현해야됨
  • 테스트는 항상 유선 연결을 통해 로그를 관찰