본문 바로가기
프론트엔드/TypeScript

[ TypeScript ] TypeScript+React TODO 리스트 만들기 (2)

by CODESIGN 2022. 10. 22.

앞에서 TypeScript+React를 사용한 정적인 리스트를 만들어 보았습니다.

 

 

[ TypeScript ] TypeScript+React TODO 리스트 만들기 (1)

React와 TypeScript를 사용하여 TODO 리스트를 만들기에 앞서 차근차근 코드를 이해하고자 정적인 리스트 페이지를 먼저 만들어 보려고 합니다. 목차 1. package.json 파일 생성 2. typescript 설치 명령어 3. T

codesign.tistory.com

 

 

이번에는 리스트에 데이터 모델을 추가해보았습니다.

 

파일 전체 아웃라인

> react-ts 파일

   > node_modules

   > public

   > src

      > src

           > components

              > Todos.tsx 

         > models

            > todo.ts (이 파일 만들 예정입니다.)

         > App.tsx

         > index.tsx

 

1. todo.ts 파일 생성하기 

src 폴더 밑에 models라는 새로운 폴더를 하나 만들었습니다. models로 이름을 지은 이유는 여기에 다양한 데이터 모델. 즉, 프로젝트에서 사용할 다양한 데이터를 만들 예정이기 때문입니다. models 파일에 todo.ts 파일을 추가했습니다. 이 파일에는 컴포넌트를 생성하지 않을 거라서 .tsx가 아닌 .ts 파일로 추가했습니다. 

 

 

이 todo.ts 파일에 class를 생성하고 Todo 객체를 만들었습니다. Todo 객체는 id와 text 필드를 갖도록 설정해주고 둘 다 문자열 타입으로 설정해 주었습니다.

 

todo.ts

class Todo { 
    id: string;
    text: string;
}
export default Todo;

 

하지만 실제로 VScode에서 코드를 썼을 경우 오류가 표시가 뜹니다. 바로 id와 text 부분에서요.

‘text 프로퍼티를 초기화하는 부분이 없고’, ‘생성자에서 값이 할당되지 않습니다’.

이 경고 메시지가 말하는 건 여기에 정의된 이 클래스는 인스턴스화되어야 한다는 것입니다.

 

 

지금 이 프로퍼티들은 Todo에 추가되고 타입도 지정되었지만 값이 할당되는 부분은 없습니다. 그래서 생성자를 추가해 해당 필드에 값을 할당해 주고 그러기 위해서는 이 생성자에는 인수가 필요합니다.

 

 

2. ‘todoText’ 인수 만들어주기

 

todo.ts

class Todo { 
    id: string;
    text: string;
    // 아래에 이 생성자에는 인수가 필요합니다.
    constructor(todoText: string) {
        this.text = todoText;
        this.id = new Date().toISOString(); // toISOString(): 스트링으로 변환 시킵니다. 
    }
}
export default Todo;

 

이제 Todo 클래스를 사용할 준비가 되었습니다. App.tsx에서 todos를 배열 형태로 테스트용 Todo를 몇 개 만들어보았습니다.

 

App.tsx

import Todos from './components/Todos';
import Todo from './models/todo';

function App() {
  // added
  // Todo 클래스를 사용해 객체를 만들면 됩니다
	const todos = [
		new Todo('Learn React'), // new Todo()를 두 번 호출해서 Todo를 두 개 만들겠습니다
		new Todo('Learn TypeScript')
	];
  // 이제 todoText에 값을 넘겨야 합니다.
  // todos는 문자열 배열이 아니라 Todo 객체 배열입니다
  return (
    <div>
      <Todos items={['lean react', 'learn typescript']} />
    </div>
  );
}

export default App;

 

이제 이 배열을 Todos의 items 프로퍼티에 값으로 넘길 것입니다. Todo 객체로 구성된 배열을 받으려면 문자열 배열 대신에 Todos 컴포넌트에서 타입 표기를 변경해야 합니다.

 

Todos.tsx

import React from 'react';
//added
import Todo from '../models/todo';
//String[]에서 Todo[]로 변경
const Todos: React.FC<{items: Todo[]}> = (props) => {
    return (
    <ul>
        {props.items.map((item) => (
	        <li key={item.id}>{item.text}</li>
      ))}
    </ul>
    );
};

export default Todos;

 

items에 받을 값을 Todo 배열로 바꿉니다. Todo 클래스로 만든 배열이요, 즉, items는 객체로 채워진 배열이고 그 객체는 Todo 클래스의 정의에 부합하는 객체입니다. 그러니까 배열의 객체는 id 프로퍼티를 가질 겁니다. 타입은 문자열이고, text 프로퍼티도 가질 거예요. 타입은 문자열이고요.

 

정확히는 이 클래스를 생성자로 사용해 생성된 객체일 겁니다. 그 객체로 구성된 배열을 tems 프로퍼티로 받는 거고요.

 

이걸로 Todos.tsx 코드 수정은 끝입니다

 

이제 App.tsx에서 todos 배열을 items 프로퍼티 값으로 넣어주면 됩니다.

이렇게 todos를 Todos 컴포넌트의 items 프로퍼티 값으로 넣으면 되죠.

 

 

App.tsx

import Todos from './components/Todos';
import Todo from './models/todo';

function App() {
	const todos = [
		new Todo('Learn React'),
		new Todo('Learn TypeScript')
	];
  return (
    <div>
      <Todos items={todos} />
    </div>
  );
}

export default App;

 

Todos.tsx

import React from 'react';
import Todo from '../models/todo';

const Todos: React.FC<{items: Todo[]}> = (props) => {
    return (
    <ul>
        {props.items.map((item) => (
	        <li key={item.id}>{item.text}</li>
      ))}
    </ul>
    );
};

export default Todos;

 

3. 결과물

이렇게 해도 TypeScript+React TODO 리스트 만들기 (1)에서 만든 것과 화면에 출력되는 건 차이가 없습니다. 

하지만  TypeScript+React TODO 리스트 만들기 (2)에서는 여러 가지 타입 표기와 클래스들 덕분에 어떤 형태의 데이터가 필요한지, 어떤 형태의 컴포넌트가 필요한지 명확해졌습니다. 이를 통해 우리는 개발자로서 코드에 이상이 없고 구조가 명확하다는 걸 알 수 있죠. 또한 이렇게 되면 컴포넌트나 데이터를 잘못 사용하는 일도 훨씬 줄어듭니다. 그리고 오류를 개발 과정에서 미리 수정할 수 있습니다. 예를 들면, 잘못된 todos를 넘기면 코드 편집창에 바로 경고 메시지가 나타납니다. 앱 실행 중에 갑자기 오류를 알리는 대신에요. 이게 바로 타입스크립트의 장점입니다.

댓글