최근 진행한 프로젝트에서 firebase를 활용하였다.
나는 이 프로젝트에서 firebase를 처음 사용하게 되었고,
진행하면서 겪은 수 많은 시행착오들에 대하여 기록을 남기려고 한다.
가장 처음 맞닥드린 문제는 구글 로그인 부분이었다. 관련 가이드는 아래 링크와 같다.
firebase-인증-웹-Firebase SDK로 로그인 과정 처리
구글 로그인을 하는 방식에는
1. 팝업
2. 리다이렉트
두 가지 방법이 있었다. 나는 프로젝트에 팝업 방식을 적용하였다.
해당 기능을 적용하고 로그인 시도를 했을 때, 계정이 없다면 신규 가입, 있다면 로그인을 해 준다.
가입 및 로그인 기능 자체는 잘 되었는데, 문제는 콘솔창에 뜨는 오류였다.

해당 문제는 로그인이 되어있는 상태에서 로그인을 시도하면 생기는 문제라고 하는데...
로그아웃을 하고 onAuthStateChanged 에서도 user 정보가 보이지 않는데도 뜬다.
검색을 하면서 발견한 해결 방법이 몇 가지가 있는데... 약간의 편법들이 들어간 방법이라, 궁극적인 해결 방법은 찾지 못하였다.
<meta name="Cross-Origin-Opener-Policy" content="same-origin">를 추가하였지만, 여전히 동일한 오류가 발생했다. 내가 찾은 모든 해결방법을 적용해보았지만 결국 해결하지 못하였다.
일단 기능은 잘 되어 넘어가고 이후에 수시로 확인해보았지만, 여태 해결을 하지 못했다.
혹시 해결 방법을 아시는 분이 있다면 알려주시면 감사합니다.
CSR 방식으로 개발되었기 때문에, 새로고침을 할 때 마다 로그인 정보가 날아가는 문제가 있었다. 해당 문제를 해결하고자 처음에는 localStorage에 로그인 token을 저장하는 방법을 사용하려 했다. token을 localStorage에 저장하고 받아오는 것 까지는 가능했으나, 서버가 따로 존재하지 않았기에 클라이언트에서는 token으로 유저 정보를 받아올 수 있는 방법이 없었다.
생각보다 간단한 방법으로 해결되었다. firebase에서 제공하는 onAuthStateChanged 메서드를 사용하면 로그인 유저를 받아올 수 있었다.
나는 다음과 같이 onAuthStateChanged를 사용하여 유저가 존재한다면 uid를 가지고 서버에서 user 정보를 받아오도록 로직을 구성하였다.
const initUser = () => {
this.auth.onAuthStateChanged(user => {
if (user) {
login(user.uid);
}
});
};
사실 이 메서드의 존재는 처음부터 알고 있었으나, 활용법을 제대로 몰라 한참을 헤맸던 것 같다.
나름 공식문서를 꼼꼼히 읽었다고 생각했는데, 다음엔 좀 더 제대로 읽어야겠다. 😅
이미지 업로드 기능을 구현하던 중, 이미지를 URL로 받아올 수 있는 방법이 없을까 싶어 찾아보았다. 처음에는 firebase 내에 기능이 없는 줄 알고 Base64 형식으로 보냈지만, 데이터의 크기가 커서 url로 변경하는 방법을 다시 찾았다.
방법은 간단했는데, firebase console에서 storage 기능을 활성화 시켜주면 된다.
allow read, write: if request.auth != null; 적용한 코드는 아래와 같다.
하나의 이미지만 올리고, 파일 이름은 "현재timestamp_랜덤숫자" 형태로 올리도록 하였다.
const handleUpload = (event: Event) => {
const target = event.target as HTMLInputElement;
const file: File = (target.files as FileList)[0];
if (!file) return;
// 파일 이름을 고유하게 만듭니다.
const fileName = Date.now() + "_" + Math.floor(Math.random()*10000);
// Firebase Storage에 저장할 파일 경로를 지정합니다.
// images 폴더 아래에 이미지가 저장됩니다.
const filePath = `images/${fileName}`;
// 업로드할 파일의 다운로드 URL을 생성합니다.
uploadBytes(ref(storage, filePath), file)
.then(() => {
// 업로드한 이미지 URL을 받아옵니다.
getDownloadURL(ref(storage, filePath))
.then((url) => {
imageUrl.value = url;
});
})
.catch(e => {
console.log(`이미지 업로드에 실패했습니다. ${e}`);
});
};
간단한 프로젝트를 구성할 때는 서버를 굳이 구축하지 않고 간편하게 사용할 수 있는 장점이 있지만, 조금만 복잡한 로직을 구현하려 하면 기능적 문제가 있어 쉽지 않았다.
특히 조건이 많은 조회성 SQL문을 작성하는 데 큰 무리가 있어서 원하는 기능을 구현하지 못하기도 했다.
firebase를 다시 사용할거냐 라고 물어봤을 때, 개인적으로는 부정적 입장이다.
차라리 내가 서버를 직접 구축하는게 더 편한 것 같다는 생각을 많이 했기 때문이다.
결국 해당 프로젝트는 서버를 별도로 개발하기로 결정하였다.
하지만, 부피가 작은 프로젝트를 진행한다면, firebase는 좋은 선택권 중 하나가 될 것이다.
빠르게 프로토타입을 보여야 할 때는 firebase를 사용하는 것이 좋은 것 같다.