9주차
기간:
24.08.12 ~ 24.08.18
요약 3줄
- 새 출발을 앞두고 기대반 설렘반 두려움반으로 보냈던 한 주
- 화요일이 마지막 근무일이었는데 월요일까지 하던 프로젝트를 마무리 하느라 정신 없이 퇴사한 기분
- 이번 주차 일일 챌린지 모두 클리어가 목표였지만... 거제도 여행 후 피곤함에 마지막 하나를 제출 못 해서 아쉬웠다ㅠㅠㅠㅠ
이번주 목표
- 일일 강의, 일일 챌린지, 일일 스프린트 전부 완료하기
- 주간 회의록 작성하고 8월 18일(일) 17시까지 제출하기
결과
여행 후 일일 챌린지를 제출하려고 고군분투하다가 결국 주간 회고록을 제 때 제출하지 못했다ㅠ 그동안 회고록은 기한 내에 잘 내고 있었는데 아쉬웠다. 10주차 회고록과 함께 제출 해야지!
그리고 이번주 챌린지를 올 클리어하려고 거제도 여행지에서도 카페에 가서 강의 듣고 퀴즈 풀이를 했는데 아쉽게도 마지막 과제를 제출하지 못했다ㅠ 여행 피곤함과 다음날 첫출근이라는 부담감으로.... 안타깝게 포기했다ㅠㅠㅠ 환급 결과는 어떻게 될지 모르겠지만 끝까지 마무리 하는데에 의의를 두자!!!
일일 스프린트
🔽 2024/08/12 월요일
내일 저녁 회식이 있으니 오늘 코드 챌린지 제출까지 끝내버리자!!!!!⚡️
[⚠️] 캐럿마켓 클론코딩: From #10.0 to #10.10 강의 듣기
[⚠️] 코드 챌린지
[✅] 아이유 콘서트 티켓팅 (성공)
🔽 2024/08/13 화요일
마지막 근무🥸 마음이 싱숭생숭
[✅] 캐럿마켓 클론코딩: From #10.5 to #10.10 강의 듣기
[✅] 코드 챌린지 제출
[✅] 송별회 겸 회식
[✅] 마지막 마무리 잘하기!
🔽 2024/08/14 수요일
원래 쉬는 날이 더 바쁜 법~~ 밀린 개인 일정들 뿌샤뿌샤
[✅] 캐럿마켓 클론코딩: From #11.0 to #11.9 강의 듣기
[✅] 코드 챌린지 제출
[✅] 채용건강검진 검사
[✅] 입사 서류 준비
[✅] 여권 사진 촬영
[✅] 엄마랑 저녁
[✅] 여행 짐싸기
🔽 2024/08/15 목요일
거제도 여름 휴가 1일차~ 일일 퀴즈는 포기할 수 없쥐ㅎ_ㅎ
[✅] 거제도 여행 1일차
[✅] 캐럿마켓 클론코딩: From #13.0 to #13.12 강의 듣기
[✅] 일일 퀴즈 제출
🔽 2024/08/16 ~ 2024/08/17 금요일, 토요일
[✅] 거제도 여행 2~3일차
🔽 2024/08/18 일요일
[✅] 캐럿마켓 클론코딩: From #14.0 to #14.5 강의 듣기
[❌] 코드 챌린지 제출
[✅] 여행 짐정리
[❌] 9주차 주간회고록 작성 및 제출
이번주 강의 요약
새롭게 알게 된 것 :
1. 네비게이션 바
- app/(auth) 폴더 생성해서 옮겨주기!
- 인증을 목적으로 하는 페이지 넣어주기 (Ex: login, create-account 등등)
- 괄호를 사용한 네이밍은 URL에 전혀 영향이 없다!
- URL 변경 없이 grouping 할 수 있는 방법
- app/(tabs)
- User가 갈 수 있는 모든 페이지!
- (tabs) 폴더 안에 layout을 만들면 auth 폴더에는 영향을 주지 않는다.
import TabBar from "@/components/tab-bar";
export default function TabLayout({ children }: { children: React.ReactNode }) {
return (
<div>
{children}
<TabBar />
</div>
);
}
2. Skeletons
- loading state를 위한 skeleton
- skeleton은 로딩 중일 때 보여주는 component라고 생각하면 된다.
3. Product Component
<Image width={200} height={200} src="/goguma.jpg" alt="고구마 사진" />
- Image 태그는 우리의 이미지를 최적화 시켜준다.
- 이미지 크기를 잘 모를 땐 w & h 대신 fill을 쓰기도 한다.
- 부모 엘리먼트를 이미지로 가득 채운다.
- 이미지의 position: absolute된다! → 부모의 속성을 position: relative로 바꿔주고 사이즈를 지정해주면 원하는 사이즈로 지정이 가능하다.
- 이미지에 border-radius를 주려면 부모 속성에 주고 overflow: hidden 처리해야한다!
1) Lazy load
- 이 이미지는 유저가 보고 있는 동안에만 load(download)된다는 뜻
- 백만개의 이미지가 있으면 브라우저가 그 image를 전부 다운로드 하지 않게 한다.
2) srcset이 설정
- srcset은 다른 이미지를 보여줄 수 있도록 허용하는 속성이다.
- style=”color: transparent”는 로딩 되기 전에는 투명한 박스로 보여진다는 것이다.
- 이미지 크기를 잘 모를 땐 w & h 대신 fill을 쓰기도 한다.
- 부모 엘리먼트를 이미지로 가득 채운다.
- 이미지의 position: absolute된다! → 부모의 속성을 position: relative로 바꿔주고 사이즈를 지정해주면 원하는 사이즈로 지정이 가능하다.
- 이미지에 border-radius를 주려면 부모 속성에 주고 overflow: hidden 처리해야한다!
3. Utils
// getTime은 Unix Epoch(1970년 1월 1일 자정) 이후의 밀리초를 제공한다
new Date().getTime()
// 원화 변환
export function formatToWon(price: number): string {
return price.toLocaleString("ko-KR");
}
// N일전 처리
export function formatToTimeAgo(date: string): string {
const dayInMs = 1000 * 60 * 60 * 24;
const time = new Date(date).getTime();
const now = new Date().getTime();
const diff = Math.round((time - now) / dayInMs);
// -3을 '3일전' 형태로 변환해주는 라이브러리
const formatter = new Intl.RelativeTimeFormat("ko");
return formatter.format(diff, "days");
}
3. Product upload
- React Hook Form은 React에서 form을 만들고 검증하는 아주 인기 있는 라이브러리이다.
- Next.js 캐시를 사용하면 database의 응답을 cache에, 즉 서버 메모리에 저장할 수 있다.
- response를 재사용한다는 뜻으로 유저가 제품을 요청할 때 database에 다시 접속할 필요가 없다. cache에 이미 저장되어 있는 이전 response를 사용하면 된다.
- for가 input의 id와 같으면 label을 클릭할 때마다 input이 focus된다!
<label
htmlFor="photo"
className="border-2 aspect-square flex items-center justify-center flex-col text-neutral-300 border-neutral-300 rounded-md border-dashed cursor-pointer"
>
<PhotoIcon className="w-20" />
<div className="text-neutral-400 text-sm">사진을 추가해주세요.</div>
</label>
<input
onChange={onImageChange}
type="file"
id="photo"
name="photo"
accept="image/*"
className="hidden"
/>
- 유저들에게 업로드된 파일을 보여주고 싶을 때 브라우저에 있는 URL.createObjectURL을 사용
- 우리 브라우저에만 존재하고 다른 사람들은 볼 수 없다! 그 URL은 이 파일이 업로드 된 메모리를 참조한다.
- 이 API를 URL을 리턴해주는데 오직 사용자만 볼 수 있는 링크이다. 새로고침하면 링크가 만료된다.
4. Optimistic Updates
- prisma의 update 메소드는 database안의 record를 수정하고 나서, 수정된 record를 return해준다.
- post를 update해서 조회수를 올리고 update method가 그 post를 return해준다.
- update method는 필요한 게 세 가지 있다.
- 업데이트할 record가 무엇인지 나타내는 where
- 어떻게 업데이트 할지 나타내는 data
- update method는 업데이트할 post를 찾지 못하면 에러를 발생시킨다! → 전체가 터지는 걸 막기 위해 try, catch로 잡아준다.
async function getPost(id: number) {
try {
const post = await db.post.update({
where: {
id,
},
data: {
views: {
// 사칙 연산을 위한 atomic operation이 있다. 현재값을 모르더라도 계산 가능
increment: 1,
},
},
include: {
user: {
select: {
username: true,
avatar: true,
},
},
_count: {
select: {
comments: true,
likes: true,
},
},
},
});
return post;
} catch (e) {
return null;
}
}
- dislike는 로그인한 유저가 만든 like를 삭제하기만 하면 된다!
- like를 여러번 누르면 error가 뜨기 때문에 try, catch로 잡아줘야 한다.
4-1. Cache Tags
- 클릭할 때 마다 경로를 revalidate하기 때문에 페이지 전체가 재실행 된다. 재실행되며 조회수 또한 올라가는데 이건 올바르지 않다.
- caching을 이용하여 확인할 것! post를 cache하고 like개수와 isLiked 여부로 cache할 것!
- revalidateTag시 전체 like-status를 저장하면 모든 post의 like가 저장되는 것이다! (절대 안 됨)
- 캐시할 post id를 꼭 넣어서 해당 post like status만 revalidate 해야한다!
4-2. useOptimistic
mutation이란 유저가 데이터를 보내주면 우리는 거기에 맞게 데이터베이스를 수정해서 보여주는 것. 유저가 우리 백엔드에 있는 리소스를 변형하는 것이다. 유저가 mutation을 trigger하면 우리에겐 두 가지 옵션이 있다.
1) mutation이 완전히 끝날 때까지 그냥 기다리는 것. mutation 진행 상황을 알려주면서(Ex: 회원가입 완료 버튼 눌렀을 때 버튼을 disable하고 회색으로 표시 했던 것)
- 계정을 생성하는 종류의 mutation은 결과가 나올 때까지 그대로 기다리는 수밖에 없다. 결과가 에러일 수도 있기 때문에!
2) 유저에게 optimistic response를 먼저 주는 것. optimistic response는 마치 백엔드에서 mutation이 성공한 것처럼 UI를 수정하는 것이다.
- 게시물 like/dislike mutation의 경우는 굳이 백엔드에서 mutation이 다 끝날 때까지 기다릴 필요가 없다. 1번 mutation보다 훨씬 덜 중요하다.
- useOptimistic hook을 사용해 편하게 처리할 수 있다! useOptimistic은 UI를 낙관적으로 업데이트 할 수 있는 react hook이다.
useOptimistic은 두 개의 파라미터가 필요하다.
1) 첫번째는 mutation이 발생하기 전에 유저에게 보여주고 싶은 initial 데이터
- 서버에서 보낸 데이터
2) 두 번째는 이 initial data를 수정하는 함수가 들어가야 한다.
- useState와 비슷한 구조
const [state, reducerFn] = useOptimistic({isLiked, likeCount}, (previousState, payload) => {
// return 값은 초기 데이터와 형식이 같아야 한다!
// 반드시 새 데이터를 return 해줘야 한다!
return {
isLiked: !previousState.isLiked,
likeCount: previousState.isLiked ? previousState.likeCount - 1 : previousState.likeCount + 1,
}
});
const onClick = async () => {
// 필요하면 여기에 payload를 넘겨서 사용할 수도 있다.
reducerFn(undefined);
if(isLiked) {
await dislikePost(postId);
} else {
await likePost(postId);
}
}
주간 회의와 조별 활동
이번주 활동:
-
기억에 남는 것:
-
칭찬하고 싶은 점
- 저녁 일정을 고려하여 미리 강의를 듣고 과제를 한 것
- 일몰이 아름다웠던 거제도 카페에서 강의를 듣고 퀴즈를 푼 것 (새로운 경험이었다^_^)
고치거나 버려야 할 점
- 제출에 초점을 두다 보니 퀄리티가 떨어진 부분이 아쉬웠다... 코드에 대한 깊은 고민 없이 구현하기 급급했던 것 같다. 일과 동시에 스터디도 잘 해내시는 분들은 진짜 대단한 것 같다ㅠㅠ 아직 개발에 대한 깊이가 부족한 것 같기도하고... 부족함은 언제나 잘 느껴진닿ㅎㅎㅎ
'Frontend' 카테고리의 다른 글
노마드스터디 리액트 10주 5기 10주차 주간회고록 (1) | 2024.08.26 |
---|---|
노마드스터디 리액트 10주 5기 8주차 주간회고록 (0) | 2024.08.09 |
노마드스터디 리액트 10주 5기 7주차 주간회고록 (0) | 2024.08.04 |
노마드스터디 리액트 10주 5기 6주차 주간회고록 (0) | 2024.07.26 |
노마드스터디 리액트 10주 5기 5주차 주간회고록 (0) | 2024.07.19 |