
npm i -D postcss-preset-env tailwindcs
npx tailwind init
tailwind.config.js
module.exports = {
content: ['./src/**/*.tsx'],
theme: {
extend: {},
},
plugins: [],
}
Javascript 플러그인을 사용하여 CSS를 변환
postcss.config.js
module.exports={
plugins: ['tailwindcss','postcss-preset-env']
}
global.css에 적용
@tailwind base;
@tailwind components;
@tailwind utilities;
npm install classnames --save
변수값에 따라 대상의 css를 컨트롤
classNames({'prop':true}) // 'prop'
classNames({'prop':false}) // ''
classNames(`border-gray-400`,{"border-red-500":error}) //error가 있을 때 빨간색으로
서버로부터 데이터를 가져오고 보낼때 사용하는 모듈
post
const res = await axios.post('/auth/register',{email,password, username,})
프론트의 entry point에서 Axio로 통신할 서버의 url을 지정(환경변수 이용)
Axios.defaults.baseURL=process.env.NEXT_PUBLIC_SERVER_BASE_URL+"/api";
express의 Router를 사용하여 해당 요청 받기
import { Request, Response, Router } from "express";
const register = async (req: Request,res:Response)=>{
const {props} = req.body;
}
const router=Router()
router.post('/register',register)
server.ts에서 해당 라우터를 받아 app에 연결
import authRoutes from "./routes/auth"
app.use("/api/auth",authRoutes)
통신하려는 데이터의 origin이 다를 때 허용하지 않는다. cors 모듈을 사용하여 클라이언트에서 외부의 요청을 받아오게 허용할 수 있다.
import cors from 'cors'
const origin = "http://localhost:3000"
app.use(cors({
origin
}))
로그인시 쿠키로 인증 토큰을 발행하기 위한 설정
도메인 주소가 다르면 별도 설정 없이는 쿠키가 전송되지 않는다.
Backend에서는 cors 부분에서 credentials: true
const handleSubmit = async (e:FormEvent) =>{
e.preventDefault();
try {
const res= await axios.post('/auth/login',{
password,
username,
},{
withCredentials: true,
})
console.log('res',res);
router.push("/")
} catch (error: any) {
console.error(error);
seterrors(error?.response.data||{});
}
}
유저 정보는 Context에 담아서 이용한다. 여러개의 컴포넌트에서 동시에 필요한 경우가 많기 때문이다.
import { createContext } from "react";
import { User } from "../types";
interface State{
authenticated: boolean;
user: User | undefined;
loading: boolean;
}
const StateContext = createContext<State>({
authenticated: false,
user: undefined,
loading: true,
})
const DispatchContext = createContext<any>(null);
Context를 사용하기 위해서는 컴포넌트를 Context Provider로 감싸야한다.
export const AuthProvider = ({children}:{children: React.ReactNode}) =>{
return(
<DispatchContext value={dispatch}>
<StateContext.Provider value={state}>{children}</StateContext.Provider>
</DispatchContext>
)
}
export const useAuthState = () => useContext(StateContext);
export const useAuthDispatch = () => useContext(DispatchContext);
//in _app.tsx
import { AuthProvider } from '../context/auth';
export default function App({ Component, pageProps }: AppProps) {
Axios.defaults.baseURL=process.env.NEXT_PUBLIC_SERVER_BASE_URL+"/api";
return <AuthProvider>
<Component {...pageProps} />
</AuthProvider>
}
useState 대신 사용하는 react 내장 함수
dispatch와 짝을 이루어 각 상황에 맞게 변수 값을 설정한다.
export const AuthProvider = ({children}:{children: React.ReactNode}) =>{
const [state, defaultDispatch] = useReducer(reducer, {
user: null,
authenticated: false,
loading: true
})
const dispatch = (type:string,payload?: any) =>{
defaultDispatch({type,payload})
}
return(
<DispatchContext.Provider value={dispatch}>
<StateContext.Provider value={state}>{children}</StateContext.Provider>
</DispatchContext.Provider>
)
}
npm i jsonwebtoken dotenv cookie --save
npm i @types/jsonwebtoken @types/cookie --save-dev
백엔드에서 환경변수(.env)를 사용하기 위한 모듈
//compare password
const passwordMatches = await bcrypt.compare(password,user.password);
//wrong password
if(!passwordMatches) return res.status(401).json({password: "Wrong password"})
//issue token
const token = jwt.sign({username},process.env.JWT_SECRET)
전달 받은 쿠키를 사용자 브라우저에 저장
//save cookie
res.set("Set-Cookie",cookie.serialize("token",token,{
httpOnly: true,
secure: process.env.NODE_ENV === "development",
sameSite:"strict",
maxAge: 60 * 60 * 24 * 7, // 1 week
path: "/"
}))