처음 만든 건 화면 세 개였어요. 한 줄 적으면 잎이 하나 붙고, 네 장이 되면 클로버가 되는 것. 목업을 먼저 잡아 놓고 그대로 옮겼는데, 여기서 규칙을 하나 세웠습니다. Material 기본 모양은 하나도 쓰지 않는다. 기본 AppBar, 잉크 리플, 보라색 시드 컬러가 한 개라도 남아 있으면 "플러터로 만든 티"가 나거든요. 버튼도 카드도 Container 로 직접 그리고, 색·그림자·자간은 목업 값을 그대로 옮겨 적었어요.


선행 한 번에 잎이 하나씩 붙는다

오늘 한 일을 한 줄로 적어 넣는다
네 장째를 채우면 클로버가 상단 배지로 날아간다

코인 하나로 캡슐 머신을 돌린다

왕복하는 게이지를 탭한 순간이 오늘 점수가 된다

잡은 점수와 오늘의 색·숫자·아이템을 한 장으로 받는다

뽑은 행운권이 등급별로 쌓인다

태울 카드를 직접 골라 성공 확률을 올린다
재료가 빨려 들어가고 게이지가 한 바퀴 돌면 성패가 갈린다

선행한 날이 달력에 색으로 남는다
어떤 서비스인가요?
착한 일을 한 줄 적으면 잎이 하나 붙고, 네 장이 모이면 네잎클로버가 완성되는 앱이에요. 그 클로버로 행운권을 뽑고 모읍니다
어떤 계기로 만들게 됐나요?
평소에 업보라는 걸 자주 생각했어요. 카르마라고도 하죠. 덕은 쌓는 거라고 하잖아요. 야구선수 오타니도 자기 덕을 위해 쓰레기를 줍는다고 알려져 있고요
제가 좋아하는 롤 프로팀 T1 의 팬 문화에서도 영감을 받았어요. 1년에 한 번 열리는 롤드컵 기간이 되면 팬들이 일부러 착한 일을 하고 인증을 올려요. 내 선행이 조금이라도 응원하는 팀에 보탬이 되길 바라면서요
그러다 생각이 들더라고요. 운이라는 게 정말 문득 찾아오기만 하는 걸까, 그렇게 수동적인 걸까. 능동적으로 얻을 수는 없을까. 그러다 네잎클로버가 떠올랐고, 선행을 쌓아 스스로 운을 만드는 서비스로 만들어 봤어요
이름은 어떻게 지었나요?
처음엔 ooloo 였는데, 가챠 쪽으로 방향을 틀면서 LuckyPicky 로 바꿨어요. "럭키비키"랑 발음이 비슷해서 입에 붙고, 골라 뽑는다는 성격에도 picky 가 맞더라고요
주로 어떤 분이 쓰나요?
2030 여성을 주 타깃으로 잡았어요. 하루에 한두 번 잠깐 들어와 한 줄 적고 나가는 쪽이요
만드는 데 얼마나 걸렸나요?
6월 중순에 시작해서 두 달쯤 됐어요. 아직 스토어에는 안 올렸고요
작업하면서 어떤 제약이 있었나요?
작업 PC 가 윈도우라 iOS 는 코드만 맞춰 두고 빌드 검증을 못 해요. 화면 확인은 전부 안드로이드 에뮬레이터에서 합니다
지금은 안 하기로 한 게 있나요?
중국어는 뺐어요. 간체·번체가 갈리고 본토 스토어는 심사와 퍼블리셔가 따로라, 혼자 감당할 운영비가 아니라서요
소셜 로그인도 아직이에요. 익명 로그인으로 시작하고 복구 코드로 막아 뒀습니다
홈 한가운데 클로버에 잎이 하나 붙어요.
네 장째를 적는 순간 클로버가 완성돼서 상단 배지로 날아갑니다.
코인 한 개로 행운권 한 장이 나와요.
같은 등급 셋을 태워 재조합하거나, 여러 장을 먹여 한 장을 강화합니다.
게이지가 왕복하는 걸 탭한 순간의 값이 오늘 점수가 돼요.
처음 만든 건 화면 세 개였어요. 한 줄 적으면 잎이 하나 붙고, 네 장이 되면 클로버가 되는 것. 목업을 먼저 잡아 놓고 그대로 옮겼는데, 여기서 규칙을 하나 세웠습니다. Material 기본 모양은 하나도 쓰지 않는다. 기본 AppBar, 잉크 리플, 보라색 시드 컬러가 한 개라도 남아 있으면 "플러터로 만든 티"가 나거든요. 버튼도 카드도 Container 로 직접 그리고, 색·그림자·자간은 목업 값을 그대로 옮겨 적었어요.
처음 메인은 소원권이었어요. 선행 하나에 잎 하나, 네 번이면 클로버가 완성되고, 그 클로버로 소원권을 만드는 구조요. 그런데 만들고 보니 소원 문구를 사용자가 직접 써야 하더라고요. 쓰는 부담이 있는 데다 다 쓰고 나면 그걸로 끝이라, 재미 요소가 영 떨어졌어요.
그래서 클로버를 아예 코인처럼 쓰기로 했습니다. 클로버 하나를 넣고 캡슐 머신을 돌려 행운권을 랜덤으로 뽑는 쪽으로요. 무엇이 나올지 모르는 도파민이 붙으니까 매일 열어볼 이유가 생겼어요.
로컬에만 저장하던 시절엔 앱을 지우면 모은 게 전부 날아갔어요. 뽑기까지 붙이고 나니 이건 더 못 미루겠더라고요. 게다가 클라이언트가 재화를 계산하면 마음만 먹으면 얼마든지 늘릴 수 있고요.
Supabase 로 옮기면서 앱이 테이블을 직접 쓰지 못하게 막았어요. 잎 적립도 뽑기도 강화도 전부 security definer 함수 안에서만 일어나고, 앱은 결과 JSON 만 받습니다. 대신 테스트용으로 똑같은 규칙을 구현한 로컬 백엔드를 하나 더 뒀어요 — 규칙을 고칠 땐 SQL 과 그 파일을 항상 같이 고칩니다.
뽑기만 있으면 카드가 쌓이기만 하고 쓸 데가 없어요. 중복 카드도 계속 나오고요. 피파 게임에서 선수 카드를 재료로 태워 등급을 올리잖아요 — 그걸 그대로 가져왔습니다. 같은 등급 셋을 태워 다시 뽑는 재조합, 여러 장을 먹여 한 장을 올리는 강화 두 가지로요.
처음엔 카드 상세 아래에 바텀시트로 붙였어요. 좁으니까 재료를 고르는 화면이 답답했고, 무엇을 태우는지도 잘 안 보였고요. 아예 전용 화면으로 꺼내서 지갑에서 카드를 직접 골라 태우게 바꿨습니다. 강화는 대상 → 재료 두 단계, 재조합은 재료 세 장 한 단계로요.
연출도 여기서 많이 갈아엎었어요. 재료 카드가 중앙으로 빨려 들어가고, 게이지가 차고, 성공하면 카드가 뒤집히고 실패하면 화면이 흔들립니다. 그 과정에서 결과가 미리 새는 문제로 한참 고생했는데, 그건 아래 시행착오에 적었어요.
이 서비스의 모토가 운은 찾아오는 게 아니라 찾아가는 거잖아요. 그런데 앱 안에서 그걸 몸으로 느끼는 대목이 없더라고요. 선행을 적는 것도, 뽑기를 돌리는 것도 결국 결과는 서버가 정하는 거니까요.
그래서 운세 탭에 타이밍 게임을 넣었어요. 게이지가 0에서 100 사이를 왕복하고, 탭한 순간의 값이 그대로 오늘의 행운지수가 됩니다. 오늘 내 운을 내 손으로 정하는 거죠. 표시값에 커브를 걸어서 90 점대 구간을 순식간에 스쳐 지나가게 했어요 — 그래야 100 을 잡는 맛이 나거든요.
광고 규칙을 만지다 보니 모델이 계속 어긋났어요. 클로버 하나가 곧 뽑기 한 번이면, 선행으로 만든 클로버와 광고로 받은 클로버가 구분이 안 되잖아요. 그러면 "선행으로 운을 만든다"는 축이 통계에서부터 무너집니다.
그래서 재화를 둘로 나눴어요. 뽑기는 광고로만 들어오는 코인을 쓰고, 선행으로 만든 클로버는 커스텀 행운권 제작·강화 전용이 됩니다. 클로버는 여전히 선행으로만 생기고, 통계에도 그것만 쌓여요. 사용자가 문구를 직접 써서 만드는 커스텀 행운권도 이때 붙였습니다.
문구를 고칠 때마다 스토어 심사를 기다리는 게 말이 안 됐어요. 그래서 문구를 Supabase 테이블에서 받아오고, 못 받으면 앱에 실린 문구로 떨어지게 했습니다. 폴백 단위를 (면, 언어, 등급) 조합별로 잘게 쪼개서, 한 면씩 천천히 서버로 옮겨도 안전하게요.
그 다음에 소스를 어디에 둘지로 한 번 뒤집혔는데, 그것도 시행착오에 적었습니다.
익명 로그인은 세션을 기기에 둬요. 웹은 localStorage 고요. 그래서 다른 기기에서 열면 새 계정이 되고, 모은 게 전부 사라진 것처럼 보입니다. 소셜 로그인을 붙이는 게 정석이지만 그건 심사·약관까지 딸려 오는 일이라, 먼저 복구 코드를 만들었어요.
계정마다 "형용사 + 뜬금없는 명사" 조합의 코드를 발급해 두고 — 명란한 참치마요 오붓한 스파게티 같은 — 새 기기에서 그 코드를 넣으면 옛 계정의 재화·카드·기록이 현재 세션으로 넘어옵니다. 세션은 건드리지 않고 서버에서만 옮기는 방식이라, 로그인 구조를 바꾸지 않고도 자산이 안 날아가요.