탭탭은 사파리 익스텐션을 기반으로 동작하는 앱입니다. 이 구조상 사파리 익스텐션과 네이티브 앱 간의 통신은 필수적입니다. 이번 글에서는 탭탭의 사파리 익스텐션이 네이티브 앱과 어떤 방식으로 소통하는지, 그리고 그 과정에서 고려한 설계 포인트들을 정리해보려 합니다.
통신 구조 설계
탭탭의 기획은 사파리 익스텐션에서 생성된 데이터(하이라이팅, 코멘트, 링크, 썸네일 등)를 쉐어 익스텐션을 통해 네이티브 앱으로 전달하는 구조였습니다. 즉, 사용자는 웹 페이지에서 컨텐츠를 수집하고, 해당 데이터는 네이티브 앱에 저장 및 관리되는 방식입니다.
Extensions run in their own address space. Communication between the extension and the app from which it was activated uses interprocess communications mediated by the system framework. They don’t have access to each other’s files or memory spaces. Extensions are designed to be isolated from each other, from their containing apps, and from the apps that use them. They are sandboxed like any other third-party app and have a container separate from the containing app’s container.
확장은 자체 주소 공간에서 실행됩니다. 확장 프로그램과 활성화된 앱 간의 통신은 시스템 프레임워크를 통해 매개되는 프로세스 간 통신을 사용합니다. 서로의 파일이나 메모리 공간에 접근할 수 없어요. 확장 프로그램은 서로로, 포함된 앱과 그것을 사용하는 앱들과도 격리되도록 설계되어 있습니다. 이들은 다른 서드파티 앱처럼 샌드박스 형태이며, 앱 내 컨테이너와는 별도의 컨테이너를 가지고 있습니다.
애플 가이드 문서 - How extensions communicate
이 과정에서 가장 큰 고민은 각 컴포넌트가 서로 독립적인 Sandbox 환경에서 실행된다는 점이었습니다. 사파리 익스텐션, 쉐어 익스텐션, 그리고 네이티브 앱은 각각 분리된 권한을 가지기 때문에, 일반적인 방식으로는 직접적인 데이터 접근이나 통신이 불가능합니다. 따라서 탭탭의 통신 아키텍처를 설계할 때 핵심은, 독립적으로 실행되는 환경에서 안정적이고 일관적인 데이터 전달 경로를 어떻게 설계할 것인가였습니다.
An app group allows multiple apps developed by the same team to access one or more shared containers. ... Apps can belong to one or more app groups. You can also use an app group to share data between an app extension or App Clip and its host app.
앱 그룹은 같은 팀이 개발한 여러 앱이 하나 이상의 공유 컨테이너에 접근할 수 있게 해줍니다. ... 앱 그룹을 사용해 앱 확장 프로그램이나 앱 클립과 호스트 앱 간에 데이터를 공유할 수도 있습니다.
애플 가이드 문서 - Configuring app groups
이 문제를 해결하기 위해 Apple의 공식 문서와 여러 레퍼런스를 조사했고, AppGroup을 활용하면 익스텐션과 네이티브 앱 간에 데이터를 공유할 수 있다는 점을 알게 되었습니다.
이를 바탕으로 탭탭은 다음과 같은 유저 플로우를 중심으로 통신 구조를 설계했습니다. 사용자가 사파리 익스텐션에서 데이터를 생성하고 공유하면, 해당 데이터는 쉐어 익스텐션을 통해 전달되고, 이후 AppGroup의 공유 컨테이너에 저장됩니다. 네이티브 앱은 이 공유 컨테이너를 통해 데이터를 읽어와 바인딩합니다.

이러한 구조를 통해 사파리 익스텐션, 쉐어 익스텐션, 네이티브 앱은 서로 직접적으로 의존하지 않으면서도, AppGroup을 통해 느슨하게 연결됩니다.
단일화 된 DB 구축
전체적인 통신 구조를 설계한 이후, DB 설계를 진행했습니다. 초기 단계에서는 명확한 사용 패턴과 요구사항이 정리되지 않은 상태였기 때문에, 다소 도전적인 DB 구조를 설계했습니다.
사파리 익스텐션에서 생성되는 데이터(하이라이팅, 코멘트 등)와 쉐어 익스텐션에서 추출되는 데이터(썸네일 이미지, URL 등)를 서로 다른 성격의 데이터로 보고, 이를 각각 분리된 DB에 저장하려는 방향으로 설계했습니다. 이러한 판단에는 기술적 제약도 있었습니다. 당시에는 사파리 익스텐션에서 생선된 데이터와 쉐어 익스텐션에서 추출한 데이터를 하나의 흐름으로 동시에 수집하는 방법을 명확히 알지 못했기 때문입니다. 각 익스텐션이 서로 독립적으로 동작하다 보니, 각 데이터를 한 시점에 묶어서 처리하는 것이 쉽지 않았고, 그 결과 데이터를 분리해 저장하는 구조를 선택하게 되었습니다.
하지만 이 방식은 한계가 있었습니다. 사파리 익스텐션 데이터와 쉐어 익스텐션 데이터는 서로 다른 컴포넌트에서 생성되었을 뿐, 사용자 관점에서는 하나의 컨텐츠를 구성하는 단일 데이터였기 때문입니다. 결국 네이티브 앱에서는 이 두 데이터를 하나의 뷰, 하나의 도메인 모델로함께 처리해야 했습니다.

이를 분리된 DB로 관리한다면, 공통 식별자를 기준으로 매번 데이터를 조합해야 했습니다. 이는 설계 단계에서부터 불필요한 복잡도를 증가시킨다고 판단했고, 사파리 익스텐션 데이터와 쉐어 익스텐션 데이터를 단일 도메인 모델로 보고 하나의 DB에서 관리하는 방향으로 구조를 재설계하게 되었습니다.
DB는 아래와 같은 이유로 SwiftData를 사용해 구현했습니다.
1. SwiftData는 SwiftUI와의 호환성이 뛰어나고, 모델 정의부터 상태 변화 반영까지 선언적으로 관리할 수 있다는 점에서 탭탭의 구조와 잘 맞다고 판단하였기 때문입니다.
2. 탭탭의 데이터 모델은 서로 관계를 맺는 복잡한 구조를 가지고 있어, 단순한 Key-Value 형태로 관리하기에는 한계가 있었습니다. 이러한 구조에서는 각 데이터 간의 관계를 명확하게 표현하고 관리하는 것이 필수적이었습니다. SwiftData는 모델 간의 관계를 코드로 직관적이고 명확하게 정의할 수 있기 때문에, 복잡한 데이터를 안정적으로 관리하는 데 적합하다고 판단했습니다.
탭탭의 통신 아키텍처

결과적으로 탭탭은 독립된 컴포넌트들이 AppGroup을 통해 안전하게 데이터를 주고받을 수 있는 구조를 갖추게 되었습니다. 또한 사파리 익스텐션과 쉐어 익스텐션에서 생성된 데이터를 단일화된 DB로 통합함으로써, UI와의 연동을 단순화할 수 있었습니다. 이러한 설계를 통해 탭탭은 샌드박스 환경에서도 안정적이고 일관적인 데이터 흐름을 확보할 수 있었고, 확장성과 유지보수 측면에서도 유리한 구조를 마련할 수 있었습니다.
다음 글에서는 쉐어 익스텐션에서 사파리 익스텐션 데이터를 추출하는 방법과, JavaScript를 활용하여 사파리 익스텐션 내에서 데이터를 핸들링하는 과정에 대해 자세히 다뤄보겠습니다. 이를 통해, 탭탭이 독립적인 컴포넌트 환경에서도 어떻게 하나의 흐름으로 데이터를 수집하고 단일 DB에 저장할 수 있는지 구체적으로 다뤄볼 예정입니다.
'탭탭 - TapTap > 개발일지' 카테고리의 다른 글
| [개발일지] 03. 신기하고 재밌는 탭탭 온보딩! 어떻게 구현했을까요? (0) | 2026.01.14 |
|---|---|
| [개발일지] 02. 쉐어 익스텐션에서 탭탭 익스텐션 데이터를 추출하는 방법 (0) | 2026.01.06 |