광고 리워드 앱
광고 시청과 미션 수행으로 포인트를 적립하고 현금으로 출금하는 리워드 앱. 웹·모바일·관리자 시스템 전체를 구축했습니다
사례 요약
고객사
광고 리워드 서비스 운영사 (비공개)
분야
광고 리워드, 포인트 기반 앱 서비스
기간
2026년 2월 ~ 2026년 5월 (약 4개월)
고민
리워드 앱은 포인트가 실제 현금이 되는 구조라, 적립·정산·어뷰징 방지·세무 처리가 모두 맞물려야 서비스를 열 수 있었습니다
활용 기능
광고 시청 적립, 미션과 미니게임, 추천 보상, 멤버십, 출금 승인, 관리자 정산 콘솔
성과
적립부터 출금까지 전 과정을 하나의 시스템에서 처리, 원천징수와 정산을 자동 반영하는 구조 확보
1. 고객사 소개
- 고객사: 광고 리워드 서비스 운영사 (비공개)
- 분야: 광고 리워드 서비스 운영
- 서비스 형태: 모바일 앱(안드로이드·iOS) + 웹, 포인트 적립 후 현금 출금
- 과제: 광고 수익과 사용자 보상, 세무 처리를 하나의 구조로 묶은 리워드 서비스 구축
당사는 웹 서비스, 모바일 앱, 관리자 콘솔, 정산 구조를 포함한 풀스택 개발을 담당했습니다.
2. 도입 배경
리워드 앱은 겉으로 보면 단순합니다. 광고를 보면 포인트가 쌓이고, 포인트가 모이면 현금으로 바꿉니다. 하지만 이 문장 안에는 서비스를 여는 데 필요한 조건이 전부 들어 있습니다.
서비스를 열기 위한 다섯 가지 조건
첫째, 포인트가 실제 현금이기 때문에 적립의 근거가 남아야 합니다. 광고를 정말 봤는지, 미션을 실제로 수행했는지 확인되지 않으면 그 포인트는 지급할 수 없습니다. 사용자는 "분명히 봤는데 안 들어왔다"고 문의하고, 운영자는 확인할 방법이 없으면 답할 수 없습니다.
둘째, 출금은 금전 거래입니다. 소득이 발생하므로 원천징수를 해야 하고, 지급 전에 검토하는 절차가 필요합니다. 금액을 계산하는 것과 그 계산 근거를 남기는 것은 다른 일입니다.
셋째, 보상이 있는 서비스에는 반드시 어뷰징이 따라옵니다. 계정을 여러 개 만들어 추천 보상을 반복 수령하거나, 광고를 보지 않고 적립만 요청하는 시도가 생깁니다. 이런 시도를 막지 못하면 광고 수익보다 지급액이 커져 서비스 자체가 성립하지 않습니다.
넷째, 광고 수익은 외부에서 들어옵니다. 광고 네트워크와 오퍼월이 보내는 결과를 받아 포인트로 바꿔야 하는데, 이 신호는 지연되거나 중복으로 올 수 있습니다. 같은 광고에 두 번 적립하면 그만큼 손실입니다.
다섯째, 정산이 맞아야 합니다. 광고 수익은 들어오고 포인트는 나갑니다. 이 둘을 각각 관리하면 서비스가 수익을 내고 있는지 알 수 없습니다. 지급액과 수익을 같은 기준으로 집계해야 정책을 조정할 근거가 생깁니다.
화면보다 데이터 구조가 먼저다
리워드 앱이 실패하는 이유는 대개 기능이 부족해서가 아닙니다. 지급 구조가 수익을 넘어서거나, 어뷰징을 막지 못해 비용이 새거나, 출금 처리가 늦어 신뢰를 잃는 쪽입니다. 그래서 이 프로젝트에서는 화면보다 데이터 구조를 먼저 정했습니다.
2026년 2월부터 5월까지 이 다섯 가지를 전제로 서비스를 구축했습니다. 화면을 만드는 일보다 적립·정산·검증의 흐름을 정하는 일이 프로젝트의 중심이었습니다.
한 줄 요약 포인트가 실제 현금이 되는 구조라, 적립·정산·어뷰징 방지·세무 처리가 모두 맞물려야 서비스를 열 수 있습니다.
3. 활용 기능
웹 서비스를 본체로 두고, 모바일 앱이 이를 감싸는 구조로 만들었습니다. 여기에 회사 소개 웹과 관리자 콘솔을 더해 하나의 저장소에서 관리합니다.
구성
사용자 웹, 모바일 앱, 회사 소개 웹을 하나의 저장소에서 관리합니다. 세 애플리케이션이 같은 규칙과 타입을 공유하므로, 정책이 바뀔 때 한쪽만 구버전으로 남는 상황이 생기지 않습니다.
앱과 웹의 관계
핵심 기능은 모두 웹에 구현하고, 모바일 앱은 이를 담는 껍데기 역할을 맡습니다. 기능을 고칠 때 앱 심사를 기다리지 않아도 되고, 안드로이드와 iOS에 같은 화면을 제공할 수 있습니다.
다만 앱에서만 할 수 있는 일은 앱이 처리합니다. 소셜 로그인은 외부 브라우저로 넘겨 처리하고 결과를 딥링크로 돌려받으며, 푸시 알림과 결제 앱 연동은 앱 계층에서 다룹니다. 웹으로 할 수 있는 것과 앱이어야 하는 것을 나눠, 개발 속도와 기능 범위를 함께 확보했습니다.
포인트 원장 구조
포인트는 잔액 하나로 관리하지 않습니다. 지갑에 현재 잔액을 두고, 모든 증감을 원장에 기록합니다. 언제 어떤 이유로 얼마가 들어오고 나갔는지가 건별로 남기 때문에, 잔액이 맞지 않으면 원장을 따라 원인을 찾을 수 있습니다.
적립이 즉시 확정되지 않는 경우도 있습니다. 광고 네트워크의 확인이 필요하거나 검증 절차가 남은 적립은 대기 상태로 두고, 확정된 뒤에 잔액에 반영합니다. 대기와 확정을 구분하면 취소된 적립을 잔액에서 빼는 일이 생기지 않습니다.
적립 경로
포인트가 들어오는 경로를 여러 갈래로 두었습니다. 광고 시청, 미션 수행, 출석 체크, 미니게임, 추천 보상, 친구 돕기가 각각의 경로이며, 경로별로 적립 출처를 구분해 기록합니다.
경로를 나눈 이유는 운영 판단에 필요하기 때문입니다. 지급액이 늘었을 때 어느 경로에서 늘었는지 알아야 정책을 조정할 수 있습니다. 광고 적립이 늘어난 것과 추천 보상이 늘어난 것은 원인도 대응도 다릅니다.
광고 수익과 정산
광고 수익은 외부 네트워크에서 발생합니다. 수익 데이터와 지급 내역을 함께 관리해, 한 기간에 얼마가 들어오고 얼마가 나갔는지 확인할 수 있게 했습니다. 정산 원장을 별도로 두고 기간별 스냅샷을 남기므로, 지난 시점의 상태를 되짚을 수 있습니다.
국가별 정책도 분리했습니다. 보상 단가와 조건이 지역에 따라 달라질 수 있어, 이 값을 설정으로 관리합니다. 서비스가 국내에만 머물지 않을 경우를 대비한 구조입니다.
출금과 세무 처리
출금은 신청·검토·지급 단계를 거칩니다. 사용자가 신청하면 관리자가 확인하고 승인하는 흐름이며, 각 단계의 상태가 기록됩니다. 원천징수는 신청 시점에 자동으로 계산해 반영하므로, 지급액과 세액이 항상 함께 남습니다.
본인 확인 절차도 출금과 연결했습니다. 금전이 오가는 거래이므로 계정과 실제 사용자가 일치하는지 확인해야 하고, 확인 결과가 없으면 출금 단계로 넘어가지 않습니다.
어뷰징 방지
계정과 기기를 연결해 한 계정이 여러 기기에서 동시에 쓰이거나, 한 기기에서 여러 계정을 돌려 쓰는 상황을 제한합니다. 세션은 유효 기간을 두고 주기적으로 다시 확인하며, 차단된 계정은 접근 단계에서 걸러집니다.
광고 적립은 시청 기록을 남겨 검증합니다. 적립 요청만으로 포인트를 주지 않고, 광고 네트워크가 보내는 결과와 대조합니다. 외부에서 오는 신호가 중복으로 들어오는 경우를 처리하도록 해, 같은 시청에 두 번 적립되지 않게 했습니다.
미션과 미니게임
적립 경로를 광고 시청 하나로 두면 사용자가 앱을 열 이유가 하루에 한 번으로 줄어듭니다. 그래서 미션과 미니게임을 함께 배치했습니다.
미션은 카테고리로 구분해 관리자가 등록합니다. 광고 제공사와 연결된 미션은 외부에서 완료 신호를 받아 처리하고, 자체 미션은 앱 안에서 수행 여부를 확인합니다. 완료 기록을 사용자별로 남기므로 같은 미션을 중복으로 수행하는 것을 막을 수 있습니다.
미니게임은 출석 체크, 룰렛, 드롭볼, 부스트로 구성했습니다. 각 게임은 적립 금액이 크지 않지만 매일 들어올 이유를 만듭니다. 보상 금액과 실행 가능 횟수는 정책 값으로 관리해, 운영 중에 조정할 수 있게 했습니다.
추천과 멤버십
추천 보상은 초대한 사람과 초대받은 사람 양쪽에 적용됩니다. 초대받은 사용자가 광고를 보거나 미션을 완료하면 초대한 사용자에게도 일정 비율이 돌아가는 구조로, 광고 커미션과 미션 커미션을 각각 기록합니다.
이 구조는 어뷰징에 가장 취약한 지점이기도 합니다. 계정을 여러 개 만들어 서로 추천하면 실제 활동 없이 보상이 발생합니다. 그래서 추천 이력을 별도로 관리하고, 기기 연결과 본인 확인을 함께 걸어 반복 수령을 제한했습니다.
멤버십은 등급을 두어 적립률과 이용 조건을 구분합니다. 결제는 토스페이먼츠를 연동했고, 결제 요청과 등급 적용을 분리해 결제 실패가 등급 상태를 흔들지 않도록 했습니다.
알림과 노출 관리
푸시 알림, 공지, 모달 안내, 배너, 플로팅 광고를 관리자 콘솔에서 다룹니다. 리워드 서비스는 사용자가 매일 들어오게 만드는 것이 운영의 핵심이라, 알림과 노출 수단을 코드가 아니라 운영 도구로 관리해야 합니다.
발송 이력을 기록해 두므로 어떤 알림이 언제 나갔는지 확인할 수 있습니다. 알림 대상과 발송 출처를 구분해 저장해, 전체 발송과 특정 조건 발송을 나눠 다룹니다.
관리자 콘솔
운영에 필요한 화면을 20개 이상 구성했습니다. 회원과 미션, 재무와 정산, 출금 승인, 광고 수익, 공지와 알림, 배너와 노출 설정, 앱 업데이트 정책, 국가별 정책, 계정 삭제 요청이 각각의 영역입니다.
관리자 동작에는 감사 기록을 남깁니다. 포인트를 조정하거나 출금을 승인하는 일은 금전에 직접 영향을 주므로, 누가 언제 무엇을 바꿨는지 남아야 합니다.
앱 업데이트 정책과 운영 설정도 콘솔에서 다룹니다. 강제 업데이트가 필요한 시점이나 점검 안내를 앱 배포 없이 적용할 수 있어야, 문제가 생겼을 때 즉시 대응할 수 있습니다. 계정 삭제 요청은 별도 화면에서 처리해, 요청과 처리 결과가 기록으로 남습니다.
화면 구성
사용자 화면은 매일 들어와서 할 일이 바로 보이도록 구성했습니다. 홈에서 보유 포인트와 오늘 할 수 있는 적립 활동을 먼저 보여 주고, 미션·미니게임·마켓·포인트 내역·설정이 각각의 영역으로 나뉩니다. 라운지와 공지처럼 안내 성격의 화면은 그 뒤에 배치했습니다.
포인트 내역 화면은 사용자가 가장 민감하게 보는 곳입니다. 적립과 사용, 대기 중인 적립을 구분해 보여 주고, 각 항목이 어떤 활동에서 발생했는지 표시합니다. 잔액만 보여 주면 "왜 이 금액인지" 묻는 문의가 그대로 운영 부담이 됩니다.
출금 화면은 단계를 나눴습니다. 신청 가능 금액과 원천징수 후 실지급액을 먼저 보여 주고, 본인 확인이 끝나지 않은 계정은 그 단계로 안내합니다. 금전이 걸린 화면에서 예상과 다른 금액이 나오면 신뢰를 잃기 때문에, 계산 결과를 신청 전에 명시했습니다.
진행 방식
4개월 동안 포인트 구조를 먼저 확정하고 그 위에 기능을 얹는 순서로 진행했습니다. 적립 경로와 원장 구조, 출금 흐름이 정해지지 않으면 어떤 기능을 만들어도 나중에 다시 손봐야 합니다.
구조가 잡힌 뒤에 적립 경로를 하나씩 붙였습니다. 광고 시청을 먼저 완성해 외부 연동과 검증 흐름을 확인하고, 그다음 미션과 미니게임, 추천 보상을 추가했습니다. 경로마다 검증 방식이 다르므로 하나를 끝까지 겪어 본 뒤에 다음을 붙이는 편이 안전했습니다.
관리자 콘솔은 기능이 완성될 때마다 함께 만들었습니다. 포인트와 출금을 다루는 서비스에서 관리 도구가 없으면 개발 기간 내내 데이터베이스를 직접 열어 확인하게 되고, 그 상태로는 운영을 넘길 수 없습니다.
핵심 설계 계산 결과만 남기면 안 되고, 어떤 사건으로 그 값이 되었는지가 남아야 합니다. 원장을 둔 이유입니다.
4. 성과
적립부터 출금까지의 전 과정을 하나의 시스템에서 처리하는 구조를 완성했습니다. 광고 시청과 미션으로 쌓인 포인트가 원장에 기록되고, 출금 신청 시 원천징수가 자동 반영되며, 관리자 승인을 거쳐 지급됩니다. 각 단계가 기록으로 남기 때문에 문의가 들어왔을 때 확인할 근거가 있습니다.
포인트를 잔액이 아니라 원장으로 관리한 것이 운영에서 가장 크게 작용했습니다. "포인트가 왜 줄었는지" 같은 문의는 잔액만 있으면 답할 수 없지만, 원장이 있으면 조회로 끝납니다. 적립을 대기와 확정으로 나눈 덕분에, 취소된 광고 적립을 이미 지급한 뒤에 회수하는 상황도 피했습니다.
적립 경로를 구분해 기록하면서 정책 조정의 근거가 생겼습니다. 지급액 변화를 경로별로 볼 수 있어, 어떤 보상을 조정해야 하는지 판단할 수 있습니다. 광고 수익과 지급액을 함께 확인하는 화면을 관리자 콘솔에 둔 것도 같은 목적입니다.
웹을 본체로 두고 앱이 감싸는 구조를 택한 덕분에, 기능 수정이 앱 심사 주기에 묶이지 않습니다. 리워드 서비스는 정책과 보상 구성을 자주 조정하게 되는데, 이 구조에서는 그 조정이 웹 배포로 끝납니다.
어뷰징 방지를 사용자가 체감하지 않는 위치에 둔 것도 결과에 영향을 미쳤습니다. 기기 연결과 세션 확인은 배경에서 동작하고, 본인 확인은 출금 시점에만 요구합니다. 가입 단계에서 모든 검증을 걸면 정상 사용자가 먼저 이탈하기 때문입니다.
정책 값을 관리자 콘솔에서 다루도록 한 덕분에, 보상 금액이나 미션 구성을 바꿀 때 개발이 개입하지 않습니다. 리워드 서비스는 지급액과 수익의 균형을 보며 계속 조정해야 하는데, 그 조정 주기가 배포 주기에 묶이면 대응이 늦어집니다.
2026년 2월부터 5월까지 약 4개월간 웹, 모바일 앱, 회사 소개 웹, 관리자 콘솔을 모두 구축했습니다.
5. 기술 구성
Web — Next.js 14 App Router와 TypeScript, Tailwind CSS로 구성했습니다. 사용자 화면과 관리자 콘솔을 같은 애플리케이션에서 라우트로 분리하고, API도 같은 코드베이스에 두었습니다.
Mobile — React Native와 Expo로 앱을 만들고, 웹 서비스를 감싸는 방식으로 구성했습니다. 소셜 로그인은 외부 브라우저로 넘긴 뒤 딥링크로 결과를 받고, 푸시 알림과 결제 앱 연동은 앱 계층에서 처리합니다.
Backend / Data — Prisma ORM과 PostgreSQL을 사용합니다. 사용자와 세션, 지갑과 포인트 원장, 미션과 광고 시청 기록, 출금과 정산, 알림과 운영 설정이 각각의 모델로 나뉘어 있습니다.
인증 — 세션 토큰을 해시로 저장하고 유효 기간을 두었습니다. 계정과 기기를 연결해 동시 사용을 제한하며, 관리자 세션은 일반 사용자와 분리된 흐름으로 처리합니다. 소셜 로그인은 카카오와 구글을 지원합니다.
결제 / 알림 — 멤버십 결제는 토스페이먼츠를 연동했습니다. 푸시 알림은 Firebase Cloud Messaging을 사용하고, 발송 이력을 기록합니다.
구성 — 모노레포로 사용자 웹, 모바일 앱, 회사 소개 웹을 함께 관리합니다. 개발 환경은 컨테이너로 구성해 데이터베이스를 로컬에서 띄웁니다.
설계 기준 — 이 서비스에서 가장 중요한 것은 포인트의 근거입니다. 금전으로 바뀌는 값이므로 계산 결과만 남기면 안 되고, 어떤 사건으로 그 값이 되었는지가 남아야 합니다. 원장을 두고, 적립 출처를 구분하고, 관리자 동작에 감사 기록을 남긴 것 모두 이 기준에서 나온 결정입니다.
구현하면서 다룬 문제
- 외부 신호의 중복과 지연.: 광고 네트워크와 오퍼월의 결과는 늦게 오거나 여러 번 올 수 있습니다. 같은 사건에 두 번 적립되지 않도록 처리하고, 확정 전 적립은 대기 상태로 관리했습니다.
- 어뷰징과 사용성의 균형.: 검증을 강하게 걸면 정상 사용자도 불편해집니다. 기기 연결과 세션 확인처럼 사용자가 체감하지 않는 장치를 앞에 두고, 본인 확인은 출금 시점에만 요구하도록 배치했습니다.
- 세무 처리의 위치.: 원천징수를 지급 시점에 계산하면 신청 내역과 금액이 맞지 않습니다. 신청 시점에 계산해 함께 기록하도록 해, 사용자가 신청할 때 본 금액과 실제 지급액이 일치하게 했습니다.
- 웹뷰 환경의 제약.: 소셜 로그인과 결제는 웹뷰 안에서 그대로 동작하지 않습니다. 해당 흐름만 앱이 가로채 외부 브라우저나 결제 앱으로 넘기고, 결과를 딥링크로 돌려받도록 구성했습니다.
- 운영 정책의 변경 빈도.: 보상 금액과 미션 구성은 운영 중 자주 바뀝니다. 정책 값을 코드에 고정하지 않고 관리자 콘솔에서 다루도록 해, 배포 없이 조정할 수 있게 했습니다.
6. 프로젝트 정보
| 항목 | 내용 |
|---|---|
| 사업명 | 광고 리워드 앱 개발 |
| 담당 범위 | 풀스택 개발 (웹, 모바일 앱, 관리자 콘솔, 정산 구조) |
| 적용 기술 | Next.js 14, React Native, Expo, TypeScript, Prisma, PostgreSQL, 토스페이먼츠, Firebase Cloud Messaging |
비슷한 프로젝트를 준비 중이신가요?
요구사항과 일정만 알려주시면 적합한 구성과 예상 범위를 정리해 드립니다.
댓글 0
첫 번째 댓글을 남겨보세요.