택스리펀 계산기는 해외여행 중 발생하는 부가세 환급(Tax Refund)을 당일 환율로 쉽게 계산해주는 앱입니다.
- 구매금액 입력만으로 환급 예상 금액과 내 화폐 기준 가격을 확인 가능
- 환급액 기록 및 여행별 지출 정리
- 8개 언어 지원 / 173개국 출시
| Names | GitHub | Parts |
|---|---|---|
| 이재건 | @Quaker-Lee | 시작화면, 계산화면, 설정화면, 프로젝트 초기 세팅, 앱배포 |
| 나영진 | @bryjna07 | 기록화면, 환율화면, 파이어베이스 세팅 |
개발 - 2025.04.28 ~ 2025.06.27
업데이트 - 2025.06.27 ~ ing
리팩토링 - 2025.07.14 ~ ing
- 전 세계 173개국에서 자유롭게 사용 가능
- 각 국가별 통화 및 환급(부가가치세/VAT) 정책 반영
- 다양한 언어와 국가별 환경에 최적화된 사용자 경험 제공
- 매일 최신 환율 데이터를 자동 반영
- Firebase를 통한 신뢰성 높은 환율 정보 제공
- 구매금액, 환급금, 환급 후 실수령 금액을 내가 사용하는 화폐로 즉시 확인
- 구매금액만 입력하면 예상 환급액과 실제 내 화폐로 환급받을 금액을 즉시 확인
- 각 국가의 VAT(부가세) 정책에 맞춘 환급액 자동 계산
- 복잡한 공식이나 수식 없이 누구나 쉽게 사용 가능
- 구매한 물품별로 기록을 남겨 여행 전체 지출 및 환급액을 한눈에 파악
- 나라별·여행별로 기록을 분류하여 체계적으로 관리
- 총 지출 금액, 총 환급액 등 여행 경비를 쉽게 확인
- 한국어, 영어, 일본어, 스페인어, 독일어, 프랑스어, 이탈리아어, 러시아어 등 8개 언어 지원
- 모든 화면과 안내 메시지가 현지 언어로 자연스럽게 제공
- 소형 기기(아이폰 SE 등) 완벽 지원
- 다크모드 및 접근성 기능 제공
- 사용자 개인정보를 절대 수집, 저장, 전송하지 않음
- 모든 기록은 오직 로컬(사용자 기기)에서만 관리
- App Store 개인정보 보호 가이드라인 100% 준수
- 기준 통화와 여행 국가의 중복 선택 방지
- 실시간 입력값 검증으로 입력 실수 최소화
- 각 국가별 숫자 표기법/통화 단위 로컬라이징
- 쉽고 빠른 국가, 통화, 언어 선택 및 자동 저장
- UIKit: 인터페이스 구현
- SnapKit: 코드 기반 AutoLayout
- Then: 선언형 UI 구성
- Firebase Firestore: 데이터베이스
- Combine: 비동기 데이터 스트림 및 이벤트 처리
- RxSwift + RxCocoa: 비동기 스트림 처리 및 UI 반응형 바인딩
- UserDefaults: 로컬 저장소 관리
- Protocol-Delegate: 모달 및 팝업 데이터 전달
- MVVM: 화면(View)과 데이터(Model) 분리, ViewModel을 통한 데이터 바인딩
- Singleton: 전역에서 단 하나의 인스턴스만 사용
- FreeCurrencyAPI: 실시간 환율 API
- iOS 16.0+
- Swift 5.0+
| ViewModel | 사용하는 모델/서비스 |
|---|---|
StartVM |
ExchangeRateAPIService, ExchangeSyncManager, FirebaseExchangeService, RefundCondition, CurrencyDisplayUnit |
CalculateVM |
SavedCard, RefundCondition, CurrencyDisplayUnit, SaveUserDefaults |
SavedVM |
SavedCard, SaveUserDefaults |
SavedModalVM |
SavedCard, SaveUserDefaults, RefundCondition |
ExchangeVM |
FirebaseExchangeService, CurrencyDisplayUnit |
SettingVM |
ExchangeRateAPIService, FirebaseExchangeService, SaveUserDefaults |
- 사용 기술: RxSwift, FirebaseFireStore, FreeCurrencyAPI
- 앱 실행 시, ExchangeSyncManager(싱글톤)가 RxSwift 기반 비동기 체인(.flatMap, .catch, .subscribe 등 연산자 활용)으로 환율 데이터 동기화 수행
- 오늘 날짜와 Firebase 내 환율 데이터 날짜를 비교,
오늘 데이터가 없는 경우에만 API 호출 → Firebase 업데이트
- 오늘 날짜와 Firebase 내 환율 데이터 날짜를 비교,
- 사용 기술: MVVM + RxSwift, RxCocoa, FirebaseFireStore, FreeCurrencyAPI
- 기준 화폐·여행 국가 선택 → 환율/환급조건 안내
- 국기-정책 매칭(getRefundPolicy, RefundCondition.flagToPolicyMap)
- RxSwift
BehaviorRelay를 활용, 환율 정보와 안내문 텍스트 실시간 바인딩
- 사용 기술: MVVM + Combine, 사용자 입력 검증, UserDefaults
- 구매 금액 입력 → 해당 국가 부가세율 기반 환급액 자동 계산
isValidFloatingPoint로 실시간 입력 제한- 천 단위/소수점 등 국가별 포맷 파싱(parseLocalizedNumber), 유럽식/영미식 등 자동 대응
- 환급액 계산, 환급액 환산, 저장 로직 분리
- 결과는 기준 화폐로 환산, 구매/환급/변환 금액 등 전체 상태를 SavedCard에 저장
- 저장·표시 전 포맷 가공(
roundedString) SettingPage에서 화폐/국가 변경 시 Combine 기반으로 UI 자동 갱신
- 사용 기술: MVVM + RxSwift, RxCocoa, UserDefaults + Codable, Fastis
- Rx 상태관리, 저장 기록 리스트 출력
- Fastis 라이브러리로 날짜·화폐별 동시 필터링(RxCombineLatest 활용)
- 기록 상세정보 모달에서 저장 당시 환율·환급 조건 제공
- 화폐별 분류 및 총액 합산 기능 지원
- 사용 기술: MVVM + RxSwift, RxCocoa, Combine, FirebaseFireStore
- 기준 화폐/여행 국가 변경 시 실시간 환율 갱신 (Combine, Rx 혼합 구조)
- Firebase에 저장된 환율 기반, 필요 시 API 자동 갱신
- 주요 통화코드 우선 정렬 및 국가별 표기 대응
- Double+Formatted로 포맷 대응, 환율 표시는 항상 2자리 소수점
- 사용 기술: MVVM + RxSwift, Combine, FirebaseFireStore, UserDefaults, UIKit 다크모드
- 기준 통화, 여행국가 변경 시 환율정보 연동 관리
- SettingVM.shared 싱글톤 형태로 전역 관리
- Combine, Rx 동시 사용(호환성/호출 예시 등)
- 다크모드 값 변경 시 즉시 반영, 기록 삭제·초기화 기능(UserDefaults 리셋)
- Double 확장으로 국가별 로케일/천 단위/소수점 구분자 자동 반영
- 국가별로 소수점 이하 자리수 지정 가능(기본 2자리)
- 소수점 이하가 0인 경우, 소수점 및 0 제거
- 8개 언어, 정책·환율 안내·에러 안내 등 전 UI 다국어화
- 포맷 문자열(최소 금액/통화/환급율 등)도 현지화, 인자순서 국가별로 조정
앱이 시작될 때, ExchangeSyncManager를 통해 오늘 날짜 기준 환율 데이터를 Firebase에서 조회합니다.
- ✅ 데이터 존재 → 아무 동작 없음
- ❌ 데이터 없음 → 외부 환율 API에서 요청 후 Firebase에 저장
사용자가 기준 통화 또는 여행 국가를 선택하면, Firebase에서 동기화된 환율을 기반으로 당일 환율을 표시합니다.
TaxRefundCalculator/
├── Application/ # AppDelegate, SceneDelegate
├── Resources/ # Assets, LaunchScreen
├── SupportingFiles/ # Info.plist, GoogleService-Info.plist
├── API/ # API 통신 계층
├── CalculatePage/ # 계산 화면
├── ExchangePage/ # 환율 화면
├── Extension/ # UIView 관련 확장
├── Modals/ # 팝업 모달
├── Models/ # 데이터 모델
├── SavedPage/ # 저장된 계산 기록
├── SettingPage/ # 설정
├── StartPage/ # 앱 시작 화면
├── TabBar/ # 탭바 컨트롤러
├── Utils/ # 유틸리티
└── Localizable/ # 다국어 지원
🔍 원인
- API 비용 절감 및 트래픽 최소화를 위해 파이어베이스에 USD 기준 환율만 저장
- 하지만, 사용자가 기준 통화를 변경할 때 즉시 다양한 기준 환율로 환산/표시해야 하는 복잡성 발생
✅ 해결 방안
- displayUnit 등 통화별 표준 단위 로직 설계
- 선택 기준 통화에 맞게 실시간 변환하는 함수화
- 모든 환율 표기를 Double+Formatted로 일관성 있게 출력
🔥 개선 효과
- 서버 부하 없이 다양한 통화 기준으로 환율 신속 제공
- 글로벌/다국적 사용자 환경에 실시간 맞춤 환율 노출
- 유지보수 및 성능, 신뢰도 동시 확보
🔍 원인
- 영미식(1,234.56)·유럽식(1.234,56) 등
- 다양한 숫자 표기법이 혼재된 환경에서 기존에는 단순히 콤마(,)만 제거하고 Double로 변환했기 때문에
- 일부 국가에서는 숫자 파싱 및 계산이 제대로 되지 않거나 잘못된 결과가 발생.
✅ 해결 방안
- NumberFormatter를 활용해 Locale.current 및 주요 국가 로케일에 따라
- 천 단위/소수점 구분자를 자동 인식하도록 parseLocalizedNumber 함수 구현
- 계산/저장/표시 등 모든 과정에서 로케일에 맞는 포맷 일관성 유지
- 전 세계 국가의 표기법을 완벽하게 대응
🔥 개선 효과
- 영미식, 유럽식, 그 외 표기법까지 모든 글로벌 사용자에게 일관된 숫자 인식 및 계산 정확도 보장
- 숫자 관련 문의/오류 감소, 글로벌 신뢰성 강화
🔍 원인
- NSLocalizedString 포맷 인자(예: %1$@, %2$@)의
- 국가별 순서 차이로 인해 언어에 따라 안내문이나 환급조건 표시가
- 의도와 다르게 표시되는 이슈 발생
✅ 해결 방안
- 각 언어별 Localizable.strings에서 포맷 인자의 순서를 명확히 구분(%1$@ 등 사용)
- 모든 언어별 포맷을 점검하고 인자 위치 통일
- 코드 리뷰 및 PR 단계에서 인자 순서, UI 표시 검증 프로세스 추가
🔥 개선 효과
- 어떤 언어를 선택해도 정확한 안내문, 환급 조건 노출
- 다국어 UX 품질 상승, 오역/오표시로 인한 혼란 방지
🚀 모달(시트) 하단 여백 및 리스트 위치 트러블슈팅 (링크)
🔍 원인
- UISheetPresentationController의 레이아웃 시스템과 UITableView의 초기 콘텐츠 오프셋 동기화 이슈
- 시트와 테이블뷰의 레이아웃 적용 시점이 달라 하단 여백이 어긋나거나 리스트/버튼이 잘리는 현상 발생
✅ 해결 방안
- 시트(Sheet) 레이아웃과 테이블뷰의 contentInset/contentOffset을 SafeArea 및 시트 크기에 맞게 동적으로 조정
- 뷰 레이아웃 완료 후(예: viewDidLayoutSubviews) 명시적으로 동기화 처리 로직 추가
🔥 개선 효과
- 모든 기기에서 모달 하단 여백 및 리스트 위치가 정상적으로 표시됨
- UI 깨짐, 겹침 등 사용자 경험 이슈 근본적으로 해결
🚀 금액 입력의 콤마(,)로 인한 계산 오류 트러블슈팅 (링크)
🔍 원인
- 금액 입력값에 ,(콤마)가 포함되어 있을 때 (예: "1,000" 등)
- Swift에서 해당 값을 Double로 변환 시 변환 실패로 인해 계산 로직이 제대로 동작하지 않음
✅ 해결 방안
- 입력값에서 콤마(, )를 제거 후 숫자 타입(Double)으로 변환하도록 로직 수정
- 예시 코드
let pureNumber = input.replacingOccurrences(of: ",", with: "")
let amount = Double(pureNumber)- 모든 금액 입력 필드에 동일하게 적용
🔥 개선 효과
- 금액 입력 시 콤마가 포함되어도 정상적으로 계산
- 입력/계산 오류 완전 해결
- 사용자 경험 및 서비스 신뢰도 향상
커밋 메시지
- Feat: 새로운 기능 추가
- Fix: 버그 수정
- Docs: 문서 수정
- Style: 코드 포맷팅
- Refactor: 코드 리팩토링
- Test: 테스트 코드
- Chore: 기타 변경사항
- Cmt: 주석 수정
PR 규칙
- PR 탬플릿 준수
- 머지 전 팀원의 승인 필요
- 기능별 스크린샷 첨부
