안녕하세요.
프론트 개발을 좋아하지만, 백엔드는 JAVA를 외치던 이상한 개발자입니다.
그래서 이번엔 정신을 차리고 Nest JS로 백엔드 개발을 해봅니다.
일단, 프론트도 같이 만들거니까 모노레포를 써봐야겠습니다.
근데 모노레포를 쓰면 이점이 뭘까?

그렇습니다. 제 마음을 사로잡은건 interface가 공유가 된다는 것이었습니다.

그 중에 TurboRepo를 사용하기로 했는데,

이런 강점이 있습니다.
프론트 배포는 vercel,

백엔드 배포는

제일 큰 선택 이유는 인프라까지 신경쓰고 싶지 않았고
이리 따져도 저리 따져도 비용적인 측면에서 이러한 방식이 이점이 컸다.
집에 라즈베리파이 홈 서버가 존재하긴 하지만,
장난감으로 가지고 놀기에는 적합하지 실제 서비스를 배포하기엔 아쉬움이 많다.
여름이라... 집에 정전도 종종 난다 ㅠ ㅠ
무튼, 그래서 일단 기획서부터 뽑았다.
| 구분 | 기능/컴포넌트 | 세부 명세 | 주요 API / 데이터 소스 |
|---|---|---|---|
| 프로젝트 개요 | 프로젝트 목표 | 학교 도서관 좌석 예약 웹 버전을 만들고, 데이터 기반의 예측, 통계, 알림 등 부가 기능 제공 | - |
| 아키텍처 | 기술 스택 | 백엔드: NestJS, TypeORM\<br>DB: PostgreSQL\<br>배포: Railway\<br>코드 관리: Turborepo | - |
| 서버 구조 | 모놀리식(Monolithic) 구조. 하나의 NestJS 서버에서 모든 기능 처리. | - | |
| 인증 | 로그인 처리 | 인증 위임 방식. 사용자의 ID/PW를 받아 서버가 학교의 다단계 인증 절차를 대신 수행하고 서비스 전용 JWT 발급. (비밀번호 절대 저장 안 함) | versionCheck.do\<br>userKey.do\<br>mLogin.do |
| 데이터베이스 | User 엔티티 | 사용자 정보 관리 (studentId, name, major) | 내부 DB |
SeatEventLog | 전체 좌석의 상태 변경(OCCUPIED/VACATED)을 **기간 태그(periodType)**와 함께 기록. (예측의 핵심) | 내부 DB | |
MyUsageLog | 우리 앱 사용자의 좌석 이용 기록 저장. (개인 통계용) | 내부 DB | |
NotificationRequest | 빈자리 알림 신청 정보 관리. | 내부 DB | |
AcademicCalendar | 시험 기간, 방학 등 특별 기간 정보 관리. | 내부 DB | |
| 핵심 기능 | 전체 좌석 조회 | HTML 응답을 **파싱(스크레이핑)**하여 열람실 전체 좌석 현황을 JSON으로 제공. | GET /seatMap.do |
| 좌석 예약/반납/연장 | 사용자의 요청을 받아 학교 API로 대신 전달하는 프록시(Proxy) 역할 수행. | assignSeat.do\<br>returnSeat.do\<br>contSeat.do | |
| 내 좌석 확인 | 현재 예약 중인 좌석 정보를 학교 API를 통해 조회. | mySeatStatusNew.do | |
| 확장 기능 | 빈자리 예측 | SeatEventLog 데이터를 기간별로 필터링하여 특정 좌석의 이용 패턴(4/8시간 등)을 실시간 분석 후 제공. | 내부 DB (SeatEventLog) |
| 개인 통계 | MyUsageLog 데이터를 분석하여 누적 이용 시간 등 개인화된 통계 제공. | 내부 DB (MyUsageLog) | |
| 백그라운드 | 데이터 수집기 (Cron) | 시스템 계정으로 학교 API 세션을 유지하며, 주기적으로 seatMap.do를 호출/파싱하여 SeatEventLog에 데이터 적재 및 알림 발송. | seatMap.do |
일단 자동 자리 연장과 빈 자리 잡기를 어떻게 할까 고민이 많았는데, 우선 구현을 해보기로 했다.
그래서 일단 백엔드 부터 구현을 하기로 했다.
packages 폴더 안에 db와 types를 넣고


엔티티와 DTO를 정의했다.
api의 package에

이렇게 의존성을 추가해주면 된다.
그럼 저걸 긁어와서 쓰는 것임.
우선적으로, 데이터를 조금이라도 빨리 모으는게 예측 시스템을 만드는 것에 도움이 될거라 생각해 그 부분 부터 만들었다!

데이터를 어떻게 저장을 하면 좋을까 고민을 하다
결국 상태 변화에 대한 데이터만 있으면 되니

이런 식으로 데이터를 수집했다.
여기까진 그리 어렵지 않았다...
근데 조금 힘들었던게,
부산대 Place는

해당하는 열람실의 이미지 위에 좌석을 "적절히" 위치시킨다.
그리고 저 각각의 자리 요소에 JS를 삽입시켜서 클릭시 자리 예약을 할 수 있도록 만들어 놨다.
그래서 어떻게 하는게 제일 효율적일까 고민을 해보았는데,
일단 이미지 즉 도서관의 모습을 뒷 배경에 보여주는 것이 사용자 경험에 유리하다고 생각했고, 지금 당장은 이미지로 해도 문제가 없다는 생각이 들었다.
근데 저 버튼들은 해당 자리에 노란색과 회색과 빨간색의 이미지를 위치 시키는 방식이라, 이건 굳이 그렇게 할 필요가 없다고 생각해 html 요소로 바꾸었다.

그 결과 대략 이런 모습이 되었다.
아직 조금 더 디자인 적으로 수정이 필요하지만... 아직 프론트 제작 설명도 안 했지만... 맛보기로 보여주자면 이렇다.
그리고 디비 설정의 경우에는


이렇게 하면 된다.
설정이 참 편하다 ㅋㅋ;
아! 그리고 당연, 이 모든 과정은 로그인 API를 우선적으로 하고 작업을 진행했다.