프로젝트 개요/동기
친환경에 대한 사람들의 관심이 높아짐에 따라, 전기차의 수요 또한 가파르게 증가하고 있다. 하지만 전기차의 수요 증가에 비하여 충전 인프라의 부족으로 전기차 사용자의 불편을 초래한다는 것을 알 수 있다.
우리 'SPACE AXE'팀은 그 중 전기차 충전 요금과 주차 정산 요금을 따로 결제해야 하는 불편함에서 착안하여, 전기차 충전 요금과 주차 정산 요금을 한 번에 결제할 수 있는 시스템, 박차고(Park-Charge-Go)를 제안한다.
기존의 경우 주차 정산 요금과 전기차 충전 요금을 따로 결제해야 하는 시스템이며, 이러한 부분이 전기차 사용자들로 하여금 불편함을 유발하는 원인이 되었다. 박차고의 경우, 별도로 결제하던 요금들을 한 번에 정산할 수 있도록 하여 이러한 불편함을 해소하는 것에 집중하였다.
| Flutter | dart |
|---|---|
![]() |
| NestJS | TypeORM |
|---|---|
![]() |
사용자가 애플리케이션을 실행하면 메인 화면으로 이동한다. 메인 화면에서는 로그인, 인근 주차장 조회, 이용 내역 조회, 카드 관리 페이지, 차량 관리 페이지, QR 결제 페이지, 사전 결제 페이지로 이동할 수 있다.
사용자가 로그인 버튼을 터치하면 로그인 페이지로 리다이렉트된다. 사용자는 회원가입 버튼을 터치하여 회원가입을 진행할 수 있고, 아이디 / 비밀번호 찾기 버튼을 터치하여 분실한 아이디를 찾거나 비밀번호를 재설정할 수 있다. 로그인 기능은 회원 결제 및 내역 조회 등의 기능을 제공할 때 사용된다.
'주차장 위치 확인하기' 버튼을 터치하면 네이버 지도 API를 사용하여 공공데이터에 저장되어 있는 주차장 목록을 시 단위로 필터링하여 보여주며, 사용자의 위치 5km 이내에 있는 박차고의 자체 데이터베이스에 내장되어 있는 주차장 목록을 보여준다.
'카드 관리' 버튼을 터치하여 카드 관리 페이지로, '차량 관리' 버튼을 터치하여 차량 관리 페이지로 이동할 수 있다. 각각의 페이지에서 등록되어 있는 카드 / 차량의 조회, 등록 및 삭제를 수행할 수 있다.
애플리케이션 하단에 위치한 플로팅 액션 버튼1을 왼쪽으로 슬라이드하면 QR 결제 페이지로 이동할 수 있다. 해당 페이지를 최초로 구동한 유저의 경우 카메라의 권한을 요청하는 팝업 메시지가 발생하며, 권한을 취득하면 카메라를 통해 QR 코드를 인식할 수 있는 상태가 된다. POS에서 발급한 QR 코드를 인식하면 백엔드에서 결제의 유효성 검사를 실행하며, 유효하다고 판단될 경우 기존에 등록되어 있던 카드의 정보를 활용하여 결제를 진행하게 된다.
애플리케이션 하단에 위치한 플로팅 액션 버튼을 오른쪽으로 슬라이드하면 사전 결제 페이지로 이동할 수 있다. 해당 페이지에 진입할 시, 사전 결제가 필요한 차량이 입차되어 있는 경우 결제 정보를 화면에 표시한다. 결제 버튼을 터치할 경우, 기존에 등록되어 있던 카드의 정보를 활용하여 사전 결제를 진행하게 된다.
POS의 메인 화면에서, 입차 버튼을 터치하면 자동차 번호를 입력하는 페이지로 리다이렉트된다. 해당 페이지에서 차량 번호를 입력한 후 입차 버튼을 터치하면 차량이 입차된다. 출차 시에 자동차 번호를 입력한 후 출차 버튼을 터치할 경우, 중계 서버와의 교신을 통해 백엔드 서버에서 해당 차량이 사전 결제한 차량인지 확인한 후, 사전 결제가 완료된 차량의 경우 바로 출차에 성공하게 되며, 사전 결제가 완료되지 않은 경우 QR 결제 페이지로 리다이렉트된다.
POS의 QR 결제 페이지에서는 백엔드에서 결제 정보를 받아와 결제용 QR 코드를 생성, 이를 사용자에게 보여준다. 이 페이지에서 사용자는 결제 금액 등의 정보를 확인할 수 있다. 사용자는 앞서 설명한 애플리케이션의 QR 결제 페이지를 사용하여 QR 코드를 스캔, 중계 서버를 통해 백엔드 서버에 결제를 요청할 수 있다.
충전기에서 충전 시작 버튼을 터치하면 자동차의 번호를 입력하는 페이지로 이동하고, 자동차의 번호를 입력하면 충전 시간을 설정할 수 있는 페이지로 이동하게 된다. 충전 시간을 설정하면 자동으로 충전이 시작되며, 지정된 시간 이후 충전이 종료된다. 사용자는 충전 종료 버튼을 터치하여 지정된 시간이 지나기 이전에도 충전을 임의로 종료할 수 있으며, 충전 시작과 충전 종료 시 중계 서버에 이벤트를 발생시켜 백엔드 서버에 충전 시작 시간과 충전량을 기록한다.
데이터베이스에 저장되어 있는 카드 번호를 복호화하여 PortOne API 서버에 테스트 결제 요청을 진행, 유효성 검사를 진행한다. 테스트 결제가 성공하면 실제로 정산 금액만큼 카드 결제가 진행되며, 일정 시간 후 출금정정이 진행된다.
데이터베이스에 사용자의 비밀번호를 저장할 때, Javascript의 crypto 모듈을 사용하여 해싱을 진행한다. 사용자가 로그인 요청을 진행할 때, 비밀번호를 해싱한 값을 데이터베이스에 있는 값과 대조하여 유효성 검사를 진행한다. 카드 번호를 저장하는 경우, AES-256 알고리즘을 사용하여 카드의 암호화를 진행한 후 데이터베이스에 삽입, 카드 결제 요청이 들어왔을 때 복호화를 진행하여 결제에 사용한다. 사용자가 카드 번호를 조회할 때, 데이터베이스에서 카드 번호를 복호화하고, 중간 8자리를 백엔드에서 마스킹하여 프론트엔드에 전달한다. 위와 같은 방법으로 만약에 데이터베이스가 해킹당했을 경우 원본 값을 유추할 수 없도록 대처하였다.
POS와 충전기는 주차장 중계 서버에 연결되어 있으며, 사용자가 입차 / 출차 / 충전 등의 행동을 시행할 경우 POS와 충전기는 중계 서버에 이벤트를 발생, 중계 서버는 이를 감지하여 백엔드 서버에 대신 요청을 보낸다.
Github Actions에서 SSH 원격 접속으로 자동 배포를 구현했을 때, npm을 인식하지 못하는 문제가 발생하였다. 어떠한 이유인지는 불명이나 bashrc에 기록되어 있던 nvm.sh가 동작하지 않았고, 이로 인해 nvm을 인식하지 못하여 생기는 문제였다. 자동 배포 스크립트에 nvm.sh를 강제 실행시킴으로써 이를 해결하였다.
Flutter에서 httpOnly 쿠키의 핸들링 이슈로 인하여 자동 로그인이 구현되어 있지 않다. 구조적 개편을 통해 자동 로그인을 추후 도입할 예정이다.
OpenCV와 Raspberry Pi 5 모델과의 호환성 문제 및 레퍼런스 부족으로 인하여 카메라에서 자동차 번호를 인식하여 입 / 출차 및 충전 시작 / 종료를 기록한다는 최초 기획에서 번호를 수기로 입력하는 방식으로 변경되었다. 이후 연구를 통해 카메라로 자동차 번호를 인식하는 기능을 추가할 예정이다.
최초 기획에서는 카드 리더를 통한 현장 결제를 구상하였으나, 카드 리더를 구매하고 이를 적용하는 것에 어려움이 있다고 판단하여 이를 구현하지 않았다. 이는 카카오페이 등 서드파티2 플랫폼을 이용한 결제 모듈을 통한 결제 등으로 구현할 예정이다.
Flutter에서 USB의 입출력을 감지할 수 없었기에 USB 연결 시 충전 시작, USB 연결 해제 시 충전 종료를 자동으로 감지하는 기능을 구현할 수 없었다. 실제 상용화를 하는 경우 실제 충전기에서의 시작 / 감지를 인식하면 되므로 이를 통해 해결할 수 있다.
시스템에 대한 보완 및 추가 기능 구현 등을 통하여 창업경진대회에 출품 및 창업을 할 수 있을 것으로 보이며, 이를 통해 전기차와 같은 친환경 제품들에 대한 인프라 제공으로 사용을 장려, 친환경에 이바지할 수 있을 것이다.


.png)

