본문 바로가기
내일배움캠프/Weekly I Learned

[WIL 2023.08.06] 내배캠 12주차

by 괴코딩 2023. 8. 6.

📝 Situation(상황): 이번주 목표

기존에 만들었던 투두리스트를 TS를 이용하여 리팩토링 한다.

Next.js 학습하기

👀 Task(임무): situation 중 문제들

기존에 만들었던 투두리스트를 TS를 이용하여 리팩토링 한다.

  • 정적 이미지 파일 사용하기
  • react-router-dom 사용하기
  • redux 사용하기

 

🔍 Action(접근방법): 해결시도

정적 이미지 파일 사용하기

원래 자바스크립트 환경에서는

export { default as all } from "./all.png";
export { default as culture } from "./culture.png";
export { default as game } from "./game.png";

이미지 폴더 안에 index.js 파일을 하나 생성해서 export해서 사용할 수 있었다.

 

그런데 이걸 타입스크립트로 하려하니 빨간줄이 쫙쫙 그이면서 난리가 난 것.

이럴때에는 /src/@types에 import-png.d.ts라는 이름으로 타입 설정 파일을 생성하면 된다.

declare module '*.png' {
  const content: string;
  export default content;
}

이렇게 d.ts 파일을 만들어두면

export { default as cappadociaImg } from './Cappadocia.jpg';
export { default as checkImg } from './Check.png';
export { default as deleteImg } from './Delete.png';
export { default as detailImg } from './Detail.png';
export { default as nonCheckedImg } from './nonChecked.jpg';

잘~가져다 쓸 수 있다.

 

react-router-dom 사용하기

이것도 별 거 아니었는데 아마 오늘 가장 많이 시간을 잡아먹지 않았나 싶다..

타입스크립트에서 react-router-dom을 쓰려면 명령어로 설치할 때 @types/를 붙여줘야 한다.

난 yarn 명령어를 쓰니까

yarn add react-router-dom @types/react-router-dom

요렇게 설치만 해주면 원래 자바스크립트로 라우터 쓰는 것 처럼 코드 작성하면 된다. 

타입스크립트라고 따로 뭐 디정하거나 그런 과정이 없는데 진짜 너무 당황스러웠던게

자꾸 이렇게 뜨는 것이다...왜 뭐야. 뭐가 문제야.

이것 때문에 tsconfig.json 설정도 건드려 보고~ node_modules도 지웠다가 다시 깔아보고~온갖 기행을 다 해봤지만 

오류가 사라지지 않았는데 이유는.. 이 Router 파일의 경우엔 Router.tsx로 써줘야 하는게 맞다.

그런데 Router.ts 였어서 계속 위와 같은 오류가 떴었던 것!

돌려줘 내 시간..진짜 고통스러운 하루였다.

 

redux 사용하기

리덕스를 쓸 때에도 몇가지 고려해줘야 할 부분들이 있었다.

(툴킷 없이 그냥 맹짜 리덕스만 썼을 때를 전제로 한다.)

 

원래는 리듀서 파일에 Action value, Action creator, Initial state, Reducer 이렇게 작성을 해줬다면

타입스크립트를 쓰면서 추가가 되어야 하는 부분은 Action creator의 타입을 정해줄 Action interface와 Initial state의 타입을 정해주는 interface 2가지를 추가로 작성해주어야 한다.

 

// Action interface
interface AddTodoAction {
  type: typeof ADD_TODO;
  payload: Todo;
}

interface DeleteTodoAction {
  type: typeof DELETE_TODO;
  payload: number;
}

interface UpdateTodoAction {
  type: typeof UPDATE_TODO;
  payload: number;
}

type TodoActionTypes = AddTodoAction | DeleteTodoAction | UpdateTodoAction;

// Action Creator
export const addTodo = (payload: Todo): AddTodoAction => {
  return {
    type: ADD_TODO,
    payload,
  };
};

export const deleteTodo = (payload: number): DeleteTodoAction => {
  return {
    type: DELETE_TODO,
    payload,
  };
};

export const updateTodo = (payload: number): UpdateTodoAction => {
  return {
    type: UPDATE_TODO,
    payload,
  };
};
// Initial State
interface TodosState {
  todos: Todo[];
}

const initialState: TodosState = {
  todos: [],
};

사실 더 간편한 방법도 있겠지만 이정도가 지금의 나의 최선인 것 같다.

이렇게 작성한 인터페이스를 바탕으로

// Reducer
const todos = (state = initialState, action: TodoActionTypes) => {
  switch (action.type) {
    case ADD_TODO:
      return {
        todos: [...state.todos, action.payload],
      };
    case DELETE_TODO:
      return {
        todos: [...state.todos.filter((e) => e.id !== action.payload)],
      };
    case UPDATE_TODO:
      return {
        todos: [
          ...state.todos.map((e) => {
            if (e.id === action.payload) {
              e.isDone = !e.isDone;
            }
            return e;
          }),
        ],
      };
    default:
      return state;
  }
};

원래의 리듀서에 action 타입을 따로 명시해주면 된다.

타입이 3가지라서 type을 써서 '|'로 구분해 줬는데 지금 생각해보니 어제 배웠던 제네릭을 써봐도 좋지않았나 싶다.

 

그리고 이 리듀서를 활용하려면 configStore.ts 파일에 루트타입을 export 해주어야 적용이 가능하다.

export type RootState = ReturnType<typeof rootReducer>;

이렇게 빼내준 것을

import { useSelector } from 'react-redux';
import { RootState } from 'redux/config/configStore';

사용할 파일에 import 해주고

const todos = useSelector((state: RootState) => state.todos.todos);

state의 타입을 지정해주면 사용이 가능해진다.

 

타입스크립트 쓰기 시작하니까 뭐 하나 작성 할 때마다 빨간줄 쩍쩍 그이는거 사람을 상당히 초조하게 한다.

 

 

 

📃 Result(결과): action 후 성과

완성된 나의 투두리스트~

타입스크립트는 여전히 헷갈리고 어렵지만 확실히 정확에서 자바스크립트랑 비교가 안되는 것 같다.

하긴 그렇게 엄격하게 관리를 하는데.. 디버깅에 매우 유용!

 

📓 Point(정리): 이번주 요약

이전에 자바스크립트로 만들었던 투두리스트를 타입스크립트로 리팩토링 해보았다.

투두리스트 리팩토링 후, Next.js에 대해 학습하는 시간을 가졌다.

 

 

 

 

반응형