본 포스트에서는 리액트와 타입스크립트를 이용하여 네이버 API로 데이터를 검색해서 목록 화면을 구성해 보겠습니다.
 
 

React + TypeScript Naver API로 목록 만들기

 

저번 포스트에서는 프로젝트 경로를 생성하고 개발에 필요한 모듈들을 설치해 보았습니다. React 외에 TypeScript를 사용하기 위한 준비도 마쳤습니다. 이제 VSCode에 프로젝트를 반입해서 간단하게 "Hello World"를 출력하는 프로그램을 작성해 보겠습니다.

 

VSCode로 프로젝트 열기

먼저 빈 VSCode 창을 하나 열고 [폴더 열기] 버튼을 클릭합니다.

만들어 둔 searchNaverApiTs 폴더를 선택하여 엽니다.

해당 폴더를 선택하면 VSCode에 프로젝트가 아래와 같이 반입됩니다.

 

프로젝트 구조 생성

프로젝트 하위에 폴더를 두 개 만들어 보겠습니다.

 

[./public]

public 이라는 폴더에는 html, css, image 등 정적인 Resources를 관리합니다.

 

[./src]

src 라는 폴더에는 React 기반으로 개발하는 JavaScript 소스 코드를 관리합니다.

 

일단 public 경로는 비워두고 이번에는 src 경로부터 작성해 보겠습니다. 먼저 애플리케이션을 초기화 할 main.tsx 파일을 ./src 경로 하위에 생성하고 아래와 같이 작성합니다. 확장자를 .js 가 아닌 .tsx 로 작성합니다.

import ReactDOM from 'react-dom';

ReactDOM.render(<App />, document.getElementById('app'));

<App /> 컴포넌트가 있는 app.tsx 파일도 아래와 같이 작성합니다.

const App = () => (
    <div>Hello World</div>
)

export default App;

VSCode에서 TypeScript로 작성하게 되면 위와 같이 작성했을 때 main.tsx에는 App 컴포넌트를 import 하지 않았으므로 아래와 같은 Syntax Error가 표시됩니다.

오류가 발생한 곳에 커서를 가져가 보면 아래와 같이 오류에 대한 설명이 나오고 VSCode가 바로 수정할 수 있는 방법이 있는 상태라면 [빠른 수정] 이라는 링크가 표시됩니다.

[빠른 수정] 링크를 클릭해보면 App 컴포넌트를 ./app 파일에서 참조하겠다는 처리 방안이 표시되고, 선택할 경우 모듈을 import 시킵니다.

현재까지 작성한 프로젝트의 폴더 및 파일 구조는 아래와 같습니다.

 

컴파일 옵션 설정

TypeScript는 브라우저에서 바로 해석할 수 있는 형태가 아니므로 컴파일 과정을 거쳐 JavaScript로 변환이 필요합니다. 컴파일은 tsc 명령을 통해서 수행할 수 있습니다. 아래 명령어를 실행시키면 tsc 명령 형식 및 옵션을 조회할 수 있습니다.

tsc -help

컴파일을 할 때마다 tsc 명령에 옵션을 주고 컴파일 할 수도 있겠지만 일관성 있는 컴파일 정책을 위해서 tsconfig.json 파일을 생성하고 프로젝트에서 사용할 컴파일 옵션을 정의합니다. tsconfig 파일에 설정할 수 있는 옵션은 정말 다양하게 있지만 우리는 아래 정도의 옵션만으로 컴파일을 진행하겠습니다.

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "target": "es5",
    "module": "commonjs",
    "outDir": "./public/dist",
    "rootDir": "./src",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}

전체 옵션에 대한 내용은 아래 링크의 공식 문서를 참고하시면 됩니다.

https://www.typescriptlang.org/tsconfig

 

TSConfig Reference - Docs on every TSConfig option

From allowJs to useDefineForClassFields the TSConfig reference includes information about all of the active compiler flags setting up a TypeScript project.

www.typescriptlang.org

사용한 옵션들에 대해서는 간략하게 짚어 보겠습니다.

옵션 설명
jsx  JSX 코드를 컴파일 하는 방법을 설정합니다.
target  컴파일 할 ECMAScript 버전을 설정합니다.
module  사용할 모듈 시스템을 설정합니다.
outDir  컴파일 결과물인 .js 파일을 생성할 위치를 설정합니다.
rootDir  컴파일 Source의 루트 경로를 설정합니다.
esModuleInterop  CommonJS와 ES Modules 간의 상호 운용성이 생기게 할 지 여부를 설정합니다.
forceConsistentCasingInFileNames  사용할 파일명을 정확히 작성할 지 여부를 설정합니다.
strict  엄격한 타입 검사를 수행할지 설정합니다. (TypeScript를 사용하는 이유이니 true를 권장합니다.)
skipLibCheck  선언 파일 (.d.ts)의 타입 확인 여부를 설정합니다.

 

여기까지 진행한 다음 tsc 명령을 한 번 수행해 봅니다.

D:\workspace\searchNaverApiTs> tsc

컴파일 옵션에서 rootDir을 ./src, outDir을 ./public/dist로 설정했으므로 /src 아래 생성한 app.tsx 파일과 main.tsx 파일이 컴파일 되어 ./public/dist 경로 하위에 js 파일을 생성한 것을 확인할 수 있습니다.

TypeScript 컴파일러가 tsconfig.json에 선언한 옵션에 따라 TypeScript를 es5 기준의 JavaScript로 변환해서 브라우저에서 실행할 수 있는 상태로 변경했습니다. 단순히 tsc 명령을 수행하면 실행하는 경로 하위에 있는 모든 *.tsx 및 *.ts 파일을 컴파일 합니다. 

 

원하는 파일만 컴파일하기 위해서는 tsc [파일명] 형식으로 실행하는 방법도 있고, tsconfig.json 파일에 compilerOptions와 동일한 레벨에 files를 선언해서 관리할 수도 있습니다.

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "target": "es5",
    "module": "commonjs",
    "outDir": "./public/dist",
    "rootDir": "./src",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  },
  "files": [
    "main.tsx",
    "app.tsx"
  ]
}

여기까지 진행했다면 한 번 실행해 보겠습니다. ./public 하위 경로에 index.html 파일을 생성하고 /dist/main.js 파일을 참조합니다.

<!DOCTYPE html>
<html>
    <head>
        <title>Search Naver API</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    </head>
    <body>
        <div id="app"></div>
        <script type="text/javascript" src="./dist/main.js"></script>
    </body>
</html>

그리고 전과 동일하게 webpack.config.js 파일을 현재 환경에 맞춰서 생성합니다.

'use strict'
const path = require('path');

module.exports = {
    entry: {
        main: ['./public/dist/main.js']
    },
    module: {
        rules: [{
            test: /\.jsx?$/,
            use: {
                loader: 'babel-loader'
            }
        }]
    },
    devServer: {
        static: './public',
        host: 'localhost',
        port: 8080
    }
};

package.json 파일에도 start script를 추가합니다.

"scripts": {
  "start": "NODE_ENV=development webpack-dev-server"
}

위 내용까지 모두 마쳤다면 yarn start로 프로젝트를 구동합니다.

D:\workspace\searchNaverApiTs> yarn start
yarn run v1.22.17
$ NODE_ENV=development webpack-dev-server
<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Loopback: http://localhost:8080/, http://127.0.0.1:8080/
<i> [webpack-dev-server] Content not from webpack is served from './public' directory
[BABEL] Note: The code generator has deoptimised the styling of /Users/a20201022/Documents/searchNaverApiTs/node_modules/react-dom/cjs/react-dom.development.js as it exceeds the max of 500KB.
asset main.js 1.16 MiB [emitted] (name: main)
runtime modules 27 KiB 12 modules
modules by path ./node_modules/ 1.06 MiB
  modules by path ./node_modules/webpack-dev-server/client/ 62.1 KiB 12 modules
  modules by path ./node_modules/webpack/hot/*.js 4.4 KiB 4 modules
  modules by path ./node_modules/react/ 120 KiB 4 modules
  modules by path ./node_modules/html-entities/lib/*.js 115 KiB 4 modules
  modules by path ./node_modules/scheduler/ 29.4 KiB 4 modules
  modules by path ./node_modules/react-dom/ 732 KiB 2 modules
  ./node_modules/ansi-html-community/index.js 4.26 KiB [built] [code generated]
  ./node_modules/events/events.js 14 KiB [built] [code generated]
  ./node_modules/object-assign/index.js 2.17 KiB [built] [code generated]
modules by path ./public/dist/*.js 753 bytes
  ./public/dist/main.js 488 bytes [built] [code generated]
  ./public/dist/app.js 265 bytes [built] [code generated]
webpack 5.66.0 compiled successfully in 2314 ms

오류 없이 잘 구동되었다면 http://localhost:8080 으로 접속하여 확인을 합니다. "Hello World"가 출력되면 좋겠지만 아래와 같은 오류가 발생하고 화면에는 아무것도 출력되지 않습니다.

 

이어지는 내용부터는 다음 포스트에서 다루겠습니다. 추가 설정을 마치고 화면에 "Hello World"를 출력하는 부분까지 다음 포스트에서 진행해 보겠습니다.

300x250

+ Recent posts