2026.08 – 현재
FinQ
금융 학습 애플리케이션
- App Store 출시 서비스의 AWS 3-Tier(VPC · ALB · EC2 · RDS) 운영 환경을 구축하고, SSM Session Manager로 서버 접근 경로 단일화
- GitHub Actions · ECR · SSM으로 배포를 자동화하고, 배포 결과와 일일 AWS 비용을 Slack으로 공유하는 운영 체계 구성
App Store에 출시해 운영 중인 금융 학습 앱의 AWS 운영 환경과 배포 자동화를 구축하고, 백엔드 API를 개발했다.
프로젝트 요약
| 항목 | 내용 |
|---|---|
| 소속 | SWYP 앱 6기 (IT 직무 협업 프로젝트) |
| 기간 | 2026.08 ~ 2026.10, App Store 출시 후 운영 중 |
| 형태 | 9인 팀 (PM 2 · 디자이너 3 · iOS 2 · 백엔드 2) |
| 역할 | 백엔드 팀장 · AWS 인프라 담당 |
| 담당 범위 | AWS 운영 환경, 배포 자동화, 운영 알림·비용 관리, 백엔드 API |
핵심 성과
- App Store 심사 통과 및 출시, 실사용자 대상 운영
develop반영부터 운영 서버 배포, 결과 공유까지 자동화- 출시 후 학습 완료율 75% (목표 50%), 3일 이상 스트릭 유지 20%, Premium 클릭률 5%
- 백엔드 저장소 커밋 161건 중 113건 직접 작성
주요 기여
- VPC · ALB · EC2 · RDS 3-Tier 운영 환경 구축
- GitHub Actions · ECR · SSM 배포 파이프라인, Slack 배포 알림
- SSM Session Manager 기반 서버 접근 경로 단일화
- AWS 일일 비용 이메일·Slack 보고 체계
- 인증·학습·보상·푸시 알림·백오피스 API와 API 문서 체계
1. 프로젝트 개요
1.1 배경
FinQ는 사회초년생을 위한 iOS 금융 학습 앱이다. 매일 추천되는 생활 속 금융 질문 3개에서 학습을 시작하고, OX·객관식 퀴즈로 확인하며, 지식맵과 XP·레벨·스트릭으로 학습 상태를 본다.
사용자 설문(97명)에서 97.9%가 이미 금융 활동을 하고 있었지만, 57.7%는 금융 정보를 찾아봐도 절반 이상 이해하지 못한 경험이 있었다. 학습 장벽으로는 용어가 어렵다(64.9%), 무엇부터 알아야 할지 모르겠다(42.3%)가 꼽혔다. 팀은 어려운 용어 해설 대신 생활 속 궁금증에서 시작하는 학습으로 방향을 잡았다.
1.2 문제 정의
실사용자가 있는 서비스를 백엔드 2명이 기능 개발과 함께 운영해야 했다. 배포 실수와 장애는 곧바로 사용자 경험으로 이어지고, 배포·알림·비용 관리도 같은 인원이 맡았다. 사람이 서버에 접속해 수동으로 배포하는 방식으로는 반영 시점과 버전을 추적하기 어렵고, 비용 이상도 늦게 알게 된다.
1.3 목표와 요구사항
- 기능 변경이 운영 서버에 자동으로 반영되고, 결과를 팀 전체가 확인
- 서버 접근과 CI 인증에 장기 키를 두지 않음
- 운영 비용을 매일 확인
- 회원·비회원 이용 범위를 구분한 API, 앱 개발자가 직접 검증할 수 있는 API 문서
2. 시스템 설계
2.1 전체 아키텍처

외부 요청은 ALB에서만 받고, 백엔드 서버(EC2)와 데이터베이스(RDS)는 내부 영역에 둔다. 백엔드는 Spring Boot(Java 21) 컨테이너로 회원·콘텐츠·학습·보상·알림 API를 제공한다. 앱 푸시는 Firebase, 비밀번호 재설정은 이메일, 배포 결과와 일일 비용은 Slack으로 연결한다.
2.2 설계 의사결정
| 결정 | 근거 |
|---|---|
| SSM Run Command 배포 | 배포를 위해 SSH 포트를 열거나 SSH 키를 CI에 저장하지 않음 |
| GitHub Actions OIDC | AWS 장기 Access Key를 저장소 Secret에 두지 않고 Role 위임으로 임시 자격 증명 사용 |
| 커밋 SHA 이미지 태그 | 운영 중인 버전을 커밋 단위로 추적, latest 덮어쓰기로 인한 버전 혼동 방지 |
| SSM Session Manager 접근 | Bastion 없이 IAM 기반으로 서버 접근 경로 단일화 |
| 성공·실패 모두 Slack 알림 | PM·앱 개발자도 반영 시점과 실패 여부를 바로 확인 |
2.3 기술 스택
| 분류 | 기술 | 사용 목적 |
|---|---|---|
| 인프라 | AWS VPC, ALB, EC2, RDS | 3-Tier 운영 환경 |
| 배포 | GitHub Actions, ECR, SSM, Docker | 빌드·이미지 저장·원격 배포 |
| 운영 | Ansible, CloudWatch, Grafana | 서버 구성, 메트릭·로그 모니터링 |
| 백엔드 | Spring Boot, Flyway, MySQL | API, DB 스키마 버전 관리 |
| 외부 연동 | Firebase(FCM), Slack, 이메일 | 푸시, 배포·비용 알림, 비밀번호 재설정 |
3. 주요 구현
3.1 배포 파이프라인
배포는 develop push 한 번으로 운영 서버 반영과 결과 공유까지 끝난다. GitHub Actions가 JAR를 빌드하고, OIDC로 AWS Role을 위임받아 커밋 SHA 태그로 이미지를 ECR에 푸시한다. 이후 SSM Run Command로 EC2의 배포 스크립트를 실행하고 명령이 끝날 때까지 기다린 뒤, 실행 결과(상태·출력·오류)를 확인한다. 배포 스크립트가 실패하면 워크플로도 실패로 끝나고, 성공·실패 결과가 Slack으로 전송된다.
- name: Deploy to EC2 through SSM
run: |
COMMAND_ID=$(aws ssm send-command \
--instance-ids "${EC2_INSTANCE_ID}" \
--document-name "AWS-RunShellScript" \
--parameters "${PARAMETERS}" \
--query "Command.CommandId" --output text)
aws ssm wait command-executed \
--command-id "${COMMAND_ID}" --instance-id "${EC2_INSTANCE_ID}"
3.2 운영 알림과 비용 관리
배포 결과는 브랜치·커밋·실행자·로그 링크와 함께 팀 Slack에 공유된다. AWS 일일 리소스 비용은 이메일과 Slack으로 자동 보고해, 비용 이상을 다음 날 바로 확인한다.
3.3 푸시 알림
푸시 토큰 등록·갱신·해제 API와 알림 수신 설정 API를 만들고, Firebase Admin SDK로 FCM 발송과 무효 토큰 정리를 구현했다. 알림에 동의한 사용자를 대상으로 매일 22시 학습 리마인드를 배치 발송한다.
3.4 API 문서와 계약
Swagger UI와 API 메타데이터를 표준화하고, API 에러 코드를 하나의 카탈로그로 모아 API별로 발생 가능한 에러와 실제 에러 응답 예시를 문서에 노출했다. 공통 응답과 문서의 불일치는 API 필드 계약 회귀 테스트로 막았다.
3.5 백엔드 개발 범위
| 영역 | 구현 |
|---|---|
| 기반 | Flyway 스키마·환경별 설정, JWT 인증, 토큰 재발급, Refresh Token 만료 세션 정리 |
| 인증 | 이메일 가입·로그인, Kakao·Apple 로그인(토큰·Authorization Code·nonce 검증), 계정 연동·해제, 탈퇴 시 연관 데이터 삭제, 비밀번호 재설정 |
| 학습·보상 | 스트릭 계산·보상, 일별 통계 집계 스케줄러, 홈 추천 질문 3개, 비회원 홈·콘텐츠·채점 |
| 백오피스 | 통계 조회·사용자 목록 API, API 키 설정 검증 |
커밋 기반 작업 내역 (113건, 2026.08.22 ~ 10.02)
- 저장소 구조:
content·learning·home·reward·streak·notification·backoffice도메인, Flyway 마이그레이션 27개, 테스트 클래스 66개 - 기반 구성: Flyway 초기 스키마·환경별 설정, USER 도메인 영속성과 MySQL 영속성 테스트, JWT 인증, Access Token 재발급, 로그아웃 세션 종료, Refresh Token 만료 세션 정리
- 인증과 계정: 이메일 가입·로그인(약관 저장 실패 시 롤백 테스트), Kakao 액세스 토큰 검증 로그인, Apple Identity Token·Authorization Code·nonce 검증, 기존 회원 Kakao·Apple 연동, Apple Refresh Token 암호화 저장, 소셜 연결 해제와 탈퇴 통합, 종속 데이터 cascade 삭제, 인증번호 확인 후 일회용 토큰 기반 비밀번호 재설정
- 온보딩과 마이페이지: 온보딩 상태, 관심 주제 저장·수정, 마이페이지 조회와 프로필 수정 API 분리, 프로필·캐릭터 이미지 URL 매핑, 닉네임 15자 통일
- 학습과 보상: 스트릭 도메인·계산·보상·조회 API, 일별 통계 저장 구조와 집계 스케줄러, 홈 추천 질문 3개 보장, 비회원 홈·지식맵·콘텐츠 조회·문제 채점
- 푸시 알림: 토큰 도메인과 등록·갱신·해제 API, 알림 수신 설정, Firebase Admin SDK, FCM 발송과 무효 토큰 정리, 알림 동의 사용자 배치 발송, 학습 리마인드 스케줄러(22시), 토큰 활성 상태 관리
- API 문서와 계약: Swagger UI 표준화, 에러 코드 통합 카탈로그와 API별 에러 예시, OpenAPI 3.1 규격 복구, 공통 응답·문서 불일치 수정, 필드 계약 회귀 테스트
- 백오피스: 통계 조회·사용자 목록 API, API 키 설정 검증 강화
- 배포: ECR 빌드·푸시, EC2 배포·Slack 웹훅 스텝,
latest태그 제거
4. 트러블슈팅
4.1 Flyway 마이그레이션 버전 충돌
- 요약
- 브랜치 간 같은 Flyway 버전 V10이 충돌해, 푸시 토큰 마이그레이션을 V11로 옮기는 hotfix로 해결했다.
- 현상
- 서로 다른 브랜치에서 작성한 마이그레이션이 같은 버전
V10을 쓰면서, 병합 후 같은 버전의 마이그레이션이 두 개가 됐다. - 원인 분석
- Flyway는 버전 번호로 적용 순서와 이력을 관리하므로 같은 버전이 둘이면 마이그레이션을 진행할 수 없다. 브랜치별로 다음 번호를 각자 정하면서 충돌이 생겼다.
- 해결
- 푸시 토큰 테이블 마이그레이션을
V10__create_push_token.sql에서V11__create_push_token.sql로 바꾸는 hotfix를 적용했다. - 검증
- hotfix 병합 후 이후 마이그레이션(V11 이후)이 순서대로 추가·적용됐다.
4.2 로그아웃한 기기의 푸시 토큰 처리
- 요약
- 로그아웃 시 푸시 토큰을 삭제하던 방식을 활성 상태 비활성화로 바꾸고, 비활성 토큰을 발송 대상에서 제외했다.
- 현상
- 로그아웃 시 해당 세션의 푸시 토큰 행을 삭제하는 방식이라, 토큰 상태 이력이 남지 않고 같은 기기가 다시 로그인할 때 재등록 흐름에 의존했다.
- 원인 분석
- 발송 대상 조회 쿼리가 사용자 알림 동의 여부만 보고 토큰의 현재 유효 상태를 구분하지 않았다.
- 해결
- 푸시 토큰에 활성 상태(
active)를 추가하고, 로그아웃 시 삭제 대신 해당 세션의 토큰을 비활성화하도록 바꿨다. 사용자별·배치 발송 조회 쿼리에active = true조건을 추가해 비활성 토큰을 발송 대상에서 제외했다. - 검증
- 로그아웃 후 비활성화되고 재등록 시 다시 활성화되는 흐름과 발송 대상 제외를 Repository·Service·Controller 테스트로 확인했다.
5. 검증 및 성과
5.1 검증 방법
서비스 지표는 출시 후 앱 사용 데이터로 측정했다. 학습 완료율은 학습 시작 대비 완료 비율, 리텐션은 전체 사용자 중 3일 이상 연속 학습을 유지한 비율, 수익화 지표는 결제 없이 Premium 배지 노출 대비 클릭 비율("준비 중" 안내)로 정의했다.
5.2 결과
| 지표 | 목표 | 결과 |
|---|---|---|
| 학습 완료율 | 50% | 75% |
| 3일 이상 스트릭 유지 | 20% | 20% |
| Premium 클릭률 | 5% | 5% |



