anby
통합 자원 관리 SaaS — 예약·웨이팅·주문을 하나의 “자원”으로 묶습니다.
왜 만들었나
교내 타 학과의 외주 프로젝트가 출발점이었습니다. 현장에서 예약과 웨이팅이 동시에 이루어져야 하는데 서로 다른 서비스를 써야 하는 불편함을 직접 확인했습니다.
주 타깃으로 삼은 교내 동아리·학생회는 공간 대여, 물품 대여, 축제 주점처럼 관리할 자원이 분명히 있는데도 대부분 전산화되어 있지 않았습니다. 같은 자원을 두고 여러 서비스를 중복으로 쓰는 구조를 하나로 합치면 되겠다고 판단했습니다.
유·무형의 대상을 “자원”으로 추상화해 관리 가능한 객체로 만들고, 이용자의 요청은 전부 “티켓” 단위로 다룹니다. 예약·웨이팅·주문은 서로 다른 기능이 아니라, 같은 자원에 대한 다른 종류의 티켓입니다.
맡은 부분
- 관리자 대시보드 RESTful API 엔드포인트 설계 및 구현
- 대규모 트래픽 처리를 고려한 티켓 도메인 데이터 구조와 DynamoDB 스키마 설계
- DynamoDB 조건부 업데이트와 낙관적 락으로 중복 예약 방지 및 동시성 제어
- ARM 서버리스 전환과 비용 최적화, Grafana 기반 운영 모니터링 구축
시스템 구성
-
인증·인가
API Gateway의 Lambda Authorizer로 JWT를 발급·검증해 관리자 API 접근을 통제합니다. 로그인·회원가입은 Cognito가 처리하되, 서버 요청 보안 처리를 위해 사용자 정보는
users테이블에서 별도로 관리합니다. -
ARM 기반 서버리스
x86 대비 ARM 람다가 동일 성능에서 20% 저렴하다는 점을 확인하고, Go로 작성한 서버 코드를 ARM 람다에 올렸습니다. Go를 고른 이유도 람다 환경에서의 가벼운 런타임과 빠른 콜드 스타트였습니다.
-
SQS로 유실 방지
람다 타임아웃이나 DB 과부하 상황에서 데이터가 유실될 수 있는 문제를 SQS로 막았습니다. FIFO 큐로 설정해 메시지가 순차적으로 처리되도록 보장했습니다.
-
테이블 분리
티켓은 서비스별로 상태 변화가 잦아 예약·주문·웨이팅 테이블을 분리했습니다. 대신
projects테이블에 연동 관계를 두어, 독립된 티켓 테이블들을 복합 프로젝트로 묶어 관리할 수 있게 했습니다.
부딪힌 문제와 해결
모니터링 비용
람다 메모리 구성
DynamoDB 스키마
테이블 7종 전체 보기
resources — 자원
| 속성 | Type | 설명 |
|---|---|---|
| PK | string | projectID#resourceID |
| SK | string | 자원 ID |
| name | string | 자원 이름 |
| type | string | MENU | OPTION | CATEGORY | RESERVATIONTARGET |
| field | string | 자원에 필요한 정보를 직렬화 |
| imageURI | string | presigned URI |
| state | bool | 자원 사용 가능 여부 |
| capacity / used | int | 자원 수량 / 사용된 자원량 |
| createdAt / updatedAt | datetime | 생성 · 업데이트 시각 |
projects — 프로젝트와 연동 관계
| 속성 | Type | 설명 |
|---|---|---|
| PK | string | userID#projectID · parentProjectID |
| SK | string | INFO · childProjectID |
| name | string | 프로젝트 이름 |
| type | string | RESERVATION | ORDER | WAITING · META |
| field | string | 프로젝트에 사용되는 정보 직렬화 |
| state | bool | 프로젝트 활성 여부 |
| GSI_meta | string | 복합 프로젝트 검색용 GSI |
waiting_tickets · order_tickets · reservation_tickets — 티켓
세 테이블은 같은 형태를 공유합니다. 상태 변화 빈도가 서로 달라 물리적으로 분리했습니다.
| 속성 | Type | 설명 |
|---|---|---|
| PK / SK | string | 프로젝트 ID / 티켓 ID |
| requester | string | 요청자 ID |
| data | string | 요청자 정보를 직렬화 |
| requestedTime | datetime | 티켓 생성 시각 |
| startTime / endTime | datetime | 티켓 유효 시작 · 종료 시각 |
| expiredTime | datetime | 티켓 파기 시각 |
| state | string | PENDING | ACQUIRE | RELEASED |
| memo | string | 요청 사항 |
| OSI | string | 유효 주문 처리를 위한 인증 키 (order 전용) |
users · teams — 사용자와 팀
| 테이블 | 키 | 설명 |
|---|---|---|
| users | email (PK) | userID · username · createdAt · updatedAt |
| teams | teamID (PK) | SK로 INFO · MEMBER#userID · PROJECT#projectID를 구분. owner / admin / member 권한과 GSI_team · GSI_project 보조 인덱스 |