데브코스 1차 과제로 A-Z 개인 프로젝트의 회고입니다.
1차 프로젝트 진행 기간은 아래와 같았습니다.
- 2022-11-21(월) : 프로젝트 시작일
- 2022-12-05(일) : 프로젝트 1차 제출 기한 ❌(제출 실패)
- 2022-12-11(일) : 프로젝트 2차 제출 기한 ✅(제출 성공!)
프로그래머스 개인 프로젝트 인 Spring Boot 상품 관리 API 구현을 강의 내용을 바탕으로 cloning 하고 API를 구현하는 1차 과제입니다.
저는 도메인을 영화로 변경한 후 DB 설계, API 설계, spring boot, react코드 작성을 진행하였습니다.
본 프로젝트를 진행하면서 저는 아래의 과정을 거쳐 개발을 진행 하였습니다.
1. 도메인 선정
2. figma를 활용한 페이지별 필요한 데이터 정리.
3. db 설계(erd 그리기)
4. 1번을 바탕으로 기능 설계 및 API 설계
5. API 개발
6. react 개발
7. 버그 수정
원래 주제는 front end 즉 도메인이 커피숍 주문관리로 고정된 상태로 API를 설계하는 과제였습니다. 저는 좀 욕심을 내서 그냥 주어진 프론트와 db를 가지고 API코드르 짜는것 보다 주문 관리의 도메인 내에서 다른 주제를 선정하고 해당 주제에 대한 DB 설계와 API 설계 프론트 설계를 하고싶었습니다.
주문관리중 내가 배울 것이 많은 게 뭐가있을까 고민하다 우리가 실제도 많이 사용해 프론트엔드 화면에 대한 레퍼런스를 구하기 쉽고, 관련된 data도 많이 필요할 것 같은 영화 예매 프로그램으로 도메인을 변경을 결정한 후 개발을 시작했습니다.
우선적으로 Figjam을 활용해 MegaBox와 생각해본 내용을 바탕으로 예상 화면을 뽑고,
해당 화면에서 사용자가 할 수 있는 상호작용을 정리한 후, 필요할 것으로 예상되는 데이터(스키마)를 산출헀습니다.
그리고 시간 상의 문제로 먼저 취해야할 부분을 선정 하여 우선순위를 두었습니다.
사용자에게 보여지는 화면을 기준으로 생각한 스키마를 ER 다이어그램을 그리며 조금씩 고도화 시켰습니다.
최종적으로 사용한 DB 구조는 다음과 같습니다.
기능을 정리한 것으로 바탕으로 생각한 API의 모습과 실제 구현한API의 모습은 다음과 같습니다. 우선순위에 따라 모든 사항을 구현하진 못했습니다.
POST
/api/schedules
request: {
startTime:yyyy-mm-ddThh:mm,
movieId:UUID(String),
screenId:UUID(String)
}
response: -
/api/reservations
request: {
scheduleId:UUID (),
phoneNumber: 000-0000-0000(String),
price: Number,
rowArray: String[],
colArray: Number[]
}
response: {
movieReservationId: UUID(String)
}
GET
/health
request: -
response: "health"
/api/movies/active
request: -
response: [
{
movieId: UUID(String),
title: UUID(String),
releaseDate: XXXX-XX-XX(String),
psterUrl: url(String)
}
]
/api/theaters
request: -
response: [
{
theaterId: UUID(String),
theaterName: String
}
]
/api/schedules?theaterId={theaterId}&date={date}&movieId={movieId}
Request Param:
- theaterId : UUID(String)
- date : yyyy-mm-dd (String) default: today
- movieId : UUID(String)
request: -
response: [
{
scheduleId: UUID (String),
title: String,
startTime: yyyy-mm-ddThh:mm,
endTime: yyyy-mm-ddThh:mm,
theaterName: String,
screenName: String,
}
]
/api/schedules/{scheduleId}
Path Variable:
- scheduleId : UUID(String)
request: -
response: {
scheduleId,
title,
startTime,
endTime,
theaterName,
screenName
}
/api/schedules/{scheduleId}/seats
Path Variable:
- scheduleId : UUID(String)
request: -
response: {
a:[...true,true,true,false],
b:[...true,true,true,false],
...
} ( Map<String,Boolean[]> )
- Reservation
/api/reservation/lookup/{userPhone}
Path Variable:
- userPhone : 000-0000-0000 (String)
request: -
response: [
{
movieReservationId,
phone: UUID(String),
seatCount: Number,
price: Number,
movieTitle: String,
movieStartTime: hh:mm:ss,
movieEndTime: hh:mm:ss,
date: yyyy-mm-dd,
rowArray: String[],
colArray: Number[]
}
]
PUT
😭
DELETE
😭
첫페이지
좌석선택 페이지
예매 성공시 alert창
조회 모달
조회 결과
해당 프로젝트를 진행하면서 느낀 점은 DB 를 설계하는 것이 보통일이 아니라는 생각이 들었습니다.
ERD 도 그릴줄 몰랐고, 정규화 같은것도잘몰랐을 뿐더러 DB 를 설계하는게 이 프로젝트가 처음이었기 때문에 DB 를 설계하는데 엄청난 시간이 들어갔습니다. DB 설계가 완료된 후에도 크고 작은 변경사항들이 계속 있었기 때문에 테이블의 이름도 계속 바뀌고 길어지는 등의 문제가 있었습니다.
그리고 DB 설계가 중요한 이유도 뼈저리게 느꼈습니다. db 가 복잡해 지니 원하는 데이터를 가져오기 위한 join 문도 점점 복잡해져 갔고, join 문이 복잡해지다 보니, jdbc 템플릿을 이용할때 오타를 찾기도 힘들고,버그를 잡기도 점점 복잡해져 갔습니다. 실제 회사들의 DB 설계를 한번 경험해 보고 싶다는 생각도 가지게 되었습니다.
또한 api 설계는 고려할게 많구나 라고 느꼈습니다. uri 를 이렇게 주는게 맞을지, 이 정보를 request body 와 request param, path variable 중 무엇으로 넘겨 주어야 할지, response 는 무엇을 주어야할지, 등등 크고 작은 고려할 것들이 많았습니다. 경험을 많이 하는것으로 어떤게 best prectice 일지 알아가야 할 것 같습니다.
api 가 안나오는 이유를 알게 되었습니다. 프론트 엔드 개발자로 백엔드 개발자와 협력할 떄는 왜 API 를 안주지?? 데이터를 안주니까 할 일이 없다느 생각만 했었는데 저 혼자 프론트와 백엔드까지 모든 분야를 진행해보니 백엔드 개발자 입장에서는 프론트가 어떤 데이터가 필요할지 알기 힘들 것 같다는 생각이 들었습니다. 프로젝트를 진행하는데 API 의 설계는 전적으로 백엔드의 책임이라고 생각했는데 그게 아니라 우선 프로젝트의 도메인을 가지고 프론트에서 필요한 데이터, 조건등을 충분히 얘기한 뒤 백엔드가 그 정보를 바탕으로 DB 를 설계해 api를 제공하는 방식으로 백엔드와 프론트엔드가 함께 설계해 나가야 하는 구나 라는 것을 새삼 깨닫게 되었습니다.
아래로는 1차 프로젝트를 진행하면서 한 주요 고민사항과 기억에 남는 문제해결 그리고 아쉬운 점을 적어보았습니다.
상영관은 극장이 없으면 존재할수 없고 좌석은 상영관이 없으면 존재할 수 없을 것 같은데 그럼 이것들은 약한 객체인가?
라는 고민이 들었습니다. 하지만 그렇게 될경우 약한객체는 복합키로 ID(많은 예제들이 그렇게 안내함) 를 가져야 하기 때문에, 좌석의 경우에는 극장의 ID, 상영관의 ID, 좌석의 행번호, 좌석의 열번호 까지 모두 가지게 될 것 같았습니다. 이것과 관련해서 다른 개발자 친구에게 물어보니 SQL 스럽지 못하고 오히려 No SQL 에 가까운것 같다는 이야기를 듣고, 약한 객체긴 하지만 유니크한 ID 컬럼을 따로 두는 형태로 DB를 설계하였습니다.이런 목표들을 지속적으로 수정해 나가고 싶습니다...