1️⃣ ERD
1) ERD란?
ERD(Entity Relationship Diagram) 이란 개체-관계 모델로, 관계형 데이터베이스에서 주로 사용되는 다이어그램이다.
이는 테이블간의 관계를 다이어그램으로 표현하여 개체간 관계, 즉 DB의 구조를 한 눈에 파악할 수 있다는 장점이 있다.
구성 요소로는 크게 세 가지가 있다. 'Entity(개체)', 'Relationship(관계)', 'Diagram(다이어그램)' 으로, 말 그대로 ERD 를 표현하는 구성 요소들이다.
최근에 정보처리기사 필기를 공부하면서 그동안 잘 알지 못했던 관련 개념들을 공부할 수 있었다.
하지만 프로젝트 진행 당시 ERD에 대한 지식이 전혀 없었기 때문에 많은 시행착오를 겪었다.
지난 게시글에 올린 '요구사항 분석 및 설계' 단계에서 서비스에서 필요한 기능들을 뽑아냈다.
이후 해당 기능들을 바탕으로 필요한 개체가 무엇인지 설정하는 단계가 그 시작이 되었다.
2) ERD 작성
(1) 객체(Entity) / 관계(Relationship)
객체 지향적 관점에서 예약 서비스에 필요한 개체가 무엇인지 생각해보았다.
우선 서비스를 이용하는 사용자가 있을 것이다. 이를 'USER' 라고 정했다.
다음으로 예약 서비스이기 때문에 'RESERVATION'을 하나의 개체로 보고, 유저와 어떤 관계가 있을지 생각했다.
한 명의 유저는 여러 개의 예약을 할 수 있으므로 유저와 예약은 '일대다' 관계가 성립한다.
즉, 1:N 으로 표현할 수 있다.
사실 위 단계까지 진행하는데에 시간이 꽤 걸렸다. ERD 를 작성해본 적도 없었고, 예약 서비스의 DB구조를 어떻게 짜야할지 전혀 감이 안잡혔기 때문이다. 따라서 관련 정보를 찾아보고 적용하는데에 애를 먹었다.
다음으로 예약 시설과 관련된 'ROOM' 을 생각했다.
하나의 예약은 하나의 시설에 대한 것이지만, 개체 단위로 생각해보면 예약과 룸은 '다대일' 관계가 된다.
즉, N:1 으로 표현할 수 있다.
이외에도 많은 개체가 생길 수 있겠지만, 나는 최대한 단순하게 작성하려고 노력했고, 필요한 부분만 넣으려고 했기에 최종적으로 위 세 개의 개체가 만들어졌다.
정리하자면 크게 'USER', 'RESERVATION', 'ROOM' 개체가 각각 1:N, N:1 관계가 된다.
(2) 속성(Attribute)
이제부터 개체를 엔티티라고 표현하겠다.
위 작업으로부터 엔티티와 관계를 정했으니, 각 엔티티의 속성을 정해야 한다.
여기서는 해당 개념에 대한 자세한 설명은 하지 않겠다.
1. USER
유저 엔티티에서 어떤 정보가 필요할까?
다시 요구 사항 분석 단계에서 작성한 명세서를 보면 된다. 이곳에서 각 유저는 어떤 속성을 갖는지 찾을 수 있을 것이다.
이 과정에서 느낀 점은 다시 한번 설계 단계가 얼마나 중요한지 깨달았다.
다음은 유저 엔티티의 속성을 뽑아내는 과정이다.
- 기본 PK값이 있어야 한다. 이는 각 엔티티를 구분해주며, 이름을 'user_id' 라고 정했다.
- 해당 엔티티가 생성, 수정된 날짜인 'create_id' 와 'update_id' 가 있다. 이는 실제 서비스에서 필요없을진 몰라도, 해당 데이터가 언제 생성되고 변경되었는지 알 수 있다.
- 유저에 대한 기본 정보인 이메일, 비밀번호, 이름, 핸드폰 번호를 각각 'email', 'password', 'name', 'phone_num' 이다.
- uuid 는 Firebase로부터 자동으로 생성된 것으로, 각 회원마다 갖게 되는 고유 번호이다. HTTP통신을 통해 데이터를 주고 받을 때, 숫자로 된 user_id 보다 uuid 로 구분하는 것이 바람직하겠다고 판단하여 넣었다. 사실 이 부분도 아쉬운 점이 많은데, 후에 보안 관련 부분에서 자세히 설명하도록 하겠다.
2. RESERVATION
다음은 예약 엔티티이다. 해당 엔티티에 대한 속성을 어떻게 정해야 효율적인지 많은 고민을 통해 최대한 간결하고 필요한 속성만 넣었다. 아래는 예약 엔티티의 속성을 뽑아내는 과정이다.
- 기본 PK값이 있어야 한다. 이름을 'reservation_id' 라고 정했다.
- 예약 고유 토큰인 'reservation_token' 이다. 이는 예약별로 구분하기 위한 고유 토큰이며, 임의로 생성되어 저장된다. 유저 엔티티의 uuid와 비슷한 역할을 한다고 생각하면 된다. 실제로 통신을 할 때도 번호보다 토큰을 이용하는 방법이 안정적이고, 보안적인 측면에서도 좋다고 하여 넣었다.
- FK값으로 'user_id' 와 'room_id' 가 있다. 위에서 말했듯 예약 엔티티는 유저와 룸 엔티티와 각각 1:N, N:1 관계로, 서로 연관되어있다. 따라서 예약 정보엔 누가 예약했는지, 어느 시설물을 예약했는지 알 수 있는 FK값이 필요하다.
- 마찬가지로 실제 서비스에선 필요없을 수 있겠지만, 데이터가 언제 생성되고 수정되었는지 알기 위해 'create_date', 'update_date' 가 있다.
- 예약 정보에서 중요한 정보인 예약 시간이다. 우리 서비스는 최대 2시간 동안 예약할 수 있다. 이러한 시간 간격을 데이터로 어떻게 저장할지 많은 고민을 했다. 찾아보니 시작 시각과 종료 시각을 통해 데이터를 저장하는 것이 좋다고 판단했다. 나중에 유효성 검사시에도 편리하겠다는 생각을 했다. 따라서 'start_time' 과 'end_time' 을 넣어주었다.
- 마지막으로 'purpose', 'member_num' 이다. 이는 요구 사항에서 작성한대로 예약 정보에 예약 목적과 인원수가 필요하기 때문에 넣어주었다.
3. ROOM
마지막으로 룸 엔티티이다. 사실 예약 정보는 대부분 RESERVATION 엔티티에 담기고, 해당 예약이 어떤 룸에 대한 예약인지 알기만 하면 되므로 룸 엔티티는 비교적 간단하게 설계할 수 있었다.
- 기본 PK값이 있어야 한다. 이름을 'room_id' 라고 정했다.
- 해당 룸이 최대로 수용할 수 있는 인원인 최대 인원 수를 'max_num' 으로 표현했다.
- 해당 룸의 이름에 대한 정보를 'name' 으로 표현했다.
위 과정을 통해 최종적으로 완성된 ERD 는 아래와 같다.
2️⃣ API
API(Application Programming Interface) 는 정의 및 프로토콜 집합을 통해 두 소프트웨어 구성 요소가 서로 통신할 수 있게 해주는 계약이라고 할 수 있다. 이는 요청(Request)과 응답(Response)를 사용하여 두 애플리케이션이 서로 통신하는 방법을 정의한다.
그 중 나는 REST(Representational State Transfer) API 를 만들기로 했다. REST는 클라이언트가 서버 데이터의 액세스하는 데 사용할 수 있는 GET, PUT, DELETE, 등의 함수 집합을 정의한다. 클라이언트와 서버는 HTTP 통신을 통해 데이터를 교환한다.
REST API의 특징은 이름에서도 알 수 있듯 '무상태'이다. 이는 서버가 요청 간에 클라이언트 데이터를 저장하지 않음을 의미하며, 서버에 대한 클라이언트 요청은 웹 사이트를 방문하기 위해 브라우저에 입력하는 URL과 유사하다. 또한 서버의 응답은 웹 페이지의 일반적인 그래픽 랜더링이 없는 일반 데이터이다.
자세한 설명은 다음에 하기로 하겠다. 이 역시 프로젝트 전까지는 개념도 잘 몰랐다. 따라서 어떠한 방식으로 클라이언트와 서버가 통신을 하는지, 데이터가 어떤 방식으로 이동하는지, 호출과 응답 등에 대한 공부를 하면서 코딩을 병행했다.
실제로 RESTful한 API 를 만들기 위해서 지켜야 하는 규칙이 몇몇 있다. 이를 지키며 API 명세서를 작성하려고 노력했으나, 혼자 공부한 내용이기 때문에 이상하거나 틀린 내용이 있다면 언제든 알려주시면 감사하겠다.
다음은 API 목록들이다.
- / users / signsup POST : 회원 가입
- / users GET : 회원 정보 조회
- / users / update PUT : 회원 정보 수정
- / users DELETE : 회원 탈퇴
- / room / {roomId} / reservation GET : 해당 룸 예약 조회
- / room / {roomId} / reservation POST : 예약 등록
- / room / {roomId} / reservation / {reservationToken} GET : 등록한 예약 상세 보기
- / room / {roomId} / reservation / {reservationToken} PUT : 예약 수정
- / room / {roomId} / reservation / {reservationToken} DELETE : 예약 삭제
- / room / {roomId} / date / {checkDate} GET : 특정 날짜, 룸 시간대별 예약 확인
- / reservation / {uid} GET : 해당 유저 예약 조회
사실 처음에 작성한 목록은 위와 같지 않았다.
실제 코드에 적용하고 테스트해보며 가능한 선에서 작성한 결과가 위와 같다.
예를 들어 uuid 를 URL에 그대로 노출시켜 검색하는 등의 방법을 사용하는 것은 실제 서비스를 하진 않겠지만 보안의 문제가 있다고 판단하여 수정하였다. 이러한 구조적 변화 말고도 요청, 응답 방식에도 몇몇 변화를 주었다.
PathVariable 방식을 ResquestParam 방식으로, 혹은 그 반대로 적용한 것도 있었다.
3️⃣ 결론
ERD 와 API 를 설계, 작성하면서 어려운 점이 많았다.
생소한 개념과 어떤 방식으로 진행해야 맞는 것인지, 오류는 없는지 물어볼 사람이 없었기에 스스로 판단해야 했다.
따라서 후에 공부를 많이 하고 다시 보면 엉망진창일 것이라는 생각을 했다.
그래도 나는 한 번이라도 이러한 경험을 해보며 고민하고 공부한 경험 자체에 초점을 두어 모두 중요한 시간이었다고 생각한다. 틀리면서 배운다면 기억에도 잘 남고, 틀리지 않기 위해 더 노력할 수 있기 때문이다.
처음엔 막막했지만 이렇게 하나씩 단계를 밟으며 진행하는 재미가 쏠쏠했다.
몰랐던 지식도 알게 되어 적용하는 것도 재미있었고, 조금이나마 성장했다는 뿌듯함도 느꼈다.
아 그리고 가장 중요한 것은 프로젝트를 진행할 때 설계 단계가 얼마나 중요한지 다시 한 번 정말정말정말 매우많이 깨달았다.
미리 좋은 설계를 하면 코딩만 하면 된다는 말이 얼추 이해가 갔다.
정처기 필기를 공부하면서 단순히 시험 합격의 목적이 아닌, 실제 부족한 부분을 공부하기 위해 노력한 것도 이와 같은 이유 때문이다.
이제 개발 공부에 몰두할 수 있는 환경이 되었으니 더 열심히 해야겠다.