- While they're alley fighting, where does that leave us? - It leaves you head down, eyes forward, doing good work earning returns for the firm or the bank, as the case may be. As the case may be : 경우에 따라, 임기응변으로.
-He'll come up with a workaround. Like he has in the past. Come up with : (해답·돈 등을) 찾아내다[내놓다]
-So was his getting out ahead of it with a press conference part of the plan? -These things are fluid. Get out ahead : to have an advantage over the people you are competing against ex) The way to deal with the pressure is to get out ahead.
11.0 Product Model hot reloading을 하면 일종의 서버 재시작이 돼서 PrismaClient가 계속 new로 생성됨. DB에 커넥션 리밋이 있음. Planet Scale에 리밋이 있을 것이다. 좋지 않은 것이니. 고쳐
항상 다음 순으로 한다. Model 생성 -> data base 수정 -> mutation -> 데이터 가져오기
Model 생성
model Product {
id Int @id @default(autoincrement())
created DateTime @default(now())
updated DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int
image String
name String
price Int
description String @db.MediumText
@@index([userId])
}
useSWR로 data와 mutate를 받을 수 있다. mutate()의 처음 인자는 변경할 데이터, 두번째 인자는 해당 API를 재 호출 할지 선택하는 옵션이다. default는 true. 첫번째 mutate함수 처럼 사용하면, 기존의 swr 캐에 저장된 data가 인자 {product:{name:"potato"}}로 치환 되기 때문에 화면에 potato 관련 정보만 보이고 나머지는 다 날아가버린다. 그래서 두번 째 mutate처럼 써야한다. 원래 data를 전개해서 넣고, product안을 수정하는데 product에서도 나머지는 전개해서 넣고, name만 바꾼다.
이건 그냥 자바스크립트 문법.
다음 처럼 하면 favorite이 Optimistic UI Update 되는거야. 캐시만 변경하는거지. mutate({ ...data, isLiked:!data.isLiked }, false);
두번째 인자가 false니까 다시 api 불러오지 않게 그리고 주석처리 된 toggleFave({})도 주석풀어야 실제 API콜이 될테니까. 최종본
그럼 왜 bound냐? 왜 bound mutation이냐? useSWR로 받아온 mutate와 짝지어진 데이터만 변경 가능해서. 다른 request로 받은 놈의 cache도 바꾸고싶다? 다른 화면의 다른 요청의 cache를 바꾸고싶다? unbound mutation !!
11.9 Unound Mutations
import useSWR, { useSWRConfig } from "swr"; const { mutate } =useSWRConfig(); mutate("/api/users/me", (prev) => prev && { ok: !prev.ok }, false); //prev -> 현재 caching된 데이터 가져오기. 어디서든 접근 가능. mutate("/api/users/me") //이렇게 하면 그냥 업데이트
10.2 useUser Hook return router.push("/enter"); push는 페이지 이동이라 브라우저 history에 남음 return router.replace("/enter"); //남지않음 페이지가 성공적으로 로드 됐을 때만 히스토리에 남음
페이지마다 같은 api( 유저정보불러오기)를 다시 불러오면 좋지 않지. 메모리에 담아서 캐싱해. SWR을 써보자.
10.3 SWR (Stale-While-Revalidate = http 캐시 무효화 전략) SWR은 캐싱된 데이터가 있으면 일단 화면을 그리고, 백그라운드에서 API call을 보내서 데이터가 바뀐게 있는지 체크하고, 있으면 업데이트 한다. SWR 설치 npm install swr
참고로 저렇게 중복 메시지가 나오는 이유는 리액트가 컴포넌트 2개 만들었기 때문. 그리고 react strict mode이기 때문. next.config.js에서 reactStrictMode를 false로 바꾸면됨. 근데 true해야 에러 더 잘 잡음.
useSWR 은 처음 인자로 url을 받는데 이를 key라고 하고, 두번째는 함수를 받고 fetcher라고 한다. 그래서 URL을 이용하여 fetcher함수를 통해 api call을 하고 data를 주고 에러가 났을 경우 error를 준다.
앞서 말한 key는 데이터의 id이기도 하다. useSWR 안에는 super_cache라는게있다.
9.0 Introduction authentication = 유저가 누구인지 알아내는 것. authorization = 유저가 권한이 있는지 알아내는 것.
이 섹션에서 구현할 로직 1. Phone Number Sended to Backend --> User? Login : Sign in 2. Create Token -- Connect to User with Random Number 3. Enter Phone Number(Twillo) --> User receive Token(Random Number) by SMS 4. Enter Token --> Send Token to Backend --> Token? Log the user In!
Update or create records (upsert) upsert()는 기존 데이터를 업데이트하거나 새 데이터베이스 레코드를 생성합니다. 다음 쿼리는 upsert를 사용하여 특정 이메일 주소로 사용자 레코드를 업데이트하거나, 존재하지 않는 경우 해당 사용자 레코드를 생성합니다. 출처: 사용자 sugar댓글
VSCode의 block 주석 하는 법: Shift + Alt + A or 상단메뉴 Edit -> Toggle block comment
자동으로 if문 처럼 동작하최종 shortened버전
9.2 Token Logic
아래 index는 https://www.prisma.io/docs/concepts/components/prisma-schema/relations/relation-mode
9.3 Twilo Setup 9.4 Sending SMS https://console.twilio.com/us1/develop/sms/try-it-out/send-an-sms?frameUrl=%2Fconsole%2Fsms%2Fgetting-started%2Fbuild%3Fx-target-region%3Dus1 npm i twilio 트윌로는 현재 node 16까지밖에 지원 안함. 그래서 nvm에서 노드 16으로 바꿔서 하니 잘 깔림.
느낌표 있으면 typescript한테 있는 타입이라고 말해주는 것.
9.5 Sending Email npm install --save @sendgrid/mail //아직 메일 인증되지 않아서 에러가 뜨는 것 같음 일단 넘어가자.
9.6 Token UI
prisma stuio에서
User삭제하려고 하면 안됨. User가 지워질 때, Token 물고있어서 그러면 어떻게 하냐?.( onDelete ) Cascade: 부모도 삭제해라. SetNull: user값을 null로 둔다. 근데 여기선 그런 것은 필요없으니 Cascade로 두자.
8.1 Form Submission front에서 헤더를 정해주지 않으면, req.body는 string으로 오게 됨. 그래서 req.body.email 이런식으로 사용 못함 헤더에 Content-Type을 application/json으로 설정하면 req.body가 json형식으로 내려옴. 그래서 req.body.email 사용 가능.
8.2 Clean Code part One - 재밌다. fetch.then()이런거 정리 함. 8.3 Clean Code part Two
7.0 Introduction 일단 잠깐 쉬고 form만드는 짓을 해보자. form은 너무 귀찮음. React Hook Form package 써보자.
7.1 Making Forms Alone npm i react-hook-form (React18) npm i react-hook-form --legacy-peer-deps(React18이전) 일단 깔았고, 이거 안깔고 하면 좋은 UX를 위해 할 일이 너무 많음을 보여줌.
5는 tailwind css라 건너 뜀 6.0 Before We Start 6.1 What is Prisma Prisma란? Node.js Typescript ORM(Object Relational Mapping) 번역기라고 보면 됨. 쿼리 없이 js로 DB 다룰 수 있게 해주는거.
6.2 Prisma Setsup 1. VSCode extension에서 Prisma 설치. 2. npm i prisma -D 설치 3. 명령어 바로 prisma하면안되고 npx prisma로 해야 함. npx prisma init 그럼 prisma폴더와 .env 생김 아래 안내문구도 뜸. 저대로 해보자.
prisma/schema.prisma가서 provider를 mysql로 바꾸장
@같은 것들은 공식문서에 다 있다.
6.3 What is PlanetScale serverless database platform = 데이터베이스 제공해준다. serverless = 서버를 우리가 유지보수 할 필요 없다는 뜻. AWS의 RDS(관계형데이터베이스서비스)가 아님. 거기선 모든 설정 해야 함. scale up/down다 해야 함. MySQL-compatible = MySQL이 아님 그래서 설정을 좀 바꿔야 함. 나중에 보자.
MySQL이 아닌 이유는 얘네가 Vitess를 사용하기 때문. Vitess는 유튜브를 scale하기 위해 구글이 만든 것 다시말해 Vitess는 대기업들이 규모에 맞게 MySQL을 scale하기 위해 쓰는 방법. 초당 수백만개의 쿼리, 수십만개의 연결, 수만개의 노드가 필요하면 scaling어렵다. youtube,naver,slack,airbnb,twitter등에서 쓰임 ㄷㄷ 오픈 소스임. planetscale의 가격:
planetscale은 개발자 경험이 좋음. DB를 깃처럼 사용 할 수있다. 브랜치 따서 만들고.. downtime없이 배포 가능. 계정 만들자. 깃헙 있으면 그걸로 가입 가능.
pscale region list를 실행해보자. 근데 로그인 안돼있어서 안됨. 로그인 하자: pscale auth login 그럼 브라우저 창이 뜨고, 터미널의 Confirmation Code가 같은지 확인 하면 됨
다시 pscale region list 실행
ap-northeast에 DB만들어보자.
pscale database create carrot-market --region ap-northeast carrot-market이란 DB를 해당 지역에 만듦. 터미널에 링크 뜸.
컴퓨터와 PlanetScale 사이에보안 연결 어떻게 만들까? connect Create a secure connection to a database and branch for a local client pscale connect carrot-market 위 명령어 치면 로그인 된 내 계정의 DB에 연결이 됨. 따로 id,pw 저장 할 필요 없음.
id5인 사람(존재하지않는 사용자)이 만약 댓글 추가 하려면, 작성자의 정보화 함께 댓글을 달려면 맨 처음 User DB에서 id가 5인 사용자가 존재하는지 확인함. 그렇기 때문에 Users DB에 반드시 있어야 함.(MySQL,PostgresQL 에서)
근데 Vitess는 가능함. DB 분화에 특화되어있음. 그래서 댓글 생성 전에 사용자가 존재하는지 확인하지 않음. foreign key constraint를 지원하지 않음. 그래서 저렇게 저장해도 오류 일어나지 않음. 이는 좋은게 아니야 그래서 이런 기능이 없는 Vitess가 아닌 Prisma에서 체크를 해야 함.
relationMode = prisma하면 됨.
그러면 Data 스키마를 push해보자. npx prisma db push
Prisma Client가 생성됨! 플래닛 스케일 가면 스키마 업로드 된거 확인 가능.
6.6 Prisma Client npx prisma studio 실행하면 DB 관리자 페이지 보임.
이걸로 DB추가도 가능
일단 client를 추가해보자 npm i @prisma/client -D를 안붙인 이유는 백엔드에서 직접 이 client를 사용할 것이기 때문 =서비스에서 사용한다. lib폴더에 client.ts만들고 아래 내용 작성
import { PrismaClient } from "@prisma/client";
export default new PrismaClient();
그럼 prismaclient만든거야 그리고 다음처럼 해보자. npx prisma generate
노드모듈에 설치 됨. 모듈 가서 보면 내가 친 DB 스키마가 typescript로 등록 되어 있음
user라는 우리가 정의한 테이블을 다룰 수 있다.
BUT 그냥 brower에서 접근 가능한 저런 파일에서 DB를 직접 조작할 수 있는 소스를 쓰면 보안에 말도안되는 결점이 되겠지. 그래서 다행이도 에러가 뜸. nextjs 프론트엔드에서 prisma를 임포트 할 수 없다.
그렇다면 이 client를 어디서 사용해야 하나?
6.7 API Routes 보통은 백엔드 서버를 따로 만들지 근데 NextJS에서 API만들기도 가능. pages폴더에 api폴더 만들면 됨 NextJS서버에 API가 생긴거 규칙 가능단함.
그리고 실행시키고 플래닛스케일로 오면 데이터가 생김
6.7 Recap npx prisma db push npx prisma generate = 데이터베이스에 말걸 수 있는 client 생김
수정으로 할거면 html이나 body 같은 최상위 요소에 dark 클래스 추가 하면 되는거지
4.12 Just In Time compiler tailwind 3.0전에는, purge 작업이 필요했음. 매우 큰 css 파일에서 사용하지 않는 css의 클래스 네임을 삭제 함. 근데 이젠 css파일이 빈 상태에서 시작함. JIT 컴파일러 사용함으로써 실시간으로 사용하려는 클래스를 생성함. 그래서 클래스끼리 조합이 가능한거다.
많은 reset들이 있는데 아래 처럼 설정해서 그럼
그러나 tailwind의 가장 좋은점은!
tailerwind에서 벗어나고 싶으면 what if I want to break free from the restrictions of taliwind? 예전엔 다음 처럼 했었어야 한다.<h1 style={{fontSize:800}}/>