바로신고

바로신고 다산콜센터(120), 경찰청(112), 소방서(119)에 문자 기반 긴급 신고를 빠르고 간편하게 할 수 있는 앱입니다. 주요 기능 신고 대상 선택 — 다산콜센터, 경찰청, 소방서 중 선택 간편한 신고 작성 — 상황 설명 입력 + 사진 첨부 신고 이력 관리 — 접수완료, 처리중 등 상태 실시간 확인 알림 기능 — 신고 접수 및 처리 완료 푸시 알림 기술 스택 영역 기술 Backend Rails 8 + Turbo iOS Hotwire Native 1.2.2 (Swift, XcodeGen) Android Hotwire Native 1.2.5 (Kotlin) 호스팅 Render 다운로드 App Store (심사 중) Google Play (준비 중) 지원 문의: theqwe2000@naver.com ...

2026-03-07 00:00 · 1분 소요 · Seunghan

Flutter TestFlight 업로드 삽질 — exportArchive Failed to Use Accounts 해결

Flutter로 앱을 만들고 TestFlight에 올리려는데, 아카이브 빌드는 성공하고 IPA export에서 멈췄다. exportArchive Failed to Use Accounts라는 에러가 뜨는데, 구글링해도 명쾌한 답이 없었다. 결국 3가지 다른 에러를 연달아 만나면서 해결했고, 그 과정을 정리한다. 에러 1: exportArchive Failed to Use Accounts flutter build ipa --release --dart-define=ENV=prod --export-options-plist=ios/ExportOptions.plist 아카이브 빌드는 잘 된다: ✓ Built build/ios/archive/Runner.xcarchive (197.5MB) [✓] App Settings Validation • Version Number: 1.0.1 • Build Number: 9 • Display Name: My App • Bundle Identifier: com.example.app 근데 바로 다음 줄에서: ...

2026-03-31 00:00 · 4분 소요 · Seunghan

Flutter에서 iOS Live Activity 잠금화면 미리보기 만들기 — CustomPainter로 네이티브 위젯 재현

왜 Live Activity 미리보기가 필요했나 여행 앱에서 iOS Live Activity를 구현하고 나면, 사용자에게 표시 모드를 선택하게 하는 설정 화면이 필요하다. 일정 모드, 예산 모드, 자동 모드, 결합 모드 — 이렇게 네 가지 옵션이 있는데, 문제는 이 모드를 바꿨을 때 잠금화면에서 실제로 어떻게 보이는지 사용자가 알 수 없다는 점이었다. 설정 화면 하단에 Dynamic Island compact 형태의 간단한 미리보기는 있었다. 하지만 사용자가 Live Activity를 가장 많이 보는 곳은 잠금화면이다. 작은 알약 모양 미리보기로는 “이 모드를 선택하면 잠금화면이 이렇게 바뀝니다"를 전달하기 어려웠다. ...

2026-03-26 00:00 · 8분 소요 · Seunghan

Flutter GoRouter ShellRoute로 바텀 네비게이션 전역 유지하기 — 삽질부터 Liquid Glass 인터랙션까지

바텀 네비가 사라지는 순간 Flutter 앱을 만들다 보면 어느 순간 이런 상황을 만난다. 메인 화면에 탭 5개짜리 바텀 네비게이션 바가 있고, 할일 수정이나 새 메모 생성 버튼을 누르면 context.push('/tasks/new')로 화면을 전환한다. 그런데 화면이 전환되는 순간 바텀 네비가 통째로 사라진다. iOS 네이티브 앱에서는 탭 안에서 push 하면 탭 바가 유지된다. Apple의 메모 앱에서 메모를 열어도, 미리 알림에서 항목을 수정해도 하단 탭 바는 그대로 있다. 그런데 Flutter에서는 기본적으로 이렇게 동작하지 않는다. 원인을 찾아보니 라우터 구조 자체의 문제였다. ...

2026-03-24 00:00 · 9분 소요 · Seunghan

Hotwire Native iOS에서 삭제 버튼이 안 눌리는 이유 — WKUIDelegate와 turbo_confirm의 함정

삭제 버튼을 눌렀는데 아무 일도 일어나지 않는다 Rails + Hotwire로 웹앱을 만들고, Hotwire Native(구 Turbo Native)로 iOS 앱을 감싸서 배포하는 구조를 쓰고 있었다. 웹에서는 모든 것이 잘 동작했다. 삭제 버튼을 누르면 “정말 삭제하시겠습니까?” 확인 다이얼로그가 뜨고, 확인을 누르면 삭제가 진행됐다. 그런데 iOS 네이티브 앱에서 같은 버튼을 누르면 아무 반응이 없었다. 에러도 없고, 크래시도 없고, 그냥 조용히 무시됐다. 상태 변경 버튼, 라운드 추가/삭제 버튼, 토너먼트 삭제 버튼 — turbo_confirm이 붙은 모든 버튼이 죽어있었다. ...

2026-03-22 00:00 · 9분 소요 · Seunghan

iOS WebView 채팅 메시지가 박스를 뚫고 나간다 — overflow-wrap: anywhere로 해결한 크로스프로젝트 수정기

증상: 긴 메시지가 채팅 버블을 뚫고 나간다 Rails 8 + Hotwire Native로 만든 iOS 앱에서 채팅 기능을 테스트하던 중 문제를 발견했다. 긴 URL이나 공백 없는 연속 문자열을 보내면 메시지가 채팅 버블 영역을 벗어나 화면 밖으로 튀어나가는 현상이 발생했다. 웹 브라우저에서는 멀쩡하게 보이는데, iOS 네이티브 앱(WKWebView)에서만 문제가 재현됐다. 가로 스크롤이 생기고, 메시지 영역 전체 레이아웃이 깨져버린다. 처음엔 “Tailwind break-words 넣어놨는데 왜 안 되지?” 싶었지만, 파고 들어가보니 CSS overflow-wrap, flexbox intrinsic sizing, iOS WebKit 호환성이 복합적으로 얽힌 문제였다. ...

2026-03-22 00:00 · 9분 소요 · Seunghan

Turbo Native iOS에서 data-turbo-confirm이 동작하지 않는 이유 — WKUIDelegate 누락 문제

버튼을 눌러도 아무 일도 일어나지 않는다 Rails 8 + Hotwire Native으로 iOS 앱을 만들고 있었다. 웹에서는 잘 동작하는 삭제 버튼이 네이티브 앱에서는 완전히 먹통이었다. <%= button_to "삭제", tournament_path(@tournament), method: :delete, form: { data: { turbo_confirm: "정말 삭제하시겠습니까?" } } %> 웹 브라우저에서 클릭하면 “정말 삭제하시겠습니까?” 확인 다이얼로그가 뜨고, 확인하면 삭제가 진행된다. 그런데 iOS 앱에서는 버튼을 탭해도 아무 반응이 없다. 에러도 없고, 로그도 없고, 그냥 조용히 무시된다. 처음에는 turbo_confirm을 form: 옵션에 넣느냐 data: 옵션에 넣느냐의 문제인 줄 알았다. button_to의 turbo_confirm은 form 태그의 data 속성으로 전달해야 하기 때문이다. 하지만 코드는 정확했다. 웹에서 되는데 네이티브에서만 안 되니까 iOS 쪽 문제가 확실했다. ...

2026-03-22 00:00 · 10분 소요 · Seunghan

Hotwire Native + Rails 8 삽질 7가지 — 실기기에서만 터지는 버그들

Rails 8 + Hotwire Native으로 만든 모바일 앱의 대시보드 페이지를 Render에 배포한 뒤 실기기에서 점검하면서 만난 삽질 7가지를 정리했다. WKWebView 위에서 돌아가는 하이브리드 앱 특성상, 데스크톱 브라우저에서는 발견되지 않는 함정들이 많았다. 이 글에서 다루는 주요 키워드: Hotwire Native 모바일 레이아웃, Content Security Policy CDN 차단, Turbo const/let 재선언 에러, backdrop-filter 성능, Stimulus 컨트롤러 자동 등록, CSS contain 최적화. 프로젝트 환경 Backend: Rails 8 + PostgreSQL Frontend: Hotwire (Turbo + Stimulus) + ERB + Tailwind CSS 4 Mobile: Hotwire Native (iOS WKWebView) Realtime: ActionCable (WebSocket) Deploy: Render.com Asset Pipeline: importmap-rails (CDN pin 방식) 대시보드 페이지 구성: 코트 카드 grid (코트 수 x 라운드 수), 선수 DnD 리스트, 경기 목록, 교류 현황 통계. 코트 5개 x 8라운드 = 40장의 카드가 한 페이지에 렌더링되는 구조. ...

2026-03-21 00:00 · 8분 소요 · Seunghan

Rails 8 Hotwire 실전 삽질기 — DnD 배정, N+1 자동 감지, 테마별 Favicon

Rails 8 + Hotwire로 실시간 토너먼트 대시보드를 만들면서 하루 동안 겪은 3가지 삽질과 해결 과정. 이 문제들은 엣지 케이스가 아니라, Hotwire 프로그래밍 모델이 런타임에서 드러내는 자연스러운 마찰 지점들이다. 1. Turbo Stream + Stimulus DnD: DOM 교체 후 이벤트가 사라진다 문제 선수 칩을 코트 카드에 드래그하면 서버에 POST → Turbo Stream으로 코트 카드와 선수 목록을 교체하는 구조를 만들었다. 첫 번째 드래그는 잘 된다. 두 번째부터 아무 반응이 없다. 이벤트도, 요청도, 응답도 없다. ...

2026-03-21 00:00 · 9분 소요 · Seunghan

Hotwire Native iOS — 로그인 모달 충돌, Tailwind 4 사이드바, path config 삽질 기록

Hotwire Native iOS 앱에서 하루 동안 세 가지 버그를 잡았다. 각각 원인이 다르지만 공통점이 있다: 겉으로 보이는 증상과 실제 원인이 전혀 다른 곳에 있었다. 1. 로그인 페이지가 홈 탭에서만 보이는 문제 증상 4개 탭(홈, 과제, 알림, 마이)이 있는 앱에서, 비로그인 상태로 앱을 열면 홈 탭에서만 로그인 페이지가 뜨고, 나머지 탭을 누르면 빈 화면이나 에러가 표시된다. Rails 서버는 4개 탭 모두 /login으로 정상 리다이렉트하고 있었다. 원인: path-configuration의 context: "modal" Hotwire Native의 path-configuration에서 /login이 이렇게 설정되어 있었다: ...

2026-03-19 00:00 · 5분 소요 · Seunghan

Rails 8 + Hotwire Native iOS — 실시간 알림 뱃지 & 사이드 메뉴 네비게이션 구현

Rails 8 기반 Hotwire Native iOS 앱에서 두 가지 문제를 해결한 기록이다. 알림 뱃지 실시간 갱신 — 서버에서 알림이 생성되는 순간 앱 아이콘 뱃지와 내비게이션 벨 버튼을 즉시 업데이트 사이드 메뉴 네비게이션 누락 — tournament ID 같은 동적 파라미터가 필요한 URL을 사이드 메뉴에서 올바르게 이동 1. 문제 배경 알림 뱃지 APNs 푸시 알림의 badge 필드를 설정하지 않으면 iOS 앱 아이콘에 숫자가 표시되지 않는다. 또한 알림을 읽어도 뱃지가 초기화되지 않는 문제가 있었다. ...

2026-03-17 00:00 · 7분 소요 · Seunghan
Rails 8 Hotwire Native Production Checklist

Rails 8 + Hotwire Native iOS 실전 삽질 체크리스트 — 세션, CSRF, 채팅, 코트맵까지

Rails 8 + Hotwire Native로 iOS 앱을 만들면서 겪은 실전 이슈들을 정리했다. 공식 문서에 안 나오는 것들 위주로. 1. WKWebView 세션 쿠키가 앱 종료 시 날아간다 증상 앱을 완전히 종료(kill) 후 재실행하면 로그인이 풀린다. 원인 Rails 기본 cookie_store는 만료 시간이 없는 세션 쿠키를 생성한다. WKWebView는 앱 종료 시 세션 쿠키를 삭제할 수 있다. 해결 # config/initializers/session_store.rb Rails.application.config.session_store :cookie_store, key: "_app_session", expire_after: 30.days, same_site: :lax expire_after를 설정하면 영속 쿠키가 되어 앱 종료 후에도 유지된다. same_site: :strict는 절대 사용하지 말 것. WKWebView에서 쿠키 전송이 안 된다. ...

2026-03-17 00:00 · 5분 소요 · Seunghan

Rails 8 + Hotwire Native 앱의 역할 기반 UI 분리와 모바일 최적화 삽질기

Rails 8 + Hotwire Native 조합으로 iOS 앱을 운영하는 중에, 하루 동안 발생한 여러 문제를 연쇄적으로 해결한 기록이다. 작은 UI 깨짐에서 시작해서 권한 체계 재설계까지 이어진 과정을 정리한다. Hotwire Native의 핵심 매력은 하나의 Rails 앱으로 웹과 네이티브 iOS/Android를 동시에 지원한다는 점이다. 하지만 이 구조는 “웹에서 잘 보이면 앱에서도 잘 보인다"는 착각을 쉽게 심어준다. 실제로는 WKWebView의 렌더링 환경, 네이티브 네비게이션 바의 존재, 역할별 UI 분기 등 웹 브라우저와 전혀 다른 고려사항이 따라온다. ...

2026-03-17 00:00 · 7분 소요 · Seunghan
Rails Stimulus DnD Mentor Board Troubleshooting

Rails + Stimulus 드래그앤드롭 멘토 배정 보드에서 만난 삽질 5가지

Rails 8 앱에서 멘토-팀 배정을 드래그앤드롭으로 관리하는 보드를 만들었다. Stimulus 컨트롤러 + fetch + 서버 사이드 HTML 교체 방식이었는데, “되는 줄 알았던” 기능들이 프로덕션에서 하나씩 터졌다. 1. Stimulus 컨트롤러가 아예 로드 안 됨 증상 data-controller="mentor-assignment-board"를 붙였는데 드래그가 안 먹는다. 브라우저 콘솔에 에러도 없다. 원인 importmap-rails를 쓰는 프로젝트에서 한 번이라도 rails assets:precompile을 실행하면 public/assets/ 디렉토리가 생긴다. 이후 개발 환경에서도 Rails는 이 정적 파일을 우선 서빙한다. 문제는 precompile 시점에 존재하지 않았던 Stimulus 컨트롤러들이 public/assets/에 없다는 것. Rails가 public/assets/를 먼저 보기 때문에, app/javascript/controllers/에 있는 새 파일을 무시한다. ...

2026-03-12 00:00 · 4분 소요 · Seunghan

App Store 스크린샷 리젝 2.3.3 해결기 — AI 생성 이미지에서 실제 앱 캡처로

App Store에 첫 앱을 제출했는데, 스크린샷 문제로 리젝당했다. 해결까지의 삽질 기록. 리젝 사유 Guideline 2.3.3 - Performance: Accurate Metadata The screenshots do not show the actual app in use in the majority of the screenshots. 심사 디바이스: iPad Air 11-inch (M3) 원인 Gemini Image Generation API로 Neo-Brutalism 스타일의 가짜 UI 마케팅 이미지를 만들어서 스크린샷으로 제출했다. 앱 화면과 전혀 다른 디자인이었으니 당연한 결과. Apple이 요구하는 건: 대다수(majority) 스크린샷이 실제 앱 사용 화면이어야 함 마케팅/프로모션 자료만으로는 부적절 스플래시/로그인 화면만으로도 부족 다만, 실제 앱 화면 + 텍스트 오버레이 조합은 허용된다. 대부분의 앱이 이 방식을 쓴다. ...

2026-03-11 00:00 · 4분 소요 · Seunghan

Flutter iOS TestFlight 업로드 실패: objective_c.framework 시뮬레이터 슬라이스 오류

Flutter 앱을 flutter build ipa --release로 빌드하고 TestFlight에 업로드했더니 altool이 거절했다. 원인, 삽질 과정, Makefile 자동화까지 정리한다. 오류 메시지 UPLOAD FAILED with 3 errors Invalid executable. The "Runner.app/Frameworks/objective_c.framework/objective_c" executable references an unsupported platform in the x86_64 slice. Simulator platforms aren't permitted. Invalid executable. The "Runner.app/Frameworks/objective_c.framework/objective_c" executable references an unsupported platform in the arm64 slice. Simulator platforms aren't permitted. Unsupported Architectures. The executable for Runner.app/Frameworks/objective_c.framework contains unsupported architectures '[x86_64]'. flutter build ipa는 성공했고 IPA 파일도 정상 생성됐다. 문제는 빌드 단계가 아니라 업로드 단계에서 발생했다. 즉, Xcode 설정이나 Flutter 프로젝트 구성 자체의 문제가 아니라 Flutter가 조용히 임베드하는 서드파티 프레임워크 바이너리 안에 문제가 있다는 뜻이다. ...

2026-03-09 00:00 · 6분 소요 · Seunghan

Flutter 앱에 iOS 위젯 추가하기 — pbxproj 수동 편집부터 딥링크까지

Flutter 앱에 iOS 홈 화면 위젯을 붙이는 작업을 했다. 처음엔 단순해 보였는데 생각보다 손댈 곳이 많았다. Xcode GUI를 쓰면 간단하지만 CLI 환경에서 project.pbxproj를 직접 수정해야 하는 경우를 위해 전 과정을 정리한다. 목표 홈 화면 위젯 2종: 2×2(systemSmall), 2×1(systemMedium) 위젯에서 앱의 미처리 항목 수를 실시간으로 표시 위젯 버튼 탭 → 앱 특정 화면으로 이동 (딥링크) 1. 위젯 익스텐션 파일 구성 ios/ ├── Runner/ │ ├── AppDelegate.swift │ ├── Info.plist │ └── Runner.entitlements └── ReceiptWidget/ ← 새로 추가 ├── ReceiptWidget.swift ├── Info.plist └── ReceiptWidget.entitlements ReceiptWidget.swift 하나에 Provider, View, Widget, Bundle을 모두 담았다. 사이즈별로 View를 분리하고 @Environment(\.widgetFamily)로 분기하는 패턴이 깔끔하다. ...

2026-03-08 00:00 · 5분 소요 · Seunghan

iOS 앱 배포 막히는 순간들 — Bundle ID 이전 불가·ITMS-90683·AI 아이콘 생성까지

Flutter 앱을 TestFlight에 올리는 과정에서 겪은 삽질들을 기록한다. Apple Developer 계정 전환, Bundle ID 등록, 권한 누락 에러, 그리고 AI로 아이콘과 스크린샷을 자동 생성하는 방법까지. 1. Apple Developer 계정이 다를 때 — Bundle ID 이전은 불가 앱을 A 계정(Team A)에서 개발하다가 B 계정(Team B)으로 배포하려고 했다. 기존 Bundle ID가 A 계정에 이미 등록되어 있어서 B 계정으로 등록하려 하면 409 Conflict 에러가 난다. { "errors": [{ "status": "409", "code": "ENTITY_ERROR.ATTRIBUTE.INVALID", "detail": "An App ID with Identifier 'com.xxx.yyy' is not available." }] } Bundle ID는 계정 간 이전이 불가능하다. 해결책은 두 가지다: ...

2026-03-08 00:00 · 4분 소요 · Seunghan

Rails 앱을 Hotwire Native로 iOS 앱 만들어 TestFlight 올리기까지의 삽질 기록

Rails 8로 만든 긴급 신고 웹앱 바로신고를 Hotwire Native으로 iOS 앱으로 감싸서 TestFlight에 올리기까지의 과정을 정리합니다. 기술 스택 Backend: Rails 8 + Turbo iOS: Hotwire Native 1.2.2 + XcodeGen 빌드: Makefile 자동화 프로젝트 구조 ios/ ├── project.yml # XcodeGen 설정 ├── ExportOptions.plist # App Store 내보내기 ├── Makefile # 빌드 자동화 └── BaroSingo/ ├── AppDelegate.swift ├── SceneController.swift ├── AppTab.swift ├── Bridge/ │ ├── FormComponent.swift │ ├── HapticComponent.swift │ └── ShareComponent.swift └── Resources/ ├── Assets.xcassets/ └── path-configuration.json 삽질 1: Hotwire Native API 변경 Hotwire.config.userAgent — 읽기 전용 // ❌ 컴파일 에러: 'userAgent' is a get-only property Hotwire.config.userAgent = "BaroSingo iOS" // ✅ 해결: makeCustomWebView 사용 Hotwire.config.makeCustomWebView = { configuration in let webView = WKWebView(frame: .zero, configuration: configuration) webView.customUserAgent = "BaroSingo iOS/1.0 Turbo Native" return webView } Hotwire.loadPathConfiguration — 존재하지 않는 API // ❌ 컴파일 에러: no member 'loadPathConfiguration' Hotwire.loadPathConfiguration(from: [source]) // ✅ 해결: config.pathConfiguration.sources 직접 설정 Hotwire.config.pathConfiguration.sources = [ .file(Bundle.main.url(forResource: "path-configuration", withExtension: "json")!), .server(URL(string: "\(baseURL)/api/hotwire/path-configuration")!) ] Bridge Component에서 ViewController 접근 // ❌ 컴파일 에러: optional type must be unwrapped delegate.webView?.findViewController() // ✅ 해결: delegate?.destination 사용 guard let viewController = delegate?.destination as? UIViewController else { return } 교훈: Hotwire Native는 버전별 API 변경이 잦다. 공식 소스코드와 실제 동작하는 프로젝트를 참고하는 게 가장 확실하다. ...

2026-03-07 00:00 · 4분 소요 · Seunghan
Rails Sso Universal Links Hotwire Native

Rails 두 앱 사이에 SSO 구현하기 — 세션 유실·리다이렉트 루프·Universal Links 삽질까지

두 개의 Rails 8 서비스가 있다. 하나는 메인 앱(IdP 역할), 다른 하나는 연동 서비스(RP 역할). 연동 서비스 로그인 페이지에 “메인 앱으로 로그인” 버튼을 넣고, SSO로 인증 후 돌아오는 플로우를 구현했다. 거기에 iOS Hotwire Native 앱이 설치돼 있으면, 브라우저 대신 네이티브 앱에서 인증이 진행되도록 Universal Links까지 붙였다. OAuth 2.0 같은 표준 프로토콜을 쓰지 않고 직접 구현한 이유는 두 서비스 모두 직접 운영하는 내부 시스템이고, 외부 IdP(Auth0, Cognito 등)를 붙이기에는 오버엔지니어링이었기 때문이다. 핵심 개념(토큰 발급, 검증, 세션 관리)은 표준과 동일하다. ...

2026-02-17 00:00 · 9분 소요 · Seunghan
Rails Flutter Iap Unimplemented Features Audit

Rails + Flutter 앱 미구현 항목 점검 및 인앱 결제(IAP) 연동 기록

음성 메시지 기반 소셜 앱을 출시 준비하면서 미구현 항목을 전수 점검했다. route는 있는데 controller action이 없거나, Flutter UI는 완성됐는데 결제 로직이 // TODO 로 막혀 있는 경우들이 꽤 있었다. 정리하고 하나씩 구현한 기록. 미구현 항목 점검 방법 백엔드 점검 가장 빠른 방법은 routes.rb와 실제 controller를 비교하는 것이다. bundle exec rails routes | grep -v "^ #" route가 있는데 controller에 해당 action이 없으면 런타임에 ActionController::MethodNotImplemented 에러가 난다. 미리 찾아내는 게 낫다. 프론트엔드 점검 Flutter는 // TODO, SnackBar(content: Text('기능 준비 중')) 패턴을 검색하면 빠르다. ...

2026-01-30 00:00 · 5분 소요 · Seunghan
Hotwire Native Ios Tab Bar Patterns

Hotwire Native iOS 탭바 앱 구축 — HotwireTabBarController 적용기와 삽질 모음

Rails 앱을 Hotwire Native로 래핑할 때 단일 Navigator 대신 HotwireTabBarController 패턴으로 전환하면서 생긴 문제들을 정리한다. 시뮬레이터에서는 안 보이던 버그가 TestFlight에서 터지고, 로컬 개발 환경 설정이 꼬이는 등 여러 지점에서 시간을 날렸다. 1. HotwireTabBarController 기본 구조 단일 Navigator 대신 탭별로 독립적인 Navigator와 WKWebView를 갖는 구조다. // AppTab.swift enum AppTab: String, CaseIterable { case home, ai, request var systemImage: String { switch self { case .home: return "house" case .ai: return "message" case .request: return "checkmark.circle" } } var selectedSystemImage: String { switch self { case .home: return "house.fill" case .ai: return "message.fill" case .request: return "checkmark.circle.fill" } } var url: URL { let base = AppDelegate.baseURL switch self { case .home: return base.appendingPathComponent("dashboard") case .ai: return base.appendingPathComponent("conversations") case .request: return base.appendingPathComponent("service_requests") } } var hotwireTab: HotwireTab { HotwireTab( title: "", image: UIImage(systemName: systemImage)!, selectedImage: UIImage(systemName: selectedSystemImage)!, url: url ) } } // SceneController.swift 핵심 부분 private lazy var tabBarController: HotwireTabBarController = { let controller = HotwireTabBarController(navigatorDelegate: self) controller.load(AppTab.allCases.map(\.hotwireTab)) // 탭 아이콘만 표시, 텍스트 제거 controller.viewControllers?.forEach { vc in vc.tabBarItem.title = nil vc.tabBarItem.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0) (vc as? UINavigationController)?.delegate = self } return controller }() 탭 제목을 없애고 아이콘만 남기려면 tabBarItem.title = nil과 imageInsets 조정이 같이 필요하다. title만 nil로 하면 아이콘 위치가 내려가지 않아서 어색하게 보인다. ...

2025-12-26 00:00 · 5분 소요 · Seunghan
Hotwire Native Webview 8 Fixes

Hotwire Native WebView 삽질 모음 — 네이티브 앱에 Rails WebView 래핑할 때 자주 겪는 8가지 문제

Rails 앱을 Hotwire Native(Turbo Native)로 래핑해서 iOS/Android 네이티브 앱을 만들다 보면, 브라우저에서는 멀쩡한데 WebView에서만 이상하게 동작하는 것들이 꽤 많다. 실제로 작업하면서 겪은 문제와 적용한 수정을 한 곳에 정리해 둔다. 대부분 CSS 몇 줄 또는 path configuration JSON 한 줄로 끝난다. 1. 더블탭 줌 / 300ms 클릭 딜레이 증상 버튼을 빠르게 두 번 탭하면 화면이 확대된다. 단순 탭에도 눌렸다는 느낌이 살짝 늦다 (약 300ms). 원인 iOS WKWebView는 더블탭 줌 제스처를 감지하기 위해 첫 번째 탭 이벤트를 ~300ms 동안 잡아둔다. user-scalable=yes(viewport 기본값) 상태에서는 핀치 줌과 더블탭 줌이 활성화되어 있다. ...

2025-11-25 00:00 · 4분 소요 · Seunghan
Flutter Ipa No Codesign Api Key Testflight

flutter build ipa가 갑자기 실패한다면 — Development 인증서 없이 TestFlight 배포하는 법

Flutter iOS 앱을 여러 Apple 계정으로 관리하다 보면 한 프로젝트에서는 make testflight가 잘 되는데 다른 프로젝트에서는 동일한 Makefile이 실패하는 상황이 생긴다. 오늘 겪은 케이스를 정리한다. 증상 ❌ Error (Xcode): No signing certificate "iOS Development" found: No "iOS Development" signing certificate matching team ID "XXXXXXXX" with a private key was found. flutter build ipa 실행 시 위 오류로 실패한다. Distribution 인증서는 키체인에 있는데 Development 인증서가 없다는 메시지다. 원인: flutter build ipa 내부에서 일어나는 일 flutter build ipa는 내부적으로 다음 순서로 동작한다. ...

2025-11-04 00:00 · 4분 소요 · Seunghan
Flutter Ios Build Dark Mode Logout Debugging

TestFlight 올리려다 터진 Flutter iOS 빌드 오류 5종 — 다크모드·로그아웃 버그까지 한 번에

빌드를 올리려는데 한꺼번에 여러 문제가 터졌다. 코드 생성기가 실패하고, 없어진 파일이 있고, 빌드 번호 규칙을 몰라서 거절당하고, UI는 다크모드가 하드코딩되어 있고, 로그아웃은 토큰을 안 지웠다. 하나씩 정리한다. 1. Retrofit 옵션 파라미터 문법 오류 → .g.dart 생성 실패 증상 dart run build_runner build 실행 시 일부 API 서비스 파일에서: Expected to find ')' 원인 Retrofit의 추상 메서드에서 옵션 파라미터({}) 위치를 잘못 씀. // ❌ 잘못된 문법 — 닫는 중괄호 뒤에 쉼표 Future<Response> getItems( @Path('id') String id, {@Query('type') String? type}, // ← 이렇게 쓰면 안 됨 ); // ✅ 올바른 문법 — 포지셔널 파라미터 뒤에 { 바로 열기 Future<Response> getItems( @Path('id') String id, { @Query('type') String? type, }); Dart 문법에서 옵션 파라미터는 마지막 포지셔널 파라미터 바로 뒤에 {를 열어야 한다. },로 닫은 뒤 쉼표를 찍으면 파서가 다음 인자로 인식하려다 실패한다. ...

2025-11-01 00:00 · 5분 소요 · Seunghan
Ios Sso Entitlements Testflight Errors

iOS TestFlight 배포 삽질 모음: SSO 에러부터 entitlements mismatch까지

Flutter 앱 여러 개를 TestFlight에 올리면서 반복적으로 마주친 에러들을 정리했다. 1. Apple Sign-In 에러 1000 SignInWithAppleAuthorizationException(AuthorizationErrorCode.unknown, The operation couldn't be completed. (com.apple.AuthenticationServices.AuthorizationError error 1000.)) 원인 Runner.entitlements에 Sign in with Apple capability가 없어서 발생한다. 해결 두 곳 모두 설정해야 한다. ① ios/Runner/Runner.entitlements <key>com.apple.developer.applesignin</key> <array> <string>Default</string> </array> ② Apple Developer Console developer.apple.com → Identifiers → 앱 Bundle ID 선택 → Sign in with Apple 체크 → Save 프로비저닝 프로파일이 이미 있다면 재생성이 필요하다. ...

2025-08-30 00:00 · 4분 소요 · Seunghan
Flutter Dead Ui Fix Xcode26 Widget Bug

Flutter 미구현 UI 컴포넌트 연결 + Xcode 26 베타 WidgetKit 설치 버그 우회

Flutter 앱 작업 중 두 가지 문제를 연달아 처리했다. 하나는 UI 차원의 문제 — onTap: () {} 로 껍데기만 있는 컴포넌트들을 실제로 연결하는 작업. 다른 하나는 Xcode 26.2 베타에서 시뮬레이터에 앱을 설치하면 익스텐션 때문에 앱 자체가 설치되지 않는 문제다. 1. 동작하지 않는 UI 컴포넌트 연결 Flutter 개발 중 흔히 발생하는 상황: 화면은 다 만들어졌는데 버튼에 onPressed: () {}, 카드에 onTap: () {}만 달려 있고 실제 동작이 없는 상태. 패턴별 정리 알림 벨 아이콘 ...

2025-07-16 00:00 · 4분 소요 · Seunghan
Ios Codesign Testflight Full Setup

iOS 코드 서명 처음부터 끝까지 — Distribution Cert에서 TestFlight 업로드까지 수동 세팅

Flutter 앱을 TestFlight에 올리는 과정에서 코드 서명 관련 설정을 처음부터 다시 잡으면서 정리한 내용이다. Xcode 자동 서명이 아닌 수동 + App Store Connect API Key 방식으로 진행했다. 전체 흐름 [1] Distribution Certificate 발급 [2] APNs Certificate 발급 (CSR 생성 필요) [3] App ID에 Push Notifications 활성화 [4] Provisioning Profile 생성 (App Store, Push 포함) [5] xcodebuild archive + export (API Key 인증) [6] xcrun altool로 TestFlight 업로드 1. Distribution Certificate Apple Developer → Certificates → + → Apple Distribution 선택. ...

2025-06-18 00:00 · 4분 소요 · Seunghan
개인정보처리방침 이용약관 면책조항 문의