프로젝트 생성

npx create-react-app toyproject

 

패키지 설치

npm install tailwindcss postcss-cli autoprefixer

 

css 설정파일 생성 ( tailwind.config.js)

npx tailwindcss init -p

 

PostCSS 설정 파일 생성

notepad postcss.config.js

 

내용 추가

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [],
  theme: {
    extend: {},
  },
  plugins: [],
}

 

index.css

@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';


body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}

 

tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ['./src/**/*.{js,ts,jsx,tsx}'],
  theme: {
      extend: {},
  },
  plugins: [],
};

 

추가적으로 만들기 전 라우터 사용하기 위해서 설치

npm install react-router-dom

 

// import logo from './logo.svg';
import './App.css';
import React from 'react';
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Main from './pages/main';
// import About from './pages/About';



function App() {
  return (
    <BrowserRouter>
      {/* <Header /> */}
      <Routes>
        <Route path="/" element={<Main />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;

 

만들어준 후 공통 header.tsx 작업을 들어간다.

 

일단 메인쪽에서 애니메이션 효과를 사용할 것이기에 해당 npm 을 설치한다.

npm install react-scroll framer-motion

 

import React from 'react';
import { Link } from 'react-router-dom';

const Header: React.FunctionComponent = () => {
  return (
    <header>
        <h2 className="dn none">상단메뉴</h2>
        <div>
            <button>견적문의</button>
            <p>000-0000-0000</p>
        </div>
      <nav>
        <ul>
          <li>
            <Link to="/">Main</Link>
          </li>
          <li>
            <Link to="/about">회사 소개</Link>
          </li>
          <li>
            <Link to="/about">사업 현황</Link>
          </li>
          <li>
            <Link to="/about">파트너사 문의</Link>
          </li>
        </ul>
      </nav>
    </header>
  );
};

export default Header;

헤더 부분 만들어주고 좀있다가 테일윈드css 를 적용해보겠다.

공식 문서 

https://tailwindcss.com/docs/installation

 

Installation - Tailwind CSS

The simplest and fastest way to get up and running with Tailwind CSS from scratch is with the Tailwind CLI tool.

tailwindcss.com

 

여기서 필요한 부분을 확인하면서 추가를 하도록 하겠다.

정렬을 위해서 해당 클래스를 넣어주면

 

이런형태로 들어간다.

 

 

이런식으로 적용이 되는걸 확인 할 수 있다. 

추후에 개인 프로젝트로 하나 만들예정이다. 

 

깃허브

https://github.com/asdf132645/finish

React.lazy() 와 Suspense 먼저 알아보겠다. (해당 기록은 학습한 내용을 전반적으로 기록하면서 정리한 내용이다.)

코드 분할과 지연된 컴포넌트 로딩은 초기 시간이 감소, 성능향상에 장점이 있다.

React.lazy()

React.lazy 함수를 사용하면 dynamic import를 사용해 컴포넌트를 렌더링할 수 있다. 

다이나믹 임포트는 spa 이므로 한번에  사용하지 않는 컴포넌트까지 불러오는 단점이 존재한다.

리엑트에서는 React.lazy 를 통하여 동적으로 import 즉 모듈등 페이지를 불어올 수 있도록 제공한다. 

이렇게 React.lazy를 사용하면 처음부터 불러오는게 아니라 동적으로 필요할때 불러오기 떄문에

초기 렌더링 지연시간을 어느정도 줄일 수 있다.

 

구문은

import Component from './Component';

const Component = React.lazy(() => import('./Component'));

 

 React.lazy로 감싼 컴포넌트는 단독으로 쓰일 수는 없고, React.suspense 컴포넌트의 하위에서 렌더링을 해야 한다.

 


React.Suspense

라우터로 분기가 나누어진 컴포넌트들을 위 코드처럼 lazy 를 통해 임폴트 하면 해당 path로 이동할때 컴포넌트를 불러온다 이 과정에서 로딩하는 시간이 생기게 된다.

 

서스펜스는 아직 렌더링이 준비되지 않은 컴포넌트가 있을 떄 로딩 화면을 보여주고, 로딩이 완료되면 렌더링이 준비된 컴포넌트를 보여주는 기능이다.

기본 문법

<Suspense fallback={<Spinner />}>
  <UserList />
</Suspense>

 

위와 같이 사용하여 감싸고 사용하며 비동기 동기(useEffect, useState)api 호출등으로 사이드 이펙트가 발생할때 그 부작용을 방지할 수 있으며 해결 방안이 된다.


 

React.lazy와 Suspense의 적용

앱에 코드 분할을 도입할 곳을 결정하는것은 사실 까다롭다. 중간에 적용시키는 것보다는 웹 페이지를 불러오고 진입하는 단계인 route 에 이 두기능을 적용하는게 좋다.

import { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';

const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));

const App = () => (
  <Router>
    <Suspense fallback={<div>Loading...</div>}>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </Suspense>
  </Router>
);

 

라우터에 Suspense를 적용하는 것은 간단한 편이라고 한다.

라우터가 분기되는 컴포넌트에서 각 컴포넌트에 React.lazy를 사용하여 import한다.

그리고 Route 컴포넌트들을 Suspense로 감싼 후 로딩 화면으로 사용할 컴포넌트를 fallback 속성으로 설정해주면 된다.

초기 렌더링 시간이 줄어드는 분명한 장점이 있으나 페이지를 이동하는 과정마다 로딩 화면이 보여지기 때문에 서비스에 따라서 적용 여부를 결정해야 한다.

이번글은  깔끔하면서 체계적인 모듈화 및 코드를 작성할 수있도록 리액트 클린 아키텍처를 작성해보겠다.

 

아키텍처의 중요성은 로버트 c 마틴의 클린 아키텍처에서 서술하기를 기능은 구조에 의지한다는 것이다. 이 점을 이해하기위해서는 코딩이라는 행위에 담겨져 있는 내재적 관점을 살펴 봐야 한다. 우리가 회사에 들어가서 하는 행위는 코딩이며 목정적성을 생각하면 다음과 같다.

 

우리는 코드를 이해하고 읽으며 수정/ 추가 유지보수 하는 일을 많이 하게된다. 따라서 이런 행위를 우리는 제일 먼저 프로젝트의 구조를 파악하고 아키텍처와도 밀접한 관계성을 갖는다. 예를 들어 지저분한 방에서 물건을 찾을 때 와 정돈된 방에서 물건을 찾는 속도는 차이가 나듯이 프로젝트의 구조에서도 정돈된 구조는 개발자의 속도에도 영향을 끼친다.

 

회사의 입장에서는 클린한 코드로 최소한의 인력으로 최대의 이익을 창출해야 하며 이는 소프트웨어 아키텍처의 목표인 필요한 시스템을 만들고 유지보수하는데 투입되는 인력을 최소화 하는것과 상응하게 된다.

 

클린 아키텍처란?

로버트 가 제안한 방법으로 관심사를 확실히 분리하여 효율적으로 재사용이 높은 컴포넌트를 구현 할 수 있게끔 만들수 있는 아키텍처 이다. 최소한의 노력으로 최대의 효율을 얻게 해주는 것이다.

 

 

클린 아키텍처의 기본 이론

  • 체계적으로 계층이 분리되어야한다.
  • 각 계층은 서로 맡은 역할을 충실히 수행한다.
  • 계층간의 의존성 관계가 잘 이루어져야한다.

핵심 개념

  • 안쪽의 원(비즈니스 로직) 바깥의 원(UI나 data source)에 대해 전혀 알지 못한다.
  • 안쪽 영역으로 갈수록 추상화와 정책의 수준이 높아지며, 반대로 갈수록 구체적인 세부사항으로 구성된다.

클린아키텍처 구조의 이해

 

이 글에서는 Next.js 프로젝트를 대상으로 위의 규칙을 준수하여 구성해 보겠다.
Next.js의 많은 예제들의 수준과 비슷하게 한다면, 아래와 같은 계층을 가진 구조의 모양이 나올 수 있다.

Core

입력과 출력으로부터 거리가 멀기 때문에 고수준이라고 볼 수 있는 계층이다.
앞서 말한 원칙에서 세부적인 도메인 로직이 아닌, 웹 애플리케이션 로직과 추상화된 코드들이 들어간다.
예를 들면 아래와 같은 성격의 코드들이 들어갈 수 있다.

  • 애플리케이션이 외부와의 통신을 위해 필요한 구현체
  • 도메인과 연관이 없는 고수준의 유틸리티
  • 재사용가능한 컴포넌트
    • ex) Button, Input, Select
  • 중요도가 높은 외부 모듈(라이브러리)의 어댑터

Core 계층에 있는 코드들은 절대 Core 원의 외부에 있는 계층(lib/components, pages)을 참조하면 안 된다.

Components / Lib

이 계층은 도메인에 종속적이며, Core 계층의 코드들을 참조할 수 있고, 아래 예시와 같은 코드들이 들어간다.
( 주문이라는 도메인이 속한 프로젝트라고 가정. )

 

- src
     - lib
         - order
             - constatns
             - hooks
             - mutations
             - queries
             - utils
             - ....
 
 - src
     - components
         - order
             - ItemList.tsx
             - Price.tsx
             - Payment.tsx
             - ...

 

  • Lib
    • 도메인에 관련되어 있는 로직들.
    • components 계층과 pages 계층에서 참조되어진다.
  • Components
    • 도메인에 관련되어 있는 컴포넌트.
    • 도메인에 국한되어 재사용성은 낮다.
    • pages 계층에서 참조되어진다.

Pages

도메인에 의존도가 높은 계층. 입력/출력과 밀접해있으며, 가장 저수준이라고 볼 수 있다.
Next.js의 기본 설정 값인 파일 시스템 기반으로 라우팅 처리를 하며, Components Lib 계층의 코드들을 참조하여 구성할 수 있다.

- src
   - pages
     - api
       - order
         - [...slug].tsx  // src/lib/order/.. 참조
         - ...
     - order
       - [id].tsx // src/components/order/.. 참조
       - _middleware.tsx // src/lib/order/.. 참조
       - ...

 

Dependency diagram

위의 구조와 규칙을 가지고 간략히 의존성 그래프로 표현하면 아래와 같은 모양이 될 것이다.

의존성은 모두 단방향으로만 흘러가고, 역으로 참조해서는 안 된다.

예를 들어, core 계층에 API 통신을 위한 구현체가 있다고 가정해 보자.
이 구현체는 UI의 형태 혹은 상태, 세부적인 도메인 로직를 알아서는 안되며, 알아도 좋을 게 없다.
마찬가지로 도메인에 종속적인 코드들 또한, 이 구현체가 비동기 통신을 위하여 어떤 객체를 사용하여 구현이 되었는지, 어떻게 API 서버와 통신을 하는지 전혀 알 필요가 없다.

이러한 관심사의 분리로 인해 각 모듈은 여러 책임에서 벗어나기 쉽고, 테스트하기도 더 쉬워지며, 유지 보수 비용도 줄어들 것이다.

 

아래는 내가 직접 응용한 구조이다. 

 

 

core -> common에 api 를 담은 폴더와 타입들을 지정해둔 각 서비스 마다 dto 폴더를 생성하여 정의하였고

useCasese -> 각 서비스 아래에 폴더이른과매칭되는 ts 파일로 어플리케이션 비즈니스 로직을 수행하는 영역으로 api 통신에 있어 중간다리하는 역할 하는 부분으로 구분을 지었다. 

controller -> 부분은 pages 폴더 추후에 추가할 custom hook 폴더를 추가할 예정이다.

 

결론

실무에서 업무를 하다보면 직관적이지 못한 프로젝트 구조들로 인해 많은 시간을 낭비하였다. 좋은코드구조는 남들이보기에 한눈에 들어오는 구조이며 누구나 이해할 수 있는 영역이라고 생각한다.그런 구조를 생각하면서 구조를 짜고 코드를 생성 한다면 개발자의 시간 등이 많이 아껴지리라고 본다.

 

 

깃허브 https://github.com/asdf132645/reactToyProject

 

node express 에 대한 개념 설명과 개념을 정리 해보겠다.

 

1. 미들웨어 스택

express 서버 코드의 핵심은 클라이언트의 각 요청을 처리하는 라우팅 로직을 구현하는것이고, 라우팅 로직을 구현하는 것은 곧 미들웨어 스택을 구출을 의미한다. 미들웨어 스택은 클라이언트의 요청을 처리하는 함수들이 설정된 순서대로 저장되어있는 구조를 의미한다. 이는 미들웨어, 라우터 핸들러, 에러 핸들러로 구성되어있다. 라우터라는 단위로 묶을 수 있다.

 

1. 애플리케이션 레벨 미들웨어

애플리케이션 레벨이란 아래서 살펴볼 express()로 생성할 수 있는 app 객체의 app.use()나 app.METHOD()(ex. app.get, app.post) 함수를 이용해 미들웨어를 app 인스턴스에 바인딩하는 미들웨어이다. 마운트 경로가 없는 미들웨어 함수는 앱이 요청을 수신할 때마다 실행하게 된다.

 

app.get('/pages/', (req, res, next) => {
  console.log('Time : ', Date.now());
  next();
});

app.get((req, res, next) => {
  console.log('Not Found');
});

 

하나의 경로에 app 메서드 여러개가 묶일 수 있는데 다음예시를 주의깊게 보자

 

app.get('/pages/:id', (req, res, next) => {
  if (req.params.id == 0) next('route');
  else next();
}, (req, res, next) => {
  res.send('regular');
}
});

app.get('/pages/:id', (req, res, next) => {
  res.send('special');
}

 

위에 경우는 2개묶인 app 메서드가 위에 있으므로 special 보다 먼저 실행된다. next() 는 지금 라우터 미들웨어 스택을 벗어난 다음 라우터로 제어가 넘어가게 하는것이다. 라우터 미들워ㅔ어 스택이란 하나의 app.use()나 app.메서드 에 묵인 라우팅 미들웨어들을 말한다.

여기서 그냥 next()는 regular로 넘어가게 된다. id가 0이 아니라서 regular로 넘어간다면, 거기서 next()를 호출하지 않았으므로 special은 호출되지 않는다. 

next() 안에 인자가 들어가는 경우는 아마 next('route')와 next(err)뿐일 것 같다. next 안에 뭔가 인자가 들어가면 express 앱은 그것을 오류 발생이라고 보고 오류 처리와 관련없는 다른 모든 미들웨어를 다 건너뛰고 오류 처리(error handling) 라우터로 넘어간다. 단 하나 'route'만 빼고 말이다. 'route'는 현재 메소드를 벗어나 path에 해당하는 다음 라우터로 제어가 넘어가는 것이다.

 

2. 라우터 레벨 미들웨어

라우터 레벨은 express.Router()로 생성할 수 있는 router 인스턴스에 미들웨어가 바인딩되는 것이다. 그것 외에는 애플리케이션 레벨 미들웨어가 차이가 없다. router.use()나 router.METHOD() 함수를 이용해 로드할 수 있다.

express.Router() 로 router 객체를 생성할 수 있는데, 미들웨어와 HTTP 메소드 라우트를 router 객체에 붙일 수 있다.

 

//app.js
const express = require('express');
const app = express();
const pageRouter = ('./routes/pages');
app.use('/pages', pageRouter);
//pages.js
const express = require('express');
const router = express.Router();

router.get('/pages/:id', (req, res, next) => {
  //pages id가 0이면 'regular'가 아닌 'special'로 넘어감
  if (req.params.id == 0) next('route');
  //pages id가 0이 아니라면 'regular'로 넘어감
  else next();
}, (req, res, next) => {
  res.send('regular');
}
});

//pages id가 0일 때 넘어올 미들웨어
router.get('/pages/:id', (req, res, next) => {
  res.send('special');
}

module.exports = router;

 

3. 오류 처리 미들웨어

오류 처리 미들웨어는 (err, req, res, next)를 인자로 받는 것이다. 항상 4개의 매개변수가 필요하다. 이게 오류 처리 미들웨어의 시그니처다. err.stack으로 에러 메시지를 볼 수 있다.

 

//오류의 종류에 상관없이 모든 오류를 잡는 미들웨어
app.get((err, req, res, next) => {
  console.log(err.stack);
  res.status(500).send('Something broke!');
});

주의할 점은 오류 처리 미들웨어는 app.use() 및 라우트 호출을 정의한 뒤 거의 코드의 맨 끝에 정의해야 한다는 점이다. 

위의 경우 모든 오류를 잡는 미들웨어 하나만 만들었는데, 에러마다 다른 오류 처리 미들웨어 함수를 정의할 수도 있다. 이 경우 catch-all 에러 핸들러는 그 오류 처리 미들웨어들 중에서도 가장 아래 있어야 한다.

오류 처리 미들웨어는 다음과 같이 부를 수 있다.

 

4. 기본 제공 미들웨어

기본 제공은 정적 리소스를 제공할 루트 디렉토리를 정하는 express.static 같은 것이 있다. 현재 문서에는 빌트인 미들웨어는 express.static 뿐이라고 되어 있다. 정적 파일을 전달해주는데, 여기서는 /public 디렉토리가 정적 파일들이 모여 있는 루트 디렉토리가 된다. 아래서 더 자세히 설명하겠다.

app.use(express.static(__dirname + '/public'));

 

 

5. 써드파티 미들웨어

마지막으로 써드파티 미들웨어는 npm 에서 설치한 helmet이나 cookie-parser 같은 모듈들이 해당이 된다. 쉽게 말해 express 자체적으로 제공하지 않고 따로 설치해야 하는 것들은 다 써드파티라고 보면 된다.

npm i cookie-parser
const express = require('express');
const app = express();
const cookieParser = require('cookie-parser');

app.use(cookieParser());

이 때 cookieParser()를 하면 미들웨어를 반환한다. 

오늘은 리액트 를 통해 디비에 값을 뿌리는 작업을 진행 하겟당!

 

전에 작업한 링크

https://asdf1326.tistory.com/7

 

리액트 express 를 사용하여 MySQL 연동하기

오늘은 리액트 node js express 를 사용하여 MySQL 을 연동할것이다. 근데 오늘 몸상태가 최악..ㅠ 1. 프로젝트 생성 나는 vscode와 웹스톰을 번갈아가면서 쓴다 ㅎ 이번에는 vscode 로 진행을 하였다.~ 터

asdf1326.tistory.com

 

일단 필요한 구조를 설명하자면 

클라이언트 폴더, 서버 폴더 분리해서 직접 생성 한 디비를 연결작업을 진행해보겠다~!

클라이언트 생성명령어 npx create-react-app 폴더명칭 --template typescript

서버측은 위에 링크 참고

위에 폴더를 차례대로 생성 후 일단 디비를 생성

 

스키마 하나 새로 생성 후 use nodejs 로 데이터베이스 선택

위에처럼 생성

데이터 추가 후 명령어로 테이블 확인

 

index.js 

const express = require("express");
const app = express();
const mysql = require("mysql");
const PORT = process.env.port || 3000;

const db = mysql.createPool({
  host: "127.0.0.1",
  user: "root",
  password: "0000",
  database: "nodejs",
});

 app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
  res.header("Access-Control-Allow-Headers", "x-access-token, Origin, X-Requested-With, Content-Type, Accept");
  next();
});

app.get("/list", (req, res) => {
  const sqlQuery = "SELECT *FROM BOARD;";
  db.query(sqlQuery, (err, result) => {
    res.send(result);
  });
});

app.listen(PORT, () => {
  console.log(`running on port ${PORT}`);
});

여기서 주의할점이 가끔 cors 에러가 뜨곤 한다 미리 사전의 방지를 하는것이 좋다!

header에 추가적인 조치를 취해준다. 응답 헤더부분에 추가적으로 넣으면 된다. 내가 추가한 값이 제대로 들어가있다~

원래는 다른 코드를 써서 조작을해야 안전하게 하나의 도메인만 받는게 좋다 * 로 설정해둔 오리진 부분은 사실 많이 쓰지 않는 방식이다.!

인터넷 검색으로 치면 많은 설명들이 나온다 꼭 개발이 아닌과정에서는 확인 후 사용해주자~

이제 서버측은 셋팅이 끝낫당.!

클라이언트쪽으로 넘어가서 만들어보자~

클라이언트 소스확인 가능한 깃허브 주소 : https://github.com/asdf132645/client

 

GitHub - asdf132645/client

Contribute to asdf132645/client development by creating an account on GitHub.

github.com

import { Component } from "react";
import Axios from "axios";
import Table from "react-bootstrap/Table";
import Button from "react-bootstrap/Button"; 

const Board = ({
  id,
  title,
  registerId,
  registerDate,
}: {
  id: number;
  title: string;
  registerId: string;
  registerDate: string;
}) => {
  return (
    <tr>
      <td>
        <input type="checkbox"></input>
      </td>
      <td>{id}</td>
      <td>{title}</td>
      <td>{registerId}</td>
      <td>{registerDate}</td>
    </tr>
  );
};

/**
 * BoardList class
 */
class BoardList extends Component {
  state = {
    boardList: [],
  };

  getList = () => {
    Axios.get("http://localhost:3000/list", {})
      .then((res) => {
        const { data } = res;
        this.setState({
          boardList: data,
        });
      })
      .catch((e) => {
        console.error(e);
      });
  };

  /**
   */
  componentDidMount() {
    this.getList();
  }

  /**
   * @return {Component} Component
   */
  render() {
    // eslint-disable-next-line
    const { boardList }: { boardList: any } = this.state;

    return (
      <div>
        <Table striped bordered hover>
          <thead>
            <tr>
              <th>선택</th>
              <th>번호</th>
              <th>제목</th>
              <th>작성자</th>
              <th>작성일</th>
            </tr>
          </thead>
          <tbody>
            {
              // eslint-disable-next-line
              boardList.map((v: any) => {
                return (
                  <Board
                    id={v.BOARD_ID}
                    title={v.BOARD_TITLE}
                    registerId={v.REGISTER_ID}
                    registerDate={v.REGISTER_DATE}
                  />
                );
              })
            }
          </tbody>
        </Table>
        <Button variant="info">글쓰기</Button>
        <Button variant="secondary">수정하기</Button>
        <Button variant="danger">삭제하기</Button>
      </div>
    );
  }
}

export default BoardList;

npm install axios 로 모듈 설치해주고

우리는 서버 포트는 3000이다. 명확하게 클라이언트 포트도 나눠주자!

요로코롬 start 할때 포트 8000 으로 이어주자~ 그래야 겹치지 않고 서로다른 포트에서 연결이 잘되니깐!

이제 마지막으로 화면을 확인하고 네트워크를 봐주자~

잘나온다 ! 네트워크도 확인 해보자!

 

응답값이 아주이쁘게 들어가있다.!! 뷰만 할때는 못느낀건데.. 컴포넌트 반복문 쓸때 좀 낮설다.. map 함수를 써서 반환 시키는게 참 낮설다... 뷰는 v-for 써주고 key 써주면 아주 이쁘게 잘들가는뎅.. 참 낮설어...! 암튼이게 문제가 아니고 다음에는 테이블내용 추가 수정등을 해볼것이다~ 그리고 리덕스도 차근차근 적용하고~ 라우터도 해볼것이다~ 이것으로 코인의 백엔드 조작 탐방 일기 끄읏~~~

다음 일기에서 계속~!~

오늘은 리액트 node js express 를 사용하여 MySQL 을 연동할것이다. 근데 오늘 몸상태가 최악..ㅠ 

 

1. 프로젝트 생성 

나는 vscode와 웹스톰을 번갈아가면서 쓴다 ㅎ 이번에는 vscode 로 진행을 하였다.~

터미널 창을 킨후

npx create-react-app simple-react-board --template typescript

로 실행하면 파일이 생성되면

 

각종 파일들에 들어가서 다 변경해주고

필요한 모듈을 설치해준다.

npm i react react-dom typescript

npm i @types/react @types/react-dom @types/node

 

tsconfig.json 에 들어가서 

변경 나는 es6를 사용할거니깐!

 

이제 서버 프로젝트를 새로 생성해준다.

서버 프로젝트로 폴더 이동 후

npm init -y

생성 된걸 확인했으면 이제 관련 모듈들을 설치해주자

 

npm install express body-parser mysql
npm install nodemon

nodemon은 서버 코드가 수정됐을때 자동으로 서버를 재시작해주는 모듈

 

index.js 를 하나 만들어주고

const express = require('express');
const app = express();
const PORT = process.env.port || 8000;

app.listen(PORT, ()=>{
console.log(`running on port ${PORT}`);
});

 

node index.js  를 치면 실행

 

실행된게 보이면 성공

 

패키지json 에 스크립트에 코드추가

"start": "node index.js",

"dev": "nodemon index.js"

 

터미널에서 컨트롤 c 로 서버를 끄고 아래 명령어로 실행시킨다.

npm run dev

 

이렇게 나오면 성공~

데이터베이스 연동을 위해 index.js 수정

위로 변경 후 로컬호스트를 킨다.

/ 으로 첫 화면인 홈으로 진입시 seccess 적어둔게 잘뜬건 보인다 제대로 연동이 되었는지 확인을 한다!

Workbench 로 들어가서 쿼리를 실행해서 /으로 진입시 1값을 잘넣고 있는지 확인하자.

 

쿼리문 작성해서 보면 아주 잘넣어지고있다~

 

다음에는 클라이언트 프로젝트에서 axios 를 사용해보겟다 ~

+ Recent posts