손으로 쓴 감동, 내 손안의 편지보관함 |
---|
잃어버렸거나 잊혔거나 여기저기 흩어져 있는 편지들
또는 친구에게 전달하여 더 이상 읽을 수 없는 편지까지
편지 내용과 편지지, 편지 봉투까지 저장해 언제, 어디서나 앱에서 꺼내 보세요
✉️ 앱 스토어(링크)
GitHub | 권운기 | 권지원 | 김현진 | 양주원 | 정은수 |
담당 역할 | 홈탭 사이드메뉴뷰 테마 |
지도탭 | 편지 디테일 뷰 Kingfisher |
쇼핑 탭 | Firebase 검색뷰 로그인뷰 느린우체통 |
- XCode 15.2
- Swift 5.9.2
- iOS 16.0
이름 | 버전 | 사용기술 |
---|---|---|
Vision | 편지 이미지의 글자를 인식 | |
Clova | AI로 편지 내용 한 줄 요약 | |
우체국 API | - 우체국 관련 API - 우체국 영업시간 제공 |
|
NaverMapApi | NMapsGeometry (1.0.1) NMapsMap (3.17.0) |
- 우체국, 우체통 카테고리 필터링 - 우체국, 우체통의 위치를 API에서 가져와 지도에 핀으로 표시 - 지도 위에 검색 반경 표시 |
Firebase | 10.20.0 | - Authentication: Google, Apple 회원가입 및 로그인 - Firestore Database: 로그인 해 저장한 편지 데이터 관리 - Storage: 편지 이미지 관리 |
Kingfisher | 편지 이미지와 편지지 쇼핑몰의 이미지를 비동기로 로딩하고 캐시 관리 | |
SwiftUI | - searchable: 초성 검색, 검색 결과에 하이라이트 -SafariService로 사용자가 외부에서 편지지를 쉽게 구매할 수 있도록 함 - UserNotifications로 느린 우체통의 편지 알림 |
스크린샷 | 스크린샷 | 스크린샷 |
---|---|---|
영상 | 영상 | 스크린샷 |
---|---|---|
영상 | 스크린샷 | 스크린샷 | 스크린샷 |
---|---|---|---|
영상 | 영상 | 스크린샷 |
---|---|---|
영상 | 스크린샷 |
---|---|
영상 | 영상 | 스크린샷 |
---|---|---|
영상 | 영상 | 스크린샷 | 스크린샷 |
---|---|---|---|
실행 화면 | 설명 |
---|---|
- 새 편지를 저장합니다. - 보낸 편지, 받은 편지를 구분하여 저장할 수 있습니다. - 편지를 작성하거나 받은 날짜를 지정할 수 있습니다. - 사진 촬영을 촬영하면 자동으로 텍스트가 인식됩니다. - Naver Clova AI를 활용해 편지 내용을 한줄로 요약할 수 있습니다. - 텍스트 스캔 결과와 편지 요약은 모두 사용자가 수정할 수 있습니다. - 저장한 편지 리스트를 보여줍니다. - 편지를 눌러 사진과 내용을 자세히 볼 수 있습니다. - 화면 우측 상단의 미트볼 아이콘을 눌러 저장된 편지를 편집하거나 삭제할 수 있습니다. - 편지를 검색합니다. 검색어는 편지 내용과 한줄 요약을 포함합니다. |
실행 화면 | 설명 |
---|---|
- 우체국 API를 사용해 우체국 위치와 우체통 위치와 영업시간을 보여줍니다. - 지도는 Naver 지도 API를 사용하며, 내 위치로 이동하거나 원하는 지역을 검색할 수 있습니다. - 지도상에 현재 검색 가능한 위치 반경을 원으로 그려줍니다. |
실행 화면 | 설명 |
---|---|
- 테마로 구분된 편지지 이미지를 보여줍니다. - 이미지를 클릭하면 해당 편지지를 판매하는 사이트로 링크되는 Safari 창이 Modal로 나타납니다. |
실행 화면 | 설명 |
---|---|
- 화면 우측 상단의 햄버거 아이콘으로 진입합니다. - 로그인에 활용한 API의 이름, 이메일, 프로필사진을 가져옵니다. - 계정 관리 및 테마를 지원합니다. |
프로젝트 총 기간: 2023.12.21 ~ 2024.02.28 (2개월)
- 아이디어 선정 (약 1주)
- 기간: 2023.12.21 ~ 2023.12.29
- 팀 빌딩
- 아이디어 회의
- 프로젝트 사전 준비 (약 1주)
- 기간: 2024.01.02 ~ 2024.01.10
- 팀 규칙, PR 규칙 및 코딩 컨벤션 선정
- UI 브레인 스토밍 및 필요 기술 선정
- 선정된 기술에 대하여 구현 가능 여부 사전 스터디
- 우체국 API 사용 신청
- 개발 기간 1 (2주)
- 기간: 2024.01.11 ~ 2024.01.24
- 피그마 디자인 제작
- 지도 API 연결
- 우체국 API XML로 받아와 지도에 위치 표시
- 로그인 뷰 UI 구현 및 Firebase Authentication 연결
- 홈, 상세화면 뷰 UI 구현 및 Firestore Database 연결
- 편지 저장 뷰 UI 구현 및 OCR, 텍스트 요약 API, Firebase Storage 연결
- 쇼핑몰 뷰 구현 및 SFSafariView 연결
- 재정비 (2일)
- 피그마 디자인 수정
- 유저 피드백을 위한 설문조사 제작 및 진행
- 추가 개발 사항 선정
- 개발 기간 2 (4주)
- 기간: 2024.01.29 ~ 2024.02.25
- Social 로그인 기능 완성
- 로컬 푸시 기능 추가 구현
- 모든 뷰 고도화 작업
- 느린 우체통 기능 추가 구현
- 발표 준비 및 발표(3일)
- 기간: 2024.02.26 ~ 2024.02.28
- 편리함과 효율성 제고
- 디지털 시대의 소통에 따뜻함 추가
- 이메일과 인스턴트 메시징이 지배하는 현대사회에, 느린 우체통 기능은 소통에 따뜻함과 의미를 더함
- 개인적인 소통의 부활
- 자신의 생각과 감정을 글로 표현하는 데 더 많은 시간을 할애하게 되며, 다른 사람들과의 관계를 강화
- 디지털 네이티브 세대에게 과거의 소통 방식을 경험할 기회를 제공
- 리팩토링의 중요성 학습
- 설문조사 및 유저 테스트의 필요성 인지
- 체력과 건강이 프로젝트의 성공에 중요함을 인지
- 결과물을 내기까지 기획, 디자인과 같은 과정을 거치며 많은 의사결정이 필요함을 학습
- 거시적 일정관리의 필요성을 학습
- 앱 잠금 서비스
- 받은 편지에 대한 개인적인 마음과 감정을 담을 수 있는 편지 메모란을 앱에 추가
- 라디오 사연처럼 모든 사용자에게 공개되는 편지를 받는 기능을 도입하여, 사용자들 간에 긍정적인 에너지를 공유
월 2회 온오프라인 미팅을 통한 추가 기능 개발 및 유지보수
- 사용자 피드백 수집 및 적극 반영: 사용자들의 요구를 충족시키고 사용자 경험을 개선하기위해 노력
- 기술적 업그레이드: 새로운 기술이나 프레임워크를 도입하여 성능을 향상시키고 사용자들에게 더 나은 서비스를 제공
- 유지보수: 리팩토링, 코드 최적화, 부가기능 추가
- 권운기: 처음에는 되는대로 개발을 했는데, 프로젝트를 진행하면서 코드 양이 많아지다 보니 내가 적은 코드도 나중에 보면 읽기 힘들어졌습니다. 이를 통해 코드 리팩토링의 중요함을 깨달았습니다.
- 권지원: 설문조사와 유저 테스트를 통해 다양한 사용자 니즈를 파악했고, 예상과 다른 행동에서 다양한 인사이트를 얻었습니다. 이를 통해 사용자와의 의사소통의 중요함을 깨달았습니다.
- 김현진: 프로젝트의 성공을 위해서는 개발뿐만 아니라 본인과 팀원들의 건강도 중요하다는 것을 깨달았습니다.
- 양주원: 단순히 코드 개발만 하는 게 아닌 세세한 앱 디자인부터 발표까지, 다양한 계획들에 대한 토론의 중요성을 알게 되었습니다.
- 정은수: 기능 명세서나 Git Issue와 같은 프로젝트 관리 도구를 사용하여 일정을 대부분 일간 Task 같이 작은 단위로 관리했는데, 결과물을 목표한 대로 만들기 위해서는 거시적 관점에서 일정 관리를 하는 것도 필요하다는 것을 알게 되었습니다.
- Git PR에 자동 라벨을 붙여주는 Trafico 앱 깃허브 -COMPLETE User Login / Sign Up App | Swift UI + Firebase | Async / Await
- dSYM (feat. Firebase Crashlytics)
- XMLCoder 프로젝트
- 3rd party 패키지 추가하는 법
- Cocoapods 사용 하는 방법
- [SwiftUI] Photospicker을 이용해 Firebase Storage에 이미지 넣어보기
- How to Upload Images to Cloud Storage for Firebase with Swift
- Firebase Storage for iOS: Storing User Content in the Cloud
- Difference Between Firestore Set with {merge: true} and Update
- 리스트 누르면 판매 사이트 연결시키기(웹뷰)
- Swift 개발자처럼 변수 이름 짓기
- iOS Firebase Authentication: Sign In With Google Tutorial
- [SwiftUI] scrollDismissesKeyboard 스크롤 해서 키보드 내리기 (iOS 16+)
- deprecated로 알아본 custom ViewModifier 정복하기
- SwiftUI) 실전형 TextField 사용하기 예제 [MVVM, @FocusState, ScrollView movemunt]
- Confirm Dialog 사용하기
- UIApplication.shared.windows deprecate 대응
- 회원 탈퇴를 위한 Google Authentication 재설정
- UserDefault를 사용한 앱 재설치 확인
- 로딩 뷰 배경을 투명하게 설정
- 구글 로그인 GIDSignInErrorCode 핸들링
- Google login error case(Document)
- [Swift] 예외처리 (throws, do-catch, try) 하기
- DispatchGroup에 넣어 데이터 삭제 작업이 종료될 때 까지 대기
- [iOS - swift] Dispatch Group
- [iOS - swiftUI] TextField, @FocusState, 키보드 숨기기 사용 방법
- @FocusState 사용하기
- How to get image file size in Swift?
- Swift Codable을 사용한 Cloud Firestore 데이터 매핑
- [Swift] Cloud Firestore(2) 실습해보기
- Cloud Firestore에 데이터 추가
- Swift 5+) String - Raw String (String 안에서 " \ 사용하기)
- 대기중인 알림 확인, 알림 삭제
- removeDeliveredNotifications와 removePendingNotificationRequests의 차이점
- How to use Local Notification in SwiftUI: 코드의 대부분을 참고한 블로그
- UserNotification(Local Notification): 날짜와 시간으로 푸시 설정
- [iOS/Swift] 'alert' was deprecated in iOS 14.0
- Reading Firebase Auth Error Thrown (Firebase 3.x and Swift)
- Authentication in Firebase using Swift Error Handling - Part2 | Swift Tutorials | FIREBASE and XCODE
- UIApplication.applicationIconBadgeNumber is deprecated
- 앱 알림 뱃지 deprecated 관련
- Apple store bundle id 찾기
- [iOS] Swift 강제 업데이트 Alert 설정
- 버전 숫자 세 자리 중 세 번째의 사소한 패치때는 업데이트 하지 않을 수 있도록 하는 방법
- App Store 업데이트 버전 체크
- SwiftUI에서 앱 버전 확인해 강제 업데이트
- Apple store bundle id 찾기
- 앱스토어 업데이트 팝업 테스트 해 보고 싶다면 이 블로그의 내용을 참고해 번들 id와 앱 id를 업데이트 하세요.
- 앱 버전(version) 관리 규칙 공부하기!~ 4.2.1 은 어떤 방식으로?
- [SwiftUI] WKWebView를 이용한 WebView 만들기
- Date끼리의 비교
📦PJ3T3_Postie
┣ 📂App
┃ ┗ 📜PJ3T3_PostieApp.swift
┣ 📂Assets.xcassets
┣ 📂Components
┃ ┣ 📜Button.swift
┃ ┣ 📜ClearBackground.swift
┃ ┗ 📜LoadingView.swift
┣ 📂Core
┃ ┣ 📂Home
┃ ┃ ┣ 📂View
┃ ┃ ┃ ┣ 📜AddLetterView.swift
┃ ┃ ┃ ┣ 📜EditLetterView.swift
┃ ┃ ┃ ┣ 📜GroupedFavoriteListLetterView.swift
┃ ┃ ┃ ┣ 📜GroupedLetterView.swift
┃ ┃ ┃ ┣ 📜GroupedListLetterView.swift
┃ ┃ ┃ ┣ 📜GroupedMyListLetterView.swift
┃ ┃ ┃ ┣ 📜HomeView.swift
┃ ┃ ┃ ┣ 📜LetterDetailView.swift
┃ ┃ ┃ ┣ 📜LetterImageFullScreenView.swift
┃ ┃ ┃ ┣ 📜ListLetterView.swift
┃ ┃ ┃ ┣ 📜PageViewController.swift
┃ ┃ ┃ ┣ 📜SearchView.swift
┃ ┃ ┃ ┣ 📜SlowPostBoxView.swift
┃ ┃ ┃ ┗ 📜UIImagePicker.swift
┃ ┃ ┣ 📂ViewModel
┃ ┃ ┃ ┣ 📜AddLetterViewModel.swift
┃ ┃ ┃ ┣ 📜EditLetterViewModel.swift
┃ ┃ ┃ ┣ 📜GroupedLetterViewModel.swift
┃ ┃ ┃ ┣ 📜HomeViewModel.swift
┃ ┃ ┃ ┣ 📜LetterDetailViewModel.swift
┃ ┃ ┃ ┣ 📜SlowPostBoxViewModel.swift
┃ ┃ ┃ ┣ 📜SummaryApi.swift
┃ ┃ ┃ ┗ 📜TextRecognizer.swift
┃ ┃ ┗ 📜SummaryApiKeys.plist
┃ ┣ 📂Login
┃ ┃ ┣ 📂View
┃ ┃ ┃ ┣ 📜DeleteAccountButtonView.swift
┃ ┃ ┃ ┣ 📜EmailLoginView.swift
┃ ┃ ┃ ┣ 📜LoginInputView.swift
┃ ┃ ┃ ┣ 📜LoginView.swift
┃ ┃ ┃ ┣ 📜NicknameView.swift
┃ ┃ ┃ ┣ 📜ReAuthButtonView.swift
┃ ┃ ┃ ┗ 📜RegistrationView.swift
┃ ┣ 📂Map
┃ ┃ ┣ 📂View
┃ ┃ ┃ ┣ 📜CoordinaterEtc.swift
┃ ┃ ┃ ┣ 📜Coordinator.swift
┃ ┃ ┃ ┣ 📜MapCoordinator.swift
┃ ┃ ┃ ┗ 📜MapView.swift
┃ ┃ ┣ 📂ViewModel
┃ ┃ ┃ ┣ 📜LocationManager.swift
┃ ┃ ┃ ┣ 📜MapApi.swift
┃ ┃ ┃ ┣ 📜MapViewModel.swift
┃ ┃ ┃ ┣ 📜MyCoord.swift
┃ ┃ ┃ ┗ 📜NaverMap.swift
┃ ┃ ┗ 📜MapApiKeys.plist
┃ ┣ 📂Root
┃ ┃ ┣ 📂View
┃ ┃ ┃ ┗ 📜ContentView.swift
┃ ┃ ┣ 📂ViewModel
┃ ┃ ┃ ┗ 📜ContenViewModel.swift
┃ ┃ ┗ 📜ContentView.swift
┃ ┣ 📂Setting
┃ ┃ ┣ 📂View
┃ ┃ ┃ ┣ 📜AlertView.swift
┃ ┃ ┃ ┣ 📜FirebaseTestRowView.swift
┃ ┃ ┃ ┣ 📜FirebaseTestView.swift
┃ ┃ ┃ ┣ 📜InformationView.swift
┃ ┃ ┃ ┣ 📜InformationWebView.swift
┃ ┃ ┃ ┣ 📜MembershipView.swift
┃ ┃ ┃ ┣ 📜NoticeView.swift
┃ ┃ ┃ ┣ 📜ProfileEditView.swift
┃ ┃ ┃ ┣ 📜ProfileView.swift
┃ ┃ ┃ ┣ 📜QuestionView.swift
┃ ┃ ┃ ┣ 📜SplashScreenView.swift
┃ ┃ ┃ ┗ 📜ThemeView.swift
┃ ┃ ┗ 📂ViewModel
┃ ┃ ┃ ┗ 📜SettingViewModel.swift
┃ ┣ 📂Shop
┃ ┃ ┣ 📂View
┃ ┃ ┃ ┗ 📜ShopView.swift
┃ ┃ ┗ 📂ViewModel
┃ ┃ ┃ ┗ 📜ShopViewModel.swift
┣ 📂Extenstions
┃ ┣ 📜Color.swift
┃ ┣ 📜Date.swift
┃ ┣ 📜EnvironmentValues.swift
┃ ┣ 📜Font.swift
┃ ┣ 📜Logger.swift
┃ ┣ 📜String.swift
┃ ┗ 📜View.swift
┣ 📂Font
┃ ┣ 📜NanumMyeongjo.otf
┃ ┣ 📜NanumMyeongjoBold.otf
┃ ┣ 📜SairaStencilOne-Regular.ttf
┃ ┣ 📜SourceSerifPro-Black.otf
┃ ┗ 📜SourceSerifPro-Light.otf
┣ 📂Manager
┃ ┣ 📜AppStoreUpdateChecker.swift
┃ ┣ 📜AppleSignInHelper.swift
┃ ┣ 📜AuthCaseHelper.swift
┃ ┣ 📜AuthManager.swift
┃ ┣ 📜CryptoUtils.swift
┃ ┣ 📜FirestoreManager.swift
┃ ┣ 📜FirestoreNoticeManager.swift
┃ ┣ 📜FirestoreShopManager.swift
┃ ┣ 📜GoogleSignInHelper.swift
┃ ┣ 📜NotificationManager.swift
┃ ┗ 📜StorageManager.swift
┣ 📂Model
┃ ┣ 📜AppleUser.swift
┃ ┣ 📜GoogleUser.swift
┃ ┣ 📜Letter.swift
┃ ┣ 📜LetterPhoto.swift
┃ ┣ 📜OfficialLetter.swift
┃ ┣ 📜PostieUser.swift
┃ ┗ 📜Shop.swift
┣ 📂Preview Content
┃ ┗ 📂Preview Assets.xcassets
┣ 📜.DS_Store
┣ 📜GoogleService-Info.plist
┗ 📜PJ3T3_Postie.entitlements