



프로젝트 소개
iOS에서 SMS 및 메시지 스팸을 필터링해주는 앱 스팸시러 - 문자 스팸 차단 필터링을 개발했습니다. 사용자가 등록한 키워드를 기반으로 자동으로 스팸 메시지를 차단하고, 차단된 메시지의 통계를 제공하는 기능을 갖춘 앱입니다.
생각보다 훨씬 복잡했습니다. 단순한 UI 앱이 아니라 iOS의 메시지 필터링 시스템과 통신하는 시스템 레벨의 기능이 필요했기 때문입니다.
기술 스택
- SwiftUI - 최신 UI 프레임워크로 모던한 인터페이스 구현
- Message Filter Extension - iOS 시스템 메시지 필터링 통합
- App Groups - 여러 타겟 간 데이터 공유
- UserDefaults - 영구 데이터 저장 및 동기화
- Google Mobile Ads - 광고 수익화
- Localization - 다국어 지원 (한국어, 영어, 중국어, 일본어)
가장 어려웠던 점들
1. Message Filter Extension 통합
문제: iOS의 Message Filter Extension은 실제 메시지를 필터링하는 시스템 레벨의 기능이지만, 개발 문서가 부족했습니다.
먼저 Message Filter Extension이 정확히 무엇인지 이해하는 것이 어려웠습니다. 이것은 단순한 앱의 추가 기능이 아니라, iOS 시스템과 직접 통신하는 별도의 프로세스입니다. 사용자의 메시지를 실시간으로 모니터링하고 필터링 여부를 결정해야 합니다.
해결 방법:
- Apple 공식 문서의 IdentityLookup 프레임워크 깊이 있게 학습
- ILMessageFilterExtension과 ILMessageFilterQueryHandling 프로토콜 이해
- 오프라인 필터링과 네트워크 필터링의 차이 구분
- 실제 디바이스에서 테스트 (시뮬레이터로는 완전히 작동하지 않음)
2. App Groups를 통한 데이터 공유
문제: 메인 앱과 Message Filter Extension은 서로 다른 프로세스이므로, 직접적인 메모리 공유가 불가능합니다.
처음에는 일반적인 UserDefaults를 사용했는데, 메인 앱에서 설정한 필터 단어가 Extension에서 읽어지지 않는 문제가 발생했습니다. 각각의 프로세스가 독립적인 UserDefaults 공간을 가지고 있기 때문입니다.
해결 방법:
App Groups를 사용하여 공유 UserDefaults를 구성했습니다.
// 메인 앱에서 설정 저장
if let userDefaults = UserDefaults(suiteName: "group.spama") {
userDefaults.set(selectedTags, forKey: "selectedTags2")
}
// Extension에서 설정 읽기
if let userDefaults = UserDefaults(suiteName: "group.spama") {
if let value = userDefaults.array(forKey: "selectedTags2") as? [String] {
// 필터링 처리
}
}
이를 위해 Xcode에서 각 타겟의 Signing & Capabilities에 App Groups를 추가하고 동일한 그룹 ID를 지정해야 했습니다.
3. 복잡한 SwiftUI 레이아웃
문제: 태그 기반의 유동적인 레이아웃을 구현하기가 어려웠습니다. 기본 SwiftUI 레이아웃으로는 원하는 디자인을 만들 수 없었습니다.
화면에 표시되는 태그의 개수가 가변적이므로, 한 줄에 맞는 만큼 보여주고 넘어가면 다음 줄로 가는 FlowLayout이 필요했습니다. HStack과 VStack만으로는 불가능했습니다.
해결 방법:
SwiftUI의 Layout 프로토콜을 구현하여 커스텀 레이아웃을 만들었습니다.
struct TagLayoutRedesigned: Layout {
var alignment: Alignment = .center
var spacing: CGFloat = 10
func sizeThatFits(proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) -> CGSize {
// 각 행의 높이를 계산하고 전체 크기 반환
}
func placeSubviews(in bounds: CGRect, ...) {
// 각 뷰의 위치를 정확히 배치
}
}
4. 통계 데이터 관리
문제: 차단된 메시지의 통계를 계속 기록하면 UserDefaults의 데이터가 계속 증가하여 성능 문제가 발생할 수 있습니다.
매 메시지가 필터링될 때마다 통계 데이터를 저장해야 하는데, UserDefaults에 저장된 데이터가 너무 커지면 읽기/쓰기 성능이 저하됩니다. 또한 JSON 인코딩/디코딩 오버헤드도 고려해야 했습니다.
해결 방법:
- FilterStatisticsManager 싱글톤 패턴으로 통계 관리 중앙화
- 메모리에 필터링된 메시지 리스트 유지
- 변경 사항만 UserDefaults에 저장
- 필요시 오래된 데이터 정리 기능 추가 고려
5. 다국어 지원
문제: 같은 기능의 앱이지만 각 국가마다 스팸 메시지의 특성이 다릅니다.
한국에서는 금융사기, 로또, 투자 관련 스팸이 많지만, 미국에서는 광고와 프로모션이 더 많습니다. 단순히 UI만 번역해서는 실제 유용한 앱이 될 수 없었습니다.
해결 방법:
디바이스의 언어 설정에 따라 추천 키워드를 동적으로 변경했습니다.
let preferredLanguages = Bundle.main.preferredLocalizations
if let preferredLanguage = preferredLanguages.first {
switch preferredLanguage {
case "ko":
recomendTags = ["광고","구독","급등","단타"...]
case "en":
recomendTags = ["Sale", "Discount", "Free"...]
case "zh-Hans":
recomendTags = ["特价", "优惠"...]
}
}
6. 광고 통합
문제: Google Mobile Ads를 통합하면서 사용자 경험을 해치지 않으면서도 수익을 창출해야 했습니다.
과도한 광고는 앱의 사용성을 떨어뜨립니다. 특히 필터 단어를 자주 추가하는 사용자 입장에서 매번 광고가 나타나면 불편합니다.
해결 방법:
- 3개의 태그 추가 후 1번의 전면 광고(Interstitial Ad) 표시
- 배너 광고는 하단에 고정
- InterstitialAdsManager로 광고 로드 시점 최적화
배운 교훈
1. 시스템 레벨 기능은 시뮬레이터로는 부족하다
Message Filter Extension은 실제 디바이스에서만 제대로 테스트할 수 있습니다. 아무리 완벽하게 시뮬레이터에서 작동해도, 실제 디바이스에서는 다를 수 있습니다.
2. 프로세스 간 통신의 복잡성을 과소평가하지 말자
두 개의 독립적인 프로세스가 데이터를 공유하려면 App Groups와 같은 공유 저장소를 사용해야 합니다. 이는 버그의 원인이 되기 쉽고 디버깅이 어렵습니다.
3. 사용자 경험을 위해 비즈니스 로직을 설계하라
기술적으로 가능한 것과 사용자가 원하는 것은 다릅니다. 예를 들어, 모든 메시지마다 통계를 저장할 수 있지만, 실제로는 효율적인 데이터 관리와 성능 최적화가 필요합니다.
4. 로컬라이제이션은 단순 번역이 아니다
다국어 앱은 단순히 텍스트를 번역하는 것이 아니라, 각 시장의 특성에 맞게 기능을 조정해야 합니다.
최종 후기
처음에는 간단한 메시지 필터링 앱이라고 생각했지만, 실제로는 iOS의 여러 심화된 개념들을 학습하고 적용해야 하는 좋은 기회였습니다.
이 프로젝트를 통해 배운 것들:
- Message Filter Extension의 동작 원리
- App Groups를 통한 프로세스 간 데이터 공유
- SwiftUI Layout 프로토콜을 이용한 커스텀 레이아웃
- 통계 데이터 관리의 성능 최적화
- 다국어 지원의 올바른 구현
- 광고 통합과 사용자 경험의 균형
특히 인상적이었던 점은, 작은 기능 하나를 제대로 구현하기 위해 얼마나 많은 기술과 고민이 필요한지 깨달았다는 것입니다. 사용자 입장에서는 단순한 필터링 기능이지만, 뒤에는 복잡한 시스템이 작동하고 있었습니다.
이 경험이 더 나은 개발자가 되는 데 큰 도움이 되었습니다.
앱 다운로드
iOS 사용자분들도 실제로 사용해보고 싶으시다면 App Store에서 스팸시러를 검색하여 다운로드할 수 있습니다.
스팸시러 - 문자 스팸 차단 필터링
스마트한 스팸 필터링으로 안전한 메시지 환경을 만드세요
'개발' 카테고리의 다른 글
| 트럼프코인 / 밈코인 사는법 / 문샷 / 비상장코인 구매하기 (0) | 2025.01.19 |
|---|---|
| git 오류 ] fatal: unable to access 'https://github.com....': SSL certificate problem: unable to get local issuer certificate (0) | 2022.10.05 |
| swift] tableview를 그룹으로 만들었을때 테이블뷰 위에 영역이 잡히는 문제 (0) | 2021.11.12 |
| swift] 업데이트시 마이그레이션을 위한 버전 체크 (0) | 2021.08.06 |
| swift] SPM 만들기 - UIImage에 module의 image 선언하기 (0) | 2021.08.04 |