-
야구장 좌석 시야 서비스 SPOT! 서버 파트의 여정Project/SPOT! 2024. 10. 7. 15:28반응형
안녕하세요! 디자이너와 프로그래머가 만났을 때, 디프만(Depromeet) 15기의 6팀 서버 파트입니다 👋
저희 육.지.행 팀은 얼마 전 성공적으로 SPOT! 서비스의 2차 MVP 개발을 마친 후 Play Store에 서비스를 런칭했어요. 디프만에 지원하는 서버 개발자분들 대부분이 짧은 시간 내에 서비스를 런칭하는 것과 프로젝트 중 개발 역량을 키우는 것에 많은 기대감을 가지고 계실 것 같아요.
이번 포스팅을 통해 저희가 서비스를 개발하며 겪었던 일들을 개괄적으로 소개해드리고, 빠른 기간 내에 성공적으로 프로젝트를 런칭한 노하우를 공유해보려 해요.
16기 디프만 서버 파트 지원자, 그리고 사이드 프로젝트를 시작하려는 모든 개발자분들께 이 포스팅이 도움이 되었으면 해요 🥳
SPOT! 은 무슨 서비스 인가요? 😮
SPOT! 은 "내가 만드는 야구장 좌석 시야 서비스"라는 컨셉으로 개발된 서비스에요. 국내 야구장 좌석 수가 많게는 3만석까지도 있는데, 어떤 자리에서 경기를 보아야 제일 후회 없는 시간을 보낼 수 있을까?를 고민하는 과정에서 디벨롭하게 되었어요.
유저는 블로그, SNS 등 여러 사이트들을 돌아다니며 좌석 리뷰를 찾는 것의 불편함을 SPOT을 통해 해소할 수 있어요. 동시에 개인의 직관 목적에 부합하는 특징의 좌석을 추천 받을 수도 있어요. 지불한 금액이 아깝지 않다고 느껴질 최적의 좌석을 찾아, 유저로 하여금 더 나은 직관 경험을 하게 하는 것이 SPOT의 최종 목적이에요. ⚾️
많은 분들이 SPOT의 목표에 공감해주셔서, 디스콰이엇 트렌딩 1등도 차지했답니다 ✨
SPOT! 서버 파트는 어떤 팀인가요? 🧐
이번엔 저희 서버 파트 구성원과 파트 내부 운영에 대해서도 간단히 소개해드릴게요!
육.지.행 팀의 서버 파트는 대학생 2명, 백수(였으나 이제는 직장인이 된😎) 1명 총 3명으로, 전원 Java & Spring Boot에 대한 기본 지식이 있는 상태였어요. 디프만 활동이 여름 방학 시즌에 걸쳐 있었기에, 운이 좋게도 파트원끼리 일정을 맞추고 협업하는데 큰 어려움이 없는 환경이었구요.
따라서 저희는 단순히 기능을 빠르게 개발하는데 그치지 않고, 내 파트, 네 파트 구분 없이 적극적으로 소통하고, 실제 유저를 만나 서비스를 운영해보자 라는 육.지.행팀 전체의 목표를 이루기 위해 파트 내부 그라운드 룰을 만들었어요. 다양한 컨벤션, 룰이 있지만 그 중 대표적인 것 3가지만 소개할게요.
1. 기능을 개발할 땐 항상 우선순위와 협업 상대의 일정을 고려하자. 2. 처음부터 완벽하게 하기보단, 우선 돌아가게 만들고 이후 고도화하자. 3. 기능을 개발할 땐 반드시 코드 리뷰를 받자. 만약 그럴 수 없을 경우 이후라도 꼭 리뷰를 받자.
이런 암묵적 규칙 하에 ASAP으로 기능 개발에 열정을 다했으나..! 안타깝게도 프로젝트가 저희 생각만큼 원활하게 진행되지는 않았어요 😢
서버 파트에게 무슨 일이 있었던 거죠? 😱
SPOT! 서비스의 볼륨은 주어진 개발 기간 대비 상당히 큰 편이에요. 만들고 싶은 기능, 있으면 좋을 것 같은 기능, 재밌어 보이는 기능 등… 만들고 싶은 기능들을 자유롭게 제안하다보니 어느덧 티켓이 한가득 쌓여있었죠.
초기 디벨롭 할 때의 사진으로, 이후 훨씬 많은 기능이 추가되었어요 😵💫제안된 기능들을 모두 개발하기에는 현실적으로 리소스가 너무 부족했어요. 우선순위와 구현 난이도에 따라 개발 여부와 시기를 한 번 정리했음에도, 1차 MVP에서 개발해야 하는 기능들이 상당히 많았습니다.
심지어 요구사항이 구체화가 끝났을 때, 1차 MVP 출시일까지 서버 파트에게 주어진 시간은 약 5일 밖에 되지 않았어요. 저희 서버 파트원들은 기술적인 도전 욕심도 많은 편이라 더더욱 쉽지 않은 일정이었습니다.
그래서 어떻게 해결했나요? 🤓
처음 디프만 일정을 받아본 후, 개발 요구사항이 UT 이후에야 명확해질 것이라고 판단했어요. 유저 의견 없이 불명확한 기획으로 개발을 시작해봤자 이후 수정 사항만 많아지기 때문이에요.
따라서 아이디어가 확정된 6/8 부터 UT가 종료되는 7/13 까지 약 2달 동안 개발 파트원들은 손이 비는 상황이었어요.
저희 서버 파트원들은 이 기간을 보다 알차게 사용하기 위해, 도메인 기능 요구 사항과 관계 없는 서버 파트 내부 태스크를 먼저 진행했어요. 진행한 태스크들은 다음과 같아요.
1️⃣ 프로젝트 기본 세팅
요구사항이 확정되면 바로 feature 개발에 들어갈 수 있도록 필요한 서버 개발 환경을 미리 갖춰놓고자 했어요. Java & Spring Boot, Git & Github을 이용하기로 파트 내 합의를 마친 이후 바로 Spring project과 Github Repository 세팅을 시작했습니다.
패키지 관리 방식, 멀티 모듈 구조, gradle dependency, Swagger, logging 등 usecase에 영향을 미치지 않는 모든 기본 세팅들을 완료해 바로 REST API 개발을 시작할 수 있는 환경을 만들어 두었어요.
이 과정에서 다양한 관리 방식을 찾아보고, 파트원들에게 공유하며 새로운 것들을 배우기도 했죠.
주목할 점은 환경 세팅 과정에서 시스템을 통해 반복 작업들을 자동화하고자 노력했다는 점이에요!
라이브러리 depencency를 개발자가 직접 모듈별로 관리하고 major 버전으로 유지하거나, java 코딩 컨벤션을 통일하기 위해 config 파일을 주고받는 건 너무 비효율적이에요. 개발자가 기능 개발 외적으로 신경 써야 할 것들을 늘려 생산성을 저하시킵니다.
저희는 이 점에 주목하여, 팀 컨벤션을 시스템 단위로 유지할 수 있도록 다양한 자동화 방법을 도입했어요 ✨
2️⃣ 인프라 & DevOps 세팅
프로젝트 세팅을 진행하면서, 발 빠르게 인프라 세팅도 진행했어요. 개발을 빠르게 마쳐도 테스트와 배포에 문제가 생긴다면 기능 구현 일정에 큰 차질이 생기기 때문이죠.
디프만의 든든한 후원사 중 하나가 바로 Ncloud인데요, 감사하게도 디프만의 모든 팀들은 Ncloud Green Developers 프로그램에 참가할 수 있었어요. 이를 바탕으로 Ncloud에서 제공한 크레딧을 사용하면서 초기비용 0원으로 안정적인 개발 서버 환경을 구축할 수 있었답니다.
하지만, 서버 인프라 세팅은 많은 시행착오가 있었는데요, 크레딧을 가지고 간단한 서버 환경을 세팅했어요. VPC 망을 설정한 후 subnet을 구축하고 그 안에 개발 서버와 개발 DB(Cloud DB for MySQL)를 구성한 실용적이지만 아주 간단한 인프라였어요. 운영서버와 DB는 비용절감을 위해 앱 론칭 직전에 만들기로 했어요.
그런데 이렇게 개발 서버만 잘 세팅해두면 될까요? 만약 개발 서버에 배포 나가는 코드에 서버가 실행조차 안되는 문제가 생긴다면 정말 큰일이겠죠? 그래서 안정적인 CI/CD 파이프라인을 만드는 것이 아주 중요해요.
SPOT! 서버팀은 배포를 자동화하기 위해서 Github Actions와 Dockerhub를 통해 CI/CD 환경을 구축했어요. CI(Continuous Integration) 단계에서는 프로젝트의 안정적인 빌드, 테스트 단계가 포함되고 CD(Continuous Deployment) 단계에서는 빌드와 함께 서버에서 프로젝트를 실행하는 단계까지 포함돼요.
삽질의 흔적들…
이렇게 많은 시행착오를 통해 스크립트를 작성할 수 있었어요. 😄 플로우에 대해 간략하게 설명해드릴게요.
구체적인 스크립트가 궁금하시다면 SPOT! 서버 레포의 workflow 패키지를 확인해주세요.
팀원은 기능을 구현한 후 PR을 작성하고, PR이 만들어지면 자동으로 CI가 진행되어요. 빌드에 성공하고, 테스트에 모두 통과하면 그제서야 팀원에게 PR 리뷰를 받을 수 있는 단계가 되는거죠!
그리고 리뷰에 통과해 PR이 merge 된다면 자동 배포가 진행되어요. main에 commit이 push 되면 다시 한 번 CI를 거치고, 문제가 없다면 앱을 서버로 복사한 다음 실행해서 최종적으로 유저에게 릴리즈 합니다.
그렇다면 운영 서버에 배포는 어떻게 할까요?
개발 서버에서 사용하는 자동 배포 workflow를 운영 서버에도 적용하기엔, 불안정한 기능이 유저에게 노출 될 위험이 있어요. 그래서 운영 환경에는 Github Release를 이용한 수동 배포 방식을 적용했어요.
운영 서버에 신규 기능을 배포하고 싶다면, main 브랜치에서 Github Release 태그를 새로 만들어요. 생성한 태그를 Actions 탭에서 수동 배포 workflow를 이용해 운영서버에 배포하게 만들었습니다 ✨
!!!!그런데, 여기서 빅 이슈가 발생합니다. 바로 비용 문제..! 💸
Ncloud의 크레딧 소진 속도가 생각보다 너무 빨라서, 제일 저렴한 인스턴스를 사용했음에도 불구하고 1차 MVP 출시 전에 크레딧을 모두 소진해버렸어요. NCP 신규 회원 크레딧과 디프만 지원 크레딧까지 모두요.
결국 릴리즈 직전에 비교적 비용이 저렴한 AWS 클라우드로 인프라를 이전하게 됩니다. 최종 시스템 아키텍처는 아래에서 공개할게요!
3️⃣ 도커 세팅
여기서 끝이 아니에요! 옆에서 인프라를 구성하는 동안, Docker와 docker-compose 세팅도 함께 진행했어요.
저희가 Docker를 사용한 이유는 이미지 기반 배포와 간편하고 통일된 실행 환경 세팅을 위해서에요. DockerFile을 이용해 prod & dev & local 에서 각자 동일한 환경으로 어플리케이션이 실행되는 것을 보장할 수 있었고, 이미지를 기반으로 간단하고 직관적인 배포 프로세스를 구축 할 수 있었어요.
위에서 언급한 NCP 비용 이슈로 AWS로 급하게 마이그레이션하게 되었을 때, Docker를 사용했기에 쉽게 CI/CD 파이프라인을 수정할 수 있었어요 👍
잠깐! Dockerfile과 Docker-compose은 각각 왜 필요했나요?
우리 서버 인스턴스와 DB에 사용하기 위해 Docker 이미지를 커스텀할 필요가 있었고, 이를 위해서 Dockerfile을 사용했어요.
또한 개발 DB를 로컬에 구축하기 위해 어플리케이션 컨테이너 외에 DB 컨테이너가 추가로 필요했습니다. AWS에 dev 환경에 사용할 RDS를 세팅해두긴 했으나, 모든 개발자가 동일한 DB에서 개발을 진행하면 테스트 데이터가 꼬일 수 있기 때문에 로컬에서 각자 사용할 DB를 세팅할 필요가 있었거든요.
따라서 DB를 위한 MySQL 컨테이너와 Spring Boot 서버를 위한 어플리케이션 컨테이너 2개를 동시에 실행해야 했죠. 이를 편하게 관리하기 위해 Docker-compose를 사용했답니다.
기술 스택 & 아키텍처 구조와 이유
기획이 어느정도 마무리 되어가면서 우리 SPOT! 서버 팀은 본격적으로 기술 스택을 정하기 위해 의논했어요.
이 과정에서 가장 중요하게 고려한 점은, 두 달 이라는 짧은 기간 동안 목표한 기능을 모두 구현하기 위해 충분한 근거를 가지고 의사 결정을 하는 것이었어요.
충분한 논의를 거친 후 아래와 같은 기술들을 SPOT!에 적용했습니다.
🛠️ 백엔드 사용 기술
팀원 모두가 바로 사용할 수 있고, 사용하고 싶어한 Java & Spring Boot를 메인 기술 스택으로 정했어요.
(Java는 record class를 지원하는 17버전으로 채택했고, 따라서 자연스럽게 Spring Boot 3.x.x를 사용)
이외에 주목할 만한 기술은 다음과 같아요.
- Spring Data JPA & QueryDSL : query method, jpql 등을 디폴트로 활용하되, 복잡한 쿼리는 queryDSL을 이용해 개선했어요.
- Caffeine : 조회 성능 개선을 위한 로컬 캐시 라이브러리로 Caffeine을 이용했어요. (관련 LINK)
- Redis : SPOT!은 현재 단일 서버이지만, 추후 멀티 서버로 확장될 가능성을 고려하여 분산락을 활용해 동시성 이슈를 관리했어요.
⚙️ 인프라 & DevOps 사용 기술
- Docker: 도커를 통해 개발, 테스트, 프로덕션 환경 간의 일관성을 유지할 수 있었어요.
- JIB: JIB는 Java에서 컨테이너화 프로세스를 도와주는 기술인데요, 프로젝트 빌드와 컨테이너 이미지 생성까지 한번에 정말 빠른 시간 안에 해결해주는 플러그인이에요.
- AWS Secrets Manager: secret manager를 사용하면 API key나 기타 민감한 정보들을 안전하게 통합해서 관리할 수 있어요.
- Grafana + Prometheus + Loki: 프로메테우스는 메트릭을 수집하고 저장하는 툴이고, 그라파나는 이를 시각화하는 툴, Loki는 로그를 집계하는 툴이에요. 이 셋을 조합하면 서버를 실시간으로 모니터링할 수 있는 아주 멋진 대시보드를 만들 수 있어요.
- Nginx: Nginx를 사용해서 SSL 인증서를 발급받아 https 리다이렉션을 설정하고 Public IP에 구입한 도메인을 연결했어요.
🖥️ 전체 시스템 아키텍처
지금까지 소개한 기술 스택과 CI/CD 파이프라인을 적용한 시스템 아키텍처는 다음과 같아요!
언급한 기술 외에도 다양한 도구들을 활용해 서비스를 고도화했습니다 👣
아직 개선할 점이 많은 아키텍처이지만, 오늘 포스팅의 주제와는 무관하니 말을 줄일게요. (현재는 ELB를 적용한 오토 스케일링 등을 적용하고 있어요!)
짧은 mvp 기간 안에 요구사항 구현 한 방법
저희는 처음 중간 발표 때 1차 MVP를 안드로이드 스토어에 배포하자는 목표를 설정했어요
이에 따라서 다른 프로세스들도 타이트하게 잡고 ASAP하게 개발했습니다. 비록, 안드로이드 심사 반려로 인해 약간 딜레이 되었지만 이번 15기 중에서 가장 빠르게 MVP 개발을 마치고, 플레이 스토어 출시까지 완료했답니다. 😎
그럼 지금부터 저희가 빠르게 MVP를 런칭할 수 있었던 5가지 노하우에 대해서 설명드릴게요!
1️⃣ 기획 기간 동안 진행한 프로젝트 베이스 세팅
위에서 언급한 대로, 기획이 나오면 최대한 빠르게 usecase 개발에 착수하기 위해 기획에 크게 좌우되지 않는 DevOps(클라우드, Docker 등)와 기초 프로젝트 세팅을 기획 기간 동안 우선적으로 진행했어요.
이 과정을 통해 기획이 나온 후에는 바로 개발을 들어갈 수 있는 기반을 마련할 수 있었죠.
2️⃣ 주 3회 모각코를 통한 ‘작업 코어 타임’ 설정
개발 시작 후 각자 주 활동 시간이 달라서 병목이 생기거나 참여가 저조했던 시기가 있었어요. 이를 해결하기 위해 논의를 진행하였고, 주 3회 시간을 정해 모각코를 실시해 ‘작업 코어 타임’을 만들기로 했답니다. 기본 1시간, 필요할 경우 추가로 진행했는데, 이 시간 동안은 다른 시간에 비해 아주 빠른 속도로 작업 진도가 나가서 큰 역할을 했다고 생각해요.
부수적으로, 다른 파트에서도 서버 파트에게 문의가 있거나 요청 사항이 있을 경우 이 때 찾아와 빠른 속도로 협업을 진행할 수 있었어요. 이것도 부수적인 효과였지만 작업의 속도를 높이는 데 큰 역할을 했답니다.
즐거운 SPOT 서버 모각코 시간 🥳
3️⃣ 슬랙 리마인더를 활용한 데일리 스크럼
여러 팀원과 협업하다보면 상대의 작업 진척도가 궁금할 때가 많아요. 내 작업이 팀원의 작업 이후 진행되어야 하는 등, 병목 구간이 생긴다면 더더욱 그렇죠. 하지만 일정이 아직 끝나지도 않았는데 담당자에게 어디까지 했는지, 잘 되가고 있는지 꼬치꼬치 캐묻기엔 서로 부담스러워요 😅
어떻게 해야 서로의 기분을 배려하면서, 각자의 작업 진척도를 효율적으로 관리할 수 있을지 고민하다가 데일리 스크럼 문화를 도입했어요!
실제로 일일 스크럼을 통해 알게된 다른 팀원의 병목을 여유가 되는 팀원이 도와주는 등, 팀 활동에서 가장 중요시 되는 ‘소통’의 역할을 해주었어요.
4️⃣ 동작하는 코드를 우선으로 작업 후 리팩토링 진행
개발자로서 중요한 덕목 중 하나는 당연 동작하는 코드를 기간 내에 작성하는 능력이 아닐까 생각해요.
디프만 활동의 최우선 목표는 주어진 기간 내에 서비스를 런칭 하는 거에요. 여기에 모든 파트원들이 동의했고, 따라서 코드가 성에 안차도 일단은 돌아만 가면 된다!는 마음으로 티켓을 쳐내기로 했어요. 협업하는 다른 팀원들의 일정까지 고려하여 일단 빠르게 넘긴 후, 리소스가 생기면 리팩토링 & 최적화 & 고도화 등 후속 작업을 진행하는 방식이죠.
하지만 이렇게 ‘나중에 해야지~’ 하면서 하나둘 쌓아둔 태스크들을 다시 손보지 못하면 의미가 없어요.
그래서 저희는 IntelliJ IDE의 기본 내장 기능인 TODO와 github Issue 기능을 활용해, 쌓아둔 티켓들을 잊지 않도록 주의했어요. 서비스가 런칭된 지금도, SPOT 서버 파트는 미뤄뒀던 고도화 작업들을 하나하나 챙겨가고 있답니다 💪
5️⃣ 일단 지나갈게요! self-approve
SPOT! 서버 파트는 코드 리뷰 문화를 적극적으로 장려하고, 더 나은 코드를 만드려는 목적으로 branch protection rule을 만들었어요. 이 rule에 의해, 서버 모든 기능 PR은 1개 이상의 approve를 받아야만 main에 merge 될 수 있습니다.
하지만 코드 리뷰를 해 줄 동료들이 부재 중이거나, 코드 리뷰를 받지 않아도 되는 아주 사소한 변경 (오타, readme 수정 등)에도 이 rule을 적용하자니 굉장히 비효율적이었어요. 겨우 1–2줄의 변경 사항을 하루를 기다려 리뷰 받고 배포하는건 상상만해도 답답하죠 😵💫
그래서 저희는 ‘Self Approve’ rule을 추가했어요! 코드 리뷰를 기다릴 수 없는 급한 상황이라면 PR에 ‘Self Approve’ label을 추가하고, 우선 branch protection rule을 비활성화 해서 직접 merge해요.
이후 필요하다면 팀원들을 태그하여 self-approve 했으니 나중에라도 리뷰를 남겨달라고 요청합니다. 이런 Self-approve를 통해서 급하거나 사소한 PR은 빠르게 배포될 수 있었고, 팀원들은 불필요한 대기 시간을 줄일 수 있어서 생산성이 증가되었습니다 👍
지금까지 디프만 4달 동안의 SPOT! 서버 파트의 여정을 간략하게 소개해보았는데요, 재미있게 잘 읽으셨나요? 🥳 아직 못 다한 이야기가 많지만, 슬슬 마무리를 지어볼까해요! 저희 파트원들의 프로젝트 마무리 소감을 공유합니다 👏
✨ 은지
사이드 프로젝트는 굉장히 오랜만이었는데, 팀원들이 모두 열정적이고 성실하게 임해줘서 저도 덩달아 프로젝트에 몰입할 수 있었어요. 단순히 일을 나눠서 하는 것이 아니라, 서로의 파트에 관심을 가지고 한 번씩 조언을 건네주고 더 나은 코드를 만들어가는 과정에서 ‘협업’의 본질에 대해 다시 한 번 고민할 수 있었죠.
처음부터 완전무결한 팀이 아니라, 여러 문제를 마주하고 고쳐나가는 과정에서 성장한 팀이라서 더욱 끈끈하게 느껴지네요 ✨ 육.지.행 서버파트 다들 고생 많았어~~ 👏
✨ 민성
우선 정말 타이트한 일정 속에서 개발을 완료하고, 일주일만에 150명 이상의 가입자 수를 얻은 게 아직도 안믿기고 우리 서버팀 너무 자랑스럽다… 🥹
1차 MVP 때 정말 바쁘고 힘들었는데 모두 포기하지 않고 잠 줄여가면서 열심히 일한 우리 팀원들 덕분에 저도 지치지 않고 더 힘을 낼 수 있었던 것 같아요.
소통의왕, 정리의 신, 서버 권위자 은지누나, 무한 열정맨 준원이까지 모두 너무 고생했어~! 🎉 이 인연 쭉 이어가자~~
✨ 준원
안녕하세요! 서버 파트장 정준원입니다 :) 저는 SPOT의 서버 개발자로 참여하며 너무 좋은 기억들이 많고 많은 성장을 한 거 같아요. 다들 너무 착하고 열심히 하는 열정맨 투성이라 좋았어요. 다만, 해외 장학생 때문에 2주 동안 온라인 근무를 했었는데 그때 열심히 참여하지 못 한 부분이 조금 아쉽네요ㅠㅠ 육지행 팀의 16주 간의 노력이 담긴 ⚾내가 만드는 야구장 좌석 시야 서비스 SPOT!⚾ 많은 사랑 부탁드려요!!ㅎㅎ
마지막으로, SPOT!은 현재 Play Store에서 만나볼 수 있어요. 혹시 저희 서비스에 관심이 생기셨다면, 아래 링크를 통해 SPOT과 함께해 주세요 ✨
⚾️ Play Store | https://play.google.com/store/apps/details?id=com.dpm.spot
💻 SPOT! github | https://github.com/depromeet/SPOT-server
💁♀️ 문의사항 | 6jihaeng@gmail.com
반응형'Project > SPOT!' 카테고리의 다른 글
DB 쿼리 실행계획 분석:"실행계획 분석으로 쿼리 성능 개선하기: Spot! 앱의 응답 속도 최적화 여정" (0) 2024.09.30