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

[TIL 2023.08.01] 자바스크립트로 만든 투두리스트 타입스크립트로 바꾸기

by 괴코딩 2023. 8. 1.

❓발생한 이슈/고민

지난번에 만든 투두리스트를 타입스크립트로 고쳐보았다.

 

고려해야할 사항은

타입 스크립트 환경에서 

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

 

💡해결과정

정적 이미지 파일 사용하기

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

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의 타입을 지정해주면 사용이 가능해진다.

 

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

완성된 나의 투두리스트~

 

🧐궁금점과 부족한 내용

나는 개인적으로 타입스크립트에서 class 활용하는게 너무 헷갈려서 주로 interface로 타입 지정하고

export / import해서 가져다 쓰는데 보통의 경우, 일반적으로 어떻게 쓰이는지 궁금하다.

 

그리고 interface가 어디에 정의되어 있는지 여기저기 찾아다니는게 너무 불편해서 model/interface.ts 파일 하나에

다 적어놓고 가져와서 사용하는데 이렇게 해도 되는게 맞나... 잘 모르겠다. 

 

📋레퍼런스

[React] 타입 스크립트 환경에서 정적 이미지 파일 사용하기

[React] Redux와 TypeScript 함께 사용하기

[TypeScript] React+TypeScript+react-router-dom-v6로 개발 시작하기

 

반응형