노드로 서버 구동하기

5o_hyun·2023년 6월 15일
0
post-thumbnail

기본노드

기본노드 http로 백엔드 서버 만들어보자.

  1. package.json을 만든다.
    npm init
    package name : react-nodebird-back
    author : sohyun

  2. app.js를 만든다.

const http = require("http");
const server = http.createServer((req, res) => {
  console.log(req.url, res.method); // req = 요청, res = 응답
  res.write("hello node"); // 여러줄 쓰고싶을땐 write쓰다가 마지막에 end
  res.write("hello node");
  res.write("hello node");
  res.end("hello node end");
});
server.listen(3065, () => {
  console.log("서버 실행중");
});

createServer에서 요청메서드나 url에 따라서 응답을 해준다.

  1. node app.js로 실행
    터미널에 '서버실행중'이 뜨면 실행중
    지정해준 포트로 들어가서 확인 http://localhost:3065/

이렇게 줄줄이 쓰게되면 코드가 길어지니깐 express로 만들어보자.

express

express도 내부적으로 http쓰기때문에 서버로 돌릴수있는것이다.
그래서 노드가 서버가아니라 노드에서 제공하는 http모듈이 서버인것이다.

  1. npm i express 설치

  2. app.js 수정
    문자열 : write, end 대신 send를 사용한다.
    데이터 : json을 사용한다.

const express = require("express");

const app = express();

app.get("/", (req, res) => {
  res.send("hello express");
});

app.get("/", (req, res) => { // 라우트
  res.send("hello api");
});

app.get("/posts", (req, res) => {
  res.json([
    { id: 1, content: "hello" },
    { id: 2, content: "hello2" },
    { id: 3, content: "hello3" },
  ]);
});
app.post("/post", (req, res) => {
  res.json({ id: 1, content: "작성완료" });
});
app.delete("/post", (req, res) => {
  res.json({ id: 1 });
});

app.listen(3065, () => {
  console.log("서버 실행중");
});

app.get : 가져오기
app.post : 생성하기 , 애매하면 다 post (게시판조회해서 게시물 하나더 추가 등)
app.put : 전체 수정
app.delete : 제거하기
app.patch : 부분 수정
app.options : 찔러보기 서버얌..나요청하면받아줄껴?
app.head : 헤더만가져오기 (헤더/바디)

이걸 다 지키는거를 restAPI 라고 하는데 사실상 다 지키긴 어려움

swagger : 무비앱마냥 api문서를 만들어줌

express 라우터 분리

같은 주소끼리 라우터 분리.

프론트에서는 import, export를 쓰는데 백에서는 require, module.exports를 쓴다.
둘다 노드로 돌리는건데 왜 차이가 있을까?
프론트에서 import, export를 웹팩이 중간에서 내부적으로 require, module.exports로 바꿔준다.
백엔드의 node는 애초에 웹팩을 안쓰기때문에 처음부터 require, module.exports를 쓰는것이다.
나중엔 통일되겠지.....

app.js

const express = require("express");
const postRouter = require("./routes/post"); // import

const app = express();

app.get("/", (req, res) => {
  res.send("hello express");
});

app.get("/", (req, res) => {
  res.send("hello api");
});

app.get("/posts", (req, res) => {
  res.json([
    { id: 1, content: "hello" },
    { id: 2, content: "hello2" },
    { id: 3, content: "hello3" },
  ]);
});

app.use("/post", postRouter); // 수정부분 => prefix. postRouter안에있는건 /post로 주소를 하겠다. 

app.listen(3065, () => {
  console.log("서버 실행중");
});

routes > post.js (새파일)

const express = require("express");

const router = express.Router();
router.post("/", (req, res) => { // 기능:POST 주소:/post
  res.json({ id: 1, content: "작성완료" });
});
router.delete("/", (req, res) => { // 기능:DELETE 주소:/post
  res.json({ id: 1 });
});

module.exports = router;

MySQL과 시퀄라이즈 연결하기

mysql : 데이터저장소
시퀄라이즈 : 백엔드노드서버와 데이터저장소를 연결해주는 라이브러리 : 자바스크립트로 sql을 조작할수있도록 도와줌
'객체-관계-데이터베이스'
내가 짠 자바스크립트코드를 데이터베이스(mysql)에 sql문으로 바꿔서 던져주기위해 시퀄라이즈를 씀
즉, 시퀄라이즈는 ORM임

  1. MySQL 접속
  2. 다운로드
    맨아래 'MySQL Community (GPL) Downloads »' 클릭
    1) installer먼저 다운 (생략가능)
    2) communiy server (mysql설치) , workbench (터미널에있는걸 gui로 이쁘게보여줌) 다운

mac OS 에서,

macOS 에서 다운받으려고 보니 installer에 윈도우가 없어서 다음 게시글을 보고 참고해서 진행했다.
하고나서보니 installer안하고 communiy server , workbench 다운만 해도될듯.
https://www.codeit.kr/tutorials/5/MySQL-%EC%84%A4%EC%B9%98-macOS

설치를 다 하면, 시스템환경설정 열어서 맨밑에보면 설치가 되어있을것이다.
start에 체크되어있으면 실행되고있는거임.

나머지 워크벤치도 깔아준다.

이제 워크벤치를 실행해보자.
오 뭔가 ui가 뜨긴떴다.


이제, 우리가 짠 코드로 mysql을 시퀄라이즈로 조작해볼것이다.
시퀄라이즈는 자바스크립트로 mysql을 조작할수있도록 도와주는 라이브러리다.

시퀄라이즈

1. 시퀄라이즈 다운

npm i sequelize sequelize-cli mysql2 (mysql2는 노드와 mysql을 연결해주는 애.)

2. 시퀄라이즈 설정

npx sequelize init
config.json에 들어가보면 환경에따라 개발용, 테스트용, 배포용의 데이터베이스가 다 따로따로있다.
데이터베이스 실수를 방지하기위해.

config.json을 다음과같이 바꿔준다.password는 mysql비번, database에 제목

models > index.js에 들어가서 시퀄라이즈가 너무 옛날거라 입맛에 맞게 바꿔준다.

const Sequelize = require("sequelize");
const env = process.env.NODE_ENV || "development"; // 환경변수 기본값으로 development. 나중에 배포시 production || development로 바꿔 배포용일땐 production써준다
const config = require("../config/config")[env]; // config의 development를 가져온다.
const db = {};

// 시퀄라이즈에 이 정보를 보내면 mysql2드라이버에 들어가서 mysql과 노드를 연결할수있게된다.
// **** 이거 생성자함수라 꼭 순서에 맞게 사용해야한다. 두번이나 애먹음.. *****
const sequelize = new Sequelize(
  config.database,
  config.username,
  config.password,
  config
);

Object.keys(db).forEach((modelName) => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

3. 시퀄라이즈 모델 만들기

이제 mysql 테이블을 만들자.

modals 폴더에 user.js 파일을 생성한다.
이때 생성하는 파일들은 테이블이 되고, 파일안의 define의 첫번째 객체들은 해당 테이블의 컬럼이된다
테이블 데이터 컬럼

.

module.exports = (sequelize, DataTypes) => {
  const User = sequelize.define(
    "User",
    {
      //   id: {},  mysql에 기본적으로 들어있다.
      email: {
        type: DataTypes.STRING(30), // 몇글자정도? STRING, TEXT, BOOLEAN, INTEGER, FLOAT, DATETIME
        allowNull: false, // true : 선택적 ,false : 필수
        unique: true, // 고유한값
      },
      nickname: {
        type: DataTypes.STRING(30),
        allowNull: false,
      },
      password: {
        type: DataTypes.STRING(100), // 비밀번호는 암호화하기떄문에 넉넉하게 남겨놔야함
        allowNull: false,
      },
    },
    {
      // 이 두개를 써주면 한글저장.
      charset: "utf8",
      collate: "utf8_general_ci",
    }
  );
  User.associate = (db) => {};
  return User;
};

/*
	define 뒤가 모델이름 : User . 'User'는 mysql에 가면 자동으로 소문자,복수형이되어 'users' 테이블이 된다.
	첫번째 객체는 사용자에게서 받을 객체,
	두번째 객체는 기본저장
 */

4. 시퀄라이즈 관계 설정하기

테이블 파일들(user.js)을 보면 각 모델관의 관계를 설정하는 associate가 있다.

일대다관계 : hasMany belongsTo

예시1) 다른 테이블과의 일대다관계
user.js

// 하나의 user에 게시글은 여러개있을수있다. hasMany
db.User.hasMany(db.Post);

post.js

// 하나의 게시물에 user는 여러명일수 없다. belongsTo
db.Post.belongsTo(db.User);

예시2) 같은 테이블에서 일대다관계
리트윗(하나의게시물에 트윗을 한번밖에못함. 하나의게시물에 트윗은 여러개 당할수있음.)

db.Post.belongsTo(db.Post, { as: "Retweet" });

다대다관계 : belongsToMany 다대다는 중간테이블이생김

  • through : 중간테이블 이름 설정 (안해도 자동으로 생성됨)
  • as : 같은게 많을때 구분을위해사용. 나중에 getLiked등을 가져올수있음
  • foreignKey : 먼저 찾을것을 써줌 , 컬럼 아이디 설정

예시1) 다른 테이블과의 다대다관계
user.js

db.User.hasMany(db.Post);
db.User.belongsToMany(db.Post, { through: "Like", as: "Liked" });
// 한명의 사람은 여러개의 게시물에 좋아요를 누른다. belongsToMany

post.js

db.Post.belongsTo(db.User);
db.Post.belongsToMany(db.User, { through: "Like", as: "Likers" });
// 하나의 게시물은 여러사람에게 좋아요를 받을수있다. belongsToMany

예시2) 같은 테이블과의 다대다관계
팔로잉 팔로워를 찾을때 같은 user테이블 내에서 찾아야함.

db.User.belongsToMany(db.User, {through: "Follow",as: "Followers",foreignKey: "FollowingId"});
db.User.belongsToMany(db.User, {through: "Follow",as: "Followings",foreignKey: "FollowerId"});

일대일관계 : hasOne belongsTo
user.js

// 하나의 user에 userInfo는 하나다.
db.User.hasOne(db.Userinfo);

userinfo.js

db.Userinfo.belongsTo(db.User);

belongsTo를 어디 테이블에 놓아야할지 고민이 되면, 새 정보가 어디에 생기는지 고민해보면된다. 따라서, 하위개념에 belongsTo를 놓아야한다.

5. 시퀄라이즈 실행하기

개같이 2시간동안 만들어본거를 실행해보자.
테이블로 쓰려고 만들었던 파일의 상단을보면 module.exports = (sequelize, DataTypes) => {
시퀄라이즈 함수로 만든것을 볼수있다.
index.js에 import해주면(require) 해당되는 파일의 내부가 실행하면서 그 모델이 실제로 시퀄라이즈 등록이된다.

index.js

// db 빈 배열에 만든 테이블 import
db.Comment = require("./comment")(sequelize, Sequelize);
db.Hashtag = require("./hashtag")(sequelize, Sequelize);
db.Image = require("./image")(sequelize, Sequelize);
db.Post = require("./post")(sequelize, Sequelize);
db.User = require("./user")(sequelize, Sequelize);

app.js

const db = require("./models");

db.sequelize.sync()
  .then(() => {
    console.log("db연결성공");
  })
  .catch(console.error);

다음을 추가해준다.
npx sequelize db:create

created뜨면 된거임.

node app 으로 실행

이제 mysql workbench를 보면 테이블이 생성된것을 확인할수있다.

nodemon

코드를 바꾸면 알아서 재실행하게 만들어주자.

지금까지 코드를 고치면 서버를 종료시켰다가 다시 node app 으로 켜야하는 번거로움이 있었다.
npm i -D nodemon

원래는 nodemon app 으로 실행해야하는데 프론트랑 실행명령어를 똑같이하기위해 npm run dev로 실행시키고싶으니 pakage.json에 추가해준다.

profile
학생 점심 좀 차려

0개의 댓글