지난 1편에 이어 이틀 전 사전 프로젝트를 마무리한 시점에서 2편을 작성해 본다. 배운게 너무 많아서 어떻게 정리를 해야할지 모르겠지만 일단 하나씩 짧게라도 기록을 남겨본다. 최종편이 몇 편이 될 지는 나도 모름...😇
서버 쪽 배포 환경 유지가 아마 내일까지 밖에 안 될 거 같지만 그래도 남겨보는 배포 링크
https://seb42-pre-025-seb42-pre-025.vercel.app/questions
클릭하자마자 시선을 강탈하는 빨간 화면이 떠서 깜짝 놀라실 텐데요. 이에 대한 원인은 현재까지 파악하기로는 클론을 너무 똑같이 해서... 구글이 사기성 사이트로 필터링을 하고 있는 것으로 짐작 중입니다. (아닐 수도 있음 😇) 클론 과제를 성공적으로 해냈다는 증표로 삼기로 했습니다. (혼자 정신 승리)
왼쪽 하단 세부 정보 클릭 ➡️ 이 안전하지 않은 사이트를 방문을 클릭하면 사이트에 접속하실 수 있습니다. (해치지 않아요...)
1. response header에서 필요한 값 가져오기
서버가 보내주는 응답 헤더에서 location, jwt 토큰 등 필요한 정보에 접근하는 방법을 처음 배웠다. 가령 사용자가 새로운 게시글을 작성하고 등록하기 위해 서버에 post 요청을 보낸 후, 응답 헤더에 Location 값이 담겨올 때 location 값을 빼내서 해당 location으로 리다이렉션해주는 방식으로 코드를 작성했다.
const res = await postFetch(QUESTION_POST_URL, newData);
const location = res.headers.get('Location');
if (res) {
navigate(location);
}
로그인 기능의 경우, 사용자가 입력한 이메일과 패스워드를 서버에 post 요청으로 보내면 회원 DB에 있는 정보와 일치할 때 서버에서 ok 응답과 함께 access token과 refresh token을 응답 헤더의 Authorization과 Refresh에 담아 보내주기로 했다. 그래서 토큰 두 개를 tokens라는 상태에 담고 로그인 여부를 true로 처리해준 다음 리다이렉션을 해줬다.
const res = await postFetch(url, inputs);
const accessToken = res.headers.get('Authorization');
const refreshToken = res.headers.get('Refresh');
if (res.ok) {
setTokens({
accessToken,
refreshToken
});
setIsLoggedIn(true);
navigate('/questions');
}
처음에는 응답 헤더에 분명히 location이나 authorization이 있는데, 헤더 값에 접근할 수가 없었다. 스택오버플로우를 찾아보니 서버에서 access-control-expose-headers에 클라이언트에서 접근할 수 있는 항목을 설정해줘야했다.
참고로 서버의 access-control-expose-headers 설정 없이 헤더에 접근할 수 있는 값은 딱 네 가지 밖에 없었다.
console.log(...res.headers);
header 외에도 status code 등 서버에서 보내주는 다양한 데이터에 접근할 수 있었다.
📚 참고자료
모던 JavaScript 튜토리얼: fetch - 응답 헤더
2. html 태그 제거하고 text만 가져오기
게시판을 구현할 때 react-quill 라이브러리를 썼는데 그러면 사용자가 작성한 본문 입력값에 다음과 같이 html 태그가 같이 붙는다.
<p>text</p><p><strong>bold</strong></p><p><span style="color: rgb(255, 153, 0);">different</span> <span style="color: rgb(102, 185, 102);">color</span></p><p><br></p><pre class="ql-syntax" spellcheck="false">const arr = [1,2,3]
</pre>
이 때 태그를 제거하고, 사용자가 입력한 텍스트만 뽑아내기 위해 정규표현식을 찾아봤다.
const content = '<p>text</p><p><strong>bold</strong></p><p><span style="color: rgb(255, 153, 0);">different</span> <span style="color: rgb(102, 185, 102);">color</span></p><p><br></p><pre class="ql-syntax" spellcheck="false">const arr = [1,2,3]</pre>';
const text = content.replace(/(<([^>]+)>)/gi, '');
3. css로 ellipsis(말줄임표) 처리
위에서 html 태그를 제거하고 텍스트만 빼낸 이유가 질문 목록을 보여줄 때 본문의 앞 부분을 두 줄만 보여주고 그 나머지는 ... 처리를 하고 싶었기 때문이다. 이에 대한 css 코드를 다음과 같이 작성했다.
.contentBody {
height: 34px;
margin-bottom: 8px;
/* ellipsis */
line-height: 1.5;
max-height: calc(1.5 * 2); /* line-height * line */
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
4. confirm: 확인 / 취소 dialog
삭제 버튼을 눌렀을 때 사용자에게 정말 삭제할 것인지 한 번 더 되묻기 위해 confirm으로 대화 상자를 띄웠다. 요새는 모달 창을 더 많이 쓰는 추세지만만, 프로젝트에서 클론한 스택오버 플로우 사이트와 똑같이 confirm으로 구현했다. 질문과 답변 삭제를 하나의 함수로 처리했기 때문에 질문과 답변에 따른 분기 처리를 해줬다.
🔽 confirm을 사용할 수 있는 기본 코드
const result = confirm('Delete this post?');
if (result === true) {
console.log('확인 클릭');
} else {
console.log('취소 클릭');
}
🔽 실제 프로젝트에서 작성한 코드
const handleDelete = async (url) => {
const result = confirm('Delete this post?');
if (result) {
const res = await deleteFetch(url, accessToken);
if (res.ok) {
if (url.includes('questions')) {
navigate('/questions');
} else {
window.location.reload();
}
}
}
};
확인 버튼만 있는 alert, 사용자 입력값을 받을 수 있는 prompt와 함께 대표적으로 쓰이는 상호작용 기능인데, alert만 써보다가 confirm은 처음 써봤다.
5. github에서 commit history 별로 달라지는 코드를 볼 수 있는 방법
이번 프로젝트에서 여러 명과 github으로 작업을 처음 해봤는데, 중간에 파일이 꼬여서 commit 기록을 추적해 나가면서 해당 커밋 버전 별로 코드를 추적해 나가야했다. 이때 팀원 중에 한 분이 github-history.netlify.app 을 알려주셨는데 아주 유용했다.
방법은 아주 간단하다. 다음과 같이 깃헙 레포에서 추적하고자 하는 파일에 들어가서 주소창의 url의 github.com을 github-history.netlify.app으로 바꿔주면 아래 이미지와 같은 브라우저로 이동한다. 참고로 github.com에서 -history.netlify까지만 입력해주면 자동으로 .com이 .app으로 바뀐다.
6. 라이브러리 사용
게시판 에디터 구현을 위한 react-quill, 페이지네이션 기능을 위한 react-js-pagination, innerHTML 직접 주입에 대한 위험 부담을 방어하기 위한 dompurify 등 여러 라이브러리를 처음 사용해 봤다.
페이지네이션의 경우 직접 구현을 할 수도 있었지만 시간이 부족해서 라이브러리를 가져다 썼는데, 한정된 시간 내에 기능 구현을 해야 하는 프로젝트에서 적절한 선택이었다고 생각한다.
📚 참고자료
'배워서 남 주자' 카테고리의 다른 글
vercel 배포 브랜치 설정 (0) | 2023.03.16 |
---|---|
[TWIL] 사전 프로젝트를 하며 알게 된 몇 가지 - 최종편 (0) | 2023.03.05 |
[TWIL] 사전 프로젝트를 하며 알게 된 몇 가지 - 1편 (0) | 2023.02.25 |
eslint, prettier 설정 파일 세팅 (0) | 2023.02.19 |
[JavaScript] 경우의 수 구하기 (순열, 조합, 중복순열, 중복조합) (0) | 2023.02.12 |