분류 전체보기 117

Troubleshooting: 게시글 상세보기 화면에서 펫 프로필 데이터 누락 시 모든 정보가 표시되지 않는 이슈

게시글 상세보기 뷰에서 아무 정보도 불러와지지 않는 게시글들이 있다는 걸 발견했다파이어스토어 데이터베이스에서 확인해본 결과문제가 생기는 부분은"게시글 등록 시 펫을 선택해 등록했고, 이후 선택했던 펫의 프로필이 삭제된 경우" 라고 판단했다. 게시글 상세보기 뷰모델부터 차근차근 문제를 확인하다가파이어스토어 매니저의 로직을 확인할 때 쯤뭔가 알 거 같은데 정리가 필요할 거 같아서 이 글을 작성하게 됐다. case let .document(id): let documentId = (id.isEmpty && !userId.isEmpty) ? userId : id return Single.create { [weak self] single in..

카테고리 없음 2026.01.06

Troubleshooting: 좋아요 동시성 이슈 해결

문제 정의구조: model.like: [String] 배열 전체를 클라이언트가 수정 후 문서 업데이트struct CommunityModel: Codable { // ... let like: [String] // ...}증상:좋아요 35개인 글에서 A 해제 → [A, B, C...] → [B, C...] 저장 → count = 34B는 여전히 35 상태에서 해제 → [A, C...] 저장 → A 다시 포함 → count = 34결과: 실제 상태와 서버 기록 불일치 발생. 최신 변경 유실.원인: 로컬 stale 스냅샷 기반 덮어쓰기 + 원자성 부재 원인 분석로컬 상태 기반 재계산 → 최신 변경 유실전체 배열 덮어쓰기 → 동시성 붕괴원자성 부재 → count와 like 불일치확장성 리스크 → ..

카테고리 없음 2025.09.16

UIButton Configuration

커뮤니티 뷰를 만들면서 좋아요, 댓글 버튼을 만드는데 이미지와 텍스트의 간격이 너무 가까워서 띄우는 방법을 알아봤다. imageEdgeInsets를 사용해서 이미지가 버튼으로부터 멀어지게 간격을 띄울 수 있으며,titleEdgeInsets를 사용해 타이틀이 버튼으로부터 멀어지게 간격을 띄울 수 있다고 하지만,이렇게 간격을 벌리면 간격만 멀어지고 실제 버튼의 크기는 변하지 않기 때문에 이미지나 타이틀이 버튼의 클릭 범위를 벗어나게 된다고 한다.contentEdgeInsets를 사용해서 버튼의 크기에도 인셋을 줄 수 있다고 하니imageEdgeInsets를 2만큼 주고titleEdgeInsets를 2만큼 주고contentInsets을 양쪽에 2씩 주면 되겠지 생각하고 xcode로 들어가보니ㅠㅠ 그래서 새로 ..

카테고리 없음 2025.09.15

layer.shadow

버튼이나 카드 뷰에 그림자가 들어가면 화면이 더 입체적이고 깊이감 있게 보인다.이번에 디자인 시안에 그림자가 포함되어 있어서 직접 구현하게 되었고,단순히 뷰에 속성을 추가하는 것 같아 보여도 실제로는 Core Animation에서 별도의 과정이 필요하다는 걸 알 수 있었다.구현 과정UIKit에서 뷰에 그림자를 주려면 UIView 자체가 아니라 그 뷰의 layer에 접근해야 한다.대표적으로 사용하는 속성은 다음과 같다.someView.layer.shadowColor = UIColor.black.cgColorsomeView.layer.shadowOpacity = Float(0)someView.layer.shadowOffset = CGSize(width: 1, height: -3)someView.layer.s..

카테고리 없음 2025.09.11

Troubleshooting: 모달 중첩 해제

증상모달을 단계별 dismiss 체이닝으로 닫을 때애니메이션이 여러 번 재생.간헐적으로 닫힘 실패가 발생.영향사용자 입장에서는 화면이 들썩이는 느낌 → UX 저하코드 측면에서도 completion 순서 의존 → 취약한 흐름원인 분석단계별 체이닝은 중간 단계의 존재와 completion 타이밍에 강하게 의존시스템 피커(카메라/포토) 등 시스템 VC가 개입하면 흐름이 더 복잡iPad 멀티-씬, 외부 디스플레이 등 윈도우/씬 분기도 고려 대상대안 비교체이닝: presentingViewController를 따라가며 하나씩 닫기장점: 이해하기 쉽고 바로 구현 가능단점: 애니메이션 다중 표시, 흐름 취약, 단계 변경에 취약 프레젠터 루트에서 일괄 dismiss: 현재 VC의 최상위 presenter를 찾아 한 번에..

카테고리 없음 2025.08.26

TIL: ViewModel 리팩토링: Relay -> Driver, Signal

기존 뷰모델은 enum Input + PublishRelay 구조에, struct Output 내부에서 BehaviorRelay들을 두는 방식이었다.View → Input으로 이벤트 전달ViewModel 내부에서 output.xxx.accept() 호출로 상태 갱신장점직관적이고 빠르게 동작단순한 경우에는 코드가 짧고 이해하기 쉬움단점View에 노출되는 타입이 Relay → 외부에서 accept()가 가능해 불변성 위반 위험UI 스레드 보장/에러 비전파를 개발자가 직접 챙겨야 함상태 캐시를 위해 Relay가 1:1로 증식개선 방향Relay 의존을 제거transform(_:)에 입력 스트림을 주입출력은 Driver/Signal로만 전달Before: Relay 중심→ View에서 input.accept(.....

카테고리 없음 2025.08.21

flatMapFirst, flatMapLatest

팀원 코드리뷰를 하다가 flatMapLatest라는 오퍼레이터를 처음 알게 돼“이건 뭐지?” 싶어 공부하게 되었다.공부를 하다 보니 자연스럽게 flatMapFirst도 같이 알게 되었고,두 연산자의 동작 방식과 차이를 비교해서 정리해 보게 되었다.🔍 개념 정리🔹 flatMapLatest가장 최근에 들어온 요청만 처리하고,그 이전 요청은 무시하는 오퍼레이터흔히 검색창, 실시간 입력 처리, 새로고침 등“최신 상태만 유지하면 되는 상황”에서 사용input.keyword .flatMapLatest { query in network.search(query) } 🔸 flatMapFirst첫 번째 요청만 처리하고,그 작업이 끝날 때까지 다른 요청은 무시버튼 연타 방지, 실수로 여러 번 눌..

카테고리 없음 2025.08.20

PHPickerController 사진을 선택한 순서로 저장하기

커뮤니티 뷰에서 사진 업로드 기능을 구현하면서,UIImagePickerController가 iOS 18.5부터 Deprecated된다는 소식을 듣고PHPickerViewController로 마이그레이션을 진행했다.여러 장 선택, 보안성 강화, 안정적인 이미지 처리 등 장점이 있다고 한다.선택한 순서대로 이미지 불러오기PHPickerResult 배열은 항상 사용자가 선택한 순서와 같지 않을 수 있다.따라서, 선택 순서를 보장하려면 다음 과정을 거친다:results.compactMap { $0.assetIdentifier }로 ID 배열을 추출한다.PHAsset.fetchAssets(withLocalIdentifiers: [추출한 ID 배열], options: nil)을 호출한다.반환된 PHFetchResu..

카테고리 없음 2025.08.16

Date 값 간 비교

커뮤니티 뷰를 만들면서 날짜를 계산해야 할 일이 생겼다.예를 들어 게시글 작성 시간이 현재 시간과 얼마나 차이 나는지 계산해,“0분 전”, “3시간 전”, “2일 전”과 같이 사용자 친화적인 형태로 표시해야 했다. Swift에서 날짜를 비교하는 방법은 여러 가지가 있으며,사용하는 API에 따라 계산 정확도와 처리 방식이 달라진다.이번 TIL에서는 Date 값 간 차이를 구하는 대표적인 세 가지 방법과,DateComponents에서 값이 nil과 0으로 나오는 차이점을 정리했다.1. 초 단위 비교 - timeIntervalSinceDate끼리 빼면 TimeInterval(초 단위 Double)이 나오기 때문에, 이를 분·시간·일 등으로 변환할 수 있다.let now = Date()let target =..

카테고리 없음 2025.08.11

PHPickerController

이전에 앨범을 연동할 때 UIImagePickerController를 사용했었는데UIImagePickerController의 sourceType 중 앨범 연동 기능이 18.5 이후 Deprecated 된다는 소식을 접했다.애플에서는 PHPickerController의 사용을 추천한다고 한다. 추가된 기능으로는 이미지 여러 장을 한 번에 선택할 수 있는 기능,사용자가 허락한 미디어만 사용가능(보안 개선) 및 이미지를 안정적으로 처리한다고 합니다.사용법import PhotosUIimport PhotosUI PHPickerConfiguration을 생성해 설정.var configuration = PHPickerConfiguration()configuration.selectionLimit = 5configura..

카테고리 없음 2025.08.08