728x90
반응형

나중에 프론트 쪽에서 할 상태관리를 위해 front폴더에 세팅을 해준다.

자세한 내용은 아래 링크에 접속하면 확인 가능하다.

https://typo.tistory.com/entry/Nextjs-next-redux-wrapper

 

Next.js | next-redux-wrapper

NextJS에서 상태를 관리하기 수월하게 해주는 redux를 TypeScript와 함께 사용해보자. 이 포스트는 counter에 대한 state를 다루는 포스트이다. 사전 준비 create-next-app으로 프로젝트를 생성한다. $ npx create.

typo.tistory.com

 

로그인에 관한 기본적인 세팅만 해주겠다.

 

1. 먼저 필요한 npm 모듈들을 설치하자.

$ npm i react-redux redux next-redux-wrapper redux-thunk @types/redux-promise @types/redux-logger
$ npm i redux-devtools-extension redux-logger --dev-save

 

2. 루트 디렉토리에 store폴더를 생성하고 아래와 같이 구조를 만들어준다.

3. 그다음 아래 코드들을 입력해준다.

user.interfaces.ts

export interface UserState {
    userInfo : UserInfo;
    islogined : boolean;
    loginError : '';
    signupDone : boolean;
    signupError : '';
    idDuple : boolean;
    emailDuple : boolean;
    emailAuth : boolean;
    data : any;
}

export interface UserInfo {
    id : string;
    pw : string;
    email : string;
    address : string;
}

입력값으로 쓰일 User interface와 함수실행 후 반환값으로 받을 값들을 선언해준다.

마지막 data 속성은 차후에 payload로 데이터를 받기위한 저장공간이다.

UserStateUser를 포함한다.

 

 

userAct.interfaces.ts

export enum actionTypesUser {
    USER_INIT = "USER_INIT", // state 초기화
}

export type ActionsUser = UserInit 

export interface UserInit {
    type : actionTypesUser.USER_INIT;
    data : any;
}

아직은 UserState를 초기화하는 actionType 밖에 없지만 차근차근 늘려나갈 것이다.

 

 

 

/store/interfaces/index.ts

export * from './user/user.interfaces'
export * from './user/userAct.interfaces'

4. user 인터페이스와 액트를 export한다.

 

/store/interfaces/RootState.ts

import { UserState } from './index'

export interface RootStateInterface {
    user : UserState;
}

5. UserState를 가져와 RootState에 넣어준다. ( 이곳은 모든 State를 포함합니다. )

 

/store/reducer/index.ts

import { combineReducers, Reducer, AnyAction } from "redux";
import { RootStateInterface } from "../interfaces/RootState";
import user from "./user_reducer";

const rootReducer: Reducer<
	RootStateInterface,
	AnyAction
> = combineReducers<RootStateInterface>({
	user,
});

export default rootReducer;
export type RootState = ReturnType<typeof rootReducer>;

RootState 폴더에 선언한 State들을 가져와서 Reducer와 엮어준다.

 

 

/store/reducer/user_reducer.ts

import { HYDRATE } from "next-redux-wrapper";
import { getFontDefinitionFromManifest } from "next/dist/server/font-utils";
import {
    UserState,
    UserInfo,
    actionTypesUser,
    ActionsUser
} from "../interfaces";

export const initialState : UserState = {
    userInfo : <UserInfo>{
        id : "",
        pw : "",
        email : "",
        address : ""
    },
    islogined : false,
    loginError : '',
    signupDone : false,
    signupError : '',
    idDuple : false,
    emailDuple : false,
    emailAuth : false,
    data : {}
}

interface HydratePayload {
    user : UserState
}

const user = (
    state = initialState,
    action : ActionsUser | { type : typeof HYDRATE; payload : HydratePayload }
) : UserState => {
    switch (action.type) {
        case HYDRATE:
            return { ...state, ...action.payload.user};
        case actionTypesUser.USER_INIT:
            return {
                ...state,
                userInfo : initialState.userInfo
            }
        default:
            return state
    }
}

export default user;

userinitialState를 정의해주고 dispatch가 실행됐을 때의 로직을 정의한다.

나중엔 action이 추가됨에 따라 reducer의 case도 늘어날 것이다.

 

 

/store/index.ts

import { createStore, applyMiddleware, compose } from "redux";
import { createWrapper } from "next-redux-wrapper";
import promiseMiddleware from 'redux-promise';
import ReduxThunk from 'redux-thunk';
import rootReducer from "./reducer";

const createStoreWithMiddleware = applyMiddleware(promiseMiddleware, ReduxThunk)(createStore)

const configureStore = () => {
	const store = createStoreWithMiddleware (rootReducer);
	return store;
};

const wrapper = createWrapper(configureStore, { debug: true });

export default wrapper;

store를 생성하고 _app.tsx에 쓰일 wrapper를 만들어준다.

 

 

/pages/_app.tsx

import { AppProps } from "next/app";
import { NextPage } from "next";
import wrapper from "../store"; // store.ts 파일

const MyApp: NextPage<AppProps> = ({ Component, pageProps }: AppProps) => {
	return (
		<>
			<Component {...pageProps} />
		</>
	);
};

export default wrapper.withRedux(MyApp);

_app.tsx 파일의 MyApp을 만들었던 wrapper로 감싸주면 store 설정이 끝난다.

 

마지막으로 tsconfig.json에 store부분을 추가해준다.

 

tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve"
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx","store/**/*.ts"],
  "exclude": ["node_modules"]
}
728x90
반응형

+ Recent posts