처음으로 외주를 받게 되었다.
게시판 형태의 웹페이지에 기능을 추가하는 의뢰가 들어왔다.
나는 그 중에서 실시간 채팅 기능을 구현하기로 했다.
firebase
: Google에서 제공하는 클라우드 기반 개발 플랫폼으로, 모바일 및 웹 애플리케이션 개발에 필요한 다양한 도구와 서비스를 제공한다.
웹서비스를 만들 때, 회원가입, 로그인, DB 연결 등 반복해서 사용하는 기능들이 많다.
이 기능들은 서비스 주체만 다를 뿐 만드는 절차가 매우 유사하다.
이를 정형화해 서비스로 제공하는 것이 파이어베이스이다!
즉, 서버가 없이 프론트엔드만 개발해도 웹페이지를 구현할 수 있다.
장점 | 단점 |
---|---|
서버리스 인프라로, 개발자가 서버 관리를 하지 않고도 빠르게 애플리케이션을 구축하고 배포할 수 있다. | 데이터베이스 쿼리의 복잡성이 높아질 경우 성능 저하가 발생할 수 있다. |
다양한 SDK와 통합이 쉬워, 모바일 및 웹 애플리케이션의 생산성을 크게 향상시킬 수 있다. | 프로젝트가 커질수록 비용이 증가할 수 있어, 비용 관리에 유의해야 한다. |
Google Cloud와 통합이 가능하여, 확장성 있는 애플리케이션 개발을 돕는다. |
firebase의 Realtime Database를 사용하여 채팅 기능을 구현했다.
모든 구현 과정을 서술할 수는 없으므로, 구현할 때 사용했던 주요 개념만 작성하고자 한다.
(자세한 구현 과정은 깃허브를 확인)
Firebase Realtime Database는 클라우드 기반의 NoSQL 데이터베이스로, 데이터를 실시간으로 동기화하고 관리할 수 있도록 다양한 함수와 이벤트 리스너를 제공한다.
이를 통해 여러 사용자가 동시에 같은 데이터를 다룰 때 실시간으로 데이터가 업데이트 되도록 만들 수 있다.
let database = firebase.database(); // Realtime Database 인스턴스 가져오기
firebase.database()
함수를 호출하면 Firebase Realtime Database와의 연결을 설정하여 데이터베이스와 관련된 기능을 사용할 수 있다.
firebase.database()
는 Realtime Database 인스턴스를 반환하며, 이를 통해 데이터의 읽기, 쓰기, 업데이트, 삭제 등을 수행할 수 있는 다양한 메소드들을 사용할 수 있다.
database.ref().once('value')
- 데이터베이스에서 한 번 데이터를 읽는다.
- 이후의 업데이트는 감지하지 않는다.
database.ref('path').once('value').then((snapshot) => { const data = snapshot.val(); console.log(data); });
database.ref().on('value', callback)
- 데이터베이스의 특정 경로에서 데이터가 변경될 때마다 이벤트가 발생.
- 콜백 함수를 등록해서, 데이터가 변경될 때마다 콜백 함수를 호출
'value'
는 데이터의 변경을 추적하는 미리 정의된 키워드- 실시간 동기화가 필요할 때 사용
database.ref('path').on('value', (snapshot) => { const data = snapshot.val(); console.log('Updated data:', data); });
database.ref().set(값)
- 해당 경로의 데이터를 지정한 값으로 설정
- 해당 경로에 이미 데이터가 있는 경우 덮어쓰기
reference.set({ name: 'John Doe', age: 30 }).then(() => { console.log('Data is set successfully'); }).catch((error) => { console.error('Error setting data:', error); });
실시간 채팅을 구현하기 위해 realtime database를 다음과 같은 방식으로 사용했다.
⚠️ firebase Realtime Database의 document와는 다른 개념이다
document는
: 웹 페이지를 표현하고 다루기 위한 중요한 객체로, HTML이나 XML 문서를 나타내고 조작할 수 있도록 하는 인터페이스이다.
기능 | 코드 | 설명 |
---|---|---|
특정 ID를 가진 요소 접근 | document.getElementById(id) | 주어진 id를 가진 요소를 반환 |
특정 클래스를 가진 요소들에 접근 | document.getElementByClassName(myClass) | 특정 클래스 이름을 가진 요소들을 HTML Collection 형태로 반환 |
콘텐츠 수정 | document.getElementById(id).innerHTML | 요소의 HTML 콘텐츠를 읽거나 수정 |
속성 수정 | document.getElementById(id).setAttribute(attributeName, value) | 요소의 속성 값을 설정 |
⚠️ document.getElementById('myId')는 HTML 요소의 복사본이 아닌, 해당 요소를 가리키는 참조를 반환한다.
즉, 실제 HTML 요소 객체의 주소를 반환하기 때문에, 이를 통해 해당 요소의 속성이나 값을 직접 조작할 수 있다.
실시간 채팅 기능 자체를 구현하는 것은 어렵지 않았다.
그냥 DB에 메시지가 올라오면, 이벤트 리스너로 듣고, 화면에 표시하면 된다.
문제는 알림 서비스였다.
누군가 나에게 채팅을 보내면 이것을 alert
로 사용자에게 알려줘야 한다.
그러기 위해선 window.onload
에 이벤트 리스너를 등록해서 나에게 오는 채팅을 지속적으로 확인해주어야 한다.
하지만
이렇게 하면, 채팅방에 들어가서 상대방과 채팅을 하는 도중에도 계속 alert
로 알림이 뜬다.
A 사용자가 B 사용자와 채팅방에서 채팅을 하는 중이다.
B 사용자가 A 사용자에게 메시지를 보내면 A 사용자에게 alert
로 알림이 보내진다.
채팅방을 열고 있으면 굳이 알림을 보낼 필요가 없으므로 이벤트 리스너를 잠깐 삭제했다가 다시 등록해줘야 한다.
이 과정이 어려웠다.
chatModalVisible
함수를 정의하여, 모달(채팅창)이 열려있는지 확인한 뒤에 alert를 보내는 것으로 해결했다.