03 May 2023
|
nextjs
NextAuth (Auth.js) 라이브러리를 사용하면 소셜로그인 구현이 쉽다.
NextAuth 세팅
라이브 러리 설치
pages/api/auth/[…nextauth].js
위의 경로에 파일 만들고, 아래 코드처럼 입력
import NextAuth from 'next-auth';
import GithubProvider from 'next-auth/providers/github';
export const authOptions = {
providers: [
GithubProvider({
clientId: 'Github에서 발급받은ID',
clientSecret: 'Github에서 발급받은Secret',
}),
],
secret: 'jwt생성시쓰는암호',
};
export default NextAuth(authOptions);
참고로 소셜로그인은 기본적으로 JWT방식이 기본이라서 secret :
란에 JWT 생성용 암호를 임의로 길게 입력해주면 된다.
내 시크릿 코드가 깃허브에 그대로 유출되는거를 방지하기 위해서 .env 파일에 암호를 써서 사용해주자.
로그인 버튼과 페이지 생성
next-auth라이브러리안에 있는 기능을 설정해주면 자동으로 로그인페이지를 제작헤준다.
onClick이 들어가니깐 ‘use client’ 컴포넌트로 만들어서 집어넣는다.
'use client';
import { signIn, signOut } from 'next-auth/react'
// 로그인기능
<button onClick={()=>{ signIn() }}>로그인버튼</button>
// 로그아웃 기능
<button onClick={()=>{ signOut() }}>로그아웃버튼</button>
layout.js 파일에 로그인 기능이있는 컴포넌트인 LoginBtn 컴포넌트 불러오기
(layout.js는 서버컴포넌트라서, 클라이언트 컴포넌트 하나를 따로 생성해서 불러와줬디.)
(app/layout.jsx)
import LoginBtn from "./LoginBtn.js"
(...)
<body>
<div className="navbar">
<Link href="/" className="logo">Appleforum</Link>
<Link href="/list">List</Link>
<LoginBtn></LoginBtn>
</div>
{children}
</body>
페이지에서 로그인된 유저의 정보 출력을 할 때
서버 컴포넌트에서 유저정보 가져와서 클라이언트 컴포넌트에 전송해주는게 낫다. useSession 함수는 html을 다 보여주고나서 한 박자 늦게 실행될 수 있기 때문이다.
(page.js 옆에 있는 layout.js)
'use client'
import { SessionProvider } from "next-auth/react"
export default function Layout({ children }){
return (
<SessionProvider>
{children}
</SessionProvider>
)
}
SessionProvider
로 감싸놓으면 이 안에 들어가는 client component 컴포넌트들은 로그인된 유저 정보를 출력할 수 있다.
(page.js)
'use client'
import { useSession } from 'next-auth/react'
export default function Page(){
let session = useSession();
if (session) {
console.log(session)
}
(생략)
useSession() 쓰면 그자리에 지금 로그인한 유저의 정보가 담겨있다.
import { authOptions } from "@/pages/api/auth/[...nextauth].js"
import { getServerSession } from "next-auth"
export default function Page(){
let session = await getServerSession(authOptions)
if (session) {
console.log(session)
}
getServerSession() 가져오고 authOptions
가져와서 컴포넌트안에서 사용하면 그 자리에 유저 정보가 남는다.
let session 같은 변수에 담아서 출력해보거나 하면 된다.
참고로 authOption
은 맨 위에서 NextAuth 세팅 카테고리해서 작성한 파일이다.
26 Apr 2023
|
typeScript
코딩애플강의를 보고 정리했습니다.
조건부로 타입만들기
자바스크립트 삼항연산자처럼 타입스크립트도 똑같이 할 수있다.
extends 키워드와 삼항연산자
를 이용하면된다.
extends는 왼쪽이 오른쪽의 성질을 가지고 있냐 라는 뜻이다.
Ex)
type Age<T> = T extends string ? string : unknown;
let age : Age<string> //age는 string 타입
let age2 : Age<number> //age는 unknown 타입
좀 더 심화로 이런식으로 array를 활용해서 타입에 조건문을 걸어줄 수 도있다.
type FirstItem<T> = T extends any[] ? T[0] : any
let age1 :FirstItem<string[]>; // string 타입이 됨
let age2 :FirstItem<number>; // any 타입이됨
infer 키워드
- 지금 입력한 타입을 변수로 만들어주는 키워드이다.
Ex)
type Person<T> = T extends infer R ? R : unknown;
type 새타입 = Person<string> // 새타입은 string 타입이다.
- infer 키워드는 조건문 안에서만 사용이 가능하다.
- infer 우측에 자유롭게 작명해주면 타입을 T에서 유추해서 R이라는 변수에 집어넣으라는 뜻이다.
- R을 조건식 안에서 마음대로 사용 가능하다.
등등, 이런식으로 타입파라미터에서 타입을 추출해서
쓰고 싶을 때 쓰는 키워드이다.
infer 키워드를 활용하는 예시를 더 알아보자.
- array 안에 있던 타입이 어떤 타입인지 뽑아서 변수로 만들어줄 수 있다.
type 타입추출<T> = T extends (infer R)[] ? R : unknown;
type NewType = 타입추출< boolean[] > // NewType 은 boolean 타입이다.
- 함수의 return 타입이 어떤 타입인지 뽑아서 변수로 만들어줄 수 있다.
type 타입추출<T> = T extends ( ()=> infer R ) ? R : unknown;
type NewType = 타입추출< () => number > // NewType은 number 타입이다.
26 Apr 2023
|
typeScript
코딩애플강의를 보고 정리했습니다.
keyof 연산자
object의 key를 뽑아서 새로운 타입을 만들고 싶을 때 사용하는 연산자이다.
object 타입에 사용하면object 타입이 가지고 있는 모든 key 값을 union type으로 합쳐서 내보내준다.
유니온타입은 number|string
이런식의 타입을 뜻한다.
Ex)
interface Person {
age: number;
name: string;
}
type PersonKeys = keyof Person; //"age" | "name" 타입이 된다.
let a :PersonKeys = 'age'; //가능
let b :PersonKeys = 'ageeee'; //불가능
Person 타입은 age, name이라는 key를 갖고 있어서,
PersonKeys는 ‘age’|’name’이라는 리터널 타입이 된다.
나아가서, 이런식으로 코드를 짤 수 있다.
interface Person {
[key :string]: number;
}
type PersonKeys = keyof Person; //string | number 타입이 된다.
let a :PersonKeys = 'age'; //가능
let b :PersonKeys = 'ageeee'; //가능
Mapped Types
오브젝트 안에 있는 속성들을 다른 타입으로 한번에 모두 변환할때 유용하다.
type Car = {
color: boolean,
model: boolean,
price: boolean | number,
};
위의 타입에 명시된 모든 속성들을 string 타입으로 바꾸고 싶을때 이런식으로 해주면 된다.
type Car = {
color: boolean,
model : boolean,
price : boolean | number,
};
type TypeChanger <MyType> = {
[key in keyof MyType]: string;
};
여기서 in 키워드는 왼쪽이 오른쪽에 들어있냐라는 뜻이고,
keyof는 오브젝트 타입에서 key값만 유니온타입으로 뽑아주는 역할이다.
type Car = {
color: boolean,
model : boolean,
price : boolean | number,
};
type TypeChanger <MyType> = {
[key in keyof MyType]: string;
};
type 새로운타입 = TypeChanger<Car>;
let obj :새로운타입 = {
color: 'red',
model : 'kia',
price : '300',
}
이렇게 하면 새로운타입
은 color,model,price 속성을 갖고있고, 전부 string 타입이 된다.
26 Apr 2023
|
typeScript
코딩애플강의를 보고 정리했습니다.
signatures는 다음과 같은 상황에서 유용하다.
- object 자료에 타입을 미리 만들어주려고 하지만, object 자료에 어떤 속성들이 들어올 수 있는지 아직 모르는 상태
- 타입지정할 속성이 너무 많을때
등등..
예시
index signatures
interface StringOnly {
[key: string]: string;
}
let obj: StringOnly = {
name: 'kim',
age: '20',
location: 'seoul',
};
` [key: string]: string;` 이부분을 주의깊게 살펴봐야한다.
- {모든속성:string} 이라는 뜻이다.
[]
대괄호에는 string,number 둘 중 하나의 유형만 가능하다.
interface StringOnly {
age: number; ///에러남
[key: string]: string;
}
interface StringOnly {
age: string; ///가능
[key: string]: string;
}
[] 이 문법은 다른 속성과 함께 사용할 수 있지만,
{ 모든 속성 : string, age : number } 이건 뭔가 논리적으로 말이 되지 않아 에러를 낸다.
하지만 아래처럼 하면 가능하다.
interface StringOnly {
age: number; ///가능
[key: string]: string | number;
}
array형태도 가능하다.
interface StringOnly {
[key: number]: string,
}
let obj :StringOnly = {
0 : 'kim'
1 : '20',
2 : 'seoul'
}
위의 타입 코드는 { 모든숫자속성 : string }
이라는 뜻이다.
하지만, 숫자 key만 넣을거면 그냥 array + tuple 타입 쓰는게 더 직관적일 수 있다.
Recursive Index Signatures
만약 다음과 같이 오브젝트 안에 또 오브젝트가 있다고 가정해보자
let obj = {
'font-size': {
'font-size': {
'font-size': 14,
},
},
};
이렇게 중첩된 오브젝트들을 한번에 타입 지정할때 어떻게해야 할까?
interface MyType {
'font-size': {
'font-size': {
'font-size': number,
},
};
}
직접 interface 안에 ‘{}’ 이걸 3번 중첩되게 만들어도 상관없겠지만, 이런식으로도 타입 지정을 할 수 있다.
interface MyType {
'font-size': MyType | number;
}
let obj: MyType = {
'font-size': {
'font-size': {
'font-size': 14,
},
},
};
MyType이라는 타입을 만들었는데, ‘font-sze’속성은 MyType과 똑같이 생겼다고 타입을 만들어 준것이다.
Ex)
interface MyType {
'font-size': number;
[key: string]: number | MyType;
}
let obj = {
'font-size': 10,
secondary: {
'font-size': 12,
third: {
'font-size': 14,
},
},
};
25 Apr 2023
|
typeScript
코딩애플강의를 보고 정리했습니다.
class 타입을 확인할 때 implements 키워드를 사용해서 할 수 있다.
(interface도 필요함)
implements 키워드
interface CarType {
model: string;
price: number;
}
class Car implements CarType {
model: string;
price: number = 1000;
constructor(a: string) {
this.model = a;
}
}
let 붕붕이 = new Car('morning');
이렇게 작성해주면, 이 class가 이 interface에 있는 속성을 다 들고있는지 체크해줄 수 있다.
implements는 타입지정 문법이 아님
interface에 들어있는 속성을 갖고있는지 확인만하라는 뜻이다.
class에다가 타입을 할당하고 변형시키는 일은 못한다.
interface CarType {
model: string;
tax: (price: number) => number;
}
class Car implements CarType {
model; ///any 타입됨
tax(a) {
///a 파라미터는 any 타입됨
return a * 0.1;
}
}
implements는 class의 타입을 체크하는 용도지 할당하는게 아님을 명심하자