![스크린샷 2022-11-21 오후 3 48 47](https://user-images.githubusercontent.com/68465716/237099393-ff26948e-aeaa-4172-9460-77fea0e8169d.png)
회의공간 예약 및 관리 시스템
( 개발 기간 : 2022.10 ~ 운영중 [서비스 오픈: 2023.05] )
FRONTEND PROJECT ·
BACKEND PROJECT
https://kiosek.kr
- ✅ 시스템 목적
- 🏗️ 운영 서버, 개발 서버 구조 및 사양
- 📔 프로젝트 회고
- ❗️기여한 주요 내용
- 🛢️ ERD
- 📷️ 실제 키오스크 운영 사진
- 🎥 주요 기능 시연 영상
- 🎨 UI 구현
- 📱 시스템 주요 Flow
- 🔧 회의실 관리자 주요 기능
- 회의실 비매너 사용(청결 문제 등)과 자리 점유 등에 불편함을 느끼고 직접 문제를 해결하기 위해 개발한 플랫폼입니다.
- 예약 시스템이 도입되면서 발생하는 노쇼와 같은 문제를 해결하기 위해 스케줄러 기능을 통해 체크인되지 않은 예약건에 대해 자동으로 취소처리를 하고 제재를 가하는 절차를 추가하였습니다.
- 웹 사전예약 또는 키오스크 현장예약을 통해 회의공간을 예약할 수 있습니다.
- 예약 당 발급된 QR 코드를 통해 체크인을 하는 방식을 선택하여 복잡한 인증 절차를 제거하였습니다.
- 좌석을 사용하고 나면 깨끗이 치우고 사진을 찍어서 반납하는 절차를 추가함으로써 청결 문제를 해결하였습니다.
"테스트 코드는 선택이 아닌 필수다"
이전 다른 프로젝트에서는 테스트 코드가 없어서 포스트맨으로 API 테스트할 때는 잘 되다가 예기치 못한 오류가 나곤 했었다. 코드를 리팩터링하거나 로직을 수정할 경우에 발생하는 휴먼 에러 또는 예기치 못한 에러를 여러 케이스로 작성해 놓은 테스트 코드 덕분에 막을 수 있었다.
생각보다 리팩터링을 할 때 실수가 자주 생겼는데, 코드 수정 후에 테스트 코드를 실행시켜 보는 습관을 들여놓음으로써 어느 부분에서 장애가 났는지를 빠르게 확인할 수 있었다. 기존에 잘 동작하던 테스트 코드가 갑자기 실패한다는 것은 내가 방금 수정한 부분이 잘못됐다는 것이기 때문이다.
이번 프로젝트를 진행하면서 단위 테스트에 대한 모호했던 생각들이 정리되었고, 통합 테스트 코드를 통해 직접적으로 API를 테스트 코드를 작성해 놓음으로써 반복적인 작업을 줄일 수 있었다.
"실수를 받아들일 수 있어야 한다"
누구든지 실수를 할 수 있기에 상대방의 실수에 대해서 받아들일 수 있어야 하고, 내가 한 실수에 대해서 솔직해야 한다. 나는 처음에 그러지 못했던 것 같다. 나는 백엔드를 전체적으로 맡았기 때문에 프론트엔드쪽에서 문제가 발생하였을 때 같이 원인을 찾아주곤 했다. 점점 일정이 바빠지고 팀원의 실수가 잦아질 때는 속으로 화도 났던 것 같다. 하지만, 팀원측의 실수라고 생각하고 몇 시간 동안이나 원인을 파악하다가 역으로 내 잘못이었음을 알게 된 순간도 있었다. 상대방의 실수로 인해서 내 시간을 낭비한다고 생각하고 있었는데, 내 잘못임을 알게된 순간에는 정말 부끄럽기도 했고 미안한 마음이 컸다. 실수는 정말 나 너 할 거 없이 모두에게 찾아오는 시련인 것 같다.
이러한 일이 있은 후에는 마인드를 다르게 가지기로 했다. "실수는 누구든지 할 수 있고 문제를 해결했을 때는 박수를 쳐주자!"라고. 서로 발생한 실수에 대해서 사과와 원망을 하는게 아니라 문제를 해결하고 서로 기뻐해주는 것이다. 이러한 마인드를 바탕으로 하니 실수를 숨기지 않고 함께 해결해 나가는 힘이 생겼다고 생각한다.
"시각적 자료를 이용하여 상대방을 설득하자"
KIOSEK 프로젝트 초창기 UI를 설계할 때 어떻게 메인 예약 페이지를 구성해야 할지 많이 의견이 분분했고 충돌이 있었다.
더 많은 의견이 있었지만 최종적으로 고민했던 세가지 의견을 나열해 보았다.
첫 번째 의견은 네이버 예약 형식대로 박스 형태를 나열해 보자. 두 번째 의견은 원하는 시간대를 먼저 선택하면 남아있는 좌석을 리스트업 해주자. 세 번째 의견은 쏘카의 UI를 참고하여 상태바의 형태로 시간대를 나타내어서 나타내보자.
나는 세번째 의견을 냈었다. 어떻게 팀원들에게 내가 생각하고 있는 것들을 정확히 전달할 수 있을지 고민하였다.
그에 대한 결론은 내가 제대로 설명할 수 없는데 남을 설득할 생각부터 하지 말고, 쓰던지 그리던지 해서 먼저 나부터 정리를 하자. 또한 의견에 대해서만 충돌이 있어야지 사람끼리의 충돌이 있어서는 안 된다. 정리되지 않은 의견으로 설득할 때는 오히려 반감을 사기 쉽다.
팀원을 설득하기 전 시각적으로 보여줌으로써 이해를 도울 수 있는 UI를 간단하게 스케치하고 다른 방식에 비해 가질 수 있는 장점에 대해 생각해 보았다.
이에 나는 첫 번째 의견이 구현이 더 편한 장점이 있지만 30분 단위의 24시간 동안 예약에 대해서 48개의 블록이 생기는 건 사용자 입장에서 불편함을 줄 가능성이 있을 것 같다. 두번째 의견은 예약 현황을 한눈에 볼 수 없고 계속 남는 시간대가 있는지 눌러봐야 한다는 단점이 있을 것 같다. 세번째 의견으로 진행했을 경우에는 이러이러한 UI를 바탕으로 관리자가 예약을 막아놓은 시간, 이미 예약된 시간, 예약 가능한 시간을 상태바로 한눈에 보고 예약할 수 있어 더 좋은 UX를 제공해 줄 수 있을것 같다.라는 식으로 발언했던 것으로 기억한다.
해당 의견에 대해 팀원은 내가 간단하게 스케치해놓은 UI를 통해 조금 더 관심을 갖고 긍정적인 질문들을 하였고, 이제는 내가 제시한 의견에 대해서 더 구체화할 수 있는 방안에 대해서 얘기하는 방향으로 흘러가게 되었다.
내 머릿속에서도 복잡한 생각을 누군가에게 전달할 때는 데이터를 기반으로 하거나 시각적으로 보여줄 수 있는 자료가 있을 때 더 설득력이 있다고 생각한다. 상대방을 설득한다는 것은 아직도 쉽지 않은 일이다.
"머릿속으로 생각중일 때는 상대방에게 표현해야 한다."
회의도중에 팀원의 의견에 대해서 생각이나 고민을 하고 있을 때는 그걸 표현해줘야 한다. 말없이 고민을 할 경우에는 상대방은 "내 의견이 별로인가?"라고 생각할 수도 있다는 것을 알았다.
나는 그래서 상대방이 의견을 내었고 내가 잠시 생각할 시간이 필요하다면 "좋은 의견이라고 생각하는데 잠시만 머릿속으로 정리해볼게"라고 표현한다. 이러면 상대방은 자신의 의견이 존중받음을 느낄 수 있고, 그 의견에 부정적인 견해를 전달하더라도 "충분히 생각해 보고 한 말이구나"라는 느낌을 받을 수 있다고 생각한다.
👉 회고 글 보기
여러 개의 세션에서 동시에 중복된 예약을 시도하는 문제에 대해 MySQL의 Named Lock을 이용하여 문제를 해결했습니다.
Lock을 얻기 위한 용도의 DataSource를 분리함으로써, Lock이 필요하지 않은 요청들에 대해서 커넥션 풀을 보장해줄 수 있도록 하였습니다.
또한 GET_LOCK과 RELEASE_LOCK 요청에 대해 같은 커넥션을 사용할 수 있도록 JDBC로 직접 구현하였습니다.
Named Lock의 lock name은 회의실 정보와 예약 시간을 메타데이터로 이용했습니다.
최종적으로 100개의 멀티 쓰레드로 동시성 테스트를 진행했을 때 1개의 예약만 DB에 삽입되었음을 확인했습니다.
👉 블로그 글 보기
KIOSEK에서는 예약과 관련하여 시간을 많이 다루고 있습니다. 따라서, DATETIME 타입의 컬럼을 범위 비교 또는 동등 비교하여 조회하는 쿼리가 많이 존재합니다.
카디널리티, 선택도, 활용도, 수정빈도를 고려하여 DATETIME 타입의 예약 시간 컬럼을 단일 컬럼 인덱스로 적용하여 기간별 예약 내역 조회 쿼리에 대해 약 34만 개의 데이터를 대상으로 500개의 데이터를 추출하는데 174ms → 11.8ms로 1374% 향상시켰습니다.
👉 블로그 글 보기
페이지를 넘길때마다 비효율적으로 호출되던 Count Query로 인한 성능저하를 해결하기 위해, Look-Aside 전략을 이용해 Redis에 총 예약건수를 캐싱하는 방법을 적용했습니다.
예약이 들어오면 캐시 데이터를 지워주고 Cache Miss가 발생하면 Count Query를 새로 실행하고 캐싱하는 방식으로 약 34만 개의 데이터를 대상으로 1.7s → 1.1s 로 성능을 약 56% 향상 시켰습니다.
👉 블로그 글 보기
예외상황마다 각각 하나의 커스텀 예외를 생성하다보니, 커스텀 예외의 수가 너무 많아지는 문제가 있었습니다.
이를 해결하기 위해 표준예외를 사용하는 대신 현재 프로젝트에서 주로 발생하는 예외를 대상으로 한번 더 추상화하고
ErrorCode를 추가적으로 인자로 넣어주어 가독성을 높이는 방식으로 구현하였습니다.
👉 블로그 글 보기
![](https://user-images.githubusercontent.com/68465716/237363611-50fa5d46-1ef7-48b9-8c25-d083c4dab047.gif)
![](https://user-images.githubusercontent.com/68465716/237354711-477b7b4c-4f2c-4cba-ace2-a6efcd7530f4.gif)
![](https://user-images.githubusercontent.com/68465716/237363643-b9caf7a8-a994-471f-8f19-1b0c2ba420ab.gif)
실제로는 터치 디스플레이 사용
![](https://user-images.githubusercontent.com/68465716/237353578-eb4f7cd4-34d4-4b54-a643-81401d435519.gif)
참고) 사용자는 https://kiosek.kr 브라우저를 통해 예약하거나 현장에서 키오스크를 통해 현장예약하여 바로 사용할 수 있다.
1. 웹을 통해 실시간으로 회의실 예약 상황을 확인할 수 있고 원하는 시간에 테이블을 예약하면 예약당 QR코드가 발급된다.
(사용자당 하루에 1번 최대 4시간 2주뒤까지에 대해서 예약 가능하다.)
2. 발급된 예약확인 QR코드를 키오스크에 인식하여 체크인 한다.
(체크인 가능 시간은 예약 시작시간 20 분전부터 예약 시작시간 20분 후까지이며 해당 시간내로 QR체크인을 진행하지 않을 경우 미사용으로 간주되어 위반내역에 기록되며 즉시 예약이 취소된다.)
3. 사용후에는 웹을 통해 좌석사진과 함께 반납한다.
4. 사용종료시간 20분 후까지 좌석사진과 함께 반납처리하지 않을 경우 미반납으로 간주되어 위반내역에 기록된다.
5. 위반내역이 3회 발생할 경우 3일간 예약이 불가능하다.
실제 운영을 위한 관리자 기능을 아래와 같이 제공합니다.
1. 전체적인 예약 상황 모니터링
2. 회의공간 비활성화 (공간을 사용하지 못하게 해야하는 경우 특정기간 동안 비활성화)
3. 위반내역 및 제재내역을 확인 및 정지 해제
4. 예약 정책과 제재 정책을 수정
5. 사용자의 민원 확인