How We Coding

# REST

- REpresentational State Transfer

- REST is an architecture style for designing networked applications.(wiki)

- 표면적인 실체는 '스타일' 또는 '패턴'이라고 할 수 있다고 한다.




# RESTful API

- REST한 방식의 API란, 아래와 같이 잘 설계된 API를 의미한다고 한다.

  ・ 웹을 근간으로 하는 HTTP Protocol 기반이다.

  ・ 리소스는 URI(Uniform resource Identifiers)로 표현하며, 말 그대로 '고유'해야한다.

  ・ URI는 단순하고 직관적인 구조여야 한다.    

  ・ 리소스의 상태는 HTTP Methods를 활용해서 구분한다.

  ・ xml/json을 활용해서 데이터를 전송한다. (주로 json)



# CRUD

- 네트워크를 통해 웹 리소스(resource)를 다루기 위한 행위들.

- 각각의 행위를 처리하기 위한 HTTP methods(POST, GET, PUT, DELETE) 가 있다.

  ・ Create (POST)

  ・ Retrive (GET)

  ・ Update (PUT)

  ・ Delete (DELETE)



# API Design

- 복수명사를 사용 (/movies)

- 필요하면 URL에 하위자원을 표기함. (/movies/23)

- 필터조건을 허용할 수 있음 ( /movies?state=active)



# Example


 URL

Methods 

설명 

 /movies/

 GET

모든 영화 리스트 가져오기 

 /movies/

POST 

영화 추가 

 /movies/:title 

GET 

title 해당 영화 가져오기 

 /movies/:title

DELETE 

title 해당 영화 삭제 

 /movies/:title 

PUT 

title 해당 영화 업데이터 

 / movies?min=9

GET 

상영중인 영화 리스트 



'H6 > backend (Node.js, tsc)' 카테고리의 다른 글

<6> tsconfig.json 을 통한 컴파일 옵션 설정  (0) 2018.01.31
<5> node-mysql (Typescript)  (0) 2018.01.22
<4> MySQL & node-mysql  (0) 2018.01.22
<3> 에러처리..  (0) 2018.01.22
<2> app.ts 및 server.ts 만들기  (0) 2018.01.22

tsconfig.json 을 통해 컴파일 옵션을 설정할 수 있다.


- 컴파일 방법

$ tsp --p tsconfig.json


{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false
},
"exclude": [
"node_modules"
]
}


"target": "es6" // 결과물 ECMAScript 버전 설정

"module": "commons" // 모듈설정

"moduleResolution": "node" // 모듈 해석방식 설정

"sourceMap": true // 소스맵(*.map) 파일 생성 여부    

"emitDecoratorMetadata": true   // 

"experimentalDecorators": true   // ES Decorator 에 대한 실험적 기능 사용 여부

"removeComments": false // 주석 삭제

"noImplicitAny": false // 




이러한 옵션들이 있다고 한다.. (https://vomvoru.github.io/blog/tsconfig-compiler-options-kr/)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
{
  "include": [
      "src/**/*"
  ],
  "exclude": [
      "node_modules"
  ],
  "compilerOptions": {
    "target""ES2017"// 결과물 ECMAScript 버전 설정
 
    /////////// module ///////////
    "module""CommonJS"// 모듈 설정
    "moduleResolution""node"// 모듈 (검색)해석 방식 설정
    "allowSyntheticDefaultImports"false// export default 를 export 한 값들을 가지는 객체로 설정
    "forceConsistentCasingInFileNames"false// 파일명에 대소문자 구분하지 않아도 되는 기능 사용 여부
    // 직역: 파일 이름에 일관된 casing 강제 적용
 
    /////////// path ///////////
    "baseUrl""."// Non-relativ 모듈 혹은 paths 옵션의 기준 디렉토리
    "paths": { // baseUrl 옵션을 기준디렉토리로 불러올 모듈의 위치 설정이 가능
      "*": ["*"]
    }, 
    // "rootDirs": [ ], // 가상 디덱토리를 설정
    "rootDir""./"// 입력파일의 rootDir 설정
    // outDir옵션을 사용할때만 사용
    "outDir""dest"// 출력할 디덱토리
    // @TODO 테스트 필요
    // "outFile": "", // 단일파일로 출력시 파일명
    // @TODO 테스트 필요
 
    /////////// declaration ///////////
    "declaration"false// .d.ts 파일의 생성 여부
    "declarationDir"""// .d.ts 파일이 생성되는 디렉토리 설정
    
    /////////// log ///////////
    "diagnostics"false// @TODO 테스트 필요
    // Show diagnostic information.
    "traceResolution"false// 모듈 검색에 대한 로그메세지 출력 여부
    "listEmittedFiles"false// 컴파일된 결과 파일들 이름을 터미널에 출력
    "listFiles"true// 컴파일된 파일들 이름을 터미널에 출력
    "locale""ko"// 에러메세지 출력 언어 설정
    "pretty"true// 에러 메시지를 예쁘게 설정
    // @TODO 테스트 필요
 
    /////////// React ///////////
    // "jsx": "preserve", // jsx 지원
    // "jsxFactory": "React.createElement", // jsx 팩토리 함수 설정,
 
    /////////// JS ///////////
    // "allowJs": false, // 자바스크립트 파일 컴파일 허용 여부. 
    // "checkJs": false, // allowJs 옵션이 true여서 js파일 모듈을 사용시 js파일의 오류 검사 여부
    // "maxNodeModuleJsDepth": 0, // js 모듈을 검색할 최대 깊이
    
    /////////// Lint ///////////
    "strict"true// 모든 엄격한 타입 검사 옵션을 활성화
    // noImplicitAny, noImplicitThis, alwaysStrict, strictNullChecks, strictFunctionTypes
    "allowUnreachableCode"false// 도달 불가능한 코드에 대한 허용 여부.
    "allowUnusedLabels"false// 사용하지 않는 라벨에 대한 허용 여부
    "noFallthroughCasesInSwitch"true// 잘못 적혔다고 판단되는 switch문에 대한 에러 발생
    "noImplicitReturns"true// 함수의 모든 경로가 값을 반환하지 않으면 에러 발생
    "suppressExcessPropertyErrors"false// 객체 리터럴에 대한 초과 속성 검사 억제 여부
    // @TODO 부가설명 필요
    "suppressImplicitAnyIndexErrors"false// 인덱스 서명이없는 개체를 인덱싱하는 경우 --noImplicitAny 오류 억제여부
    // 자세한 내용은 문제 #1232를 참조
    // @TODO 부가설명 필요
    "noStrictGenericChecks"true// 함수에서 generic의 엄격한 검사 해제 여부
    "noUnusedLocals"true// 사용안된 지역변수에 대한 오류 보고 여부
    "noUnusedParameters"true,  // 사용안된 파라미터에 대한 오류 보고 여부
 
    /////////// edit outfile ///////////
    "charset""utf8"// 입력파일의 문자집합 형식
    "emitBOM"false,// 출력 파일의 시작 부분에 UTF-8 바이트 순서표 (BOM) 추가여부
    // "newLine": "lf", // end of line sequence 설정
    "removeComments"true// 주석 삭제
    // @TODO '/*!' 주석 테스트 필요
    "disableSizeLimit"false// @TODO 테스트 필요
    // Disable size limitation on JavaScript project.
    "noEmit"false// 결과파일을 저장하지 않음
    // @TODO 테스트 필요
    "noEmitOnError"false// 에러 발생시 결과파일을 저장하지 않음
    "preserveConstEnums"false// const enum형 선언을 지우지 않을건지 여부
    
    
    /////////// more spec ///////////
    "lib": [], // 컴파일에 포함될 라이브러리 파일 목록
    "downlevelIteration"false// target이 ES3 및 ES5 일때도 for..of, spread, destructuring 문법 지원
    "experimentalDecorators"true// ES Decorator에 대한 실험적 기능 사용 여부
    "stripInternal"false// /** @ internal * /JSDoc annotation이 있는 코드에 대한 선언을 내 보내지 않을지 여부
    // @TODO 부가설명 필요
 
    /////////// optimization ///////////
    "importHelpers"true// tslib에서 helpers (e.g. __extends, __rest, etc..)를 가져온다.
 
    /////////// sourceMap ///////////
    "inlineSourceMap"false// 소스맵을 결과코드에 추가
    // @TODO 테스트 필요
    "mapRoot""./map"// "source map 파일을 저장할 root 디렉토리 지정
    // 지정하지 않으면 변환된 파일과 동일한 디렉토리에 저장된다.
    "sourceMap"true// 소스맵(*.map) 파일 생성 여부
    // "sourceRoot": "", // 디버거가 알아야될 .ts파일 root 위치. 소스맵(*.map)에 적용된다.
    // @TODO 테스트 필요
    "inlineSources"false// 변환전 파일 .ts 코드를 결과코드에 추가
    // @TODO 테스트 필요
 
    /////////// etc ///////////
    
    "noImplicitUseStrict"false// @TODO 테스트 필요
    
    "noLib"false// 기본 라이브러리(lib.d.ts)를 가져오지 않는다.
    // @TODO 옵션 사용처
    
    "plugins": [ ], // 편집환경을 더 좋게 변경하기 위한 플러그인 기능
    
    "preserveSymlinks"false// Symlink파일에서 다른 모듈을 import시 기준경로를 Symlink 경로로 설정
    // 기존에는 Symlink파일에서 다른 모듈을 import시
    // Symlink파일의 실제 경로에서 모듈을 가져왔다.
    // https://nodejs.org/api/cli.html#cli_preserve_symlinks
    
    "skipLibCheck"false// 모든 선언파일(*.d.ts)의 유형검사를 건너뛸지 여부
    
    "watch"false// 파일 변경시 컴파일
    
    /////////// ??? ///////////
    "isolatedModules"false// @TODO 뭘까...
    // https://github.com/Microsoft/TypeScript/issues/2499
    "emitDecoratorMetadata"false// @TODO 테스트 필요
    // Emit design-type metadata for decorated declarations in source. See issue #2577 for details.
    "noResolve"false // @TODO 테스트 필요
  }
}
cs





'H6 > backend (Node.js, tsc)' 카테고리의 다른 글

<7> REST API & CRUD  (0) 2018.01.31
<5> node-mysql (Typescript)  (0) 2018.01.22
<4> MySQL & node-mysql  (0) 2018.01.22
<3> 에러처리..  (0) 2018.01.22
<2> app.ts 및 server.ts 만들기  (0) 2018.01.22

-mysql module 정의하기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
import * as mysql from 'mysql';
 
/** MySQL DB 연결 */
export module mysqlUtil {
    export const pool = mysql.createPool({
        host     : 'host',
        user     : 'user',
        password : 'password',
        database : 'database',
        timezone : 'UTC',
        connectionLimit : 50,
        waitForConnections : true
    });
}
cs


>> 다수의 Connection 관리 기법인 Connection Pool 방식을 사용하였다.

     Pool 에서 Connection을 사용하고, Pool 에 반납. 

     (https://nesoy.github.io/articles/2017-04/Nodejs-MySQL)

     

    DB Connection Pool 에 대한 이야기는 아래 URL 참고.

     https://www.holaxprogramming.com/2013/01/10/devops-how-to-manage-dbcp/


>> mysql.createPool(option); 

>> connectionLimit : 최대 커넥션 갯수

>> waitForConnections : pool 에 여유 커넷션이 없는 경우 대기 여부 설정



'H6 > backend (Node.js, tsc)' 카테고리의 다른 글

<7> REST API & CRUD  (0) 2018.01.31
<6> tsconfig.json 을 통한 컴파일 옵션 설정  (0) 2018.01.31
<4> MySQL & node-mysql  (0) 2018.01.22
<3> 에러처리..  (0) 2018.01.22
<2> app.ts 및 server.ts 만들기  (0) 2018.01.22

https://www.opentutorials.org/course/2136/12020 참고


< 설치 >

- 비트나미를 이용한 설치 (https://bitnami.com/stack/mamp)


- 설치중 맨 아래를 제외하고 체크 해제.


- pw 설정


$ cd /App(tab)/mamp(tab)/mysql/bin

./mysql -uroot -p

>> 설정한 pw 입력

mysql>


정상설치..!!



< 구조 >


테이블

레코드(행)

필드(열)


데이터베이스 (연관된 테이블들의 묶음)


하나의 애플리케이션이 하나의 데이터베이스에 대응.


하나의 PC에는 여러 개의 애플리케이션이 설치.


이것들을 그룹핑하는 것이 데이터베이스 서버 라는 것..!! (opentutorials.ort:3306)



...



< MySQL 사용하기 >


$ ./mysql (-hlocalhost) -uroot -p

$ ./mysql -hopentutorial.org -P3306 -uroot -p // 이런식으로도 접속 가능


즉 데이터베이스 서버에 접속을 하고 인증 과정을 거친 상태..!!


다음으로는 데이터베이스의 테이블을 만들기 위해 데이터베이스를 만들어야 함.


( 데이터베이스 서버 != 데이터베이스 ) 


mysql> 

데이터베이스 보기

1
show databases;

데이터베이스 생성

1
CREATE DATABASE o2 CHARACTER SET utf8 COLLATE utf8_general_ci;

데이터베이스 선택

1
use o2;

테이블 생성

1
2
3
4
5
6
7
CREATE TABLE `topic` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL,
`description` text NOT NULL,
`author` varchar(30) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

생성된 테이블 확인

1
show tables;

데이터 삽입

1
2
INSERT INTO topic (title, description, author) VALUES('JavaScript','Computer language for web.', 'egoing');
INSERT INTO topic (title, description, author) VALUES('NPM','Package manager', 'leezche');

 

테이블 내용 확인

mysql> select * from topic; // topic 테이블에 있는 모든 행을 가져온다.



< MySQL UPDATE & DELETE >


mysql> update topic set TITLE='npm' where id='2'; // topic 테이블에서 id가 2인 TITLE 을 npm 으로 변경


 mysql> delete from topic where id='2';




< node-mysql : 접속 & SELECT & INSERT & UPDATE & DELETE >


- js로 어떻게 mysql 을 제어하는가


- node-mysql 설치

$ npm install --save node-mysql


https://github.com/mysqljs/mysql 참고


코드 예시


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
var mysql = require('mysql');
var conn = mysql.createConnection({
  host     : 'localhost',
  user     : 'root',
  password : '111111',
  database : 'o2'
});
conn.connect();
 
var sql = 'SELECT * FROM topic';
conn.query(sql, function(err, rows, fields){
  if(err){
    console.log(err);
  } else {
    for(var i=0; i<rows.length; i++){
      console.log(rows[i].title);
    }
  }
});
var sql = 'INSERT INTO topic (title, description, author) VALUES(?, ?, ?)';
var params = ['Supervisor''Watcher''graphittie'];
conn.query(sql, params, function(err, rows, fields){
  if(err){
    console.log(err);
  } else {
    console.log(rows.insertId);
  }
});
var sql = 'UPDATE topic SET title=?, author=? WHERE id=?';
var params = ['NPM''leezche'1];
conn.query(sql, params, function(err, rows, fields){
  if(err){
    console.log(err);
  } else {
    console.log(rows);
  }
});
 
 
var sql = 'DELETE FROM topic WHERE id=?';
var params = [1];
conn.query(sql, params, function(err, rows, fields){
  if(err){
    console.log(err);
  } else {
    console.log(rows);
  }
});
conn.end();
cs


- 21, 30 행 확인해보기..!!

- ? 는 치환자를 두고 치환자의 순서에 따라 파라미터를 실제 값을 배열로 생성한 다음 쿼리문의 두번째 인재 값으로 전달 가능 // 보안 관련 sql injection attack 을 막을 수 있음..!!





-


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import * as express from 'express';
import * as bodyParser from 'body-parser';
//import { testRoutes } from './apis/test/route/test.route';
 
export class Server {
    /** app 에 대한 타입 설정 */
    public app: express.Application;
    constructor() {
        /** express 설정을 위한 express 선언 */
        this.app = express();
        /** bodyParser 선언 */
        this.app.use(bodyParser.urlencoded({extended: false}));
        /** 라우터 */
        //this.app.user(testRoutes.testRouter);
 
        /** Not Found */
        this.app.use( (req: express.Request, res: express.Response, next: Function) => {
           /**
            *   Error 라는 정의가 있지만 Error 에는 status 라는 정의가 없어서 any 설정
            */
 
           const err: any = new Error('not_found');
           err.status = 404;
           next(err);
        });
        /** 에러 처리 */
        this.app.use((err: any, req: express.Request, res: express.Response) => {
            err.status = err.status || 500;
            console.error(`error on request ${req.method} | ${req.url} | $err.status}`);
            console.error(err.stack || `${err.message}`);
            err.message = err.status == 500 ? 'Somthing bad happened.' : err.message;
            res.status(err.status).send(err.message);
        });
 
    }
}
cs


- '가 아닌 ` 

- 아직 잘 모르겠음. 추후 포스팅 하기..


< app.ts >


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import * as express from 'express';
import * as bodyParser from 'body-parser';
import { testRoutes } from './apis/test/route/test.route';
 
export class Server {
    /** app 에 대한 타입 설정 */
    public app: express.Application;
    constructor() {
        /** express 설정을 위한 express 선언 */
        this.app = express();
        /** bodyParser 선언 */
        this.app.use(bodyParser.urlencoded({extended: false}));
        /** 라우터 */
        this.app.user(testRoutes.testRouter);
    }
}
cs


$ npm install body-parser --save


- 모듈 가져오기

>> import * as express from 'express'; 를 통해 모듈을 불러올 수 있다



< body-parser >

- npm 모듈 중 request body 를 json 형식으로 변환해 주는 모듈

- express 를 통해 만든 app 객체의 .use() 를 활용하여 bodyParser.urlencoded() 를 해준다.

- extended 는 아래 설명대로... (https://stackoverflow.com/questions/29960764/what-does-extended-mean-in-express-4-0)


  If extended is false, you can not post "nested object"  

  person[name] = 'caw'

  // Nested Object = { person: { name: cw } }

  If extended is true, you can do whatever way that you like. 



참고 2 : http://sjh836.tistory.com/154



< server.ts >


1
2
3
4
5
6
7
8
9
10
11
import { Server } from './app';
import * as express from 'express';
 
const port: number = 80;
const app: express.Application = new Server().app;
app.set('port', port);
app.listen(app.get('port'), () => {
    console.log('server listening on port ' + port);
}).on('error', err => {
    console.error(err);
});
cs


컴파일 후

$ sudo node server 를 통해 서버를 실행시킬 수 있다.

'H6 > backend (Node.js, tsc)' 카테고리의 다른 글

<6> tsconfig.json 을 통한 컴파일 옵션 설정  (0) 2018.01.31
<5> node-mysql (Typescript)  (0) 2018.01.22
<4> MySQL & node-mysql  (0) 2018.01.22
<3> 에러처리..  (0) 2018.01.22
<1> Node.js, Express, Typescript 환경설정  (0) 2018.01.21

< Typescript 란? >




< 개발환경 세팅 >


1) Node.js 설치 (https://nodejs.org/)


2) package.json 만들기

$ npm init


2) Express 설치

$ npm install express --save


3) Typescript 설치

$ npm install -g typescript


4) compile

$ tsp filename.ts


>> tsconfig.json 파일이 있는 경우

$ tsc --p tsconfig.json


5) 실행하기

$ sudo node 파일명 (확장자 없이)









'H6 > backend (Node.js, tsc)' 카테고리의 다른 글

<6> tsconfig.json 을 통한 컴파일 옵션 설정  (0) 2018.01.31
<5> node-mysql (Typescript)  (0) 2018.01.22
<4> MySQL & node-mysql  (0) 2018.01.22
<3> 에러처리..  (0) 2018.01.22
<2> app.ts 및 server.ts 만들기  (0) 2018.01.22