dukDukz

[블록체인] 프로젝트를 위해 기본 틀 잡기 part 1 본문

웹 개발/블록체인

[블록체인] 프로젝트를 위해 기본 틀 잡기 part 1

헤일리_HJ 2021. 9. 28. 14:56

# 프로젝트를 들어가기 전에...

 

- 기본적인 틀이 필요할 듯..

거래소의 초점 → 백앤드에 있다고 봐야함

프론트도 리액트를 쓴다고 하면 양이 생각보다 많을거임

 

백엔드 기반을 만들어놔야 할 듯..

 

로컬에서만 돌렸던 것을 PC 끼리 Peer 걸어서 코인을 주고 받는것을 해봐야함

 

업비트 빗썸을 사용한다고 하면,

내 계좌에 현금을 넣는다. 

 

- 입출금 내역

- 호가 창

 

만들어봐야함

 

React 제외하고 일단은 nunjucks 로 할거임

 

데몬과 express DB 까지 3개의 서버를 돌린다고 생각하면 됨.

React 한다면 총 4개의 서버가 될듯.

리액트 책에 거래소 만들기 참고

 

데몬은 코인을 저장하는 실질적인 저장소라고 보면 될 듯

 

공통적으로 들어가는 부분 싹다 만들어놓고 시작하는것.- 와꾸잡는다..

 

 

[전체적인 틀]

 

express 의 역할은 브라우저(사용자)와의 상호작용을 위함이다.

+ express 는 html 정적 페이지를 주는데 DB 에 있는걸 가져다가 주는것도 한다.

 

express 는 거래소가 될거라서 데몬 서버가 필요하다.

그 중에 우리가 쓰는 데몬에 RPC 통신을 할 것이다.

 

express 가 중간다리 역할을 하면서 DB / 데몬과 소통하는 역할을 한다.

 

그래서 api 관련된거 -> RPC

 



 

# Setting

 

npm init

npm install express

npm install nunjucks

npm install request

npm install body-parser

npm install sequelize

npm install sequelize-cli

npm install mysql2


[한번에 하려면]
npm i express nunjucks request body-parser sequelize sequelize-cli mysql2



npx sequelize init

 

1. models > index.js

fs 부분 지우고 필요없는 부분 정리



2. config > config.json

password "root"

database "exchange_팀명"

 

로컬 컴은 development

배포용은 production 에 적어야 함



3. mysql 접속

# MYSQL

$ create database exchange;
$ use exchange



4. sever.js 생성

기본 세팅 

const express = require('express')
const nunjucks = require('nunjucks')
const app = express()
const db = require('./models')

const PORT = process.env.PORT || 3500

 

이거에 대한 세팅 하기




5. 패키지 설치

# morgan

npm install morgan

 

로그 관련된것..

req.body  |  req.query 를 자동으로 찍어주는 녀석

불필요한 콘솔 로그를 줄여줌

 

[server.js]

const morgan = require('morgan')

app.use(morgan('dev'))

 

db 세팅 바로 밑에 미들웨어를 실어준다

: get 방식 확인

 

 

 

6. nodemon 설치

# nodemon

: 서버 자동 업뎃

npm install -g nodemon

 

index.html 수정하고

server.js 에서 ctrl+s 로 저장

하면 서버 restart 안해도 잘 반영이 된다.



# nodemon 오류

[해결방법]

1. powershell 관리자 권한으로 실행

 

2.  get-ExecutionPolicy

PS C:\Windows\system32> get-ExecutionPolicy

Restricted

: 안된다는 뜻.

 

3. set-ExecutionPolicy Remotesigned

$ set-ExecutionPolicy Remotesigned

이후 y 누르고 엔터

 

 


7. 없는 페이지 404 처리

views > 404.html 만들고

[server.js]

# 404 에러처리

app.use((req,res,next)=>{
    //server.js 입장에서는 error 가 아니므로 강제로 err 를 만들어줌
    const error = new Error(`${req.method} ${req.url} 정보가 없습니다`)
    error.status = 404
    logger.error(error.message)
    res.render('404')
})

listen 위에 써주면 됨 (미들웨어. 모든 페이지가 다 거쳐가도록 '/' 이런거 안써줌)

 

 

 

8. winston 설치 - 콘솔로그 대체 => logger.info('aaaaa')

npm install winston

 

console.log 는 안쓰는 방향으로 나가야 한다.

그래서 콘솔로그 대신 찍는 winston 라는걸 사용해서 출력하도록 해보자.

 

logger.js 파일 생성 (외울 필요 없음)

const winston = require('winston')
const {format} = require('winston')

const logger = winston.createLogger({
    level : 'info',
    format : winston.format.json(),
})

if(process.env.NODE_ENV !== 'production'){
    // 개발모드인 경우
    logger.add(new winston.transports.Console({format:format.simple()}))
}

module.exports = logger

 

production / development

 

항상 테스트할때 코드와 배포할 때 코드는 같아야함

그리고 특정 값만 바꿔서 할 수 있도록 해야함

 

production 일때는 콘솔로그 안찍는 방향으로..


이렇게 작성한걸 server.js 에 옮겨 오면 된다.

[server.js]


const logger = require('./logger')

app.use((req,res,next)=>{
    logger.error('err 입니다')
    res.render('404')
})

console.log 를 logger.info 로 바꿔준다.

에러는 logger.error 로 써준다.

 

 

+) 추가로 알아볼 것들...

이렇게 된것들을 

초록색으로 빨간색으로 칠할 수 도 있고

로그를 모아놓은 로그 파일을 만들 수 있다.



콘솔로그를 많이 찍으면 안되는 이유

https://yangbongsoo.gitbook.io/study/undefined/log

 

로그는 반드시 필요한 내용만 찍자

 

yangbongsoo.gitbook.io

 

 

 

 

 

9. 라우터로 파일 쪼개기

routes 폴더 생성

[routes > index.js]

const express = require('express')
const router = express.Router()

// 거래소 관련
// api 관련

module.exports = router

 

 

9-1. RPC (API 관련 내용은 여기에 작성)

[routes > rpc.js] 생성

/api 뒤에 붙어서 오는 애들은 다 RPC 통신으로 할 것이다.

어제 써줬던 것처럼 headers / USER / PASS / RPCPORT 처럼 많이 쓰는 값을 따로 빼준다.

 

# [routes > rpc.js]

const express = require('express')
const router = express.Router()
const request = require('request')

const headers = {"Content-type":"application/json"}

const USER = process.env.RPC_USER
const PASS = process.env.RPC_PASS
const RPCPORT = process.env.RPC_RPCPORT
const ID_STRING = 'ingcoin_exchange'
const ACCOUNT = 'ingoo'



module.exports = router

 

routes > index.js 연결해주고 그거를

server.js 에서 라우터 연결을 해주면 된다.

# [routes > index.js]

router.use('/api',require('./rpc'))




# [server.js]

const router = require('./routes')

app.use('/',router)

 

테스트 해보자

 

[server.js]

// localhost:3500/api/test
router.get('/test',(req,res)=>{
    res.json({msg:'test api'})
})

 

 

보낸데로 잘 나온다.

 

 

 

9-2. RPC 블록 총 개수 알아보기

# RPC 블록 총 개수 알 수 있도록 

[routes > rpc.js]

const url=`http://${USER}:${PASS}@127.0.0.1:${RPCPORT}`

//블록개수 구하기
router.get('/getblockcount',(req,res,next)=>{
    let obj = {
        jsonrpc:"1.0",
        id:ID_STRING,
        method:"getblockcount",
        params:[]
    }
    let body = JSON.stringify(obj)  // obj -> string 으로 바꿈

    let options={
        url,
        method:"POST",
        headers,
        body
    }

    // 위에 인자값에 next 추가하고
    const callback = (err,response,data)=>{
        if(err == null && response.statusCode == 200){
            const body = JSON.parse(data)
            res.json(body)
        }else{
            next()
        }
    }
    request(options,callback)
})



# obj 부분을 객체를 만들어주는 함수로 빼면 좋을 듯 하다.

function createbody(method, params = []) {
    let obj = { jsonrpc: "1.0", id: ID_STRING, method, params }
    return JSON.stringify(obj)
}

만들어주고


사용할 때는 이렇게 하면 된다.

let body = createbody("getblockcount",[])

 

# 테스트

테스트 해보려고 한다.

브라우저 키고

 

localhost:3500/api/getblockcount

이렇게 해보면

 

엥?? 안나옴!!!

왜이럴까?

 

아마도 

const USER = process.env.RPC_USER

const PASS = process.env.RPC_PASS

const RPCPORT = process.env.RPC_RPCPORT

 

이렇게만 설정해놓고 정확한 값을 안줘서 그런듯...



# 전역변수 설정해주기 위해서

npm install dotenv

 

[server.js]

require('dotenv').config()

이렇게 선언함

 

하고 .env 파일 생성

RPC_USER=ingoo

RPC_PASS=1234

RPC_PORT=3000

이렇게 conf 파일 참고해서 작성한다.

 

잘되는지 확인해보기 위해서

[rpc.js]
require('dotenv').config()

const logger = require('../logger')

logger.info(USER)
logger.info(PASS)
logger.info(RPCPORT)

잘 나옴,,

 

[실제로는 리눅스 환경변수에 넣어놓고 해야된다.]

 

 

 

# DB 만들기

1) 방법 1

models > user.js 생성

내용 작성하거나

module.exports = (sequelize,DataTypes) =>{
    const User = sequelize.define('user',{
        userid:{
            type:DataTypes.STRING(50),
            allowNull:false,
        },
        userpw:{
            type:DataTypes.STRING(255),
            allowNull:false,
        },
        username:{
            type:DataTypes.STRING(10),
            allowNull:false,
        }
    },{
        timestamps:false,
        underscored:false,
        paranoid:false,
        modelName:'user',
        tableName:'user',
        charset:'utf8mb4',
        collate:'utf8mb4_general_ci',
    })
    return User
}

암튼 이렇게 하나 만들어서 다른거에서는 복붙해가면서 쓰면 된다.

 

 

 

2) 방법 2

$ npx sequelize-cli model:generate --name User2 --attributes userid:string,userpw:string,username:string

 

이렇게 해도 된다.

 

 

 

models > index.js

가서 연결시켜주면 된다.

db.User = require('./user')(sequelize,Sequelize)

이렇게 작성한다.

 

그렇게 하고 mysql 들어가서 

show tables;

하면 테이블이 생성된걸 확인 할 수 있다. ( 안되면 서버 껐다가 켜보기 nodemon server)