2026. 4. 15. 07:15ㆍAI Product Building/Lotto App

안녕하세요! 직접 코딩하며 만들어 나가는 '로또 사고 싶은날' 1인 개발기, 벌써 네 번째 시간입니다. 지난 3회차까지는 프로젝트의 기초 공사인 개발 환경 설정과 폴더 구조(아키텍처) 및 상태 관리 설계라는 다소 딱딱하지만 필수적인 '뼈대 세우기' 작업을 했습니다. 오늘부터는 드디어 눈에 보이는 화려한 집단장, 즉 UI(User Interface) 디자인과 컴포넌트 구현에 들어갈 차례입니다! 수많은 기존 로또 앱들이 사용자로부터 외면받는 가장 큰 이유 중 하나는 마치 10년 전에 만들어진 듯한 투박하고 촌스러운 디자인 때문입니다. 우리는 플러터(Flutter)가 자랑하는 강력하고 부드러운 렌더링 엔진을 100% 활용하여, '로또 사고 싶은날' 앱에 접속할 때마다 사용자의 시각적 만족도를 극대화할 수 있는 프리미엄 감성의 메인 화면과 입체적인 로또 공 컴포넌트를 직접 디자인해 보겠습니다.
👉 '로또 사고 싶은날' 구글스토어 다운로드 바로가기 👈
1. 사용자가 원하는 정보만 직관적으로 보여주는 메인 화면 레이아웃 설계
앱을 실행했을 때 사용자가 가장 먼저 마주하는 메인 홈 화면(Home Screen)은 앱의 첫인상을 결정짓는 가장 중요한 공간입니다. 로또 앱을 켜는 사람들의 니즈는 아주 명확합니다. '그래서 가장 최근 추첨된 로또 번호가 도대체 몇 번인데?', 그리고 '내 로또 용지 당첨 여부를 어떻게 찍어볼 수 있지?' 이 두 가지입니다. 자질구레한 텍스트나 복잡한 메뉴 트리를 나열하면 곧바로 피로감을 유발합니다.
따라서 저는 메인 화면의 레이아웃을 크게 세 가지 영역으로 심플하게 압축했습니다.
- 최상단 하이라이트 영역 (Hero Section): 최근 회차의 실시간 추첨 결과 번호를 큼직한 로또 공 그래픽으로 보여줍니다. "제 1xxx 회차 당첨 번호"라는 직관적인 타이틀과 함께 1등 당첨 금액도 함께 표기하여 기대감을 심어줍니다.
- 중앙 퀵 액션 카드 영역 (Quick Actions): 사용자가 앱에서 가장 자주 눌러야 하는 기능들을 큰 버튼 형 카드 형태로 배치합니다. 'QR 코드로 내 로또 스캔하기', '최근 나의 스캔 내역 보기', '역대 전체 회차 당첨 통계보기'를 배치하여 엄지손가락이 쉽게 닿는 곳(Thumb Zone)에서 모든 탐색이 이루어지게 했습니다.
- 플로팅 액션 바 (Floating Action Button): 어떤 화면으로 스크롤을 내리더라도 화면 우측 하단에 상시 떠 있도록 카메라 모양의 플로팅 버튼을 배치했습니다. 즉, 앱을 켜자마자 단 0.1초 만에 스캔 기능으로 진입할 수 있는 지름길을 터둔 것입니다.
2. 색채 심리학과 다크모드를 고려한 컬러 시스템 (Color System) 구축
플러터에서 UI를 그릴 때 색상을 무작위로 하드코딩(직접 숫자값 입력)하는 것은 추후 최악의 유지보수성을 가져옵니다. 저는 3회차에서 만들어 두었던 lib/core/theme.dart 파일 내부에 프라이머리 컬러(Primary Color)를 정의했습니다. '로또 사고 싶은날'이라는 이름에 걸맞게 희망과 재물을 상징하는 생동감 있는 비비드 오렌지 골드(Vivid Orange Gold) 색상을 브랜드 메인 컬러로 채택했습니다.
특히 야간에 당첨 번호를 조용히 확인하는 사용자들이 많다는 데이터에 기반하여, 심야에도 눈을 찌르지 않는 세련된 다크 모드(Dark Mode)를 완벽하게 지원하도록 디자인 시스템을 세팅했습니다. 배경화면은 완전한 흑백(#000000)이 아닌 아주 톤 다운된 다크 블루 네이비 계열을 사용하여, 로또 공의 밝은 컬러들이 화면의 어두운 배경과 강렬한 대비(Contrast)를 이루어 공이 마치 공중에 예쁘게 떠 있는 듯한 고급스러운 마감재 느낌(Glassmorphism)을 주도록 설계했습니다.
3. 이 앱의 핵심 시그니처! 동행복권 공식 컬러를 활용한 입체 로또 공 (LottoBallWidget)
텍스트로 숫자 여섯 개를 단순히 나열[10, 15, 23, 33...]하는 것은 매력이 없습니다. 당첨 번호를 보여줄 때는 실제 로또 방송에서 보는 것과 같은 동그랗고 광택이 나는 구슬 느낌을 주어야 합니다. 대한민국의 동행복권은 엄격한 색상 코드를 가지고 있습니다. 1~10번은 노란색(Yellow), 11~20번은 파란색(Blue), 21~30번은 빨간색(Red), 31~40번은 회색(Gray), 41~45번은 녹색(Green)입니다. 이 규칙에 어긋나는 색을 보여주면 사용자들은 즉각적으로 앱의 신뢰성에 의문을 품게 됩니다.
저는 이를 완벽하게 구현하기 위해 플러터의 강점인 BoxDecoration의 LinearGradient(선형 그라데이션)와 BoxShadow(그림자)를 조합했습니다. 공의 좌측 상단에는 밝은 빛이 반사되는 스포트라이트 효과를 주고, 우측 하단에는 짙은 그림자를 드리워 2D(평면) 화면에서도 실제 플라스틱 공처럼 만져질 것 같은 3D 입체감을 부여했습니다. 이는 단순한 디자인을 넘어 사용자에게 앱이 "매우 잘 만들어진 프리미엄 퀄리티"라는 신뢰감을 전달하는 가장 강력한 컴포넌트가 되었습니다.
4. 재사용 가능한 커스텀 위젯 코드로 구현하기 (animated_lotto_ball.dart)
한 번 만들어둔 로또 공 컴포넌트는 메인 화면뿐만 아니라, 스캔 내역, 통계 화면 등 수많은 곳에서 재사용(Reuse)됩니다. 그래서 우리는 이것을 분리된 독립 클래스 위젯으로 만들어야 합니다. 아래의 코드는 숫자를 입력받으면 자동으로 번호대역의 색상을 판별하고 입체감 있는 구슬 모양으로 그려내주는 '로또 사고 싶은날'의 실제 핵심 UI 컴포넌트 코드 중 일부입니다.
// lib/ui/widgets/lotto_ball_widget.dart
import 'package:flutter/material.dart';
class LottoBallWidget extends StatelessWidget {
final int number; // 로또 번호
final double size; // 공의 크기 조절을 유연하게 하기 위한 변수
const LottoBallWidget({Key? key, required this.number, this.size = 40.0}) : super(key: key);
// 동행복권 공식 번호대별 색상 판별 로직
Color _getBallColor(int num) {
if (num <= 10) return const Color(0xFFFBC02D); // 1~10: Yellow
if (num <= 20) return const Color(0xFF1E88E5); // 11~20: Blue
if (num <= 30) return const Color(0xFFE53935); // 21~30: Red
if (num <= 40) return const Color(0xFF757575); // 31~40: Gray
return const Color(0xFF43A047); // 41~45: Green
}
@override
Widget build(BuildContext context) {
final baseColor = _getBallColor(number);
// 보너스 번호 등 번호가 0이 들어올 경우 처리
final displayNum = number == 0 ? "?" : number.toString();
return Container(
width: size,
height: size,
decoration: BoxDecoration(
shape: BoxShape.circle, // 완벽한 원형
// 그라데이션을 통해 3D 입체 광택 효과 부여 (좌상단이 밝고 우하단이 어두움)
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
baseColor.withOpacity(0.5), // 반사광 느낌
baseColor,
baseColor.withOpacity(0.9), // 짙은 명암
],
),
// 공이 바닥에서 살짝 떠 있는 듯한 입체 그림자 효과 추가
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.3),
spreadRadius: 1,
blurRadius: 4,
offset: const Offset(2, 4),
),
],
),
child: Center(
child: Text(
displayNum,
style: TextStyle(
color: Colors.white,
fontSize: size * 0.45, // 공 크기에 맞춰 폰트 사이즈 자동 조절
fontWeight: FontWeight.w900,
shadows: const [ // 숫자가 더 선명해 보이도록 텍스트 셰도우 추가
Shadow(
blurRadius: 2.0,
color: Colors.black54,
offset: Offset(1.0, 1.0),
),
],
),
),
),
);
}
}
이렇게 코딩된 LottoBallWidget(number: 35) 하나만 호출하면, 앱 어디에서든 완벽한 입체 회색 로또 공이 짠 하고 나타나게 됩니다! 이제 메인 화면 레이아웃과 감성을 한 스푼 더해준 시그니처 위젯까지 준비가 완료되었습니다. 거푸집과 인테리어 소품을 만들었으니, 이 빈 화면에 '진짜 살아 숨 쉬는 데이터'를 주입할 차례입니다.
다음 주 5회차 포스팅에서는 제가 가장 많은 시행착오를 겪었던, '동행복권 오픈 API를 연동하여 매주 실시간으로 따끈따끈한 역대 당첨 결과를 가져오는 과정'과 JSON 데이터를 어떻게 예쁘게 화면에 뿌려주는지 그 상세한 통신 방법에 대해 아주 속 시원히 파헤쳐 보겠습니다. 코딩 비법노트 많이 기대해 주세요!
💡 다크모드에서 더욱 빛을 발하는 로또 공의 아름다운 애니메이션을 직접 확인해 보세요!
👉 [로또 사고 싶은날 - 지금 바로 설치하기]
```
'AI Product Building > Lotto App' 카테고리의 다른 글
| '로또 사고 싶은날' 개발기 6편: 앱의 생명! 초고속 QR 코드 스캐너 기능 구현 (CameraX & ML Kit) (1) | 2026.04.17 |
|---|---|
| '로또 사고 싶은날' 개발기 5편: 동행복권 오픈 API 연동을 통한 실시간 당첨 결과 파싱하기 (0) | 2026.04.16 |
| '로또 사고 싶은날' 개발기 3편: 유지보수를 고려한 앱 아키텍처 및 폴더 구조 설계 (0) | 2026.04.14 |
| '로또 사고 싶은날' 개발기 2편: Flutter 모바일 앱 개발 환경 완벽 구축 및 프로젝트 초기화 (0) | 2026.04.13 |
| '로또 사고 싶은날' 개발기 1편: 왜 로또 앱이었나? 기획 및 방향성 설정 (0) | 2026.04.13 |