12.31 - twinter cloneCoding 5

hun2__2·2021년 12월 31일
0

Have a fruitful vacation

목록 보기
5/24
post-thumbnail

먼저 어제 끝낸 storage에 대한 정리를 해보자면
firebase의 다른 기능들과 마찬가지로 storage도 firebase에서 받아와 export를해줘야한다.

input의 type을 file로하여 파일을 받을 수 있도록 하고 (accept속성으로 받을수 있는 파일을 제한 할 수 있다)

파일을 받아 target.files를 보면
이와같은 정보를 반환한다. 하지만 여기에는 값을 출력할 수 있는 경로가 없다. 이는 웹상의 보안을 위해 상세경로를 숨겨놓는다. 이를 위해 브라우저 API인 FileReader 객체를 사용할 것이다.
FileReader 안에있는 readAsDataURL응 이용하여 파일 위치Url을 얻을 수 있는데 이 함수는 react 생명주기처럼 '웹 브라우저가 파일을 인식하는 시점', '파일 인식이 끝난 시점'에 따라 다르게 작동한다.
인식하기 전 받아오려한다면


undefined 값과 error message가 뜰것이다.
따라서 onloadend를 사용하여 이벤트 읽기 동장이 끝나고 readAsDataURL()이 작동하도록 구현해야한다.

(참고 : https://developer.mozilla.org/ko/docs/Web/API/FileReader)

이제 url을 받아올 수 있으니 useState로 새로운 상태값을 하나 만들고 url을 넣어준다

여기에 attachment를 초기화시켜주는 함수도 만들어 취소 버튼도 만들어준다ㅎ

이제 미리보기는 가능하지만 아직 firebase storage에는 저장하지 못했다.

먼저 export했던 firebase/storage를 import하고 이전에 구현했던 create를 해주는 onSubmit에서 만약 파일이 선택되었다면 storage에 파일도 같이 create하도록 해준다. 이를 위해 firebase.storage에 .ref().child([유저id/파일id])를 넣어줘야하는데 collection([컬랙션이름]).add()할 때와는 다르게 자동으로 id를 생성해주지 않는다 따라서 우리가 고유 식별자로써 id를 생성해야한다.
yarn add uuid로 먼저 모듈을 다운받아주고
고유 식별자를 만들어주는 라이브러리인 UUID를 사용하여 파일id에 uuid로만든 id를 넣어준다.

이제 pustString을 이용하여 위에서 받아온 사진의url을 attachment에 저장했으니 storage.ref().child([유저id/파일id])에 넣어주면 storage에 업로드되고 받아올때는 getDownloadURL()함수를 사용해서 url를 받아올 수 있다.


이제 이 정보를 submit할때 같이 넣어주었으니 read해올때 사진이 보일 UI를 만들어주면


잘 작동된다!

트윗을 삭제할 때 사진도 같이 삭제 되도록 delete쪽에 코드를 수정해줘야하는데 파일을 삭제하기 위해서는 파일의 URL이 아닌 storage내에서의 파일의 위치를 알아야 한다. 이를 위해 firebase에서 제공하는 함수인 refFromURL을 사용하여 delete()해준다

이렇게 storage를 사용한 사진 업로드와 삭제까지 완료되었다.

다음으로 필터링 기능을 추가해 줄 것이다.

먼저 Profile에서 로그인한 사용자의 정보를 보여주기위해서는 userObj를 props로 받아와야한다.

그리고 dbservice에 있는 createorId 정보와 유저id를 비교하여 같은 아이들만 선택하는 쿼리문 작성이 필요하다 하지만 예전에 말했는 friebase는 NoSQL로 SQL쿼리문 없이 쿼리와 같은 기능이 있다 먼저 뭔가를 찾아주는 함수인 where(값, 비교, 비교값)을 이용하여 createorId와 userObj.uid가 같은 트윗만 필터링한다.

sql에서 정렬을 사용한것 과 같은 기능도 제공되는데 orderBy(기준, 순서)를 이용하면 된다.

이렇게 정렬된 값을 출력해보면

어림없지 error가 난다.
error코드를 보면 옆에 링크타고가서 뭔갈 만들어야 된다고 한다. firebase에선 제공하는 db관련 함수중에 아직 firebase에서 받아들일 준비가 되있지 않으면 사용할 수 없다. orderBy를 사용하기 위해서는 먼저 firebase의db에 복합색인을 설정해줘야한다.

색인작업까지 끝나면 이제 console.에서 정보를 다시 확인해보고 firebase에서 시간을 변경하여 필터링이 잘 되는지 확인한다!!

이제 필터링된 트윗들을 profile page에서 순서대로 보여준다.

cf) 오름차순보다 내림차순이 더 좋은것 같아서 바꿨다

다음으로 프로필페이지에 유저이름을 변경하는 기능을 추가할 것이다.
먼저 유저 이름이 사용되는 곳을 navigation의 profile link이름이있다. (나중에 스타일링하면서 더 필요한 것을 찾아볼 것) 아직 createAPI를 사용하지 않고있기 때문에 profile에서 user의 정보를 사용하려면 처음 user정보를 생성하는 App부터 App - router- profile 순으로 모두 props를 넘겨줘야한다. 이러한 과정을 거쳐서 user의 이름이 담긴 속성인 displayName을 수정한다고 하면 리렌더링시 이름이 바뀌어야 하지만 안 바뀐다...

왜냐하면 react의 한계중 하나인 상태값이나 prop의 내용물이 너무 많으면 그 안에 작은 변화는 인식 못하는 경우가 발생한다.
App.js에서 생성한 user객체에는 너무 정보가 담겨있다
(출처: https://firebase.google.com/docs/reference/js/v8/firebase.User?hl=ko%2Fjs%2Ffirebase.User)
그러므로 우리가 사용하는 id, displayName, updateProfile만 따로 빼서 객체를 만든 후 넘겨주는 식으로 변경해야한다. 따라서
App.js에서

로 userObj를 새로 생성해주고

로 현재 유저정보로 userObj를 업데이트해준다
그리고 router로 넘겨주는 userObj객체를 변경해준 후

다시 router에서 profile.js로 userObj객체를 넘겨주고
profile에서 유저정보를 업데이트해주면

완성!!!

이제 실시간으로 변경된다ㅎㅎㅎ

책에나와있는 clone coding기능구현이 끝났으니
코드 정리좀 하고 베포후 스타일링을 시작할꺼다ㅎㅎ

마지막으로 코드 정리를 하며 보안문제를 해결하고 스타일링은 따로 빼서 작성해야겠다.

먼저 베포하기전에 간단한 리팩토링을 진행했다. 한 파일에 너무많은 정보가 있어 가독성이 떨어지므로 componenet로 나누었다.
Home.js, Winter.js에 들어가있는 CRUD기능을 모두 componenet로 바꾸었고 Auth.js에 있는 회원가입과 소셜로그인을 나누었다.
조금 더 react스러워졌달까..?
ㅋㅋㅋ

이제 github를 이용하여 베포할 것이다 gh-pages를 이용하면 간단하게 베포할수 있다 먼저

yarn add gh-pages

를해주고
package.json안에
"homepage" : "https://[깃허브아이디].github.io/[레포이름]",
을 추가해주고
디버그부분에
"predeploy": "npm run build",
"deploy": "gh-pages -d build"
를 추가해준다.

그럼 준비 끝.

이제 베포시작!

yarn run deploy

완료가 되어도 github 서버에서 받아들이는 시간이 필요하기 때문에 바로 안들어가 질 수 있다. 당황하지말고 기다리면서 다음작업을 하자.

localhost에서는 소셜로그인이 잘 작동했지만 베포한 url로 들어가면 안 될 것이다. 그 이유는 firebase보안 정책때문이다.
firebase authentication의 sign-in method에 등록되어있는 도메인만 인증 권한을 주기 때문이다.
베포된 페이지url을 추가해준다.

firebase의 db, storage를 사용할때도 보안 정책을 신경써줘야하는데 firebase database -> 규칙에 들어가보면
문서를 보며 확인할 수 있다.
default로 데이터베이스 접근기한과 누구나 db에 접근할 수 있게 되어있다. 접근 기한을 없애고 로그인한 사람에게만 권한을 주기 위해

이와같이 수정할 수 있다.
(참고-허용항목 : https://firebase.google.com/docs/rules/rules-language?authuser=1)

storage도 동일한 방법으로 진행하면 되는데 여기는 건들게 없었다.

다음으로 비밀키 보안을 설정해준다.
처음에 비밀키를 github에 노출시키지 않기위해 작업을 했었다 하지만 원한다면 찾을 수 있는 위치에있다.. 비밀키를 알게되어도 다른 도메인에서 작동하지 안도록 하기 위해 google cloud platform에서 설정해준다.
먼저

프로젝트 개요-> 프로젝트 설정에 들어가서


서비스 계정 옆 화살표를 눌러준다.
그러면 google cloud platform에 firebase 프로젝트가 등록된다 그리고 좌측 상단을 눌러 api및 서비스 -> 사용자 인증 정보에 들어간다.

경고 표시가있는 api키에 들어가서

애플리케이션 제한사항과 웹사이트 제한사항을 아래와같이 수정한다.
(웹사이트에 localhost, firebase url, gh-page url을 추가)

이렇게 해주면 다른 도메인에서 비밀키를 사용할 수 없다.

ps. 보안까지 끝나고 책에 있는 모든 기능을 맞췄다... 근데 뭔가 부족,,, 내가 원하는 기능들을 추가하는게 더 하고싶어서 style은 그냥 책에있는거 베끼기로했다ㅎㅎ 사실 귀찮
리팩토링하는 부분에서 코드가 좀 달라져 styled도 변경해줘야했지만 styled-components를 사용하여 잘 마무리 되었다.
한가지 알게된 점은 책에있는 css대로 하려고했지만 react-router-dom 버전이 다른 탓인지 책에는 switch문 안에 div로 스타일을 줄 수 있었지만 v6에서 변경된 Routes에서는 안에 와 <React.Fragment>만 사용가능하다고 한다 그래서 를 감싸는 container를 만들어 해결했다.스타일링좀 이쁘게해보려고 이것저것 설치했지만... 기능구현 우선,,,, react JS강의를 들으면서 공부좀하고 DBzara 와 함께 리팩토링하면서 기능 추가를 해야겠다!
이거하다 올해 마지막 날이 끝나간다ㅎㅎ 이제 가족들과 올해 마지막시간을 보내고 새해를 맞이하러가야겠다
안뇽~~😁

profile
과정을 적는 곳

0개의 댓글