Firebase와 React를 이용한 실시간 공지사항 등록 서비스
인턴 생활을 하면서 처음으로 받은 개발 업무이고, 부분 기능을 개발하여 실제 서비스에 이식하였다.
원래 백엔드(Spring Boot)를 공부했었고 공교롭게도 React와 Firebase 모두 한 번도 사용해본 적 없는 기술들이다.
그렇지만 새로운 기술을 배우는 것을 좋아하고, 넓게 배워두면 분명 어딘가에서 도움이 된다고 생각했기 때문에 열심히 개발하였다.
GitHub Link
사용한 기술
- React (Frontend) 18.3.1
- Firebase (Backend) 9.23.0
- Firestore Database
- Authentication
React는 사용자에게 공지사항 목록을 표시하고 등록할 수 있는 화면 역할이다. Firebase에 공지사항 데이터와 사용자 UUID를 저장한다.
Firebase는 두 가지 서비스를 이용했다.
Firestore Database는 말 그대로 데이터를 저장하는 DB이다. 모든 공지사항을 announcements 컬렉션에 저장하였으며, type 필드를 이용해 전체 발송(general)과 특정 사용자 대상 발송(client1, ...) 공지를 구분하였다. readBy 필드의 UUID를 사용해 각 사용자의 공지사항 확인 여부를 판단했다.
Firestore 구조는 다음과 같다.
announcements
└── {announcementId} - 자동 생성
├── title: "공지사항 제목"
├── content: "공지사항 내용"
├── type: "general" 또는 "client1"...
├── timestamp: 공지사항 작성 시간
└── readBy: {
{token1}: true,
{token2}: true,
...
}
users
└── {userUid} - UID 입력
├── name: "관리자 이름"
└── role: "admin"
clients
└── {userUuid} - UUID 입력
└── name: "사용자 이름(admin, client1 등)"
특정 사용자에게 읽기 혹은 쓰기 권한을 부여하기 위해 Firestore 규칙을 설정할 수 있는데, 개발 과정에서 계속 권한 오류가 발생해 현재는 모든 사용자에게 읽기와 쓰기 권한을 부여해 놓은 상태이다. 이건 테스트 계정으로 로컬에서 실행한 프로젝트이므로 털려도 걱정이 없기에 그대로 놔두었다... 실제로 프로젝트를 개발할 때에는 규칙 설정에도 신경써야 한다.
Firestore 구조에 대해...
구조 수정 전, 전체 공지와 특정 대상 공지로 문서 자체를 나누어 데이터를 저장했다. 모든 문서는 컬렉션 안에 저장되어야 하므로, 공지 종류를 두 개로 나누기 위해서는 컬렉션-문서-컬렉션-문서와 같은 구조를 구축해야 해서 복잡했다.
이 문제는 둘째치고, 웹 페이지의 공지 목록에서 전체 공지와 특정 대상 공지 데이터를 합쳐 날짜 내림차순으로 정렬하고 싶었다. 그런데 Firestore은 NoSQL 구조라 JOIN 같은 건 없었다.
첫 번째 방법은 두 개의 컬렉션으로 저장하되 화면에 보여줄 때 모두 불러와 마치 하나인 것처럼 보이게 하는 것이다. 추후 특정할 고객이 많아질 경우 복잡해질 것이라고 판단해 패스.
두 번째 방법은 두 문서를 하나로 합친 후, String 타입인 type 필드를 추가해 대상을 구분하는 것이다. 대상을 구분하여 가져오고 싶을 경우 쿼리문 조건으로 해결 가능하다.
따라서 이와 같이 구조를 수정하였다.
1. 모든 공지사항을 하나의 컬렉션(announcements)에 저장하고, 각 문서에 type 필드 추가
2. Firestore 쿼리에서 모든 문서를 가져와 날짜 기준으로 내림차순 정렬
Authentication은 사용자의 권한을 관리해 주는 서비스이다. 관리자 계정으로 사용할 구글 계증을 등록한 후, Firestore의 users 문서에 사용자 UID 등록 후 role 필드를 `admin`으로 설정해 주었다.
웹에서 공지사항을 등록할 때, 해당 로그인 정보로 공지사항의 '작성자' 필드를 자동으로 생성하기 위해 이름도 등록해주었다.
기능 소개
- 로그인
- 공지사항 목록
- 공지사항 등록
- 공지 조회 여부 확인