Clone Twitter 🕊
-
React, Firebase, CSS, Github-pages
🕊 로그인 화면 : 이메일을 이용하여 로그인을 할 수 있는 것 뿐만 아니라, 구글과 깃허브 계정으로 연동되어 로그인을 할 수 있다. 인증하면서 발생하는 에러를 다루는 것은 아직 미숙해서 이메일과 비밀번호를 입력할 때 발생할 수 있는 에러는 '회원가입'과 '로그인' 사이에서 빨간색으로 경고가 뜰 수 있게 했고, 다른 서비스로 로그인 시 발생할 수 있는 에러는 alert을 이용해 사용자에게 알리는 방향을 택했다. 요즘 빠져있는 노랑색을 배경으로 삼았고, 트위터 하면 떠오르는 색상을 구글링을 통해 알아내서 포인트로 쓸 수 있는 곳에 썼다.
🕊 홈 화면 : 로그인을 하고 나면 이동할 수 있는 페이지. 이미지 업로드와 트윗 작성을 할 수 있고 사용자가 작성한 시간 순서대로 밑에서부터 위로 보인다. 각각의 트윗은 작성한 사용자의 이름과 이미지가 보이며 옆에는 작성한 시간을 볼 수 있다. 그리고 해당 사용자가 작성한 트윗의 경우 수정하고 삭제할 수 있는 기능이 보인다. 수정한 내용이 실시간으로 업데이트 되며 삭제하기 전에는 confirm이 다시 한 번 작동된다. 다른 서비스로 로그인하지 않고 직접 이메일과 비밀번호를 입력하여 로그인을 한 경우, 기본적인 이름과 이미지가 뜨도록 설정했다.
🕊 프로필 화면 : 해당 사용자의 현재 이름과 이미지, 그리고 자기소개가 보이며 그 밑으로는 홈 화면에서 사용자가 작성한 트윗이 보인다. 프로필을 수정할 수 있는데, 사용자의 이미지 옆에의 아이콘을 누르면 사진을 바꿀 수 있고 이름과 자기소개를 변경하고 난 뒤 '저장'을 누르면 실시간으로 프로필이 업데이트 된다. 그리고 로그아웃 버튼을 누르면 다시 로그인 화면으로 돌아간다.
배포한 뒤 발견한 버그 🐛
여러가지 아이디를 돌려가며 테스트를 했다고 생각했는데 배포하기 전에 발견하지 못한 버그였다. 실제 배포를 하고 난 뒤에 다른 사람이 들어와서 트윗을 올렸을 때 내 아이디와 사진이 똑같에 보여서 이상하다고 생각했는데 다른 사람이 작성한 트윗에도 로그인한 사용자의 이름과 이미지가 보이는 버그가 있었다. 로그인을 하고 난 뒤의 사용자의 정보를 컴포넌트로 전달하고 이를 트위터를 출력하는 곳에서도 그대로 사용한 게 원인. 그래서 아예 트위터를 작성할 시에 사용자의 이름과 이미지를 저장해서 이걸 출력하는 걸로 바꿨더니 버그는 수정됐다.
노마드코더에서 진행하는 트위터 클론 챌린지가 있어서 참여했고, 배포까지 완료를 했다. 이번 강의를 듣고 서비스를 구현하면서 백엔드를 잘 알지 못해도 구글에서 제공하는 파이어베이스를 이용해서 만들어 볼 수 있구나를 알았다. 또 이미지를 url로 변환하는 작업이 흥미로웠다.
트위터에서 하트 누르는 기능을 구현하고 싶었는데 여러가지 로직을 짜서 시도를 해 봐도 원하는 대로 실행되지 않아서 그 부분을 삭제했다. 일단 좋아요 기능을 구현하려면 현 사용자인지 확인을 하고, 한 번만 누르거나 취소할 수 있도록 해야하는데 이걸 어떻게 해야할 지... 조금 더 많이 고민을 해 봐야 하는 부분이다. 그리고 프로필 화면에서 사용자의 이미지와 이름을 수정하고 자기소개 넣는 부분을 구현하고 싶었는데 그 부분은 했으나, 사용자 본인이 쓴 트윗을 직접 수정하는 기능까진 어떻게 해야 좋을 지도 잘 모르겠더라. 사실 코드를 쓰고 나서 지저분한 거 같아 리팩토링을 한 번 더 해야 겠다. 스타일링은... 무턱대고 시작한 거라 재사용을 거의 하지 않았고 그래서 시간이 엄청 걸렸다. 스타일링에 대한 전반적인 구도를 잡고서 시작했으면 더 좋았을 것 같고 CSS가 아닌 SCSS를 이용해서 했으면 조금 더 수월하게 작업을 할 수 있었을 것 같은 아쉬움이 남는다. 이번에 스타일링을 하면서 구글링을 여러 번 했는데 스크롤바 색상을 바꾸는 것, input에 커서의 색상을 변경하는 것, 그리고 placeholder를 스타일링하는 걸 찾아봤다.
사용자가 클릭한 링크를 구별할 수 있도록 바닐라 자바스크립트 이벤트 기능을 썼다. 궁금한 건 이걸 리액트 방식으로 코드를 짤 수 있나 싶은 것. 리액트가 자바스크립트 라이브러리이기 때문에 바닐라 자바스크립트로 코드를 써도 작동은 하는데 다른 방식으로도 가능할까. 리액트 훅을 쓰려나...
강의를 듣고 나서 챌린지에 빨리 참여하고 싶단 생각에 조금 더 열심히 문서를 들여다 보지 않았다. 또 스타일링을 급급하게 시작해서 끝내려하다 보니 배포하기 전에 버그를 잡지 못했고 오히려 재사용할 수 없는 코드를 썼다. 그래서 이번 챌린지를 통해 깨달은 건 처음에 시작할 때 무작정 나무를 보기 보단 숲을 봐서 큰 그림을 그려보자. 구성을 어떻게 짤 것인지, 재사용은 어떻게 할 것인지 더 많은 고민을 하고 계획을 세운 다음에 작업을 할 것.
+ 개선해야 할 점과 앞으로 더 구현하고 싶은 것
- CSS 대신 Sass로 작업하기 / CSS-in-JS에도 관심이 많아서 Styled Component나 tailwind CSS도 궁금하다.
- 트윗에 하트 표시하기
- 사용자의 프로필에서 사용자 본인이 작성한 트윗 수정 및 삭제하기
- UX가 나쁘지 않도록 에러 다루기
파이어베이스를 이용한 트위터 클론을 해보고 싶으신 분은 노마더코더에 관련 강의가 있으니 참고해주세요 😎
트위터 클론코딩 - 노마드 코더 Nomad Coders
https://nomadcoders.co/nwitter/lobby
포스팅 작성 후 추가한 기능
🕊 프로필에서 사용자 본인의 트윗 목록을 볼 수 있으며, 수정 및 삭제 또한 가능 : 프로필에 들어가서 본인이 작성한 트윗을 수정하고 삭제할 수 있게 하고 싶었다. 수정, 삭제 기능만을 따로 옮겨서 구현할 수 없을까 고민을 했는데 그러면 state가 달라지고 조건을 같게 만들 수 없어서 어떻게 해야할까 고민... 그런데 이건 생각보다 간단하게 해결할 수 있는 문제였다. 홈 화면에서 보이는 트위터 목록의 컴포넌트를 프로필 화면 자체로 가져와서 파이어베이스에서 제공하는 기능 중 하나인 필터 기능(order by)로 트윗을 쓴 사용자와 프로필 화면을 보는 사용자의 아이디가 일치하는 지만 확인하는 코드를 넣어주니 됐다. 그리고 사진이 너무 작게 보이는 걸 수정했다. 그래도 사진을 올리는데 너무 작게 설정해놓은 거 같아 작성한 트윗 밑에 사진이 보이도록 수정함.
- 반응형이 되도록 CSS 수정
- UI 디자인 수정
- 각 트윗마다 하트 누르기 및 하트의 개수 표시
- 트윗을 작성한 사용자의 이미지를 클릭했을 때 해당 사용자의 프로필과 트윗 목록을 볼 수 있도록 함
각 트윗마다 하트를 누를 수 있고 트윗을 작성한 사용자의 이미지를 클릭하면 그 사용자의 프로필로 이동하게끔 하는 기능까지 구현 -! 작성한 트윗의 사용자의 프로필로 렌더링될 때, 잠시 로그인한 사용자의 이미지와 이름이 뜨는 건 안 보이게 할 수 없나. 이건 또 어떻게 수정을 해야하나...
🕊 각 트윗마다 하트 표시 : 하트 누를 수 있는 거 고민을 되게 많이 했다. 여러가지 로직을 생각했지만 한 가지만 염두해두고 코드를 쓰니까 됐다. 트윗을 새롭게 만들어서 서버에 보낼 때 'likeUsers' 라는 배열을 만들어서 그 배열에 로그인한 사용자가 하트를 눌렀는지 안눌렀는지를 Booleans으로 확인을 하고 이게 true면 채워져 있는 하트로, false면 비워져 있는 하트로 보여준다. 그리고 하트를 누를 때 이벤트가 발생한다. likeUsers가 true면 해당 사용자를 배열에서 빼고, false면 배열에 다시 추가하는 로직을 작성했더니 구현이 되었다.
// Home.js에서 Tweet.js 컴포넌트에 props으로 줄 때
<div className="TweetList">
{tweetList.map(tweet => (
<Tweet
key={tweet.id}
tweetObj={tweet}
isOwner={tweet.creatorId === signedInUser.uid}
likedUser={tweet.likeUsers?.includes(signedInUser.uid)}
userId={signedInUser.uid}
/>
))}
</div>
// Tweet.js
const onHeartClick = async () => {
if (likedUser) {
const filterUsers = tweetObj.likeUsers.filter(user => user !== userId);
await updateDoc(doc(dbService, `tweets/${tweetObj.id}`), {
likeUsers: filterUsers
});
}
if (!likedUser) {
await updateDoc(doc(dbService, `tweets/${tweetObj.id}`), {
likeUsers: [...tweetObj.likeUsers, userId]
});
}
};
🕊 홈에서 트윗 작성자의 사진을 눌렀을 때 해당 작성자의 프로필 및 트윗 목록을 볼 수 있음 : 그리고 트윗을 작성한 사용자의 프로필과 목록을 보여주는 것. 이건 react-router-dom과 관련된 것이었다. '/' 다음으로 사용자의 uid를 받아서 이를 url에 표현되도록 하는 거였는데, 아무리 검색하고 문서를 읽어봐도 어떻게 감도 안 옴... 한 번도 구현해본 적이 없는 기능이라 어떻게 해야할 지 몰랐던 것 뿐, 한 번 구현되는 걸 알고 나니 그리 어려운 건 아닌데 솔직히 아직도 잘 이해는 가지 않는다. Route path="/:uid"를 주고 그 하위요소로 Profile을 주었는데 이 Profile 컴포넌트에서 usePrams()를 쓰니까 되네...? 그래서 트윗 목록의 쿼리를 배열하는 규칙을 정할 때 로그인한 사용자가 아닌, 트윗을 작성한 사용자의 uid로 정렬할 수 있도록 하니 다른 컴포넌트를 만들지 않고서도 원하는 기능이 구현되었다.
// Router.js
<HashRouter>
<Switch>
.
.
<Route path="/:uid">
<Profile
signedInUser={signedInUser}
refreshUser={refreshUser}
/>
</Route>
.
.
</Switch>
</HashRouter>
// Profile.js
import { useParams } from 'react-router';
const Profile = ({ signedInUser, refreshUser }) => {
const { uid } = useParams();
.
.
};
+ Udemy에서 Modern React with Redux 강의를 듣다가 이와 관련된 부분이 나와서 포스팅을 덧붙인다. Route path에 ':uid'라고 쓸 수 있는 이유는 이것이 react-router-dom에서 나온 것이기 때문이다. 콜론 뒤에 uid가 아닌 다른 단어를 붙이고 useParams을 써서 콘솔로 보면 콜론 뒤의 단어가 보이는 걸 알 수 있다. 이게 어떻게 발생돼서 운영이 되는건지 몰랐는데, 라이브러리로 react-router-dom을 썼기 때문에 가능한 것. '/' 뒤에 콜론은 url에서 변수의 이름을 붙일 수 있는 용도라고 생각하면 될 듯.
'Front End > Toy Project' 카테고리의 다른 글
리액트 Waveyy (0) | 2021.11.16 |
---|---|
VanillaJS Momentum (0) | 2021.10.04 |
[Hello WM] Responsive Web (0) | 2021.08.09 |
[Hello WM] Media query (0) | 2021.08.06 |
[Hello WM] Section Artists (0) | 2021.07.21 |
댓글