Meta Beef
Meta Beef Github 페이지
노마드코더에서 트위터 클론 코딩 강의를 수강하며 만들어보았다.
이름은 Meta Beef 라고 지었는데, 요즘 핫해보이는 메타버스와 내 닉네임 RAREBEEF의 합성어이다.
로고도 이전에 직접 제작한 내 프로필 사진을 사용하였다.
강의 내용에 포함된 기능 외 공식 문서를 참고하여 프로필 사진, 닉네임, 비밀번호 변경, 회원 탈퇴 기능 등을 추가해 보았고 스타일은 모두 직접 작업하였다. 모바일 환경에서도 정상적으로 출력되도록 반응형으로 만들었는데, 실 테스트는 아이폰 환경에서만 진행했기 때문에 안드로이드에서 어떻게 보일지는 미지수.
프론트엔드를 독학하며 백엔드와의 협업 방식을 어떻게 공부할 수 있을지 조금 막막했었는데, 이번 프로젝트에 사용된 파이어베이스를 통해 어떤 식으로 작업이 이루어지는지 어느 정도 감을 잡을 수 있었다.
또 체계적인 컴포넌트 분리의 중요성과 그 방법에 대해 알 수 있었다.
참고로 이번 프로젝트가 내가 만든 것 중 최초로 DB와 통신하는 모양새를 갖춘 웹 어플리케이션이다.
백엔드로 구글의 Firebase를 사용했다.
사용한 기능은 아래와 같다.
로그인, 회원가입 등 사용자 인증 기능이다.
해당 기능을 통해 회원가입, 이메일 로그인 & 로그아웃, 소셜 로그인, 탈퇴, 비밀번호 재설정, 프로필 사진, 닉네임 등의 기능을 구현하였다.
SNS 기능의 핵심이 되는 데이터베이스이다. 유저가 글을 작성하면 이 데이터베이스에 정보가 업로드되며, 다른 유저가 실시간으로 글을 읽을 수 있다.
글 작성 시 데이터베이스에 저장되는 필드는 아래와 같이 구성하였다.
여기서 문제가 하나 있었는데, 글 작성 당시의 닉네임과 프로필 사진이 DB에 업로드되다보니 나중에 작성자의 닉네임과 프로필 사진이 변경되어도 이전에 작성한 글에는 변경 사항이 반영되지 않는 문제가 있었다.
따라서 작성자 정보에 변동이 생길 경우 작성자의 모든 글을 DB에서 찾은 뒤 변경 내용을 업데이트하도록 만들었다.
파일을 저장하는 스토리지 기능이다.
업로드한 사진을 저장하는 용도로 사용하였는데, 이 프로젝트에서 업로드되는 사진의 종류는 게시글 첨부 사진, 프로필 사진 두 가지가 존재한다.
사진은 업로드한 유저의 id를 이름으로 한 폴더 내부에 저장된다.
사진은 FileReader를 통해 data url로 변환 후 스토리지에 업로드하였고, 다시 불러올 때는 getDownloadURL()
메소드를 통해 접근 가능한 url을 받아온 뒤 <img>
태그의 src
값으로 할당하여 사용했다.
결론적으로 DB에 저장되는 profileImg 나 attachmentUrl 필드의 값은 getDownloadURL()
로 받아온 접근 가능한 url이다.
게시글을 삭제하면 첨부된 사진의 스토리지 데이터도 삭제된다.
또한 유저가 프로필 사진을 변경할 경우 스토리지에서 기존 프로필 사진을 삭제한 후 새로운 사진을 업로드되도록 하였다.
게시글의 작성자 정보가 상단으로 올라간다.
게시글 첨부 사진이 하단으로 내려간다.
스크린샷 화질이 조금 깨져보이는데 실제로는 멀쩡하다.
기본적인 다크모드 스타일은 css의 미디어 쿼리로 처리하였다.
그러나 미디어 쿼리만으로는 manifest.json 과 index.html 의 테마 컬러를 변경할 수 없기 때문에 다크모드와 라이트모드 간의 전환이 완벽하게 이루어지지 못한다. 특히 아이폰의 경우 다크모드로 전환해도 상단 노치 여백의 색상이 변하지 않고 밝은 색으로 남아있게 된다.
따라서 manifest.json 을 테마에 맞춰 두 개로 분리하고 index.html 에 아래의 스크립트를 추가하여 테마 모드 전환 시 manifest.json 의 경로와 index.html 의 테마 컬러를 변경할 수 있도록 하였다.
다크모드를 구현해 본 것은 처음인데, 생각보다 별게 없어서 다음 프로젝트부터는 왠만하면 다크모드를 추가할 예정이다. 따라서 다음부터는 다크모드 구현이 좀 더 쉽도록 버튼 등의 컴포넌트를 별도로 분리하고 색상 등의 속성값을 변수로 할당해 사용하는 것에 조금 더 중점을 두고 프로젝트를 진행하지 않을까 싶다.
<script>
const isDark =
window
.matchMedia("(prefers-color-scheme: dark)")
.matches || false;
const manifest = document.getElementById("manifest");
const themeColor = document.getElementById("theme-color");
function switchTheme(isDark) {
if (isDark) {
manifest.href = "%PUBLIC_URL%/manifest-dark.json";
themeColor.content = "#1d1d1d";
} else {
manifest.href = "%PUBLIC_URL%/manifest-light.json";
themeColor.content = "#f5f5f5";
}
}
window
.matchMedia("(prefers-color-scheme: dark)")
.addEventListener("change", (e) => switchTheme(e.matches));
switchTheme(isDark);
</script>
글 작성에 사용되는 input
의 placeholder
가 좁은 width
환경에서 잘리는 현상을 발견해서 문구를 짧게 수정하였다.
변경 전
"일상 공유하기 (최대 120자)"
변경 후
"일상 공유하기"
대신 최대 글자수와 현재 입력 글자수를 알 수 있도록 글자 수 카운터를 추가하였다.
글자 수가 초과되면 빨간색으로 변한다.
홈페이지 중앙에 나타나는 로고에 그림자를 추가하였다.