전체 글 118

배포하고 세 시간 뒤에 사이트가 사라졌다

※ 이 글은 제가 일본어로 쓴 글(jacepark.com)을 한국어로 옮긴 것입니다.배포는 정상적으로 끝났습니다. 09:41. 사이트도 제대로 표시됐습니다. 세 시간 뒤에 접속하니 403 Forbidden이었습니다.서버에 들어가 문서 루트를 봅니다.ahha.iffthen.com/ assets/ ← 이것만 남아 있다index.html도 .htaccess도 각 페이지의 파일도 전부 사라져 있었습니다. assets/만 살아남아 있습니다. 다시 배포하니 복구됐습니다. 그리고 몇 시간 뒤에 또 사라졌습니다.첫 번째 조사 — 원인을 찾지 못했다당연히 배포 스크립트를 의심했습니다. rsync --delete를 쓰고 있었기 때문입니다. 서버를 뒤졌습니다.crontab -l → 이 사이트 관련 작업은 ..

그 공지, 사용자는 실제로 보고 있나요

※ 이 글은 제가 일본어로 쓴 글(jacepark.com)을 한국어로 옮긴 것입니다.ahha의 구독 상태 처리를 정리하면서 이런 공지를 만들었습니다.프리미엄 플랜이 종료되었습니다이용 기간이 만료되어 무료 플랜으로 전환되었습니다.기간이 만료됐을 때, 그리고 결제 수단 문제로 갱신에 실패했을 때 띄우는 공지입니다. 상태 판정도 제대로 하고, 문구도 다듬고, 중복 표시 방지까지 넣었습니다. 체크리스트에 「○」를 붙였습니다.그리고 두 세션 뒤에 다시 보다가 알아차렸습니다. 이 공지를 볼 수 있는 사용자가 거의 없었습니다.구조를 보면 바로 알 수 있다공지의 상태는 전역 변수 하나로 들고 있었습니다.export type PlanEndedNotice = "expired" | "billingIssue" | null;e..

네이티브 모듈이 Web을 죽이는 세 가지 방식

※ 이 글은 제가 일본어로 쓴 글(jacepark.com)을 한국어로 옮긴 것입니다.React Native Web을 쓰면 앱과 Web을 하나의 코드베이스로 돌릴 수 있습니다. 편합니다.그런데 네이티브 전용 라이브러리를 하나 추가할 때마다 Web이 조용히 죽습니다. 그것도 매번 다른 방식으로 죽습니다. ahha를 개발하면서 세 번을 밟고 나서야 겨우 패턴이 보였습니다.사례 1 — 검은 화면과, 엉뚱한 에러랜딩 페이지의 「Web에서 체험하기」를 누르면 앱의 미리보기 화면으로 넘어가게 해 두었습니다. 배포하고 눌러 보니 새까맣게 나왔습니다.Uncaught TypeError: Failed to set an indexed property [0] on 'CSSStyleDeclaration':Indexed prope..

샌드박스에서 「해지 → 재구매」를 반복할 수 없는 이유

※ 이 글은 제가 일본어로 쓴 글(jacepark.com)을 한국어로 옮긴 것입니다.구독 앱을 만들면 이런 검증을 하고 싶어집니다.구독한다 → 프리미엄 표시를 확인해지한다 → 「해지됨」 표시를 확인다시 구독한다 → 프리미엄 복귀를 확인만료시킨다 → 무료로 떨어지는 것을 확인각 상태에서 화면이 제대로 나오는지 봐야 하니 당연한 절차입니다. iOS에서는 이것이 사실상 불가능합니다. ahha를 개발하면서 며칠을 날리고 나서야 알았습니다.리셋이 필요한 이유 — 서버가 두 개 있다[Apple / Google 스토어 서버] 결제·구독 이력을 보관 ↓ receipt push[RevenueCat 서버] Entitlement 상태를 관리·별도 서버한쪽만 지우면 다른 쪽 데이터로부터 되살아납니다. 앱을 실..

공유 서버에서 Akamai 403 우회, 다섯 번의 방향 전환

※ 이 글은 제가 일본어로 쓴 글(jacepark.com)을 한국어로 옮긴 것입니다.ahha에는 추첨 결과 데이터가 필요합니다. 공식 사이트에서 정기적으로 가져와야 합니다.간단한 일이라고 생각했습니다. 요청을 보내고, 파싱하고, CSV로 저장하고, cron에 올리면 끝.403이 돌아왔습니다.상대는 Akamai Bot Manager몇 가지 방법을 시도했지만 전부 403이었습니다.curl https://# → 403php -r 'echo file_get_contents("https://");'# → 403User-Agent를 브라우저 것으로 바꿔도, 헤더를 전부 흉내 내도 같았습니다. 브라우저로 열면 평범하게 열립니다.Akamai Bot Manager가 TLS 핸드셰이크 단계에서 걸러내고 있었습니다.HTTP..

pod install 성공, 그런데 링크 단계에서 실패

※ 이 글은 제가 일본어로 쓴 글(jacepark.com)을 한국어로 옮긴 것입니다.ahha에 네이티브 모듈을 하나 추가했습니다. expo-tracking-transparency입니다.순서는 교과서 그대로였습니다.npx expo install expo-tracking-transparencycd ios && pod installpod install은 성공했습니다.Pod install took 27 [s] to runIntegrating client projectPod installation complete! There are 117 dependencies from the Podfileand 143 total pods installed.Podfile.lock에도 제대로 들어가 있습니다. TypeScript ..

앱을 두 번 고쳐도 안 되면, 원인은 앱 밖

※ 이 글은 제가 일본어로 쓴 글(jacepark.com)을 한국어로 옮긴 것입니다.구독을 넣은 ahha를 개발하던 중에 이런 증상을 만났습니다.Google Play에서 구독을 해지했다. 그런데 앱은 여전히 「프리미엄」이라고 표시합니다.앱 안의 「상태 새로고침」 버튼을 눌러도 바뀌지 않는다앱을 완전히 종료하고 다시 실행해도 바뀌지 않는다하루를 두어도 바뀌지 않는다두 번의 헛손질저는 이것을 앱의 버그라고 생각하고, 두 번에 걸쳐 고쳤습니다.첫 번째 — Entitlement ID 확인RevenueCat의 Entitlement 식별자가 대시보드 설정과 코드에서 일치하는지 확인했습니다. 일치했습니다. 증상은 그대로.두 번째 — SDK 캐시 회피캐시가 오래된 건가 싶어 invalidateCustomerInfoCa..

구독 앱 첫 심사, 준비물 체크리스트

※ 이 글은 제가 일본어로 쓴 글(jacepark.com)을 한국어로 옮긴 것입니다.자동 갱신 구독을 넣은 ahha를 처음으로 심사에 냈습니다. 두 번 리젝을 거쳐 통과했습니다.리젝 사유는 구독과 무관했습니다(ATT 미구현·연령 등급). 다만 준비하는 과정에서 정리한 항목이 있어 남겨둡니다. 두 스토어를 나란히 놓고 보면, 요구하는 것이 비슷하면서도 미묘하게 다릅니다.먼저 주의사항을「이 항목이 없으면 반드시 리젝된다」는 인과는 검증할 수 없습니다. 실제로 떨어진 것은 2건뿐이고, 나머지는 「넣어뒀더니 통과했다」 수준의 정보입니다.그래도 쓰는 이유는, 첫 제출에서는 무엇을 준비해야 하는지 전체 그림이 안 보이는 것 자체가 시간을 잡아먹기 때문입니다. 떨어지고 나서 채우는 것보다, 먼저 늘어놓는 쪽이 빠릅니..

app.json 수정 무효, Bare Workflow의 함정

※ 이 글은 제가 일본어로 쓴 글(jacepark.com)을 한국어로 옮긴 것입니다.직접 만든 앱 ahha의 스플래시 화면에서 로고가 작아 보여서 크게 키우려고 했습니다.app.json을 열어서 값을 고칩니다.{ "expo": { "plugins": [ ["expo-splash-screen", { "imageWidth": 76 }] ] }}76 → 130으로 바꾸고 다시 빌드. 변화 없음180으로 바꾸고 다시 빌드. 변화 없음캐시를 의심해서 클린 빌드. 변화 없음시뮬레이터를 지우고 다시 만들기. 변화 없음네 시간을 이렇게 썼습니다.먼저 결론부터답은 Expo 공식 문서에 적혀 있었습니다.android·ios 디렉터리를 Expo Prebuild로 생성하지 않은 앱에서는, app con..

구독이 끝났는데, 앱은 「이용 중」이라고 합니다

※ 이 글은 제가 일본어로 쓴 글(jacepark.com)을 한국어로 옮긴 것입니다.직접 만든 앱 ahha에 구독을 붙였을 때, 제일 마지막에 발견되고 제일 마지막에 고친 버그가 이거였습니다.샌드박스 구독이 2일 전에 만료돼 있습니다. 그런데도 앱을 열면 이렇게 나옵니다.프리미엄 플랜(이용 중)다음 갱신일: 2026/08/02이미 지나간 날짜를 「다음 갱신일」로 표시하고 있습니다. 앱을 껐다 다시 켜도 똑같습니다. 몇 번을 해도 똑같습니다.그런데 「플랜 상세 보기」를 누르면 그 순간 화면이 「무료」로 바뀝니다.먼저 결론부터유효기간 만료는 스토어의 알림 대상이 아닙니다.해지했다, 갱신됐다, 결제에 문제가 생겼다. 이건 전부 「벌어진 사건」이라서 스토어가 그 순간 푸시를 쏩니다.만료는 사건이 아닙니다. 아무..