반응형


리눅스/유닉스] 디렉토리 이동 명령, 변경 방법 - Linux, Unix Directory Command



Q: 리눅스/유닉스/Cygwin 프롬프트에서 경로 변경 방법은?


cd 명령으로 디렉토리를 이동할 수 있습니다.


하위 디렉토리로 이동


z 라는 이름의 하위 디렉토리로 가려면
cd z
이렇게 합니다.


상위 디렉토리로 이동


cd ..
이렇게 합니다. 마침표 2개입니다. 그러나 cd.. 이렇게 점2개를 붙이면 안 됩니다. (윈도우에서는 되지만)


루트 디렉토리로 이동


최상위 디렉토리로 이동하려면
cd /
이렇게 합니다. 슬래쉬 기호입니다.


특정 디렉토리로 이동


예를 들어, /usr/bin 디렉토리로 이동하려면
cd /usr/bin
이렇게 합니다.


직전 디렉토리로 이동


방금 전에 있던 디렉토리로 다시 되돌아가려면
cd -
이렇게 합니다. 마이너스 기호입니다.


자신의 홈(home) 디렉토리 이동


물결무늬(~)가, 자신의 ID 명의의 홈 디렉토리를 의미하므로
cd ~
이렇게 하면 됩니다.


현재 디렉토리 이름 확인


지금 위치한 디렉토리명을 알려면
pwd
이렇게 합니다.




ref : http://mwultong.blogspot.com/2006/09/linux-unix-directory-command.html


반응형
반응형

AMI 생성과정과 EC2 인스턴스 생성



ami 로 부터 EC2 인스턴스를 생성하게 되고 AMI 에 어떤것이 담겨있느냐에 따라 다르지만 우선 Amazon Linux AMI 를 

기준으로 설명한다면 이것은 EBS 기반의 AWS 를 지원하는 AMI 이며 EC2 인스턴스(linux) 와 EBS(HW) 를 생성하는 이미지이다







과정은 AMI 로 부터 EC2 와 EBS(마치C:\ 드라이브) 가 기본적으로 만들어지고 EBS를 기준으로 스냅샷(EBS를 그대로 복사한 것)을 하나 만들어
이 스냅샷을 기준으로 AMI(Amazon Machine Image)를 만들수 있다 (마치 .ios) 그리고 이를 통해 새로운 EC2 인스턴스를 생성 할 수 있게 된다


또한 스냅샷을 통해 다른 지역으로 Copy 가 가능한데 다른 지역으로 넘기는 것은 스냅샷을 통해서만 가능하다



반응형
반응형

본 세션에서는 Amazon VPC의 기본 사항을 살펴 봅니다. 먼저 IP 주소, 서브넷, 라우팅, 보안, NAT 등을 포함하는 VPC의 구축 및 디자인 기본 사항에 대해서 알아봅니다. 그런 다음 VPN 또는 AWS Direct Connect를 사용하여 VPC를 물리적 데이터 센터에 연결하기 위한 다양한 접근 방법과 사용 사례를 살펴봅니다. 이 세션은 Amazon VPC에서 사용할 수 있는 빌딩 블록을 이해하는데 관심이있는 아키텍트, 네트워크 관리자 및 기술적 의사 결정자를 대상으로 합니다.



반응형
반응형

TCP/IP 네트웍에서 포트 번호는, 들어오는 트래픽을 컴퓨터 내에서 실행되고 있는 적절한 프로그램에 분배시키기 위해 할당되는 숫자를 말한다. 이것은 물리적인 플러그나 소켓이 아니며, 다만 논리적인 할당일 뿐이다

# 프로그래밍에서, 포트는 "논리적인 접속장소"이며, 특히 인터넷 프로토콜인 TCP/IP를 사용할 때에는 클라이언트 프로그램이 네트웍 상의 특정 서버 프로그램을 지정하는 방법으로 사용된다. 웹 프로토콜인 HTTP와 같이, TCP/IP의 상위 프로토콜을 사용하는 응용프로그램에서는 미리 지정된 포트번호 들을 가지고 있다. 이런 것들은 IANA에 의해 지정되었으며, "잘 알려진 포트들"이라고 불린다. 다른 응용프로그램 프로세스들은 매번 접속할 때마다 포트번호가 동적으로 부여된다. 서버 프로그램이 처음 시작되면, 지정된 포트번호로 바인드된다. 그 서버를 사용하려는 모든 클라이언트 프로그램들은 지정된 포트번호에 바인드해야만 한다. 

바인드가 되면  두개의 컴퓨터간 네트워크를 이용한 통신시 발신지 컴퓨터에서 출발한 사용자 데이터(패킷)는 TCP/IP의 각 계층을 거치면서 최종적으로 목적지 주소(IP)를 가지고 있는 컴퓨터에 도착하게 됩니다. 패킷을 수신한 컴퓨터는 전송시에 사용되었던 주소필드를 제거하고, 패킷 안에 있는 데이터만을 응용프로그램에 넘겨줍니다. 

결국 데이터를 넘겨줄 컴퓨터에는 FTP, Mail, Telnet, SSH, Web 등 다양한 종류의 응용프로그램이 기동하고 있을 것입니다. 수신측 컴퓨터가 인터넷 계층에서 패킷을 수신한 후 응용층으로 데이터를 전달하려고 할 때, 컴퓨터내에 기동중인 많은 응용프로그램들 중 누구에게 데이터를 전달해야 하는지 어떻게 구분할까요? 이러한 문제를 해결하기 위해서 운영체제는 응용프로그램의 논리적인 주소인 Port 번호라는 것을 이용합니다. 즉 각각의 응용프로그램 (서비스)에 유일한 논리적 주소인 Port 번호를 할당하여서, 전송계층에서 응용프로그램을 구분할 수 있도록 하고 있습니다.  


포트번호는 0부터 65536 이다. 포트번호 0부터 1024까지는 어떤 특권을 가진 서비스에 의해 사용될 수 있도록 예약되어 있다. HTTP 서비스를 위해서는 대개 80번 포트가 지정되는데, URL에 이를 적을 필요는 없다.


# 하드웨어적인 경우, 컴퓨터나 통신장비에서, 포트는 일반적으로 다른 장치에 물리적으로 접속되는 특정한 부위를 말하며, 대개 소켓이나 플러그 등의 형태로 되어 있다. 일반적으로 PC에는 하나 이상의 직렬 포트와 한 개의 병렬 포트가 제공된다. 직렬 포트는 한번에 한 비트씩 모뎀과 같은 주변장치로 전송하는 직렬 전송을 지원하며, 병렬 포트는 한번에 여러 비트씩 프린터와 같은 주변 장치로 전송할 수 있는 병렬 전송을 지원한다.


#  Port 번호는 16 비트 크기의 정수로 되어 있어 1부터 65535번까지를 사용할 수 있으며, 자주 사용되는 표준 인터넷 서비스에 대해서는 그 번호가 미리 할당(약속)되어져 있습니다. 이러한 것을 잘 알려진 포트(Well-Known Port)라 하며, 관리는 국제 인터넷
할당번호 관리기관인 IANA(Internet Assigned Numbers Authority)에서 하고 있습니다. 
 
 예를 들면 FTP는 21번, Telnet 는 23번, SMTP(mail)는 25번, HTTP 는 80번 등으로 약속되어져 있습니다. 보통은 이러한 Well-Known 포트를 각 운영체제별로 "Services"라는 파일로 저장하고 있습니다. IANA에 의하면 보통 1번부터 1023까지는 Well-Known Port 영역으로 예약되어 있으며,


그 이상은 어플리케이션 서비스를 위해 할당되거나, 혹은 그때그때 임시로 할당되는 Port 번호들입니다.

Port 번호의 저장  
Unix의 경우 : /etc/services
Windows의 경우 : C:\windows\services
Windows NT의 경우 : C:\winnt\system32\dirvers\etc\services  파일로 저장합니다. 



호스트 (네트워크)


네트워크 호스트(network host)는 컴퓨터 네트워크에 연결된 컴퓨터나 기타 장치이다. 네트워크 호스트는 정보 리소스, 서비스, 애플리케이션을 네트워크 상의 사용자나 기타 노드에 제공할 수 있다. 네트워크 호스트는 네트워크 주소가 할당된 네트워크 노드이다.

서버와 호스트

모든 서버는 호스트이지만 모든 호스트가 서버인 것은 아니다. 네트워크에 연결이 확립된 모든 장치는 호스트의 자격이 있는 반면, 다른 장치(클라이언트)로부터의 연결을 수락하는 호스트만 서버가 될 수 있다.

개념의 기원

운영 체제에서 터미널 호스트라는 용어는 전통적으로 서비스를 컴퓨터 터미널에 제공하는 다중 사용자 컴퓨터나 소프트웨어, 또는 서비스를 소형이거나 기능이 떨어지는 장치[1]에 제공하는 컴퓨터(예: 텔레타입 터미널이나 비디오 터미널을 서비스하는 메인프레임 컴퓨터)를 가리킨다. 그 밖의 예로는 텔넷 호스트(텔넷 서버)와 xhost(X 윈도 클라이언트)를 들 수 있다.

문서는 통신 네트워크에 연결되는 범용 목적의 컴퓨터 시스템으로서 호스트를 정의한다. (운영 체제에 참여하는 리소스를 달성하는 목적)[2]




포트 (컴퓨터 네트워킹)


인터넷 프로토콜 스위트에서 포트(port)는 운영 체제 통신의 종단점이다. 이 용어는 하드웨어 장치에도 사용되지만, 소프트웨어에서는 네트워크 서비스나 특정 프로세스를 식별하는 논리 단위이다. 주로 포트를 사용하는 프로토콜은 전송 계층 프로토콜이라 하며, 예를 들어 전송 제어 프로토콜(TCP)와 사용자 데이터그램 프로토콜(UDP)가 있다. 각 포트는 번호로 구별되며 이 번호를 포트 번호라고 한다. 포트 번호는 IP 주소와 함께 쓰여 해당하는 프로토콜에 의해 사용된다.

사용 및 표기

URI 문법에 의해서 사용 및 표기할 수 있으며, IP 주소와 함께 URL을 표기하는 예는 다음과 같다.

ftp://000.000.000.000:21

위 표기에서 ftp://는 URI 스킴과 구분 기호를, 000.000.000.000은 IP 주소를 의미하며 : 다음의 21은 포트 번호를 의미한다.

포트 번호를 생략 가능한 경우가 있는데 예를 들면,

http://000.000.000.000

위와 같은 같은 월드 와이드 웹 URL은 기본적으로 80번 포트를 사용하므로 웹 브라우저는 자동적으로 이를 다음과 같은 의미로 처리한다.

http://000.000.000.000:80

일반적인 포트 번호

포트 번호는 크게 세 종류로 구분된다.

  • 0번 ~ 1023번: 잘 알려진 포트 (well-known port)
  • 1024번 ~ 49151번: 등록된 포트 (registered port)
  • 49152번 ~ 65535번: 동적 포트 (dynamic port)

잘 알려진 포트 번호의 대표적 예는 다음과 같다.




ref :

http://memoweb.tistory.com/entry/%ED%8F%AC%ED%8A%B8%EC%9D%98-%EA%B0%9C%EB%85%90%EA%B3%BC-%EB%B3%B8%EC%A7%88-port

https://ko.wikipedia.org/wiki/%ED%98%B8%EC%8A%A4%ED%8A%B8_(%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC)

https://ko.wikipedia.org/wiki/%ED%8F%AC%ED%8A%B8_(%EC%BB%B4%ED%93%A8%ED%84%B0_%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%82%B9)

반응형
반응형

최근 다시 AWS를 이용하게 되면서 AMI 선택하는데 눈에 띄는 변화를 목격했다.

아래 그림처럼 이미지 대부분이 HVM으로 바뀐 것인데 정확히는 PV가 사라진 것.




그림에는 다 나오지 않았지만 사용중인 region에서 Ubuntu의 경우 HVM 이미지만 제공하고 있다.

 

먼저 PV(Para Virtualization)와 HVM (Hardware Virtual Machine)의 차이부터 정리할 필요가 있겠는데,

PV는 반가상화로 guest os가 hypervisor를 통해 hardware를 제어하고 가볍기 때문에 퍼포먼스가 좋지만 guest os에 수정이 필요하다. 반면에 HVM은 전가상화로 보면 되는데 다른 guest와 완전히 독립되고 os 수정없이 그대로 사용가능하다는 이점이 있지만 hardware 자체가 전가상화 기능(CPU의 VT)을 지원해야 하기 때문에 이것이 부담이 되어 퍼포먼스가 PV에 비해 떨어진다고 알려져 왔었다.

 

AWS는 Xen 기반이지만 PV, HVM 모두 제공해왔고 위에서처럼 초기부터 PV 성능이 더 좋다고 알려져왔기 때문에 HVM을 선택할 일은 없었는데 왜 이렇게 바뀐 것인지 찾다가 재미있는 글을 보게 되었다.

AWS in 2015: Why You Need to Switch from PV to HVM

이 글을 보면,

PV가 HVM보다 성능이 좋기는 했지만 그 차이가 크지 않았고 AWS가 발전하면서 퍼포먼스 차이가 더 줄어들었거나 어떤 경우는 HVM이 더 좋은 성능을 내는 경우도 있다고 한다. 또 이렇게 된 이유로 Xen 자체의 기술 향상, 새로운 세대의 CPU 도입, EC2 driver의 향상 등을 들고 있다.

그리고 이번에 직접 목격한대로 AWS는 PV => HVM으로 점차 바꾸고 있는 중인 것 같고 최신 instance type들은 HVM으로만 제공하는 것으로 보인다. AMI matrix를 살펴보니 이제 PV 지원하는 instance type은 거의 없다.

 


 

위 링크에서 본 것중에 또 하나 재미있는 것은 T2 instance type에 대한 것이었는데,

CPU의 20~40%를 baseline으로 긋고 CPU 사용량이 그 이하가 되면 token을 적립하고 baseline을 초과하면 적립된 token을 소모하는 방식이라고 한다. PyCON APAC 2016에서도 잠깐 들었던 것 같은데 token이 정확히 어떤 단위인지 모르지만 과금과 관련된 얘기였던 것으로 기억된다. 어느 회사에선가 instance를 잘게 쪼개고 저녁엔 shutdown 해서 token 적립하고 아침엔 다시 올려서 적립된 token 쓰며 거의 공짜로 이용하고 있다던데. T2도 한 번 알아볼 생각.


ref : https://blurblah.net/1352



반응형
반응형




Step 4: 는 EC2의 스토리지를 설정 하는 것입니다.


여기에서 인스턴스 스토리지나 EBS를 설정 할 수 있습니다.


인스턴스 스토리지는, 인스턴스 타입 중에서 인스턴스 스토리지를 제공하는 경우에만 사용할 수 있습니다. 개념으로는 쉽게 생각하면, 우리가 사용하는 PC에 로컬로 내장되어 있는 마스터 HDD를 생각하면 됩니다. 윈도우를 사용하는 분들은 C드라이브를 연상하면 되겠네요.




인스턴스 스토리지는, 인스턴스 타입 중에서 인스턴스 스토리지를 제공하는 경우에만 사용할 수 있습니다. 개념으로는 쉽게 생각하면, 우리가 사용하는 PC에 로컬로 내장되어 있는 마스터 HDD를 생각하면 됩니다. 윈도우를 사용하는 분들은 C드라이브를 연상하면 되겠네요.


다만, 인스턴스 스토리지는 인스턴스를 끄게 되면 데이터도 함께 날라가는 임시적인 성격이 있다고 생각해야 합니다.


EBS는 쉽게 생각하면 네트웍으로 연결된 외장 HDD 를 떠올리면 되겠습니다. (그래서 일반적으로 인스턴스 스토리지보다 속도가 느릴 수 있겠죠.) EBS의 경우는 설정에 따라 인스턴스를 종료해도 데이터가 영구하게 남도록 할 수 있습니다.


단, EBS는 한번에 한 인스턴스와만 연결 될 수 있으며, 사용 요금이 있습니다. (프리티어의 경우 어느 정도까지 무료 제공되는지 확인해 보세요.)


여기서 선택한 t2.micro 인스턴스의 경우에는 EBS가 반드시 필요 하므로 위 화면과 같이 기본적으로 하나의 EBS가 추가되어 있습니다.


위 화면에서 디스크 공간의 크기와 볼륨 타입, 인스턴스가 터미네이션 될때 같이 삭제할 것인지의 여부를 선택합니다. (자세한 설명은 AWS의 EBS를 읽어보세요. http://aws.amazon.com/ko/ebs/details/)





ref : http://wingsnote.com/52

반응형
반응형


Mysql & nodejs 로 가입, 로그인 처리하기(관계형 데이터베이스 사용)










[Mysql + HeidiSQL + nodejs(express, 각종 모듈) 조합]



소스는 연습을 위한 코드임으로 날림주의!


Nodejs 에서 관계형 데이터 베이스 사용


MySQL, Oracle 등에서 사용하는 구조



데이터베이스  테이블 집합의 형태





데이터베이스로 연결 및 사용하는 방법






MySQL 을 사용하기 위해선 먼저 프로그램이 필요함

https://dev.mysql.com/downloads/


https://dev.mysql.com/downloads/mysql/




heidisql 을 설치(프리)

https://www.heidisql.com/screenshots.php?which=query




 상단에 데이터 탭을 선택하면 추가된 데이터또한 볼 수 있다


heidisql 로 좀 더 간편하게 데이터베이스를 조작할 수 있다



localhost 로 접속하여 기본 데이터 베이스 필드 만들고  DB명 test, 테이블 명 users


DB : test  생성 후 test 에서 오른족 버튼 클릭 새로생성 -> table   로 테이블 생성

필드는 아래처럼





id 를 Primary key 로 설정해주면 중복가입을 막을 수 있다


아래는 id 를 primary 를 적용한 모습

테이블 탭에서 id 를 primary key 로 적용 할 수 있다(데이터 추가는 서버 실행 시키고 난 이후 가입 정보를 입력하여 등록된 정보들이다








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
<!DOCTYPE html>
 
<html>
<head>
    <meta charset="utf-8" />
    <title>login2</title>
</head>
<body>
 
    <h1>login2</h1>
    <form method="post" action="/process/Login">
        <table>
            <tr>
                <td><label>ID : </label></td>
                <td><input type="text" name="id"></td>
            </tr>
            <tr>
                <td><label>PW : </label></td>
                <td><input type="text" name="passwords"></td>
 
 
            </tr>
 
            <tr>
                <td><input type="submit" value="Sumit" name=""></td>
                <td><input type="button" value="Join" onclick="location.href='/addUser2.html'"></td>
            </tr>
 
        </table>
 
    </form>
 
</body>
</html>


login2.html










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
<!DOCTYPE html>
 
<html>
<head>
    <meta charset="utf-8" />
    <title>Add User</title>
</head>
<body>
 
    <h1>Add User</h1>
    <form method="post" action="/process/addUser">
        <table>
            <tr>
                <td><label>ID : </label></td>
                <td><input type="text" name="id"></td>
            </tr>
            <tr>
                <td><label>PW : </label></td>
                <td><input type="text" name="passwords"></td>
            </tr>
 
            <tr>
                <td><label>name : </label></td>
                <td><input type="text" name="name"></td>
            </tr>
 
            <tr>
                <td><label>age : </label></td>
                <td><input type="text" name="age"></td>
            </tr>
 
            <tr>
                <td><input type="submit" value="Sumit" name=""></td>
                <td><input type="button" value="Login" onclick="location.href='/Login2.html'"></td>
            </tr>
 
        </table>
 
    </form>
 
</body>
</html>



addUser2.html








서버코드


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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
var express = require('express');
var http = require('http');
var serveStatic = require('serve-static');      //특정 폴더의 파일들을 특정 패스로 접근할 수 있도록 열어주는 역할
var path = require('path');
var cookieParser = require('cookie-parser');
var expressSession = require('express-session');
var expressErrorHandler = require('express-error-handler');
 
 
var mySql = require('mysql');
 
//connection 은 한정되어 있어서 풀을 만들어 그 안에서 사용한다
//connection 할때도 비용이 들어감, 만들고 닫고
 
var pool = mySql.createPool({
    connectionLimit: 10,            //접속을 10개 만들고 10개를 재사용
    host: 'localhost',
    user:'root',
    password: '00000', //MySql 설치할때의 비번을 입력하면 됨!!
    database: 'test',
    debug: false
 
});
 
 
 
var app = express();      //express 서버 객체
 
 
app.set('port'3000);
app.use(serveStatic(path.join('public', __dirname, 'public')));
 
 
 
var bodyParser_post = require('body-parser');       //post 방식 파서
//post 방식 일경우 begin
//post 의 방식은 url 에 추가하는 방식이 아니고 body 라는 곳에 추가하여 전송하는 방식
app.use(bodyParser_post.urlencoded({ extended: false }));            // post 방식 세팅
app.use(bodyParser_post.json());                                     // json 사용 하는 경우의 세팅
//post 방식 일경우 end
 
 
 
app.use(serveStatic(path.join(__dirname, 'public')));
 
 
//쿠키와 세션을 미들웨어로 등록한다
app.use(cookieParser());
 
//세션 환경 세팅
//세션은 서버쪽에 저장하는 것을 말하는데, 파일로 저장 할 수도 있고 레디스라고 하는 메모리DB등 다양한 저장소에 저장 할 수가 있는데
app.use(expressSession({
    secret: 'my key',           //이때의 옵션은 세션에 세이브 정보를 저장할때 할때 파일을 만들꺼냐 , 아니면 미리 만들어 놓을꺼냐 등에 대한 옵션들임
    resave: true,
    saveUninitialized: true
}));
 
 
 
 
//라우트를 미들웨어에 등록하기 전에 라우터에 설정할 경로와 함수를 등록한다
//
//라우터를 사용 (특정 경로로 들어오는 요청에 대하여 함수를 수행 시킬 수가 있는 기능을 express 가 제공해 주는것)
var router = express.Router();
 
 
router.route('/process/addUser').post(
    function (req, res)
    {
        console.log('process/addUser 호출됨');
        var paramID = req.body.id || req.query.id;
        var paramPW = req.body.passwords || req.query.passwords;
        var paramName = req.body.name || req.query.name;
        var paramAge = Number(req.body.age || req.query.age);
        console.log('id:' + paramID + ', paramPW: ' + paramPW + ' ,paramName: ' + paramName + ' ,paramAge: ' + paramAge);
 
        addUser(paramID, paramName, paramAge, paramPW,
            function (err, result) {
                if (err) {
                    console.log('Error!!!');
                    res.writeHead(200, { "Content-Type""text/html;charset=utf-8" });
                    res.write('<h1>에러발생 - 이미 존재하는  아이디일수 있음</h1>');
                    res.write('<br><a href="/login2.html"> re login </a>');
                    res.end();
                    return;
                }
 
                if (result)
                {
                    console.dir(result);
                    res.writeHead(200, { "Content-Type""text/html;charset=utf-8" });
                    res.write('<h1>Add Success</h1>');
                    res.write('<br><a href="/login2.html"> re login </a>');
                    res.end();
                }
                else
                {
                    console.log('데이터베이스에 추가 에러');
                    res.writeHead(200, { "Content-Type""text/html;charset=utf-8" });
                    res.write('<h1> Failed : add user</h1>');
                    res.write('<a href="/login2.html"> re login</a>');
                    res.end();
                }
            }
        );
    }
);
 
 
 
router.route('/process/login').post(
    function (req, res) {
        console.log('process/login 호출됨');
        var paramID = req.body.id || req.query.id;
        var paramPW = req.body.passwords || req.query.passwords;
        console.log('paramID : ' + paramID + ', paramPW : ' + paramPW);
 
        authUser( paramID, paramPW,
            function (err, rows)
            {
                if (err) {
                    console.log('Error!!!');
                    res.writeHead(200, { "Content-Type""text/html;charset=utf-8" });
                    res.write('<h1>에러발생</h1>');
                    res.end();
                    return;
                }
 
                if (rows) {
                    console.dir(rows);
                    res.writeHead(200, { "Content-Type""text/html;charset=utf-8" });
                    res.write('<h1>Login Success</h1>');
                    res.write('<h1> user </h1>' + rows[0].name);
                    res.write('<br><a href="/login2.html"> re login </a>');
                    res.end();
 
                }
                else {
                    console.log('empty Error!!!');
                    res.writeHead(200, { "Content-Type""text/html;charset=utf-8" });
                    res.write('<h1>user data not exist</h1>');
                    res.write('<a href="/login2.html"> re login</a>');
                    res.end();
                }
            }
        );
    }
);
 
 
 
 
 
//라우터 미들웨어 등록하는 구간에서는 라우터를 모두  등록한 이후에 다른 것을 세팅한다
//그렇지 않으면 순서상 라우터 이외에 다른것이 먼저 실행될 수 있다
app.use('/', router);       //라우트 미들웨어를 등록한다
 
 
var addUser = function(id,name,age,passwords,callback)
{
    console.log('addUser 호출');
 
    //pool로 DB접근 함수 호출(mysql 접근)
    //conn 연결된 객체
    pool.getConnection(
        function (err, poolConn)
        {
            if (err)
            {
                if (poolConn) {
                    poolConn.release();        // 사용한후 해제(반납)한다
                }
                callback(err, null);
                return;
            }
            console.log('데이터베이스 연결 스레드 아이디' + poolConn.threadId);
            var data = { id: id, namename, age: age, passwords: passwords };
 
            //users 테이블에 데이터 추가
            var exec = poolConn.query('insert into users set ?', data,
                function (err, result)
                {
                    poolConn.release();
                    console.log('실행된 SQL : ' + exec.sql);
 
                    if (err) {
                        console.log('sql 실행 시 에러 발생');
                        callback(err, null);
                        return;
                    }
 
                    callback(null, result);
                }
            );
        }
    );
}
 
var authUser = function (id, password, callback) {
    console.log('input id :' + id + '  :  pw : ' + password);
 
 
    pool.getConnection(function (err, poolConn) {
        if (err) {
            if (poolConn) {
                poolConn.release();     //pool 반환처리
            }
 
            callback(err, null);
            return;
        }
 
        console.log('데이터베이스 연결 스레드 아이디' + poolConn.threadId);
 
        var tablename = 'users';
        var columns = ['id''name''age'];
 
 
        //id 와 pw 가 같은것을 조회한다
        var exec = poolConn.query("select ?? from ?? where id = ? and passwords=?", [columns, tablename, id, password],
 
            function (err, rows)
            {
                poolConn.release();     //pool 반환처리
                console.log('실행된 ssql : ' + exec.sql);
 
                if (err) {
                    callback(err, null);
                    return;
                }
 
                if (rows.length > 0) {
                    console.log('사용자 찾음');
                    callback(null, rows);
                } else {
                    console.log('사용자 찾지 못함');
                    callback(nullnull);
                }
 
            }
        );
 
    }
);
 
 
};
 
 
 
 
 
 
var errorHandler = expressErrorHandler(
    { static: { '404''./public/404.html' } }              //404 에러 코드가 발생하면 해당 페이지를 보여주는 예외 미들웨어
);
 
app.use(expressErrorHandler.httpError(404));
app.use(expressErrorHandler);
 
//웹서버를 app 기반으로 생성
var appServer = http.createServer(app);
appServer.listen(app.get('port'),
    function () {
        console.log('express 웹서버 실행' + app.get('port'));
    }
);
 



반응형
반응형


mongoDB&mongoose 로 패스워드 

암호화하여 가입 및 로그인처리




DataBAseSample0.zip






PW 가 암호화되어 저장된 Document들






실행  flow 

  1. 회원 가입 시도

    1. 정보 입력

    2. submit 버튼으로 정보 전송

    3. mongooese 와 'crypto' 모듈을 사용하여 pw 암호화 후 암호화 하기 위한 salt 값과 과 암호화된 PW DB에 저장

  2. 로그인

    1. 정보 입력

    2. id를 통한 기본 정보를 가져온 후 pw 를 crypto 모듈을 활용하여 가입시 저장해놓은 salt  값과 로그인을 하기 위해 입력한 pw 를 암호한 후

    3. 존재하는 유저인지 비교한다

    4. 존재하는 유저라면 로그인 처리 완료

    5. 그렇지 않은경우 존재하지 않는 유저라 알림








1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  /**
   * Defines a model or retrieves it.
   * Models defined on the mongoose instance are available to all connection
   *   created by the same mongoose instance. *
   * @param name model name
* .....
   * @param collection (optional, induced from model name)
   * @param skipInit whether to skip initialization (defaults to false)
   */
  export function model<T extends Document>(name: string, schema?: Schema, collection?: string,
    skipInit?: boolean): Model<T>;
  export function model<T extends Document, U extends Model<T>>(
    name: string,
    schema?: Schema,
    collection?: string,
    skipInit?: boolean
  ): U;



//컬렉션과 스키마를 연결시킴

userModel = mongoose.model('users3', userSchema);


static 은 모댈 객체 userModel 에서 사용 가능한 함수를 등록 하는 것이고

method 는 모델 인스턴스 객체에서 사용 할 수 있는 함수를 등록하는 것




Models

Models are fancy constructors compiled from our Schema definitions. Instances of these models represent documents which can be saved and retrieved from our database. All document creation and retrieval from the database is handled by these models.

Compiling your first model

var schema = new mongoose.Schema({ name: 'string', size: 'string' });
var Tank = mongoose.model('Tank', schema); 

The first argument is the singular name of the collection your model is for. Mongoose automatically looks for the plural version of your model name. Thus, for the example above, the model Tank is for the tanks collection in the database. The .model() function makes a copy of schema. Make sure that you've added everything you want to schema before calling .model()! 








서버 코드(nodejs)


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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
var express = require('express');
var http = require('http');
var serveStatic = require('serve-static');      //특정 폴더의 파일들을 특정 패스로 접근할 수 있도록 열어주는 역할
var path = require('path');
var cookieParser = require('cookie-parser');
var expressSession = require('express-session');
var expressErrorHandler = require('express-error-handler');
 
var mongoose = require('mongoose');
 
 
//암호화 모듈
var crypto = require('crypto');
 
 
 
var database;
 
var userSchema;
 
 
var userModel;
 
 
//몽고디비에 연결 ,  보통 웹서버 만든 직후 연결 , DB 먼저 연결 되도 상관 없음
//먼저 db를 가져온다 
function connectDB() {
    //localhost 로컬 호스트
    //:27017  몽고디비 포트
    //local db 생성시 만든 폴더 명
    var databaseURL = 'mongodb://localhost:27017/test';
 
    mongoose.Promise = global.Promise;
    mongoose.connect(databaseURL);
 
    database = mongoose.connection;     //db와 연결 시도
 
    database.on('open',         //db 연결 될때의 이벤트
        function () {
            console.log('data base 연결됨 ' + databaseURL);
 
 
            //몽구스는 스키마를 정의하고 해당 스키마에 해당 하는 데이터를 집어넣는 방식으로 테이블과 유사
            userSchema = mongoose.Schema({
                //id: String,   타입만 세팅하는 것이 아니고 여러가지 속성을 넣고 싶다면 객체로 추가한다
                id: { type: String, required: true, unique: true'default':'' },         //required : 필수로 넣어야 하는 요소, unique 유일해야하는 값
                hashed_passwords: { type: String, required: true'default''' },                //passwords 는 유니크할 필요는 없음으로 뺌
                salt: {type:String, required:true},
 
                name: { type: String, index: 'hashed''default''' },                    //name 을 넣긴 하는데 hash 로 처리
                age: { type: Number'default'-1 },                        //초기 값을 -1 로
                created_at: { type: Date, index: { unique: false }, 'default'Date.now() },
                updated_at: { type: Date, index: { unique: false }, 'default'Date.now() }
            });
            console.log('userSchema 정의함');
 
//virtual 함수는 passwords 가 new userModel(...) 로 생성자에 의해 실행되면서 값이 넘어갈때 실행된다
  //method 에 추가된 함수는 인스턴스에 함수가 추가된다
//그래서 this.makeSalt() 이런 함수 호출이 가능하다
            userSchema.virtual('passwords').set( //여기서 virtual 은 C++ 에서의 virtual 과는 전혀 상관이 없다
                function (passwords)
                {
                    console.log(userModel === this);        //false
                    console.log(userSchema === this);        //false
                    dd1 = this;
                    //이때의 this 는 추가한 데이터 객체의 this 임
                    this.salt = this.makeSalt();
                    this.hashed_passwords = this.encryptPassword(passwords);
                    console.log('this.hashed_passwords 저장됨 : ' + this.hashed_passwords);
                }
            );
 
            //encryptPassword 속성 추가 , //method 에 추가된 함수는 인스턴스에 함수가 추가된다
            userSchema.method('encryptPassword',
                //plainText : plainText : 가상속성 pw 값
                //inSalt 에 따라서 암호화 방식을 다르게함
                function (plainText, inSalt) {
                if (inSalt) {
                    //'sha1'암호화 방식
                    //plainText : 가상속성 pw 값
                    //digest 암호화 처리
                    return crypto.createHmac('sha1', inSalt).update(plainText).digest('hex');
                } else {
                    //'sha1'암호화 방식
                    //document 만들때 virtual 함수에서  salt을 저장한 값을 그대로 가져와서 암호화한다
                    return crypto.createHmac('sha1', this.salt).update(plainText).digest('hex');
                }
                });
 
 
 
            userSchema.method('makeSalt',
                function (plainText, inSalt) {
 
                    console.log(userModel === this);        //false
                    console.log(userSchema === this);        //false
 
                    return Math.round(new Date().valueOf() * Math.random()) + '' ;
                });
 
            userSchema.method('authenticate',
                function (plainText, inSalt, hashed_passwords) {
                    if (inSalt) {
                        //insalt 키와 패스워드를 암호화 하여 데이터베이트 암호화된 pw 와 같은지 비교
                        return this.encryptPassword(plainText, inSalt) === hashed_passwords;
                    } else {
                        return this.encryptPassword(plainText) === hashed_passwords;
                    }
                });
 
 
            //모델 객체에 사용할 수 있는 함수를 추가(등록)한다
            //스키마에 함수를 추가 했지만 모델에서 사용 할 수 있음
            userSchema.static('findByID',
                function (id, callback) {
                    //userModel == this;
                    console.log(userModel == this);
                    return this.find({ id: id }, callback);
                }
            );
 
            /* //객체를 넣을 수도 있음
             userSchema.static.findByID = function (id, callback)
                {
                //this 는모델객체를 의미함
                    return this.find({id:id}, callback);
                }
            );
            */
 
            userSchema.static('findAll',
                function (callback) {
                    return this.find({}, callback);
                }
            );
 
 
 
            //컬렏션과 스키마를 연결시킴
            userModel = mongoose.model('users3', userSchema);
            console.log('userModel 정의함');
        }
    );
 
    database.on('disconnected',         //db 연결 끊길떄
        function () {
            console.log('data base 연결 끊어짐');
        }
    );
 
    database.on('error',         //에러 발생하는 경우
        console.error.bind(console'mongoose 연결 에러')
    );
 
}
 
 
 
 
 
var app = express();      //express 서버 객체
 
 
app.set('port'3000);
app.use(serveStatic(path.join('public', __dirname, 'public')));
 
 
 
var bodyParser_post = require('body-parser');       //post 방식 파서
//post 방식 일경우 begin
//post 의 방식은 url 에 추가하는 방식이 아니고 body 라는 곳에 추가하여 전송하는 방식
app.use(bodyParser_post.urlencoded({ extended: false }));            // post 방식 세팅
app.use(bodyParser_post.json());                                     // json 사용 하는 경우의 세팅
//post 방식 일경우 end
 
 
 
app.use(serveStatic(path.join(__dirname, 'public')));
 
 
//쿠키와 세션을 미들웨어로 등록한다
app.use(cookieParser());
 
//세션 환경 세팅
//세션은 서버쪽에 저장하는 것을 말하는데, 파일로 저장 할 수도 있고 레디스라고 하는 메모리DB등 다양한 저장소에 저장 할 수가 있는데
app.use(expressSession({
    secret: 'my key',           //이때의 옵션은 세션에 세이브 정보를 저장할때 할때 파일을 만들꺼냐 , 아니면 미리 만들어 놓을꺼냐 등에 대한 옵션들임
    resave: true,
    saveUninitialized: true
}));
 
 
 
 
//라우트를 미들웨어에 등록하기 전에 라우터에 설정할 경로와 함수를 등록한다
//
//라우터를 사용 (특정 경로로 들어오는 요청에 대하여 함수를 수행 시킬 수가 있는 기능을 express 가 제공해 주는것)
var router = express.Router();
 
 
router.route('/process/login').post(
    function (req, res) {
        console.log('process/login 호출됨');
        var paramID = req.body.id || req.query.id;
        var paramPW = req.body.passwords || req.query.passwords;
        console.log('paramID : ' + paramID + ', paramPW : ' + paramPW);
 
        if (database) {
            authUser(database, paramID, paramPW,
                function (err, docs) {
                    if (database) {
                        if (err) {
                            console.log('Error!!!');
                            res.writeHead(200, { "Content-Type""text/html;charset=utf-8" });
                            res.write('<h1>에러발생</h1>');
                            res.end();
                            return;
                        }
 
                        if (docs) {
                            console.dir(docs);
                            res.writeHead(200, { "Content-Type""text/html;charset=utf-8" });
                            res.write('<h1>Login Success</h1>');
                            res.write('<h1> user </h1>' + docs[0].id + '  :   ' + docs[0].name);
                            res.write('<br><a href="/login.html"> re login </a>');
                            res.end();
 
                        }
                        else {
                            console.log('empty Error!!!');
                            res.writeHead(200, { "Content-Type""text/html;charset=utf-8" });
                            res.write('<h1>user data not exist</h1>');
                            res.write('<a href="/login.html"> re login</a>');
                            res.end();
                        }
 
                    }
                    else {
                        console.log('DB 연결 안됨');
                        res.writeHead(200, { "Content-Type""text/html;charset=utf-8" });
                        res.write('<h1>databasae 연결 안됨</h1>');
                        res.end();
                    }
 
 
 
                }
            );
        }
    }
);
 
 
router.route('/process/addUser').post(
 
    function (req, res) {
        console.log('process/addUser 호출됨');
        var paramID = req.body.id || req.query.id;
        var paramPW = req.body.passwords || req.query.passwords;
        var paramName = req.body.name || req.query.name;
        console.log('paramID : ' + paramID + ', paramPW : ' + paramPW);
 
        if (database) {
            addUser(database, paramID, paramPW, paramName,
                function (err, result) {
                    if (err) {
                        console.log('Error!!!');
                        res.writeHead(200, { "Content-Type""text/html;charset=utf-8" });
                        res.write('<h1>에러발생 - 이미 존재하는 아이디일 수 있습니다</h1>');
                        res.write('<br><a href="/login.html"> re login </a>');
                        res.end();
                        return;
                    }
 
                    if (result) {
                        console.dir(result);
                        res.writeHead(200, { "Content-Type""text/html;charset=utf-8" });
                        res.write('<h1>Add Success</h1>');
                        res.write('<h1> name </h1>' + paramName);
                        res.write('<br><a href="/login.html"> re login </a>');
                        res.end();
                    }
                    else {
                        console.log('추가 안됨 Error!!!');
                        res.writeHead(200, { "Content-Type""text/html;charset=utf-8" });
                        res.write('<h1>can not add user</h1>');
                        res.write('<a href="/login.html"> re login</a>');
                        res.end();
                    }
 
                }
            );
        }
        else {
            console.log('DB 연결 안됨');
            res.writeHead(200, { "Content-Type""text/html;charset=utf-8" });
            res.write('<h1>databasae 연결 안됨</h1>');
            res.end();
        }
 
    }
);
 
 
router.route('/process/listUser').post(
    function (req, res) {
        console.log('process/listuser 호출됨');
        if (database) {
            userModel.findAll(
                function (err, results) {
                    if (err) {
                        console.log('Error!!!');
                        res.writeHead(200, { "Content-Type""text/html;charset=utf-8" });
                        res.write('<h1>전체 유저 검색 - 에러발생</h1>');
                        res.end();
                        return;
                    }
 
                    if (results) {
                        console.dir(results);
                        res.writeHead(200, { "Content-Type""text/html;charset=utf-8" });
                        res.write('<h1>User List</h1>');
 
                        res.write('<div><ul>');
                        for (var i = 0; i < results.length++i) {
                            var curID = results[i]._doc.id;
                            var curName = results[i]._doc.name;
                            res.write("<li>#" + i + " ->" + curID + " , " + curName + " </li>");
                        }
                        res.write('</ul></div>');
 
                        res.write('<br><a href="/login.html"> re login </a>');
                        res.end();
                    }
                    else {
                        console.log(' 조회된 사용자 없음');
                        res.writeHead(200, { "Content-Type""text/html;charset=utf-8" });
                        res.write('<h1>조회된 사용자 없음</h1>');
                        res.write('<a href="/login.html"> re login</a>');
                        res.end();
                    }
                }
            );
        }
        else {
            console.log('DB 연결 안됨');
            res.writeHead(200, { "Content-Type""text/html;charset=utf-8" });
            res.write('<h1>databasae 연결 안됨</h1>');
            res.end();
        }
    }
);
 
 
//라우터 미들웨어 등록하는 구간에서는 라우터를 모두  등록한 이후에 다른 것을 세팅한다
//그렇지 않으면 순서상 라우터 이외에 다른것이 먼저 실행될 수 있다
app.use('/', router);       //라우트 미들웨어를 등록한다
 
 
 
var dd1;
 
var authUser = function (db, id, password, callback) {
    console.log('input id :' + id.toString() + '  :  pw : ' + password);
 
 
    userModel.findByID(id,
        function (err, result) {
            if (id === undefined || password === undefined) {
                console.log('id or pw 필수');
                return;
            }
            if (err) {
                callback(err, null);
                return;
            }
 
            console.log('아이디 %s 로 검색 ');
            if (result.length > 0) {
 
                var user = new userModel({ id: id });
                console.log(user === dd1);
                //password : 현재 사용자가 로그인 하기 위해 입력한 암호
                //result[0]._doc.salt 암호화를 위해 만들었던 임의의 값
                //result[0]._doc.hashed_passwords : 암호화 되어 DB에 저장되어 있는 암호화된 PW
                var authenticated = user.authenticate(password, result[0]._doc.salt, result[0]._doc.hashed_passwords);
 
                if (authenticated) {
                    console.log(' 비번 일치 ');
                    callback(null, result);
                }
                else {
                    console.log(' 비번 일치하지 않음 ');
                    callback(nullnull);
                }
            }
            else {
                console.log('아이디 일치하는 사용자 없음');
                callback(nullnull);
            }
 
        }
    );
 
 
};
 
 
 
var addUser = function (db, id, passwords, name, callback) {
    console.log('add User 호출됨' + id + '  , ' + passwords);
 
 
    var user = new userModel({ "id": id, "passwords": passwords, "name"name });
 
    //user 정보를 DB 에 저장
    user.save(
        function (err) {
            if (err) {
                callback(err, null);
                return;
            }
 
            //데이터가 추가됐다면 insertedCount 카운트가 0 보다 큰값이 된다
            console.log('사용자 추가 됨');
            callback(null, user);
        }
    );
 
};
 
 
 
 
var errorHandler = expressErrorHandler(
    { static: { '404''./public/404.html' } }              //404 에러 코드가 발생하면 해당 페이지를 보여주는 예외 미들웨어
);
 
app.use(expressErrorHandler.httpError(404));
app.use(expressErrorHandler);
 
//웹서버를 app 기반으로 생성
var appServer = http.createServer(app);
appServer.listen(app.get('port'),
    function () {
        console.log('express 웹서버 실행' + app.get('port'));
        connectDB();        //DB 연결 , DB 연결 먼저해도 상관 없음
    }
);
 
cs
















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
131
132
133
134
135
136
var mongoose = require('mongoose');
 
var database;
var userSchema;
 
 
var userModel;
 
 
 
//pw 를뺌
function createUserSchema()
{
    userSchema = mongoose.Schema({
        //id: String,   타입만 세팅하는 것이 아니고 여러가지 속성을 넣고 싶다면 객체로 추가한다
        id: { type: String, required: true, unique: true },         //required : 필수로 넣어야 하는 요소, unique 유일해야하는 값
        name: { type: String, index: 'hashed' },                    //name 을 넣긴 하는데 hash 로 처리
        age: { type: Number'default'-1 },                        //초기 값을 -1 로
        created_at: { type: Date, index: { unique: false }, 'default'Date.now() },
        updated_at: { type: Date, index: { unique: false }, 'default'Date.now() }
    });
 
    //info 라는 컬러을 설정하면 set 이 호출됨
    userSchema.virtual('info')
        .set(function (info)
        {
            console.log(userModel === this);        //false
            var splitted = info.split(' ');
            this.id = splitted[0];
            this.name = splitted[1];
            console.log('virtual info 속성 설정됨 ' + this.id + ',' + this.name);
        }
        ).get(function ()
        {
                return this.id + ' ' + this.name ;
            }
    );
 
    //collection 과 스미카를 연결하여 usermodel 로 리턴
    userModel = mongoose.model("users4", userSchema);
    console.log('user model 정의함');
}
 
 
var dddd;
function dotest()
{
    var user = new userModel({ "info""aaaa bbbb" });
 
    user.save(
        function (err) {
            if (err) {
                console.log('에러 발생됨');
                return;
            }
 
            //데이터가 추가됐다면 insertedCount 카운트가 0 보다 큰값이 된다
            console.log('사용자 추가 됨');
        }
 
    );    //insert 가 됨
 
}
 
 
 
function connectDB() {
    //localhost 로컬 호스트
    //:27017  몽고디비 포트
    //local db 생성시 만든 폴더 명
    var databaseURL = 'mongodb://localhost:27017/test';
 
    mongoose.Promise = global.Promise;
    mongoose.connect(databaseURL);
 
    database = mongoose.connection;     //db와 연결 시도
 
    database.on('open',         //db 연결 될때의 이벤트
        function () {
            console.log('data base 연결됨 ' + databaseURL);
 
 
            //몽구스는 스키마를 정의하고 해당 스키마에 해당 하는 데이터를 집어넣는 방식으로 테이블과 유사
            createUserSchema();
 
            console.log('userSchema 정의함');
 
            dotest();
 
 
            //모델 객체에 사용할 수 있는 함수를 추가(등록)한다
            //스키마에 함수를 추가 했지만 모델에서 사용 할 수 있음
            userSchema.static('findByID',
                function (id, callback) {
                    //userModel == this;
                    console.log(userModel == this);         //true , static 으로 추가된 함수는 usermodel 에 추가 됨으로
                    return this.find({ id: id }, callback);
                }
            );
 
            /* //객체를 넣을 수도 있음
             userSchema.static.findByID = function (id, callback)
                {
                //this 는모델객체를 의미함
                    return this.find({id:id}, callback);
                }
            );
            */
 
            userSchema.static('findAll',
                function (callback) {
                    return this.find({}, callback);
                }
            );
 
 
 
            //컬렏션과 스키마를 연결시킴
            userModel = mongoose.model('users2', userSchema);
            console.log('userModel 정의함');
        }
    );
 
    database.on('disconnected',         //db 연결 끊길떄
        function () {
            console.log('data base 연결 끊어짐');
        }
    );
 
    database.on('error',         //에러 발생하는 경우
        console.error.bind(console'mongoose 연결 에러')
    );
 
}
 
connectDB();





일부 part ref : http://mongoosejs.com/docs/models.html

반응형
반응형


Indexes

Indexes support the efficient execution of queries in MongoDB. Without indexes, MongoDB must perform a collection scan, i.e. scan every document in a collection, to select those documents that match the query statement. If an appropriate index exists for a query, MongoDB can use the index to limit the number of documents it must inspect.

Indexes are special data structures [1] that store a small portion of the collection’s data set in an easy to traverse form. The index stores the value of a specific field or set of fields, ordered by the value of the field. The ordering of the index entries supports efficient equality matches and range-based query operations. In addition, MongoDB can return sorted results by using the ordering in the index.

The following diagram illustrates a query that selects and orders the matching documents using an index:


Fundamentally, indexes in MongoDB are similar to indexes in other database systems. MongoDB defines indexes at the collection level and supports indexes on any field or sub-field of the documents in a MongoDB collection.

Default _id Index

MongoDB creates a unique index on the _id field during the creation of a collection. The _id index prevents clients from inserting two documents with the same value for the _id field. You cannot drop this index on the _id field.

NOTE

In sharded clusters, if you do not use the _id field as the shard key, then your application must ensure the uniqueness of the values in the _id field to prevent errors. This is most-often done by using a standard auto-generated ObjectId.

Create an Index

To create an index using the Node.JS driver, use createIndex().

collection.createIndex( { <key and index type specification> }, function(err, result) {
   console.log(result);
   callback(result);
}

The following example creates a single key descending index on the name field:

 collection.createIndex( { name : -1 }, function(err, result) {
   console.log(result);
   callback(result);
}

The createIndex() method only creates an index if an index of the same specification does not already exist.

[1]MongoDB indexes use a B-tree data structure.

Index Types

MongoDB provides a number of different index types to support specific types of data and queries.

Single Field

In addition to the MongoDB-defined _id index, MongoDB supports the creation of user-defined ascending/descending indexes on a single field of a document.

Diagram of an index on the ``score`` field (ascending).

For a single-field index and sort operations, the sort order (i.e. ascending or descending) of the index key does not matter because MongoDB can traverse the index in either direction.

See Single Field Indexes and Sort with a Single Field Index for more information on single-field indexes.

Compound Index

MongoDB also supports user-defined indexes on multiple fields, i.e. compound indexes.

The order of fields listed in a compound index has significance. For instance, if a compound index consists of { userid: 1, score: -1 }, the index sorts first by userid and then, within each userid value, sorts by score.


먼저 유저id로 오름차순 정렬 한다음 score 값으로 내림 차순 정렬한 형태



For compound indexes and sort operations, the sort order (i.e. ascending or descending) of the index keys can determine whether the index can support a sort operation. See Sort Order for more information on the impact of index order on results in compound indexes.

See Compound Indexes and Sort on Multiple Fields for more information on compound indexes.

Multikey Index

MongoDB uses multikey indexes to index the content stored in arrays. If you index a field that holds an array value, MongoDB creates separate index entries for every element of the array. These multikey indexes allow queries to select documents that contain arrays by matching on element or elements of the arrays. MongoDB automatically determines whether to create a multikey index if the indexed field contains an array value; you do not need to explicitly specify the multikey type.

Diagram of a multikey index on the ``addr.zip`` field. The ``addr`` field contains an array of address documents. The address documents contain the ``zip`` field.

See Multikey Indexes and Multikey Index Bounds for more information on multikey indexes.

Geospatial Index

To support efficient queries of geospatial coordinate data, MongoDB provides two special indexes: 2d indexesthat uses planar geometry when returning results and 2dsphere indexes that use spherical geometry to return results.

See 2d Index Internals for a high level introduction to geospatial indexes.

Text Indexes

MongoDB provides a text index type that supports searching for string content in a collection. These text indexes do not store language-specific stop words (e.g. “the”, “a”, “or”) and stem the words in a collection to only store root words.

See Text Indexes for more information on text indexes and search.

Hashed Indexes

To support hash based sharding, MongoDB provides a hashed index type, which indexes the hash of the value of a field. These indexes have a more random distribution of values along their range, but only support equality matches and cannot support range-based queries.

Index Properties

Unique Indexes

The unique property for an index causes MongoDB to reject duplicate values for the indexed field. Other than the unique constraint, unique indexes are functionally interchangeable with other MongoDB indexes.

Partial Indexes

New in version 3.2.

Partial indexes only index the documents in a collection that meet a specified filter expression. By indexing a subset of the documents in a collection, partial indexes have lower storage requirements and reduced performance costs for index creation and maintenance.

Partial indexes offer a superset of the functionality of sparse indexes and should be preferred over sparse indexes.

Sparse Indexes

The sparse property of an index ensures that the index only contain entries for documents that have the indexed field. The index skips documents that do not have the indexed field.

You can combine the sparse index option with the unique index option to reject documents that have duplicate values for a field but ignore documents that do not have the indexed key.

TTL Indexes

TTL indexes are special indexes that MongoDB can use to automatically remove documents from a collection after a certain amount of time. This is ideal for certain types of information like machine generated event data, logs, and session information that only need to persist in a database for a finite amount of time.

See: Expire Data from Collections by Setting TTL for implementation instructions.

Index Use

Indexes can improve the efficiency of read operations. The Analyze Query Performance tutorial provides an example of the execution statistics of a query with and without an index.

For information on how MongoDB chooses an index to use, see query optimizer.

Indexes and Collation

New in version 3.4.

Collation allows users to specify language-specific rules for string comparison, such as rules for lettercase and accent marks.

NOTE

The following examples illustrate indexes and collation in the Mongo Shell.

Refer to your driver documentation for instructions on creating indexes with collation in your specific driver.

To use an index for string comparisons, an operation must also specify the same collation. That is, an index with a collation cannot support an operation that performs string comparisons on the indexed fields if the operation specifies a different collation.

For example, the collection myColl has an index on a string field category with the collation locale "fr".

db.myColl.createIndex( { category: 1 }, { collation: { locale: "fr" } } )

The following query operation, which specifies the same collation as the index, can use the index:

db.myColl.find( { category: "cafe" } ).collation( { locale: "fr" } )

However, the following query operation, which by default uses the “simple” binary collator, cannot use the index:

db.myColl.find( { category: "cafe" } )

For a compound index where the index prefix keys are not strings, arrays, and embedded documents, an operation that specifies a different collation can still use the index to support comparisons on the index prefix keys.

For example, the collection myColl has a compound index on the numeric fields score and price and the string field category; the index is created with the collation locale "fr" for string comparisons:

db.myColl.createIndex(
   { score: 1, price: 1, category: 1 },
   { collation: { locale: "fr" } } )

The following operations, which use "simple" binary collation for string comparisons, can use the index:

db.myColl.find( { score: 5 } ).sort( { price: 1 } )
db.myColl.find( { score: 5, price: { $gt: NumberDecimal( "10" ) } } ).sort( { price: 1 } )

The following operation, which uses "simple" binary collation for string comparisons on the indexed category field, can use the index to fulfill only the score: 5 portion of the query:

db.myColl.find( { score: 5, category: "cafe" } )

For more information on collation, see the collation reference page.

The following indexes only support simple binary comparison and do not support collation:

Covered Queries

When the query criteria and the projection of a query include only the indexed fields, MongoDB returns results directly from the index without scanning any documents or bringing documents into memory. These covered queries can be very efficient.

For more information on covered queries, see Covered Query.

Index Intersection

New in version 2.6.

MongoDB can use the intersection of indexes to fulfill queries. For queries that specify compound query conditions, if one index can fulfill a part of a query condition, and another index can fulfill another part of the query condition, then MongoDB can use the intersection of the two indexes to fulfill the query. Whether the use of a compound index or the use of an index intersection is more efficient depends on the particular query and the system.

For details on index intersection, see Index Intersection.

Restrictions

Certain restrictions apply to indexes, such as the length of the index keys or the number of indexes per collection. See Index Limitations for details.

Additional Considerations

Although indexes can improve query performances, indexes also present some operational considerations. See Operational Considerations for Indexes for more information.

If your collection holds a large amount of data, and your application needs to be able to access the data while building the index, consider building the index in the background, as described in Background Construction.

To build or rebuild indexes for a replica set, see Build Indexes on Replica Sets.

Some drivers may specify indexes, using NumberLong(1) rather than 1 as the specification. This does not have any affect on the resulting index.

Additional Resources



ref : https://docs.mongodb.com/manual/indexes/#id2

반응형
반응형

Databases, documents and collections in MongoDB

Descriptions

In this tutorial, we will walk you through the concepts and key facts of databases, documents, and collection of MongoDB.

Databases

A number of databases can be run on a single MongoDB server. Default database of MongoDB is 'db', which is stored within data folder.

MongoDB can create databases on the fly. It is not required to create a database before you start working with it.

"show dbs" command provides you with a list of all the databases.

show-dbs-command.png

Run 'db' command to refer to the current database object or connection.

db command

To connect to a particular database, run use command.

use command

In the above command, 'student' is the database we want to select.

w3resource MongoDB tutorial has a separate page dedicated to commands related to creation and management of the database.

Database names can be almost any character in the ASCII range. But they can't contain an empty string, a dot (i.e. ".") or " ".

Since it is reserved, "system" can't be used as a database name.

A database name can contain "$".

documents

The document is the unit of storing data in a MongoDB database.

document use JSON (JavaScript Object Notation, is a lightweight, thoroughly explorable format used to interchange data between various applications) style for storing data.

A simple example of a JSON document is as follows :

{ site : "w3resource.com" }

Often, the term "object" is used to refer a document.

Documents are analogous to the records of an RDBMS. Insert, update, and delete operations can be performed on a collection. The following table will help you to understand the concept more easily :

RDBMSMongoDB
TableCollection
ColumnKey
ValueValue
Records / RowsDocument / Object

The following table shows the various datatypes which may be used in MongoDB.

Data TypesDescription
stringMay be an empty string or a combination of characters.
integerDigits.
booleanLogical values True or False.
doubleA type of floating point number.
nullNot zero, not empty.
arrayA list of values.
objectAn entity which can be used in programming. May be a value, variable, function, or data structure.
timestampA 64 bit value referring to a time and unique on a single "mongod" instance. The first 32 bit of this value refers to seconds since the UTC January 1, 1970. And last 32 bits refer to the incrementing ordinal for operations within a given second.
Internationalized StringsUTF-8 for strings.
Object IDsEvery MongoDB object or document must have an Object ID which is unique. This is a BSON(Binary JavaScript Object Notation, which is the binary interpretation of JSON) object id, a 12-byte binary value which has a very rare chance of getting duplicated. This id consists of a 4-byte timestamp (seconds since epoch), a 3-byte machine id, a 2-byte process id, and a 3-byte counter.

Collections

collection may store a number of documents. A collection is analogous to a table of an RDBMS.

collection may store documents those who are not same in structure. This is possible because MongoDB is a Schema-free database. In a relational database like MySQL, a schema defines the organization / structure of data in a database. MongoDB does not require such a set of formula defining structure of data. So, it is quite possible to store documents of varying structures in a collection. Practically, you don't need to define a column and it's datatype unlike in RDBMS, while working with MongoDB.

In the following code, it is shown that two MongoDB documents, belongs to same collection, storing data of different structures.

{"tutorial" : "NoSQL"}
               {"topic_id" : 7}

A collection is created, when the first document is inserted.

Pictorial Presentation : Collections and Documents


Valid collection names

Collection names must begin with letters or an underscore.

A Collection name may contain numbers.

You can't use "$" character within the name of a collection. "$" is reserved.

A Collection name must not exceed 128 characters. It will be nice if you keep it within 80/90 characters.

Using a "." (dot) notation, collections can be organized in named groups. For example, tutorials.php and tutorials.javascript both belong to tutorials. This mechanism is called as collection namespace which is for user primarily. Databases don't have much to do with it.

Following is how to use it programmatically :

db.tutorials.php.findOne()

capped collections

Imagine that you want to log the activities happening with an application. you want to store data in the same order it is inserted. MongoDB offers Capped collections for doing so.

Capped collections are collections which can store data in the same order it is inserted.

It is very fixed size, high-performance and "auto-FIFO age-Out". That is, when the allotted space is fully utilized, newly added objects (documents) will replace the older ones in the same order it is inserted.

Since data is stored in the natural order, that is the order it is inserted, while retrieving data, no ordering is required, unless you want to reverse the order.

New objects can be inserted into a capped collection.

Existing objects can be updated.

But you can't remove an individual object from the capped collection. Using drop command, you have to remove all the documents. After the drop, you have to recreate the capped collection.

Presently, the maximum size for a capped collection is 1e9(i.e. 1X109) for 32-bit machines. For 64 bit machines, there is no theoretical limit. Practically, it can be extended till your system resources permit.

Capped collections can be used for logging, caching and auto archiving.

Use number of collections instead of one

This omits the requirement if creating index since you are not storing some repeating data on each object.

If applied to a suitable situation, it can enhance the performance.

Metadata

Information about a database is stored in certain collections. They are grouped in system namespace, as

dbname.system.*

The following table shows the collections and what they store

Collections with namespaceDescription
dbname.system.namespaceslist of all namespaces
dbname.system.indexeslist of all indexes
dbname.system.profilestores database profiling information
dbname.system.userslist of users who may access the database
dbname.local.sourcesstores replica slave configuration data and state
dbname.local.sourcesstores replica slave configuration data and state

There are two more options to store metadata :

database.ns files stores additional namespace / index metadata if exists.

Information on the structure of a stored object is stored within the object itself.



ref : https://www.w3resource.com/mongodb/databases-documents-collections.php


반응형
반응형



Mongoose 를 활용한 가입 로그인 처리






코드 내용이 mongoose 를 적용한 부분만 달라진 것임으로 mongoDB 를 활용한 가입과 로그인 처리 (http://3dmpengines.tistory.com/1876) 의 내용을 확인한 다음 이 페이지를 보시면 되겠습니다



mongoose 는 mongoDB의 자유형식으로 데이터를 넣는 것과는 다르게 스키마를 정의(테이블 형태를 정의)하고 해당 형식으로 데이터를 


집어 넣게 되는 형태라서 일괄적인 데이터 처리하는데 더 유용한 구조입니다





스키마를 정의할 수 있는 데이터 타입들





스키마 정의하는 방법





mongoose 를 통해 조회, 저장, 갱신, 제거 처리 메소드





html 내용과 결과는 mongoDB의 결과와 동일합니다


달라진 부분만 굵 폰트로 처리해놓았습니다


서버 nodejs 코드

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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
var express = require('express');
var http = require('http');
var serveStatic = require('serve-static');      //특정 폴더의 파일들을 특정 패스로 접근할 수 있도록 열어주는 역할
var path = require('path');
var cookieParser = require('cookie-parser');
var expressSession = require('express-session');
var expressErrorHandler = require('express-error-handler');
 
var mongoose = require('mongoose');
 
 
 
var database;
 
var userSchema;
 
 
var userModel;
 
 
//몽고디비에 연결 ,  보통 웹서버 만든 직후 연결 , DB 먼저 연결 되도 상관 없음
//먼저 db를 가져온다 
function connectDB() {
    //localhost 로컬 호스트
    //:27017  몽고디비 포트
    //local db 생성시 만든 폴더 명
    var databaseURL = 'mongodb://localhost:27017/test';
 
    mongoose.Promise = global.Promise;
    mongoose.connect(databaseURL);
 
    database = mongoose.connection;     //db와 연결 시도
 
    database.on('open',         //db 연결 될때의 이벤트
        function ()
        {
            console.log('data base 연결됨 ' + databaseURL);
            
 
            //몽구스는 스키마를 정의하고 해당 스키마에 해당 하는 데이터를 집어넣는 방식으로 테이블과 유사
            userSchema = mongoose.Schema({
                id: String,
                passwords: String,
                nameString,
                
            });
            console.log('userSchema 정의함');
 
            //컬렏션과 스키마를 연결시킴
            userModel = mongoose.model('users', userSchema);
            console.log('userModel 정의함');
        }
    );
 
    database.on('disconnected',         //db 연결 끊길떄
        function () {
            console.log('data base 연결 끊어짐');
        }
    );
 
    database.on('error',         //에러 발생하는 경우
        console.error.bind(console'mongoose 연결 에러')
    );
 
}
 
 
 
 
 
var app = express();      //express 서버 객체
 
 
app.set('port'3000);
app.use(serveStatic(path.join('public', __dirname, 'public')));
 
 
 
var bodyParser_post = require('body-parser');       //post 방식 파서
//post 방식 일경우 begin
//post 의 방식은 url 에 추가하는 방식이 아니고 body 라는 곳에 추가하여 전송하는 방식
app.use(bodyParser_post.urlencoded({ extended: false }));            // post 방식 세팅
app.use(bodyParser_post.json());                                     // json 사용 하는 경우의 세팅
//post 방식 일경우 end
 
 
 
app.use(serveStatic(path.join(__dirname, 'public')));
 
 
//쿠키와 세션을 미들웨어로 등록한다
app.use(cookieParser());
 
//세션 환경 세팅
//세션은 서버쪽에 저장하는 것을 말하는데, 파일로 저장 할 수도 있고 레디스라고 하는 메모리DB등 다양한 저장소에 저장 할 수가 있는데
app.use(expressSession({
    secret: 'my key',           //이때의 옵션은 세션에 세이브 정보를 저장할때 할때 파일을 만들꺼냐 , 아니면 미리 만들어 놓을꺼냐 등에 대한 옵션들임
    resave: true,
    saveUninitialized: true
}));
 
 
 
 
//라우트를 미들웨어에 등록하기 전에 라우터에 설정할 경로와 함수를 등록한다
//
//라우터를 사용 (특정 경로로 들어오는 요청에 대하여 함수를 수행 시킬 수가 있는 기능을 express 가 제공해 주는것)
var router = express.Router();
 
 
router.route('/process/login').post(
    function (req, res) {
        console.log('process/login 호출됨');
        var paramID = req.body.id || req.query.id;
        var paramPW = req.body.passwords || req.query.passwords;
        console.log('paramID : ' + paramID + ', paramPW : ' + paramPW);
 
        if (database) {
            authUser(database, paramID, paramPW,
                function (err, docs) {
                    if (database) {
                        if (err) {
                            console.log('Error!!!');
                            res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
                            res.write('<h1>에러발생</h1>');
                            res.end();
                            return;
                        }
 
                        if (docs) {
                            console.dir(docs);
                            res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
                            res.write('<h1>Login Success</h1>');
                            res.write('<h1> user </h1>' + docs[0].id + '  :   ' + docs[0].name);
                            res.write('<br><a href="/login.html"> re login </a>');
                            res.end();
 
                        }
                        else {
                            console.log('empty Error!!!');
                            res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
                            res.write('<h1>user data not exist</h1>');
                            res.write('<a href="/login.html"> re login</a>');
                            res.end();
                        }
 
                    }
                    else {
                        console.log('DB 연결 안됨');
                        res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
                        res.write('<h1>databasae 연결 안됨</h1>');
                        res.end();
                    }
 
 
 
                }
            );
        }
    }
);
 
 
router.route('/process/addUser').post(
 
    function (req, res) {
        console.log('process/addUser 호출됨');
        var paramID = req.body.id || req.query.id;
        var paramPW = req.body.passwords || req.query.passwords;
        var paramName = req.body.name || req.query.name;
        console.log('paramID : ' + paramID + ', paramPW : ' + paramPW);
 
        if (database) {
            addUser(database, paramID, paramPW, paramName,
                function (err, result) {
                    if (err) {
                        console.log('Error!!!');
                        res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
                        res.write('<h1>에러발생</h1>');
                        res.end();
                        return;
                    }
 
                    if (result) {
                        console.dir(result);
                        res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
                        res.write('<h1>Add Success</h1>');
                        res.write('<h1> name </h1>' + paramName);
                        res.write('<br><a href="/login.html"> re login </a>');
                        res.end();
                    }
                    else {
                        console.log('추가 안됨 Error!!!');
                        res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
                        res.write('<h1>can not add user</h1>');
                        res.write('<a href="/login.html"> re login</a>');
                        res.end();
                    }
 
                }
            );
        }
        else {
            console.log('DB 연결 안됨');
            res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
            res.write('<h1>databasae 연결 안됨</h1>');
            res.end();
        }
 
    }
);
 
 
//라우터 미들웨어 등록하는 구간에서는 라우터를 모두  등록한 이후에 다른 것을 세팅한다
//그렇지 않으면 순서상 라우터 이외에 다른것이 먼저 실행될 수 있다
app.use('/', router);       //라우트 미들웨어를 등록한다
 
 
var authUser = function (db, id, password, callback) {
    console.log('input id :' + id.toString() + '  :  pw : ' + password);
 
    //cmd 에서 db.users  로 썻던 부분이 있는데 이때 이 컬럼(테이블)에 접근은 다음처럼 한다
    /*
    var users = database.collection("users");
    var result = users.find({ "id": id, "passwords": password });
    */
 
    userModel.find({ "id": id, "passwords": password },
        function (err, docs)
        {
            if (err) {
                callback(err, null);
                return;
            }
 
            if (docs.length > 0) {
                console.log('find user [ ' + docs + ' ]');
                callback(null, docs);
            }
            else {
                console.log('can not find user [ ' + docs + ' ]');
                callback(nullnull);
            }
        }
    );
 
};
 
 
 
var addUser = function (db, id, passwords, name, callback) {
    console.log('add User 호출됨' + id + '  , ' + passwords);
 
 
    var user = new userModel({ "id": id, "passwords": passwords, "name"name });
 
    //user 정보를 저장하겠다는 함수
    user.save
    (
        function (err)
        {
            if (err)
            {
                callback(err, null);
                return;
            }
 
            //데이터가 추가됐다면 insertedCount 카운트가 0 보다 큰값이 된다
            console.log('사용자 추가 됨');
            callback(null, user);
        }
    );
 
};
 
 
 
 
var errorHandler = expressErrorHandler(
    { static: { '404''./public/404.html' } }              //404 에러 코드가 발생하면 해당 페이지를 보여주는 예외 미들웨어
);
 
app.use(expressErrorHandler.httpError(404));
app.use(expressErrorHandler);
 
//웹서버를 app 기반으로 생성
var appServer = http.createServer(app);
appServer.listen(app.get('port'),
    function () {
        console.log('express 웹서버 실행' + app.get('port'));
        connectDB();        //DB 연결 , DB 연결 먼저해도 상관 없음
    }
);
 



반응형
반응형


하단 정보를 기준으로 가입, 로그인 처리를 테스트 할수 있습니다


mongoDB에 유저 2명 추가된 정보




" " 로 속성값이 들어가있지 않다면 숫자일 수 있으니 mongodb 를 통한 find 함수(검색)시 주의해야합니다


int 형으로 변경하려면 해당 필드를 parseInt로 변경 가능합니다





로그인, 가입 화면 







로그인 & 가입 플로우


  1. 유저가 없다면 Join 으로 회원 가입을 시도

    1. 회원 가입 성공 페이지와 name 을 보여주는 페이지로 이동

    2. re login 버튼으로 로그인 화면으로 이동

  2. 유저가 있다면 login 시도

    1. 로그인이 되면 유저 정보 (id, name 을 보여줌)를 보여주는 페이지로 이동




Login.html

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
<!DOCTYPE html>
 
<html>
<head>
    <meta charset="utf-8" />
    <title>login2</title>
</head>
<body>
 
    <h1>login2</h1>
    <form method="post" action="/process/Login">
        <table>
            <tr>
                <td><label>ID : </label></td>
                <td><input type="text" name="id"></td>
            </tr>
            <tr>
                <td><label>PW : </label></td>
                <td><input type="text" name="passwords"></td>
 
 
            </tr>
 
            <tr>
                <td><input type="submit" value="Sumit" name=""></td>
                <td><input type="button" value="Join" onclick="location.href='/addUser.html'"></td>
            </tr>
 
        </table>
 
    </form>
 
</body>
</html>






addUser.html


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
<!DOCTYPE html>
 
<html>
<head>
    <meta charset="utf-8" />
    <title>login2</title>
</head>
<body>
 
    <h1>login2</h1>
    <form method="post" action="/process/addUser">
        <table>
            <tr>
                <td><label>ID : </label></td>
                <td><input type="text" name="id"></td>
            </tr>
            <tr>
                <td><label>PW : </label></td>
                <td><input type="text" name="passwords"></td>
 
 
            </tr>
 
            <tr>
                <td><label>name : </label></td>
                <td><input type="text" name="name"></td>
 
 
            </tr>
 
            <tr>
                <td><input type="submit" value="Sumit" name=""></td>
                <td><input type="button" value="Login" onclick="location.href='/Login.html'"></td>
            </tr>
 
        </table>
 
    </form>
 
</body>
</html>








서버 nodejs 코드


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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
var express = require('express');
var http = require('http');
var serveStatic = require('serve-static');      //특정 폴더의 파일들을 특정 패스로 접근할 수 있도록 열어주는 역할
var path = require('path');
var cookieParser = require('cookie-parser');
var expressSession = require('express-session');
var expressErrorHandler = require('express-error-handler');
 
var mongoClient = require('mongodb').MongoClient;
 
 
 
var database;
 
//몽고디비에 연결 ,  보통 웹서버 만든 직후 연결 , DB 먼저 연결 되도 상관 없음
//먼저 db를 가져온다 
function connectDB() {
    //localhost 로컬 호스트
    //:27017  몽고디비 포트
    //local db 생성시 만든 폴더 명
    var databaseURL = 'mongodb://localhost:27017';
    mongoClient.connect(databaseURL,
        function (err, cluster)
        {
            //이 구문까지 실행되었다면 ongoDB 에 연결된 것
            if (err) {
                console.log('db connect error');
                return;
            }
 
            console.log('db was connected : ' + databaseURL);
 
            database = cluster.db('test');
 
            //var users = database.collection('users');
 
 
        }
    );
 
}
 
 
 
 
 
var app = express();      //express 서버 객체
 
 
app.set('port'3000);
app.use(serveStatic(path.join('public', __dirname, 'public')));
 
 
 
var bodyParser_post = require('body-parser');       //post 방식 파서
//post 방식 일경우 begin
//post 의 방식은 url 에 추가하는 방식이 아니고 body 라는 곳에 추가하여 전송하는 방식
app.use(bodyParser_post.urlencoded({ extended: false }));            // post 방식 세팅
app.use(bodyParser_post.json());                                     // json 사용 하는 경우의 세팅
//post 방식 일경우 end
 
 
 
app.use(serveStatic(path.join(__dirname, 'public')));
 
 
//쿠키와 세션을 미들웨어로 등록한다
app.use(cookieParser());
 
//세션 환경 세팅
//세션은 서버쪽에 저장하는 것을 말하는데, 파일로 저장 할 수도 있고 레디스라고 하는 메모리DB등 다양한 저장소에 저장 할 수가 있는데
app.use(expressSession({
    secret: 'my key',           //이때의 옵션은 세션에 세이브 정보를 저장할때 할때 파일을 만들꺼냐 , 아니면 미리 만들어 놓을꺼냐 등에 대한 옵션들임
    resave: true,
    saveUninitialized: true
}));
 
 
 
 
//라우트를 미들웨어에 등록하기 전에 라우터에 설정할 경로와 함수를 등록한다
//
//라우터를 사용 (특정 경로로 들어오는 요청에 대하여 함수를 수행 시킬 수가 있는 기능을 express 가 제공해 주는것)
var router = express.Router();
 
 
router.route('/process/login').post(
    function (req, res) {
        console.log('process/login 호출됨');
        var paramID = req.body.id || req.query.id;
        var paramPW = req.body.passwords || req.query.passwords;
        console.log('paramID : ' + paramID + ', paramPW : ' + paramPW);
 
        if (database) {
            authUser(database, paramID, paramPW,
                function (err, docs) {
                    if (database)
                    {
                        if (err) {
                            console.log('Error!!!');
                            res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
                            res.write('<h1>에러발생</h1>');
                            res.end();
                            return;
                        }
 
                        if (docs) {
                            console.dir(docs);
                            res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
                            res.write('<h1>Login Success</h1>');
                            res.write('<h1> user </h1>' + docs[0].id + '  :   ' + docs[0].name);
                            res.write('<br><a href="/login.html"> re login </a>');
                            res.end();
 
                        }
                        else {
                            console.log('empty Error!!!');
                            res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
                            res.write('<h1>user data not exist</h1>');
                            res.write('<a href="/login.html"> re login</a>');
                            res.end();
                        }
 
                    }
                    else
                    {
                        console.log('DB 연결 안됨');
                        res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
                        res.write('<h1>databasae 연결 안됨</h1>');
                        res.end();
                    }
 
 
 
                }
            );
        }
    }
);
 
 
router.route('/process/addUser').post(
 
    function (req, res)
    {
        console.log('process/addUser 호출됨');
        var paramID = req.body.id || req.query.id;
        var paramPW = req.body.passwords || req.query.passwords;
        var paramName = req.body.name || req.query.name;
        console.log('paramID : ' + paramID + ', paramPW : ' + paramPW);
 
        if (database)
        {
            addUser(database, paramID, paramPW, paramName,
                function (err, result)
                {
                    if (err)
                    {
                        console.log('Error!!!');
                        res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
                        res.write('<h1>에러발생</h1>');
                        res.end();
                        return;
                    }
 
                    if (result) {
                        console.dir(result);
                        res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
                        res.write('<h1>Add Success</h1>');
                        res.write('<h1> name </h1>' + paramName);
                        res.write('<br><a href="/login.html"> re login </a>');
                        res.end();
                    }
                    else {
                        console.log('추가 안됨 Error!!!');
                        res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
                        res.write('<h1>can not add user</h1>');
                        res.write('<a href="/login.html"> re login</a>');
                        res.end();
                    }
 
                }
            );
        }
        else
        {
            console.log('DB 연결 안됨');
            res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
            res.write('<h1>databasae 연결 안됨</h1>');
            res.end();
        }
       
    }
);
 
 
//라우터 미들웨어 등록하는 구간에서는 라우터를 모두  등록한 이후에 다른 것을 세팅한다
//그렇지 않으면 순서상 라우터 이외에 다른것이 먼저 실행될 수 있다
app.use('/', router);       //라우트 미들웨어를 등록한다
 
 
var authUser = function (db, id, password, callback) {
    console.log('input id :' + id.toString() + '  :  pw : ' + password);
 
    //cmd 에서 db.users  로 썻던 부분이 있는데 이때 이 컬럼(테이블)에 접근은 다음처럼 한다
    var users = database.collection("users");
 
    //찾고자 하는 정보를 입력해준다
    //var result = users.find({ name: id, passwords: password });
    //var result = users.find({ "name": id, "passwords":password });
    //var result = users.find({ "name": id , "passwords": password });
    //var result = users.find({});
 
    var result = users.find({ "id": id, "passwords": password });
 
    result.toArray(
        function (err, docs) {
            if (err) {
                callback(err, null);
                return;
            }
 
            if (docs.length > 0) {
                console.log('find user [ ' + docs + ' ]');
                callback(null, docs);
            }
            else {
                console.log('can not find user [ ' + docs + ' ]');
                callback(nullnull);
            }
        }
 
    );
 
};
 
 
 
var addUser = function (db, id, passwords, name, callback) {
    console.log('add User 호출됨' + id + '  , ' + passwords);
    var users = db.collection('users');
 
    //컬렉션에 데이터 추가할때는 배열 형태로 집어 넣는다
    users.insertMany([{ "id": id, "passwords": passwords, "name"name }],
        function (err, result) {
            if (err) {
                callback(err, null);
                return;
            }
 
            //데이터가 추가됐다면 insertedCount 카운트가 0 보다 큰값이 된다
            if (result.insertedCount > 0) {
                console.log('사용자 추가 됨' + result.insertedCount);
                callback(null, result);
            }
            else {
                console.log('사용자 추가 안됨' + result.insertedCount);
                callback(nullnull);
 
            }
 
        }
    );
 
};
 
 
 
 
var errorHandler = expressErrorHandler(
    { static: { '404''./public/404.html' } }              //404 에러 코드가 발생하면 해당 페이지를 보여주는 예외 미들웨어
);
 
app.use(expressErrorHandler.httpError(404));
app.use(expressErrorHandler);
 
//웹서버를 app 기반으로 생성
var appServer = http.createServer(app);
appServer.listen(app.get('port'),
    function () {
        console.log('express 웹서버 실행' + app.get('port'));
        connectDB();        //DB 연결 , DB 연결 먼저해도 상관 없음
    }
);
 






반응형
반응형



몽고디비 기본 사용법과 데이터 조회





  • connect : 몽고디비 데이터 베이스 서버에 접속

  • collection : 컬렉션 참조( 테이블 참조와 유사)

  • find : 문서(데이터) 찾기




몽고 db 서버를 띄우기  


mongod --dbpath 원하는경로








다음처럼 데이터 값을 추가합니다





데이터가 잘 들어갔는지 확인




이것을 웹 서버에서 조회해서 존재한다면 로그인 성공으로 간주 그렇지 않으면 다시 로그인 화면으로 오는 웹 서버를 만들어보겠습니다






로그인 처리 화면



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
<!DOCTYPE html>
 
<html>
<head>
    <meta charset="utf-8" />
    <title>login2</title>
</head>
<body>
 
    <h1>login2</h1>
    <form method="post" action="/process/Login">
        <table>
            <tr>
                <td><label>ID : </label></td>
                <td><input type="text" name="id"></td>
            </tr>
            <tr>
                <td><label>PW : </label></td>
                <td><input type="text" name="passwords"></td>
 
 
            </tr>
 
            <tr>
                <td><input type="submit" value="Sumit" name=""></td>
            </tr>
 
        </table>
 
    </form>
 
</body>
</html>


login.html



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
 
<html>
<head>
    <meta charset="utf-8" />
    <title>404 Error</title>
</head>
<body>
    <h3>404 Error</h3>
    <br />
 
    <p>Can not find a page</p>
 
    <a href="/"> Home  </a>
</body>
</html>


404.html
오류페이지 처리를 위한 html






서버코드 (nodejs)

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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
var express = require('express');
var http = require('http');
var serveStatic = require('serve-static');      //특정 폴더의 파일들을 특정 패스로 접근할 수 있도록 열어주는 역할
var path = require('path');
var cookieParser = require('cookie-parser');
var expressSession = require('express-session');
var expressErrorHandler = require('express-error-handler');
 
var mongoClient = require('mongodb').MongoClient;
 
 
 
var database;
 
//몽고디비에 연결 ,  보통 웹서버 만든 직후 연결 , DB 먼저 연결 되도 상관 없음
//먼저 db를 가져온다 
function connectDB()
{
    //localhost 로컬 호스트
    //:27017  몽고디비 포트
    //local db 생성시 만든 폴더 명
    var databaseURL = 'mongodb://localhost:27017';
    mongoClient.connect(databaseURL,
        function (err, db)
        {
            if (err)
            {
                console.log('db connect error');
                return;
            }
 
            console.log('db was connected : ' + databaseURL);
            database = db;          //이 구문까지 실행되었다면 ongoDB 에 연결된 것
        }
    );
 
}
 
 
 
 
 
var app = express();      //express 서버 객체
 
 
app.set('port'3000);
app.use('public', serveStatic(path.join( __dirname, 'public')));
 
 
 
var bodyParser_post = require('body-parser');       //post 방식 파서
//post 방식 일경우 begin
//post 의 방식은 url 에 추가하는 방식이 아니고 body 라는 곳에 추가하여 전송하는 방식
app.use(bodyParser_post.urlencoded({ extended: false }));            // post 방식 세팅
app.use(bodyParser_post.json());                                     // json 사용 하는 경우의 세팅
//post 방식 일경우 end
 
 
//루트 경로 세팅
app.use(serveStatic(path.join(__dirname, 'public')));
 
 
//쿠키와 세션을 미들웨어로 등록한다
app.use(cookieParser());
 
//세션 환경 세팅
//세션은 서버쪽에 저장하는 것을 말하는데, 파일로 저장 할 수도 있고 레디스라고 하는 메모리DB등 다양한 저장소에 저장 할 수가 있는데
app.use(expressSession({
    secret: 'my key',           //이때의 옵션은 세션에 세이브 정보를 저장할때 할때 파일을 만들꺼냐 , 아니면 미리 만들어 놓을꺼냐 등에 대한 옵션들임
    resave: true,
    saveUninitialized: true
}));
 
 
 
 
//라우트를 미들웨어에 등록하기 전에 라우터에 설정할 경로와 함수를 등록한다
//
//라우터를 사용 (특정 경로로 들어오는 요청에 대하여 함수를 수행 시킬 수가 있는 기능을 express 가 제공해 주는것)
var router = express.Router();
 
//로그인 처리
router.route('/process/login').post(
    function (req, res)
    {
        console.log('process/login 호출됨');
        var paramID = req.body.id || req.query.id;
        var paramPW = req.body.passwords || req.query.passwords;
        console.log('paramID : ' + paramID + ', paramPW : ' + paramPW);
 
        if (database)
        {
            authUser(database, paramID, paramPW,
                function (err, docs)
                {
                    if (database)
                    {
                        if (err)
                        {
                            console.log('Error!!!');
                            res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
                            res.write('<h1>에러발생</h1>');
                            res.end();
                            return;
                        }
 
                        if (docs)
                        {
                            console.dir(docs);
                            res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
                            res.write('<h1>Login Success</h1>');
                            res.write('<h1> user </h1>' + docs[0].name);
                            res.write('<br><a href="/login.html"> re login </a>');
                            res.end();
 
                        }
                        else
                        {
                            console.log('empty Error!!!');
                            res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
                            res.write('<h1>user data not exist</h1>');
                            res.write('<a href="/login.html"> re login</a>');
                            res.end();
                        }
 
                    }
                    else
                    {
                        console.log('empty Error!!!');
                        res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
                        res.write('<h1>databasae 연결 안됨</h1>');
                        res.end();
                    }
                    
                    
 
                }
            );
        }
    }
);
 
 
//라우터 미들웨어 등록하는 구간에서는 라우터를 모두  등록한 이후에 다른 것을 세팅한다
//그렇지 않으면 순서상 라우터 이외에 다른것이 먼저 실행될 수 있다
app.use('/', router);       //라우트 미들웨어를 등록한다
 
 

//로그인 확인
var authUser = function (db, id, password, callback)
{
    console.log('input id :' + id + '  :  pw : ' + password);
 
    //cmd 에서 db.users  로 썻던 부분이 있는데 이때 이 컬럼(테이블)에 접근은 다음처럼 한다
    var users = db.db('test').collection("users");
 
    //찾고자 하는 정보를 입력해준다
    //var result = users.find({ name: id, passwords: password });
    //var result = users.find({ "name": id, "passwords":password });
    var result = users.find({ "name": id, "passwords"parseInt(password) });
    //var result = users.find({});
 
    result.toArray(
        function (err, docs)
        {
            if (err) {
                callback(err, null);
                return;
            }
 
            if (docs.length > 0)
            {
                console.log('find user [ ' + docs + ' ]');
                callback(null, docs);
            }
            else
            {
                console.log('can not find user [ ' + docs + ' ]');
                callback(nullnull);
            }
        }
    
    );
    
};
 
 
var errorHandler = expressErrorHandler(
    { static: { '404''./public/404.html' } }              //404 에러 코드가 발생하면 해당 페이지를 보여주는 예외 미들웨어
);
 
app.use(expressErrorHandler.httpError(404));
app.use(errorHandler );
 
//웹서버를 app 기반으로 생성
var appServer = http.createServer(app);
appServer.listen(app.get('port'),
    function () {
        console.log('express 웹서버 실행' + app.get('port'));
        connectDB();        //DB 연결 , DB 연결 먼저해도 상관 없음
    }
);
 




반응형
반응형




JSON(제이슨[1]JavaScript Object Notation)은 속성-값 쌍( attribute–value pairs and array data types (or any other serializable value))으로 이루어진 데이터 오브젝트를 전달하기 위해 인간이 읽을 수 있는 텍스트를 사용하는 개방형 표준 포맷이다. 비동기 브라우저/서버 통신 (AJAX)을 위해, 넓게는 XML(AJAX가 사용)을 대체하는 주요 데이터 포맷이다. 특히, 인터넷에서 자료를 주고 받을 때 그 자료를 표현하는 방법으로 알려져 있다. 자료의 종류에 큰 제한은 없으며, 특히 컴퓨터 프로그램의 변수값을 표현하는 데 적합하다.

본래는 자바스크립트 언어로부터 파생되어 자바스크립트의 구문 형식을 따르지만 언어 독립형 데이터 포맷이다. 즉, 프로그래밍 언어나 플랫폼에 독립적이므로, 구문 분석 및 JSON 데이터 생성을 위한 코드는 CC++C#자바자바스크립트파이썬 등 수많은 프로그래밍 언어에서 쉽게 이용할 수 있다.

JSON 포맷은 본래 더글라스 크록포드가 규정하였다. RFC 7159와 ECMA-404라는 두 개의 경쟁 표준에 의해 기술되고 있다. ECMA 표준은 문법만 정의할 정도로 최소한으로만 정의되어 있는 반면 RFC는 시맨틱, 보안적 고려 사항을 일부 제공하기도 한다.[2] JSON의 공식 인터넷 미디어 타입은 application/json이며, JSON의 파일 확장자는 .json이다.

자료형과 문법


기본 자료형

JSON의 기본 자료형은 다음과 같다:

수(Number)

기본 자료형의 수는 다음과 같이 표현된다. C나 자바에서의 8진수와 16진수를 표현하는 방법은 지원되지 않는다.

  • 정수
74
1974
750
-114
-273
3.14
-2.718
1e4
2.5e12
3.4e+4
4.56e-8
5.67E+10
6.78E-5

문자열(String)

항상 큰 따옴표(")로 묶어야 하며, 그 안에는 유니코드 문자들이 나열된다. 유니코드 중 역슬래시(\)와 큰따옴표(")는 바로 사용할 수 없다. 역슬래시는 제어문자를 표현하기 위해 사용되며 다음과 같은 의미를 지닌다.

\b 백스페이스
\f 폼 피드
\n 개행
\r 캐리지 리턴
\t 탭
\" 따옴표
\/ 슬래시
\\ 역슬래시
\uHHHH 16진수 네자리로되어 있는 유니코드 문자
"1234"
"Love"
"O-matic"
"한글"
"\"JSON\""

배열(Array)

배열은 대괄호[]로 나타낸다. 배열의 각 요소는 기본 자료형이거나 배열, 객체이다. 각 요소들은 쉼표(,)로 구별된다. 각 요소가 나타나는 순서에 의미가 있다.

1  [10, {"v": 20}, [30, "마흔"]]

객체(Object)

객체는 이름/값 쌍의 집합으로, 중괄호{}를 사용한다. 이름은 문자열이기 때문에 반드시 따옴표를 하며, 값은 기본 자료형이다. 각 쌍들은 쉼표(,)로 구별된다. 각 쌍이 나오는 순서는 의미가 없다.

 {"name2": 50, "name3": "값3", "name1": true}

JSON 메시지 단위는 배열이나 객체이다. 위의 두 예는 JSON 메시지가 될 수 있다.

예제

다음은 한 사람에 관한 정보를 갖는 JSON 객체이다.

1  {
2     "이름": "홍길동",
3     "나이": 25,
4     "성별": "여",
5     "주소": "서울특별시 양천구 목동",
6     "특기": ["농구", "도술"],
7     "가족관계": {"#": 2, "아버지": "홍판서", "어머니": "춘섬"},
8     "회사": "경기 수원시 팔달구 우만동"
9  }

장점

  • JSON은 텍스트로 이루어져 있으므로, 사람과 기계 모두 읽고 쓰기 쉽다.
  • 프로그래밍 언어와 플랫폼에 독립적이므로, 서로 다른 시스템간에 객체를 교환하기에 좋다.
  • 자바스크립트의 문법을 채용했기 때문에, 자바스크립트에서 eval 명령으로 곧바로 사용할 수 있다. 이런 특성은 자바스크립트를 자주 사용하는 웹 환경에서 유리하다. 그러나 실질적으로 eval 명령을 사용하면 외부에서 악성 코드가 유입될 수 있다. 모질라 파이어폭스 3.5, 인터넷 익스플로러 8, 오페라 10.5, 사파리구글 크롬 등 대부분의 최신 웹 브라우저는 JSON 전용 파서 기능을 내장하고 있으므로 이런 기능을 사용하는 것이 더 안전할 뿐만 아니라 빠른 방법이다.




JSON 데이터 교환 포맷 : http://www.json.org/

JSON 포멧터 :  https://jsonformatter.org/

JSON 검사기 :  https://codebeautify.org/jsonvalidator



ref : https://ko.wikipedia.org/wiki/JSON


반응형
반응형


MongoDB는 대표적인 NoSQL이며 JSON 형식으로 데이터를 저장하고 SQL과 유사한 쿼리로 수행 가능한 문서 지향 데이터베이스입니다. 

 

먼저 아래의 주소에서 몽고디비 설치파일을 다운로드 받습니다.

https://www.mongodb.com/download-center?jmp=nav#community



다운로드 받은 "mongodb-win32-x86_64-2008plus-ssl-3.4.9-signed.msi" 파일을 실행하여 몽고디비를 설치합니다.

아무런 변경없이 기본값으로 설치하면 C:\Program Files\MongoDB\Server\3.4\bin 경로에 설치됩니다.


다음을 눌러 설치하면 되고 설치 경로는 원하는 곳으로 설정하면 됩니다



시스템 환경변수에 path 부분 변수 값에 설치된 경로 bin 까지를 추가해줍니다


그리고 cmd 를 띄우고 하단 명령어를 실행시키는데 이것은 데이터베이스를 서비스하기 위한 명령어로 

이것을 실행해놔야 데이터 베이스가 동작하게 되는 것입니다



mongod --dbpath /Users/현재사용자계정이름/database/local


/Users/현재사용자계정이름/database/local 이것은 사용자 계정 폴더로 이 폴더가 있어야 동작을 합니다

/database/local  이 폴더가 없다면 직접 만들면 됩니다







이렇게가지 수행했다면 이제는 데이터베이스 서버(서비스)가 실행된것입니다


제일 하단에 27017 포트번호는 이쪽 번호로 연결이 들어오기를 기다리고 있다는 뜻입니다


다른 cmd 를 띄워 mongo를 입력하면 mongodb://127.0..0.1:27017 로 접속하는 것을 볼 수 있습니다


이렇게 나온다면 이후 필요한 작업을 할수 있습니다


cmd 창에서 계속 다음을 입력

use local      DB가 local 을 사용할수 있게 변경 하는 것 , 상단에 계정 하단에  /database/local 폴더를 만들었는데 이 local 폴더를 말함


db.users.insert({name:'3dmp', number:123456789})     이 명령어를 입력하면 (즉 객체를 통채로 저장, no-sql 방식임)

db 아래 users 컬렉션(테이블과 유사)이 없으면 추가 되고 그다음 객체 {name:'3dmp', number:123456789} 를 추가하는 명령


다음 결과를 보여주는데 이것은  데이터가 추가가 됐다는 것을 의미

WriteResult({ "nInserted" : 1 })


cmd 에서 이어서 다음을 입력..

1
2
3
4
5
6
7
8
9
10
11
12
> db.users                        //이것은 users컬렉션(테이블)까지
local.users
> db.users.find()                 //users 하단의 정보를 찾는 것
"_id" : ObjectId("5aeb379d4482a0efc7ac86e5"), "name" : "3dmp""number" : 123456789 }
> db.users.find().pretty()    //출력 결과를 좀 더 보기 좋게
{
        "_id" : ObjectId("5aeb379d4482a0efc7ac86e5"), //id 속성이 자동으로 만들어짐
        "name" : "3dmp",
        "number" : 123456789
}
>
 



cmd 창에서 입력한 전문





cmd 창으로 접근하여 아래처음 바로 원소를 추가하면 database 네임이 test 로 만들어지고 nodejs 에서 처음 database name 에 접근하기 위해선 위 코드와는 약간 다르게 접근해야 오류가 안나는데 접근 방식은 하단 코드를 참조하면 됩니다

db.users.insert({name:'3dmp', number:123456789}) 




몽고디비에 연결하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//몽고디비에 연결 ,  보통 웹서버 만든 직후 연결 , DB 먼저 연결 되도 상관 없음
//먼저 db를 가져온다 
function connectDB()
{
    //localhost 로컬 호스트
    //:27017  몽고디비 포트
    //local db 생성시 만든 폴더 명
    var databaseURL = 'mongodb://localhost:27017';
    mongoClient.connect(databaseURL,
        function (err, db)
        {
            if (err)
            {
                console.log('db connect error');
                return;
            }
 
            console.log('db was connected : ' + databaseURL);
            database = db;          //이 구문까지 실행되었다면 ongoDB 에 연결된 것
        }
    );
 
}
 




몽고디비에 연결이 된 이후 database 명으로 컬렉션(테이블) 가져오기

(바로 데이터를 추가하면 test db 가 만들어짐) 으로 연결은 애초에 connect 에서 뒤에  /test 를 붙여도 되는데  


var databaseURL = 'mongodb://localhost:27017/test';



주소 뒤에 test 가 있든 없든 db.db('test') 이 처럼 db를 한번은 가져와야함



1
2
3
4
5
//cmd 에서 db.users  로 썻던 부분이 있는데 이때 이 컬럼(테이블)에 접근은 다음처럼 한다
    var users = db.db('test').collection("users");
    //찾고자 하는 정보를 입력해준다
    //var result = users.find({ name: id, passwords: password });
    var result = users.find({});




반응형
반응형


파일을 서버의 폴더로 업로드하기





브라우저에서 파일 올리기 요청을 하면 서버에 설정해둔 경로로 파일을 업로드한다


이때 파일 업로드를 위해 사용되는 주 모듈은


1
2
3
var multer = require('multer');     //파일 업로드하기 위한 모듈
var fs = require('fs');             //파일 시스템
var cors = require('cors');         //다중 서버로 접속하게 해주는 기능을 제공, 다른 ip 로 다른서버에 접속
cs

이렇게 3개이다



아래 지정한 경로대로 서버에 업로드할 파일을 전송하게 된다



photo.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
 
<html>
<head>
    <meta charset="utf-8" />
    <title>upload file</title>
</head>
    <h1>upload file</h1
 
<form method="post" action="/process/photo" enctype="multipart/form-data">
    <table>
        <tr>
            <td><label>file</label></td>
            <td><input type="file" name="photo" /></td<!--photo 이 이름이 서버쪽으로 요청파라미터 이름으로 들어가게됨-->
        </tr>
    </table>
    <input type="submit" value="upload" name="summit" />
</form>
<body>
 
</body>
</html>





photo.html 실행시킨 모습







서버 nodejs 코드


서버코드인데 중간에 cors 를 사용한 부분이 있는데 이것은 웹페이지를 연서버가 있으면 그 서버로만 접속하게끔 되어 있는 보안 정책이 있는데 

파일 업로드하기 위해선 이것을  꼭 서버에만 접속해선 기능을 만들기 힘들수 있음으로 cors 를 상용해 이 정책을 우회한다


var cors = require('cors');         //다중 서버로 접속하게 해주는 기능을 제공, 다른 ip 로 다른서버에 접속

app.use(cors());                      //다중 접속을 위한 미들웨에



파일이 저장될 경로 세팅

1
app.use('/uploads',serveStatic(path.join(__dirname, 'uploads')));



웹은 기본적으로 '동일출저정책(Same Origin Policy, SOP)' 정책을  따른다.


이는 보안을 위한 기본정책으로, SOP는 하나의 출처(Origin)에서 로드된 문서나 스크립트가 다른 출처에 존재하는 리소스와 상호작용하지 못하도록 제약을 두는 것이다.


그런데, 간혹 이런 제약이 웹 응용프로그램을 만드는데 걸림돌이 되기도 한다.

Ajax 통신이 활발해 지고, 다른 사이트에 존재하는 Open API와 상호통신이 필요한 경우와 매쉬업(Mash-up)으로 새로운 2차 응용물을 개발하게 되면서.. 등등.. 이는 간혹 걸림돌이 된다.


근래 Node.JS로 서버를 만들고, Aptana Studio 자체 내장 웹서버로 몇 가지 테스트를 하고 있는데, 두 환경은 서로 다른 별도의 포트(Port)에서 웹을 동작시키기 때문에 여지없이 Cross Domain 문제가 발생한다.




호출하는 모든 웹 리소스를, Node.JS로부터 다운로드 받아서 실행하는 구조로 HTTP 서버를 구현하면 SOP 정책을 따를 수 있겠으나, 그렇지 못한 개발환경도 있을 터이고, 실제 서비스 환경에서는 더욱이 서로 다른 도메인(포트 포함)간 상호작용이 필요할 것이다.


SOP 정책을 우회하기 위해서는, 서버 측의 설정이 필요한데, 위 그림에서 친철히 안내하고 있는 것처럼 Access-Control-Allow-Origin 헤더, 즉 크로스 도메인으로 허용할 도메인 목록이 헤더로 제공되어야 한다.

이것을 CORS(Cross-Origin Resource Sharing)를 이용한 SOP 정책 우회라 한다.







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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
var express = require('express');
var http = require('http');
var serveStatic = require('serve-static');      //특정 폴더의 파일들을 특정 패스로 접근할 수 있도록 열어주는 역할
var path = require('path');
var cookieParser = require('cookie-parser');
var expressSession = require('express-session');
 
var multer = require('multer');     //파일 업로드하기 위한 모듈
var fs = require('fs');             //파일 시스템
var cors = require('cors');         //다중 서버로 접속하게 해주는 기능을 제공, 다른 ip 로 다른서버에 접속
var app = express();      //express 서버 객체
 
 
app.set('port'3000);
app.use(serveStatic(path.join(__dirname, 'public')));
app.use('/uploads',serveStatic(path.join(__dirname, 'uploads')));
 
 
var bodyParser_post = require('body-parser');       //post 방식 파서
//post 방식 일경우 begin
//post 의 방식은 url 에 추가하는 방식이 아니고 body 라는 곳에 추가하여 전송하는 방식
app.use(bodyParser_post.urlencoded({ extended: false }));            // post 방식 세팅
app.use(bodyParser_post.json());                                     // json 사용 하는 경우의 세팅
//post 방식 일경우 end
 
 
 
//쿠키와 세션을 미들웨어로 등록한다
app.use(cookieParser());
 
//세션 환경 세팅
//세션은 서버쪽에 저장하는 것을 말하는데, 파일로 저장 할 수도 있고 레디스라고 하는 메모리DB등 다양한 저장소에 저장 할 수가 있는데
app.use(expressSession({
    secret: 'my key',           //이때의 옵션은 세션에 세이브 정보를 저장할때 할때 파일을 만들꺼냐 , 아니면 미리 만들어 놓을꺼냐 등에 대한 옵션들임
    resave: true,
    saveUninitialized: true
}));
 
 
 
 
//파일을 올리기위한 세팅 시작
 
 
//다중 접속을 위한 미들웨에
app.use(cors());
 
//파일 업로드를 위한 설정
var fileStorage =  multer.diskStorage(
    {
        destination: function (req,file, callback)
        {
            callback(null'uploads');      //목적지 폴더 지정 : 'uploads' 를 목적지로 정한다(이쪽으로 파일이 오게됨)
        },
        filename: function (req, file, callback)
        {
            //올린 파일명이 기존과 같으면 덮어씌워짐으로 시간을 기준으로 다른 파일로 저장되게끔 처리한다
   
            var extention = path.extname(file.originalname);
            var basename = path.basename(file.originalname, extention);        //확장자 .jpg 만 빠진 파일명을 얻어온다
            var fname = basename + Date.now() + extention;
            callback(null, fname);  
 
        }
 
    }
);
 
var upload = multer(
    {
        storage: fileStorage,
        limits:
            {
                files: 10,                      //10개까지
                fileSize: 1024 * 1024 * 1024    //한번 업로드 할때 최대 사이즈
            }
    }
);
 
//파일을 올리기위한 세팅 끝
//이제 이것을 갖고 라우터를 통해서 파일을 업로드 할수 있게끔 해야함
 
 
//라우트를 미들웨어에 등록하기 전에 라우터에 설정할 경로와 함수를 등록한다
//
//라우터를 사용 (특정 경로로 들어오는 요청에 대하여 함수를 수행 시킬 수가 있는 기능을 express 가 제공해 주는것)
var router = express.Router();
 
 
 
 
//upload.array : Accept an array of files, all with the name fieldName. 
//Optionally error out if more than maxCount files are uploaded.
//The array of files will be stored in req.files. 
//('photo',1) : photo 라고 지정한 파일이 있다면 1개를 전송하라는 의미
router.route('/process/photo').post(upload.array('photo',1),
    function (req, res)
    {
        console.log('/process/photo 함수가 호출됨');
        var files = req.files;
        if (files.length > 0)
        {
            console.dir(files[0]);
        }
        else
        {
            console.log('파일이 없음');
        }
 
 
        res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
        res.write('<h1>file upload complete</h1>');
        if (Array.isArray(files))
        {
            files.forEach(
                function (elem)
                {
                    res.write('<h1>' + elem.originalname + '</h1>');
                    res.write('<h1>' + elem.filename + '</h1>');
                    res.write('<h1>' + elem.mimetype + '</h1>');
                    res.end();
                      
                }
            );
        }
 
        
    }
);
 
 
//http://localhost:3000/process/product 이 주소로 치면 라우터를 통해 바로 여기로 올 수 있다
router.route('/process/product').get(
    function (req, res) {
        console.log('/process/product  라우팅 함수 실행');
 
        //세션정보는 req.session 에 들어 있다
        if (req.session.user)       //세션에 유저가 있다면
        {
            res.redirect('/product.html');
        }
        else {
            res.redirect('/login2.html');
 
        }
    }
);
 
router.route('/process/login').post(                      //설정된 쿠키정보를 본다
    function (req, res) {
        console.log('/process/login 라우팅 함수호출 됨');
 
        var paramID = req.body.id || req.query.id;
        var pw = req.body.passwords || req.query.passwords;
 
        if (req.session.user) {
            console.log('이미 로그인 되어 있음');
 
            res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
            res.write('<h1>already Login</h1>');
            res.write('[ID] : ' + paramID + ' [PW] : ' + pw);
            res.write('<a href="/process/product">Move</a>');
            res.end();
 
        } else {
            req.session.user =
                {
                    id: paramID,
                    pw: pw,
                    name'UsersNames!!!!!',
                    authorized: true
                };
            res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
            res.write('<h1>Login Success</h1>');
            res.write('[ID] : ' + paramID + ' [PW] : ' + pw);
            res.write('<a href="/process/product">Move</a>');
            res.end();
        }
    }
);
 
router.route('/process/logout').get(                      //설정된 쿠키정보를 본다
    function (req, res) {
        console.log('/process/loginout 라우팅 함수호출 됨');
 
        if (req.session.user) {
            console.log('로그아웃 처리');
            req.session.destroy(
                function (err) {
                    if (err) {
                        console.log('세션 삭제시 에러');
                        return;
                    }
                    console.log('세션 삭제 성공');
                    //파일 지정시 제일 앞에 / 를 붙여야 root 즉 public 안에서부터 찾게 된다
                    res.redirect('/Login2.html');
                }
            );          //세션정보 삭제
 
        } else {
            console.log('로긴 안되어 있음');
            res.redirect('/Login2.html');
        }
 
 
 
    }
);
 
 
 
//라우터 미들웨어 등록하는 구간에서는 라우터를 모두  등록한 이후에 다른 것을 세팅한다
//그렇지 않으면 순서상 라우터 이외에 다른것이 먼저 실행될 수 있다
app.use('/', router);       //라우트 미들웨어를 등록한다
 
 
app.all('*',
    function (req, res) {
        res.status(404).send('<h1> 요청 페이지 없음 </h1>');
    }
);
 
//웹서버를 app 기반으로 생성
var appServer = http.createServer(app);
appServer.listen(app.get('port'),
    function () {
        console.log('express 웹서버 실행' + app.get('port'));
    }
);
 





파일을 올리고 나면 다음처럼 파일이 uploads 폴더에 저장되어 있는 것을 확인할 수 있다







정책 일부 ref : http://m.mkexdev.net/339

반응형
반응형


쿠키는 브라우저에 정보들을 저장하는 방식으로 진행된다



세션은 정보를 서버에 저장해놓고 키를 통해서 브라우저와 통신하게 되는데

이때 필요한 세션정보는 쿠키로 저장한다 => (connect.id)



Route 에 의한 경로 이동을 하게 되는데 html 에서는 action="path" 에 있는 경로나  a href="path" 에 있는 경로를 보고


서버(Nodejs) 로 해당 경로를 던지게 되면 서버(Nodejs) 에서는 해당 경로를 Route 로 등록해놓았을 경우


해당 경로에 대한 함수 처리를 하게 되는 방식으로 동작한다




세션을 통한 전체 동작은 다음 처럼 이루어진다


로그인하여 product.html 에 있는 내용을 보기위한 과정이라고 보면된다(로그인처리하면서 정보를 세션에 저장)

다 보았으면 로그아웃하면서 세센 정보를 삭제한다



(html 파일들은 public  폴더 아래 있다고 가정한다)







login2.html (로그인 담당 페이지)



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
<!DOCTYPE html>
 
<html>
<head>
    <meta charset="utf-8" />
    <title>login2</title>
</head>
<body>
 
    <h1>login2</h1>
    <form method="post" action="/process/Login">
        <table>
            <tr>
                <td><label>ID : </label></td>
                <td><input type="text" name="id"></td>
            </tr>
            <tr>
                <td><label>PW : </label></td>
                <td><input type="text" name="passwords"></td>
 
 
            </tr>
 
            <tr>
                <td><input type="submit" value="Sumit" name=""></td>
            </tr>
 
        </table>
 
    </form>
 
</body>
</html>






Product.html  (간단한 shoes 정보를 보여준다고 가정하는 페이지)



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
 
<html>
<head>
    <meta charset="utf-8" />
    <title>product</title>
</head>
<body>
    <h3>product page - Now sale</h3>
    <br />
 
    <p>Nice shoes 1</p>
    <p>Nice shoes 2</p>
    <p>Nice shoes 3</p>
    <p>Nice shoes 4</p>
    <p>Nice shoes 5</p>
 
    <a href="/process/logout"> Logout  </a>
</body>
</html>






서버코드 (Nodejs.js)



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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
var express = require('express');
var http = require('http');
var serveStatic = require('serve-static');      //특정 폴더의 파일들을 특정 패스로 접근할 수 있도록 열어주는 역할
var path = require('path');
var cookieParser = require('cookie-parser');
var expressSession = require('express-session');
 
var app = express();      //express 서버 객체
 
var bodyParser_post = require('body-parser');       //post 방식 파서
 
app.set('port'3000);
 
 
//미들웨어들 등록 시작, 아래 미들웨어들은 내부적으로 next() 가실행됨
 
//join은 __dirname : 현재 .js 파일의 path 와 public 을 합친다
//이렇게 경로를 세팅하면 public 폴더 안에 있는것을 곧바로 쓸 수 있게된다
app.use(serveStatic(path.join(__dirname, 'public')));
 
 
//post 방식 일경우 begin
//post 의 방식은 url 에 추가하는 방식이 아니고 body 라는 곳에 추가하여 전송하는 방식
app.use(bodyParser_post.urlencoded({ extended: false }));            // post 방식 세팅
app.use(bodyParser_post.json());                                     // json 사용 하는 경우의 세팅
//post 방식 일경우 end
 
 
 
//쿠키와 세션을 미들웨어로 등록한다
app.use(cookieParser());
 
//세션 환경 세팅
//세션은 서버쪽에 저장하는 것을 말하는데, 파일로 저장 할 수도 있고 레디스라고 하는 메모리DB등 다양한 저장소에 저장 할 수가 있는데
app.use(expressSession({
    secret: 'my key',           //이때의 옵션은 세션에 세이브 정보를 저장할때 할때 파일을 만들꺼냐 //아니면 미리 만들어 놓을꺼냐 등에 대한 옵션들임
    resave: true,
    saveUninitialized:true
}));
 
 
 
//라우트를 미들웨어에 등록하기 전에 라우터에 설정할 경로와 함수를 등록한다
//
//라우터를 사용 (특정 경로로 들어오는 요청에 대하여 함수를 수행 시킬 수가 있는 기능을 express 가 제공해 주는것)
var router = express.Router();
 
 
//http://localhost:3000/process/product 이 주소로 치면 라우터를 통해 바로 여기로 올 수 있다
router.route('/process/product').get(
    function (req, res)
    {
        console.log('/process/product  라우팅 함수 실행');
 
        //세션정보는 req.session 에 들어 있다
        if (req.session.user)       //세션에 유저가 있다면
        {
            res.redirect('/product.html');
        }
        else
        {
            res.redirect('/login2.html');
 
        }
    }
);
 
router.route('/process/login').post(                      //설정된 쿠키정보를 본다
    function (req, res) {
        console.log('/process/login 라우팅 함수호출 됨');
 
        var paramID = req.body.id || req.query.id;
        var pw = req.body.passwords || req.query.passwords;
 
        if (req.session.user) {
            console.log('이미 로그인 되어 있음');
 
            res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
            res.write('<h1>already Login</h1>');
            res.write('[ID] : ' + paramID + ' [PW] : ' + pw);
            res.write('<a href="/process/product">Move</a>');
            res.end();
 
        } else {
            req.session.user =
                {
                    id: paramID,
                    pw: pw,
                    name'UsersNames!!!!!',
                    authorized: true
                };
            res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
            res.write('<h1>Login Success</h1>');
            res.write('[ID] : ' + paramID + ' [PW] : ' + pw);
            res.write('<a href="/process/product">Move</a>');
            res.end();
        }
    }
);
 
router.route('/process/logout').get(                      //설정된 쿠키정보를 본다
    function (req, res) {
        console.log('/process/loginout 라우팅 함수호출 됨');
 
        if (req.session.user) {
            console.log('로그아웃 처리');
            req.session.destroy(
                function (err) {
                    if (err) {
                        console.log('세션 삭제시 에러');
                        return;
                    }
                    console.log('세션 삭제 성공');
                    //파일 지정시 제일 앞에 / 를 붙여야 root 즉 public 안에서부터 찾게 된다
                    res.redirect('/Login2.html');
                }
            );          //세션정보 삭제
 
        } else {
            console.log('로긴 안되어 있음');
            res.redirect('/Login2.html');
        }
 
 
     
    }
);
 
 
//라우터 미들웨어 등록하는 구간에서는 라우터를 모두  등록한 이후에 다른 것을 세팅한다
//그렇지 않으면 순서상 라우터 이외에 다른것이 먼저 실행될 수 있다
app.use('/', router);       //라우트 미들웨어를 등록한다
 
 
app.all('*',
    function (req, res) {
        res.status(404).send('<h1> 요청 페이지 없음 </h1>');
    }
);
 
//웹서버를 app 기반으로 생성
var appServer = http.createServer(app);
appServer.listen(app.get('port'),
    function () {
        console.log('express 웹서버 실행' + app.get('port'));
    }
);
 


반응형
반응형

설치해야할 모듈

npm install cookie-parser --save



쿠키 : 브라우저에 저장정보

세션 : 서버에 저장정보



필요한 모듈

var cookieParser = require('cookie-parser');





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
var express = require('express');
var http = require('http');
var serveStatic = require('serve-static');      //특정 폴더의 파일들을 특정 패스로 접근할 수 있도록 열어주는 역할
var path = require('path');
var cookieParser = require('cookie-parser');
 
var app = express();      //express 서버 객체
 
var bodyParser_post = require('body-parser');       //post 방식 파서
 
app.set('port'3000);
 
 
//미들웨어들 등록 시작, 아래 미들웨어들은 내부적으로 next() 가실행됨
 
//join은 __dirname : 현재 .js 파일의 path 와 public 을 합친다
//이렇게 경로를 세팅하면 public 폴더 안에 있는것을 곧바로 쓸 수 있게된다
app.use(serveStatic(path.join(__dirname, 'public')));
 
 
//post 방식 일경우 begin
//post 의 방식은 url 에 추가하는 방식이 아니고 body 라는 곳에 추가하여 전송하는 방식
app.use(bodyParser_post.urlencoded({ extended: false }));            // post 방식 세팅
app.use(bodyParser_post.json());                                     // json 사용 하는 경우의 세팅
//post 방식 일경우 end
 
 
 
 
app.use(cookieParser());
 
 
 
 
//라우터를 사용 (특정 경로로 들어오는 요청에 대하여 함수를 수행 시킬 수가 있는 기능을 express 가 제공해 주는것)
var router = express.Router();
 
 
//라우터를 통해 쿠키 정보를 저장할 수 있음
router.route('/process/setUserCookie').get(
    function (req, res)
    {
        console.log('/process/setUserCookie : 라우팅 함수 호출 ');
 
        //웹서버에서 웹 브라우저에 저장할 정보를 세팅한다
        res.cookie(
            'user', { id: '1004'name'kim', authorized: true }
        );
        res.redirect('/process/showCookie');    //페이지 리다이렉트
    }
);
 
 
// 웹브라우저에서 서버쪽에 어떤 요청을 할대 갖고 있는 쿠키정보를 넘겨준다, 이 정보는 req,cookies 에서 확인할 수 있다
router.route('/process/showCookie').get(
    function (req, res) {
        console.log('/process/showCookie : 라우팅 함수 호출 ');
 
        //req.cookies 이것은 서버에 있는 것이 아닌 클라에서 요청했을때 넘어온 req 객체에 있는  웹브라우저 쿠키 정보이다
        //즉 클라이언트에서 서버 접속시 브라우저에서 보내준 정보인데 이것을 사전에 값을 세팅하여 다시 클라로 보내
        //해당 내용을 저장하라고 send 할 수 있다
        res.send(req.cookies);
    }
);
 
 
 
router.route('/process/login/:name').post(                      //설정된 쿠키정보를 본다
    function (req, res) {
        console.log('/process/login:name 라우팅 함수에서 받음');
 
        var paramName = req.params.name;
 
        var paramID = req.body.id || req.query.id;
        var pw = req.body.passwords || req.query.passwords;
 
        res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
        res.write(paramName + ' ,  ' + paramID + " : " + paramID);
        res.end();
    }
);
 
 
//라우터 미들웨어 등록하는 구간에서는 라우터를 모두  등록한 이후에 다른 것을 세팅한다
//그렇지 않으면 순서상 라우터 이외에 다른것이 먼저 실행될 수 있다
app.use('/', router);       //라우트 미들웨어를 등록한다
 
 
app.all('*',
    function (req, res) {
        res.status(404).send('<h1> 요청 페이지 없음 </h1>');
    }
);
 
//웹서버를 app 기반으로 생성
var appServer = http.createServer(app);
appServer.listen(app.get('port'),
    function () {
        console.log('express 웹서버 실행' + app.get('port'));
    }
);
 






브라우저에 localhost:3000/process/setUserCookie 를 입력하여 클라로부터 받은 쿠키 정보에 저장할 값을 서버에서 세팅한다음

다시 클라로 전송 하여 브라우저에서 정보를 갖고있게 한다


결과화면 




쿠키 정보에서 showCookie , 쿠키 값을 보면 이름이 user인 값이 브라우저에 저장된 것을 볼 수 있다








반응형
반응형

URL 요청파라미터

post 방식 요청 path (Router) 의 맨 뒤의 경로를 값으로 쓰겠다는 것



형식 :

path/:name


클라이언트에서 요청할떄 name 으로 요청 보냄




nodejs : Express, Router 라우터로 경로에 대한 분기 처리

http://3dmpengines.tistory.com/1867


글을 먼저 참고



전과 달라진 부분만 강조하여 표시하면



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
<!DOCTYPE html>
 
<html>
<head>
    <meta charset="utf-8" />
    <title>로긴</title>
</head>
<body>
 
    <h1>로그인 Route</h1>
    <br />
    <form method="post" action="/process/Login/add">
        <table>
            <tr>
                <td><label>아이디</label></td>
                <td><input type="text" name="id"></td>
            </tr>
            <tr>
                <td><label>비번</label></td>
                <td><input type="text" name="passwords"></td>
            </tr>
        </table>
        <td><input type="submit" value="전송" name=""></td>
    </form>
 
</body>
</html>

 

submit 을 할때 경로 끝에 /add 를 붙여 이것이 경로가 아닌 파라미터로 넘어가게 한다






서버측 코드


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
var express = require('express');
var http = require('http');
var serveStatic = require('serve-static');      //특정 폴더의 파일들을 특정 패스로 접근할 수 있도록 열어주는 역할
var path = require('path');
 
var app = express();      //express 서버 객체
 
var bodyParser_post = require('body-parser');       //post 방식 파서
 
app.set('port'3000);
 
 
//미들웨어들 등록 시작, 아래 미들웨어들은 내부적으로 next() 가실행됨
 
//join은 __dirname : 현재 .js 파일의 path 와 public 을 합친다
//이렇게 경로를 세팅하면 public 폴더 안에 있는것을 곧바로 쓸 수 있게된다
app.use(serveStatic(path.join(__dirname, 'public')));
 
 
//post 방식 일경우 begin
//post 의 방식은 url 에 추가하는 방식이 아니고 body 라는 곳에 추가하여 전송하는 방식
app.use(bodyParser_post.urlencoded({ extended: false }));            // post 방식 세팅
app.use(bodyParser_post.json());                                     // json 사용 하는 경우의 세팅
//post 방식 일경우 end
 
 
 
//라우터를 사용 (특정 경로로 들어오는 요청에 대하여 함수를 수행 시킬 수가 있는 기능을 express 가 제공해 주는것)
var router = express.Router();
 
router.route('/process/login/:name').post(                      //이 경로로 들어오는 것은 post 방식으로 처리
    function (req, res) {
        console.log('/process/login:name 라우팅 함수에서 받음');
 
        var paramName = req.params.name; //이런 방식으로 경로에서 요청파라미터의 값을 얻어온다
 
        var paramID = req.body.id || req.query.id;
        var pw = req.body.passwords || req.query.passwords;
 
        res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
        res.write(paramName + ' ,  ' + paramID + " : " + paramID);
        res.end();
    }
);
 
app.use('/', router);       //라우트 미들웨어를 등록한다
 
 
//웹서버를 app 기반으로 생성
var appServer = http.createServer(app);
appServer.listen(app.get('port'),
    function () {
        console.log('express 웹서버 실행' + app.get('port'));
    }
);
 




입력 화면 :






전송 클릭



결과 화면 : 




실행 결과를 보면 add 가 post 보내기 방식과 Router를 통해 경로중 끝값인 :name 에 매칭되어 보내졌다는 결과를 볼 수 있다



파라미터를 보내는 방식은 get ,post , 라우터를 통한 파라미터 보내기 방식인 3가지가 있다






등록하지 않은 경로에 대한 예외처리는 다음 처럼 할 수 있다





상단 서버코드에서 접근 가능한 경로외의 경로 전체에  대한 코드만 추가해주면 되는데 다음과 같다

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
//라우터를 사용 (특정 경로로 들어오는 요청에 대하여 함수를 수행 시킬 수가 있는 기능을 express 가 제공해 주는것)
var router = express.Router();
 
router.route('/process/login/:name').post(                      //이 경로로 들어오는 것은 post 방식으로 처리
    function (req, res) {
        console.log('/process/login:name 라우팅 함수에서 받음');
 
        var paramName = req.params.name;
 
        var paramID = req.body.id || req.query.id;
        var pw = req.body.passwords || req.query.passwords;
 
        res.writeHead(200, { "Content-Type""text/html;characterset=utf8" });
        res.write(paramName + ' ,  ' + paramID + " : " + paramID);
        res.end();
    }
);
 
app.use('/', router);       //라우트 미들웨어를 등록한다


app.all('*',
    function (req, res)
    {
        res.status(404).send('<h1> 요청 페이지 없음 </h1>');
    }
);
 
 





'*' 정상경로가 아닌 모든 경우의 경우  res.status(..)  로 예외처리를 할 수 있다




위 이미지에 표시된 경로는 서버 public 폴더 안에 없는 경로임으로 위와 같은 예외처리 문장이 나타나게 됩니다



좀 더 예외처리를 향상되게 하고 싶다면 'express-error-handler'  모듈을 사용하여 예외처리를 할 수 있습니다


이 기능은 해당 에러에 대한 에러 페이지를 미리 만들놔 그 페이지를 보여주는 방식입니다






Path 를 찾지 못하는 경우의 flow






반응형
반응형






라우터

라우터를 사용 (특정 경로로 들어오는 요청에 대하여 함수를 수행 시킬 수가 있는 기능), Express 가 제공



특정 경로에 대한 요청은 router.route('/process/login').post(...) 이런 방식으로 '해당 경로로 들어 온것에 대해 미들웨어'를 발동 시킬 수 있다


'해당 경로 명과 .html 등의 확장명 붙어 있는 것은 서로 다른 경로로 인식함'




브라우저로 먼저 라우터와 상관 없는 메인 페이지인 Login.html 페이지로 들어간다


http://localhost:3000/Login.html



이 웹페이지의 코드는 아래와 같다


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
<!DOCTYPE html>
 
<html>
<head>
    <meta charset="utf-8" />
    <title>로긴</title>
</head>
<body>
 
    <h1>로그인 Route</h1>
    <br />
    <form method="post" action="/process/Login">
        <table>
            <tr>
                <td><label>아이디</label></td>
                <td><input type="text" name="id"></td>
            </tr>
            <tr>
                <td><label>비번</label></td>
                <td><input type="text" name="passwords"></td>
            </tr>
        </table>
        <td><input type="submit" value="전송" name=""></td>
    </form>
 
</body>
</html>


Login.html




위 그림 처럼 id, pw 를 입력한다음


 전송 버튼을 누르면 


id, pw 가 서버로 전송된다




이때 위 코드에서도 나와 있듯이 form="post' 방식으로 전달 하는데 경로를 /process/Login  으로 설정해 


서버에 전송 할 수 있다






이런 경우 nodejs.js 서버 코드에서  /process/Login 경로로 온 요청에 대해선 Router 를 통해 이에 대해서만 미들웨어가 호출되게 할 수 있다









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
var express = require('express');
var http = require('http');
var serveStatic = require('serve-static');      //특정 폴더의 파일들을 특정 패스로 접근할 수 있도록 열어주는 역할
var path = require('path');
 
var app = express();      //express 서버 객체
 
var bodyParser_post = require('body-parser');       //post 방식 파서
 
app.set('port'3000);
 
 
//미들웨어들 등록 시작, 아래 미들웨어들은 내부적으로 next() 가실행됨
 
//join은 __dirname : 현재 .js 파일의 path 와 public 을 합친다
//이렇게 경로를 세팅하면 public 폴더 안에 있는것을 곧바로 쓸 수 있게된다
app.use(serveStatic(path.join(__dirname, 'public')));
 
 
//post 방식 일경우 begin
//post 의 방식은 url 에 추가하는 방식이 아니고 body 라는 곳에 추가하여 전송하는 방식
app.use(bodyParser_post.urlencoded({ extended:false }));            // post 방식 세팅
app.use(bodyParser_post.json());                                     // json 사용 하는 경우의 세팅
//post 방식 일경우 end
 
 
 
//라우터를 사용 (특정 경로로 들어오는 요청에 대하여 함수를 수행 시킬 수가 있는 기능을 express 가 제공해 주는것)
var router = express.Router();
 
router.route('/process/login').post(         //이 경로로 들어오는 것은 post 방식으로 처리
    function (req, res)
    {
        console.log('/process/login 라우팅 함수에서 받음');
        var paramID = req.body.id || req.query.id;
        var pw = req.body.passwords || req.query.passwords;
 
        res.writeHead(200, { "Content-Type":"text/html;characterset=utf8" });
        res.write(paramID + " : " + paramID);
        res.end();
    }
);
 
app.use('/', router);       //라우트 미들웨어를 등록한다
 
 
//웹서버를 app 기반으로 생성
var appServer = http.createServer(app);
appServer.listen(app.get('port'),
    function () {
        console.log('express 웹서버 실행' + app.get('port'));
    }
);
 





결과 화면 :



라우터를 통해 처리된 결과를 클라이언트에게 보내준 정보에 출력 결과



반응형
반응형
먼저 index.html 인데 이 html 파일에서는 로그인을 위한 아이디와 pw 를 입력 받는 페이지로 구성했다

name="id" , name="passwords"

summit 버튼을 통해서 위 두개의 정보 값이 post 방식으로 서버에 넘어간다


로그인을 위한 index.html

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
<!DOCTYPE html>
 
<html>
<head>
    <meta charset="utf-8" />
    <title>로긴</title>
</head>
<body>
 
    <h1>로그인</h1>
     <br />
     <form method="post">
         <table>
             <tr>
                 <td><label>아이디</label></td>
                 <td><input type="text" name="id"></td>
             </tr>
             <tr>
                 <td><label>비번</label></td>
                 <td><input type="text" name="passwords"></td>
             </tr>
         </table>
         <td><input type="submit" value="전송" name=""></td>
     </form>
 
</body>
</html>






서버 nodejs.js 코드
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
var express = require('express');
var http = require('http');
var serveStatic = require('serve-static');      //특정 폴더의 파일들을 특정 패스로 접근할 수 있도록 열어주는 역할
var path = require('path');
 
var app = express();      //express 서버 객체
 
var bodyParser_post = require('body-parser');       //post 방식 파서
 
app.set('port'3000);
 
 
//미들웨어들 등록 시작, 아래 미들웨어들은 내부적으로 next() 가실행됨
 
//join은 __dirname : 현재 .js 파일의 path 와 public 을 합친다
//이렇게 경로를 세팅하면 public 폴더 안에 있는것을 곧바로 쓸 수 있게된다
app.use(serveStatic(path.join(__dirname, 'public')));
 
 
//post 방식 일경우 begin
//post 의 방식은 url 에 추가하는 방식이 아니고 body 라는 곳에 추가하여 전송하는 방식
app.use(bodyParser_post.urlencoded({ extended:false }));            // post 방식 세팅
app.use(bodyParser_post.json());                                     // json 사용 하는 경우의 세팅
//post 방식 일경우 end
 
 
//이건 사용자 정의형태로 미들웨어를 제작
app.use(
    function (req, res, next) {
        console.log('middle wared was called : first');
        //res.redirect('http://google.co.kr');
 
        //req 여러 정보를 얻어 올 수 있는데 그중
        //요청받은 request 정보중에서 User-Agent 정볼를 따로 분리하여 갖어올 수 있다
        var userAgent = req.header('User-Agent');
 
        //요청파라미터는 get 방식인 req.query 에 들어오게 된다
        //post 방식은 body로 들어오게된다
        //name 은 정해져있는 명칭
 
        var paramName = req.body.id || req.query.id;
        var paramNamePW = req.body.passwords || req.query.passwords;
 
        //응답 보내기
        res.send('<h3>response from server!!7!! : ' + userAgent + '[' + paramName + ' : ' + paramNamePW  + '] </h3>');
    }
);
 
 
//웹서버를 app 기반으로 생성
var appServer = http.createServer(app);
appServer.listen(app.get('port'),
    function () {
        console.log('express 웹서버 실행' + app.get('port'));
    }
);
 




위 소스에서 굵은 글씨로 id 와 pw를 얻어올 수 있다


실행 절차는 먼저 이미지의 주소로 접근한다


index.html 파일은 public 폴더 밑에 두면 된다









전송 버튼을 누른다음 클라이언트가 받게 되는 정보는 아래와 같다 [ ...... : ....... ]








반응형
반응형

get 방식


특정 경로에 있는 폴더(public 폴더)를 요청에 의해서 바로 파일을 가져올 수 있는 기능을 제공 해주는 모듈 "serve-static" 이라는 것이 존재






우선 프로젝트 폴더에 public 이란 폴더를 만들어 놓는다


public 폴더안에 /game0.jpg 가 있는 상태라 가정




이럴 경우 서버를 실행 시킨다음에 브라우저에서


http://localhost:3000/game0.jpg 를 입력하면 해당 이미지가 열리는 것을 알 수 있다



만약  public/image/game0.jpg 로 배치해 놓았다면


http://localhost:3000/image/game0.jpg  로 입혁하면 된다



또는 서버에서 


res.end("<img src='/game0.jpg' ");


를 입력하여 곧바로 이미지를 보낼 수 있다





소스코드 : 


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 express = require('express');
var http = require('http');
var serveStatic = require('serve-static');      //특정 폴더의 파일들을 특정 패스로 접근할 수 있도록 열어주는 역할
var path = require('path');
 
var app = express();      //express 서버 객체
 
app.set('port'3000);
 
//join은 __dirname : 현재 .js 파일의 path 와 public 을 합친다
//이렇게 경로를 세팅하면 public 폴더 안에 있는것을 곧바로 쓸 수 있게된다
app.use(serveStatic(path.join(__dirname, 'public')));
 
 
///users 를 붙이게 되면 특정 경로를 지정하는 것으로 특정 기능을 수행할떄 사용한다
//localhost:3000/users
//example , get 방식
//localhost:3000/users?name=tesstsssssss
 
app.use(
    function (req, res, next) {
        console.log('middle wared was called : first');
        //res.redirect('http://google.co.kr');
 
        //req 여러 정보를 얻어 올 수 있는데 그중
        //요청받은 request 정보중에서 User-Agent 정볼를 따로 분리하여 갖어올 수 있다
        var userAgent = req.header('User-Agent');
 
        //요청파라미터는 get 방식인 req.query 에 들어오게 된다
        //post 방식은 body로 들어오게된다
        //name 은 정해져있는 명칭
        var paramName = req.query.name;
 
        //응답 보내기
        res.send('<h3>response from server!!!!!!!!!!!! : ' + userAgent + '</h3>' + paramName);
 
    }
);
 
 
//웹서버를 app 기반으로 생성
var appServer = http.createServer(app);
appServer.listen(app.get('port'),
    function () {
        console.log('express 웹서버 실행' + app.get('port'));
    }
 
);
 






결과 : 



http://localhost:3000/game0.jpg



인사이드 inside








post 방식

npm install body-parser --save 이 모듈을 설치해야한다



위으 소스에서 세군대 정도만 변경 또는 추가가 되는데 주의할 점은 일반 브라우저에서는 post 방식으로 보내면 안된다

주소 뒤에 ?name='sdf'  추가 하는 방식은 get 방식이기 때문에 이렇게 보내면 안되고

body 라는 곳에 추가를 해야 하는데 이것은 postman 이라는 툴을 사용해서 post 방식으로 보다 쉽게 보내는 방식이 존재한다


postman 을 설치하고 다음 처럼 입력하면 결과를 볼 수 있다

postman 으로 param 을 선택한다음 name, 과 출력할 값을 넣어주면 기존 get 방식과 거의 동일한 실행흐름이 진행된다는 것을 알 수 있다




소스코드 :


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
var express = require('express');
var http = require('http');
var serveStatic = require('serve-static');      //특정 폴더의 파일들을 특정 패스로 접근할 수 있도록 열어주는 역할
var path = require('path');
 
var app = express();      //express 서버 객체
//post 방식 일경우 begin
var bodyParser_post = require('body-parser');       //post 방식 파서
//post 방식 일경우 end
app.set('port'3000);
 
//join은 __dirname : 현재 .js 파일의 path 와 public 을 합친다
//이렇게 경로를 세팅하면 public 폴더 안에 있는것을 곧바로 쓸 수 있게된다
app.use(serveStatic(path.join(__dirname, 'public')));
 
 
//post 방식 일경우 begin
//post 의 방식은 url 에 추가하는 방식이 아니고 body 라는 곳에 추가하여 전송하는 방식
app.use(bodyParser_post.urlencoded({ extended:false }));            // post 방식 세팅
app.use(bodyParser_post.json());                                     // json 사용 하는 경우의 세팅
//post 방식 일경우 end
 
 
///users 를 붙이게 되면 특정 경로를 지정하는 것으로 특정 기능을 수행할떄 사용한다
//localhost:3000/users
//example , get 방식
//localhost:3000/users?name=tesstsssssss
 
app.use(
    function (req, res, next) {
        console.log('middle wared was called : first');
        //res.redirect('http://google.co.kr');
 
        //req 여러 정보를 얻어 올 수 있는데 그중
        //요청받은 request 정보중에서 User-Agent 정볼를 따로 분리하여 갖어올 수 있다
        var userAgent = req.header('User-Agent');
 
        //요청파라미터는 get 방식인 req.query 에 들어오게 된다
        //post 방식은 body로 들어오게된다
        //name 은 정해져있는 명칭
        //var paramName = req.query.name;           //get 방식
 
//post 방식 일경우 begin
        var paramName = req.body.name;           //post 방식 //post 방식 일경우 end
 
        //post, get 방식 동시에 되는 것 얻기, || 연산자는 둘중에 null 또는 undefined 가 아닌 것을 리턴한다
        //var paramName = req.query.name || req.body.name;
 
        //응답 보내기
        res.send('<h3>response from server!!7!! : ' + userAgent + '[' + paramName  + '] </h3>');
 
    }
);
 
 
//웹서버를 app 기반으로 생성
var appServer = http.createServer(app);
appServer.listen(app.get('port'),
    function () {
        console.log('express 웹서버 실행' + app.get('port'));
    }
 
);
 




Postman 으로 입력하는 모습


  1. Post 옆에 url은 localhost:3000 까지만 입력하고 옆에 Params 를 눌러 파라미터를 입력한다
  2. Body 클릭
  3. "x-www-form-urlencoded" 를 클릭한다음 key, value 에 전송할 데이터를 입력


결과는 이미지 하단에 나타남










반응형
반응형

다른 사이트로 리다이렉트 시킬 수 있다

        res.redirect('http://google.co.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
var express = require('express');
 
var http = require('http');
 
var app = express();      //express 서버 객체
 
app.set('port'3000);
 
app.use(
    function (req, res, next) {
        console.log('middle wared was called : first');
        res.redirect('http://google.co.kr');
    }
);
 
 
//웹서버를 app 기반으로 생성
var appServer = http.createServer(app);
appServer.listen(app.get('port'),
    function () {
        console.log('express 웹서버 실행' + app.get('port'));
    }
 
);
 






다음은 



localhost:3000/users?name=tesstsssssss  를 브라우저 입력하면

결과로 tesstsssssss  를 볼 수 있는 예제이다

var userAgent = req.header('User-Agent');  이 구문으로 요청 req 중에서 User-Agent 정보를 볼 수 있다



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
var express = require('express');
 
var http = require('http');
 
var app = express();      //express 서버 객체
 
app.set('port'3000);
 
 
 
///users 를 붙이게 되면 특정 경로를 지정하는 것으로 특정 기능을 수행할떄 사용한다
//localhost:3000/users
//example , get 방식
//localhost:3000/users?key=state
//localhost:3000/users?name=tesstsssssss
 
app.use(
    function (req, res, next) {
        console.log('middle wared was called : first');
        //res.redirect('http://google.co.kr');
 
        //req 여러 정보를 얻어 올 수 있는데 그중
        //요청받은 request 정보중에서 User-Agent 정볼를 따로 분리하여 갖어올 수 있다
        var userAgent = req.header('User-Agent');
 
        //요청파라미터는 get 방식인 req.query 에 들어오게 된다
        //post 방식은 body로 들어오게된다
        //name 은 정해져있는 명칭
        var paramName = req.query.name;
 
        //응답 보내기
        res.send('<h3>response from server!!!!!!!!!!!! : ' + userAgent + '</h3>' + paramName);
 
    }
);
 
 
//웹서버를 app 기반으로 생성
var appServer = http.createServer(app);
appServer.listen(app.get('port'),
    function () {
        console.log('express 웹서버 실행' + app.get('port'));
    }
 
);
 






결과 화면 :


User-Agent 정보와

파라미터 중 name 에 대한 결과를 보여준다





반응형
반응형


Express 를 통해서 미들웨어를 등록(use(...)) 할 수 있고 등록된 미들웨어는 

요청이 오게 되면 그 요청에 반응하여 동작 하게 되며 순서는 등록한 순서대로 미들웨어가 실행 되게 된다

    //http 에서 제공되는 모듈에서 express 에 필요한것이 추가된 것을 파라미터 req, res 로 전달된다
    //req : request 객체
    //res : response 객체
    function (req, res, next) {


이때 다음 미들웨어를 호출 할때는 next() 함수로 다음 미들웨어를 호출하는데 

req, res 객체가 다음 미들웨어 인자로 넘어가게 된다






또한 클라이언트로 응답을 보낼때 보낼 내용을 객체로 보낼 수도 있으며

json 형태로 변환하거나 문서 자체를 json 타입으로 보낼 수도 있으며

보내는 방식 또한 여러가지 방식으로 보낼 수 있다


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
var express = require('express');
 
var http = require('http');
 
var app = express();      //express 서버 객체
 
//app 에 임의의 문자열인 port 로 속성을 세팅함
//환경 변수에 PORT 를 설정했다면 그것을 포트로 그렇지 않으면 3000 으로 포트 번호를 express 에 세팅함
app.set('port'3000);
//속성을 set 으로 설정하고 get 으로 가져올 수 있다
 
//미들웨어 등록(미들웨어 == 함수)
app.use(
    //http 에서 제공되는 모듈에서 express 에 필요한것이 추가된 것을 파라미터 req, res 로 전달된다
    //req : request 객체
    //res : response 객체
    function (req, res, next) {
        console.log('middle wared was called : first');
 
        //객체에 멤버 추가
        req.user = 'to next Middleware';
 
        next();       //next를 실행하면 그다음 미들웨어가 받아서 처리하게 됨
        //이때 req, res 를 넘겨준다
 
    }
);
 
 
//그다음 미들웨어 등록
//첫번째 미들웨어로부터 req, res 를 받게 받아서 처리하게 된다
//첫번째 미들웨어의 것을 두번째 미들웨어서 받아서 처리하게 된다
app.use(
    function (req, res, next)
    {
        console.log('middle wared was called : second');
 
        //[1 번째 방법]
        //이때 응답을 보낸다
        /*
        res.writeHead(200,  //정상 응답
            { "Content-Type": "text/html;characterset=utf-8" }    //문서를 html 형과 해당 문자 캐릭터 셋으로 보냅
        );
        res.end('<h1> response from server first </h1>' + req.user);      // 전송함
        */
 
        //[2 번째 방법]
        var val = { 'key'333 };
        //writeHead, end 를 한번에 send, 그리고 객체를 보낼 수가 있음
        //객체를 넘길대는 json 포멧으로 넘어감
        /*
        res.send(val);
        */
 
 
        //[3 번째 방법]
        //val 객체를 json 문자로 바꿔 전송 가능
        /*
        var jsonDatas = JSON.stringify(val);
        res.send(jsonDatas);
        */
 
 
        //[4 번째 방법]
        var jsonDatas = JSON.stringify(val);
        //문서 자체를 json 으로 보내는 방법
        res.writeHead(200,  //정상 응답
            { "Content-Type""application/json;characterset=utf-8" }    //문서를 json 타입으로 보냄
        );
        res.write(jsonDatas);
        res.end();      // 전송함
    }
);
 
 
 
//웹서버를 app 기반으로 생성
var appServer = http.createServer(app);
appServer.listen(app.get('port'),
    function () {
        console.log('express 웹서버 실행' + app.get('port'));
    }
 
);
 
 





반응형
반응형


Express 로 서버 띄우기




미들웨어 : 구조 내에서 중간 처리를 위한 함수
1)  express 프레임워크에서 사용할 수 있는 중간 처리 목적으로 사용
2) 요청에 대한 응답을 완수하기 전까지 중간중간 다양한 일을 처리할 수 있음
3) 미들웨어 함수 생명주기 : request, response 응답을 주기로 종료 
4) 미들웨어 함수 우선순위 : 먼저 로드되는 미들웨어 함수가 먼저 실행됨(코드 순서 중요)





cmd 를 통해 아래 명령줄을 실행해 설치

npm install express --save


이때 외장모듈과 express 이름과 충돌이 되면 설치가 안될 수 있으니 이름만들때 주의




http 로 서버 실행시키도 대기 시키는 것과 유사한데 다만 express 를 넘겨줘서 


express의 기능들을 사용 할수 있도록 넘겨준다는 점에서 약간 다르다


//웹서버를 app 기반으로 생성
var appServer = http.createServer(app);




아래 구문을 실행한 다음


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var express = require('express');
 
var http = require('http');
 
var app = express();      //express 서버 객체
 
//app 에 임의의 문자열인 port 로 속성을 세팅함
//환경 변수에 PORT 를 설정했다면 그것을 포트로 그렇지 않으면 3000 으로 포트 번호를 express 에 세팅함
app.set('port'3000);
//속성을 set 으로 설정하고 get 으로 가져올 수 있다
 
//웹서버를 app 기반으로 생성
var appServer = http.createServer(app);
 
 
 
appServer.listen(app.get('port'),
    function ()
    {
        console.log('express 웹서버 실행' + app.get('port'));
    }
    
);
 




브라우저에서 localhost:3000  를 입력했을때의 결과화면





req, res : 에 대한 설명

Request(req

The req object represents the HTTP request and has properties for the request query string, parameters, body, HTTP headers, and so on. In this documentation and by convention, the object is always referred to as req (and the HTTP response is res) but its actual name is determined by the parameters to the callback function in which you’re working.

For example:

app.get('/user/:id', function(req, res) {
  res.send('user ' + req.params.id);
});

But you could just as well have:

app.get('/user/:id', function(request, response) {
  response.send('user ' + request.params.id);
});

The req object is an enhanced version of Node’s own request object and supports all built-in fields and methods.






Response(res)

The res object represents the HTTP response that an Express app sends when it gets an HTTP request.

In this documentation and by convention, the object is always referred to as res (and the HTTP request is req) but its actual name is determined by the parameters to the callback function in which you’re working.

For example:

app.get('/user/:id', function(req, res){
  res.send('user ' + req.params.id);
});

But you could just as well have:

app.get('/user/:id', function(request, response){
  response.send('user ' + request.params.id);
});









Express 와 미들웨어



express 로 실행 되는 흐름


미들웨어 : 클라이언트로부터 요청이 오면 요청을 가로채 처리하는 것을 말함


 즉 여러개의 미들웨어가 있을 수 있음 다음 미들웨어는 next()를 실행해야 다음 미들웨어를 받을 수 있음


미들웨어 등록은 use() 로 설정한다



요청패스 URL 에 따라 다른 함수가 실행되게 만들려면 라우터를 통해서 처리한다


처리 방식은 / 도는  /users 로 요청하여 다른 함수가 실행 될 수 있도록 만들 수 있다







실행 흐름

  1. 웹서버를 실행시킨다

  2. 클라이언트에서 3000 포트로 요청을 한다

  3. 서버의 미들웨어가 요청을 받아 미들웨어의 함수로 처리한다( 클라이언트로 바로 응답을 보낼 수도 있다)

  4. 클라이언트는 요청의한 결과를 화면에 뿌려준다



Express + middleware 로 클라이언트 요청에 의한 함수 실행 시키기


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
var express = require('express');
 
var http = require('http');
 
var app = express();      //express 서버 객체
 
//app 에 임의의 문자열인 port 로 속성을 세팅함
//환경 변수에 PORT 를 설정했다면 그것을 포트로 그렇지 않으면 3000 으로 포트 번호를 express 에 세팅함
app.set('port'3000);
//속성을 set 으로 설정하고 get 으로 가져올 수 있다
 
//미들웨어 등록(미들웨어 == 함수)
app.use(
    //http 에서 제공되는 모듈에서 express 에 필요한것이 추가된 것을 파라미터 req, res 로 전달된다
    //req : request 객체
    //res : response 객체
    function (req, res, next)
    {
        console.log('middle wared was called first');
 
        //바로 응답 보내기 처리
        res.writeHead(200,  //정상 응답
            { "Content-Type""text/html;characterset=utf-8" }    //문서를 html 형과 해당 문자 캐릭터 셋으로 보냅
        );
        res.end('<h1> response from server first </h1>');      // 전송함
 
    }
);
 
 
 
//웹서버를 app 기반으로 생성
var appServer = http.createServer(app);
appServer.listen(app.get('port'),
    function () {
        console.log('express 웹서버 실행' + app.get('port'));
    }
 
);
 
 
 






서버쪽 실행화면 및 대기






브라우저에서 요청 시도 결과


아래 화면은 클라이언트에서 서버로 요청을 시도한 화면이다 (F12 -> 네트워크 에서 확인)






브라우저에서 응답 헤더를 보면 미들웨어에서 클라이언트로 보내줬던 문서 형식 "Content-Type""text/html;characterset=utf-8" 


이 응답헤더에 있다는 것을 알 수 있다


즉 클라이언트이 요청을 미들웨어가 가로채 대신 처리한다








미들웨어 여러개 처리 흐름













미들웨어 사용

Express는 자체적인 최소한의 기능을 갖춘 라우팅 및 미들웨어 웹 프레임워크이며, Express 애플리케이션은 기본적으로 일련의 미들웨어 함수 호출입니다.

미들웨어 함수는 요청 오브젝트(req), 응답 오브젝트 (res), 그리고 애플리케이션의 요청-응답 주기 중 그 다음의 미들웨어 함수 대한 액세스 권한을 갖는 함수입니다. 그 다음의 미들웨어 함수는 일반적으로 next라는 이름의 변수로 표시됩니다.

미들웨어 함수는 다음과 같은 태스크를 수행할 수 있습니다.

  • 모든 코드를 실행.
  • 요청 및 응답 오브젝트에 대한 변경을 실행.
  • 요청-응답 주기를 종료.
  • 스택 내의 그 다음 미들웨어 함수를 호출.

현재의 미들웨어 함수가 요청-응답 주기를 종료하지 않는 경우에는 next()를 호출하여 그 다음 미들웨어 함수에 제어를 전달해야 합니다. 그렇지 않으면 해당 요청은 정지된 채로 방치됩니다.

Express 애플리케이션은 다음과 같은 유형의 미들웨어를 사용할 수 있습니다.

애플리케이션 레벨 및 라우터 레벨 미들웨어는 선택적인 마운트 경로를 통해 로드할 수 있습니다. 일련의 미들웨어 함수를 함께 로드할 수도 있으며, 이를 통해 하나의 마운트 위치에 미들웨어 시스템의 하위 스택을 작성할 수 있습니다.

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

app.use() 및 app.METHOD() 함수를 이용해 애플리케이션 미들웨어를 앱 오브젝트의 인스턴스에 바인드하십시오. 이때 METHOD는 미들웨어 함수가 처리하는 요청(GET, PUT 또는 POST 등)의 소문자로 된 HTTP 메소드입니다.

다음 예에는 마운트 경로가 없는 미들웨어 함수가 표시되어 있습니다. 이 함수는 앱이 요청을 수신할 때마다 실행됩니다.


var app = express();

app.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});

다음 예에는 /user/:id 경로에 마운트되는 미들웨어 함수가 표시되어 있습니다. 이 함수는 /user/:id 경로에 대한 모든 유형의 HTTP 요청에 대해 실행됩니다.


app.use('/user/:id', function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

다음 예에는 라우트 및 해당 라우트의 핸들러 함수(미들웨어 시스템)이 표시되어 있습니다. 이 함수는 /user/:id 경로에 대한 GET 요청을 처리합니다.


app.get('/user/:id', function (req, res, next) {
  res.send('USER');
});

아래에는 하나의 마운트 경로를 통해 일련의 미들웨어 함수를 하나의 마운트 위치에 로드하는 예가 표시되어 있습니다. 이 예는 /user/:id 경로에 대한 모든 유형의 HTTP 요청에 대한 요청 정보를 인쇄하는 미들웨어 하위 스택을 나타냅니다.


app.use('/user/:id', function(req, res, next) {
  console.log('Request URL:', req.originalUrl);
  next();
}, function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

라우트 핸들러를 이용하면 하나의 경로에 대해 여러 라우트를 정의할 수 있습니다. 아래의 예에서는 /user/:id 경로에 대한 GET 요청에 대해 2개의 라우트를 정의합니다. 두 번째 라우트는 어떠한 문제도 발생키지 않지만, 첫 번째 라우트가 요청-응답 주기를 종료시키므로 두 번째 라우트는 절대로 호출되지 않습니다.

다음 예에는 /user/:id 경로에 대한 GET 요청을 처리하는 미들웨어 하위 스택이 표시되어 있습니다.


app.get('/user/:id', function (req, res, next) {
  console.log('ID:', req.params.id);
  next();
}, function (req, res, next) {
  res.send('User Info');
});

// handler for the /user/:id path, which prints the user ID
app.get('/user/:id', function (req, res, next) {
  res.end(req.params.id);
});

라우터 미들웨어 스택의 나머지 미들웨어 함수들을 건너뛰려면 next('route')를 호출하여 제어를 그 다음 라우트로 전달하십시오. 참고next('route')는 app.METHOD() 또는 router.METHOD() 함수를 이용해 로드된 미들웨어 함수에서만 작동합니다.

*use 함수에서 next('route')를 쓰면 다음 use 문으로 가는 것이 아니고 next()와 동일하게 다음 스택 미들웨어 함수로 간다


(app.use() 및 app.METHOD() 함수를 이용해 애플리케이션 미들웨어를 앱 오브젝트의 인스턴스에 바인드하십시오. 이때 METHOD는 미들웨어 함수가 처리하는 요청(GET, PUT 또는 POST 등)의 소문자로 된 HTTP 메소드입니다.)

다음 예에는 /user/:id 경로에 대한 GET 요청을 처리하는 미들웨어 하위 스택이 표시되어 있습니다.


app.get('/user/:id', function (req, res, next) {
  // if the user ID is 0, skip to the next route
  if (req.params.id == 0) next('route'); // 이게 호출되면 다음 app.get('user/:id, 쪽으로 뛴다
  // otherwise pass the control to the next middleware function in this stack
  else next(); //
}, function (req, res, next) {
  // render a regular page
  res.render('regular');
});

// handler for the /user/:id path, which renders a special page
app.get('/user/:id', function (req, res, next) {    // 
  res.render('special');
});

라우터 레벨 미들웨어

라우터 레벨 미들웨어는 express.Router() 인스턴스에 바인드된다는 점을 제외하면 애플리케이션 레벨 미들웨어와 동일한 방식으로 작동합니다.


var router = express.Router();

router.use() 및 router.METHOD() 함수를 사용하여 라우터 레벨 미들웨어를 로드하십시오.

다음 예의 코드는 위에서 애플리케이션 레벨 미들웨어에 대해 표시된 미들웨어 시스템을 라우터 레벨 미들웨어를 사용하여 복제합니다.


var app = express();
var router = express.Router();

// a middleware function with no mount path. This code is executed for every request to the router
router.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});

// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path
router.use('/user/:id', function(req, res, next) {
  console.log('Request URL:', req.originalUrl);
  next();
}, function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

// a middleware sub-stack that handles GET requests to the /user/:id path
router.get('/user/:id', function (req, res, next) {
  // if the user ID is 0, skip to the next router
  if (req.params.id == 0) next('route');
  // otherwise pass control to the next middleware function in this stack
  else next(); //
}, function (req, res, next) {
  // render a regular page
  res.render('regular');
});

// handler for the /user/:id path, which renders a special page
router.get('/user/:id', function (req, res, next) {
  console.log(req.params.id);
  res.render('special');
});

// mount the router on the app
app.use('/', router);

오류 처리 미들웨어

오류 처리 미들웨어에는 항상 4개의 인수가 필요합니다. 어떠한 함수를 오류 처리 미들웨어 함수로 식별하려면 4개의 인수를 제공해야 합니다. next 오브젝트를 사용할 필요는 없지만, 시그니처를 유지하기 위해 해당 오브젝트를 지정해야 합니다. 그렇지 않으면 next 오브젝트는 일반적인 미들웨어로 해석되어 오류 처리에 실패하게 됩니다.

다른 미들웨어 함수와 동일반 방법으로 다음과 같이 오류 처리 미들웨어 함수를 정의할 수 있지만, 오류 처리 함수는 3개가 아닌 4개의 인수, 구체적으로 말하면 (err, req, res, next) 시그니처를 갖는다는 점이 다릅니다.


app.use(function(err, req, res, next) {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

오류 처리 미들웨어에 대한 상세 정보는 오류 처리를 참조하십시오.

기본 제공 미들웨어

4.x 버전 이후의 Express는 더 이상 Connect에 종속되지 않습니다. express.static의 실행을 제외하면, 이전에 Express와 함께 포함되었던 모든 미들웨어 함수는 이제 별도의 모듈에 포함되어 있습니다. 미들웨어 함수 목록을 확인하십시오.

express.static(root, [options])

Express의 유일한 기본 제공 미들웨어 함수는 express.static입니다. 이 함수는 serve-static을 기반으로 하며, Express 애플리케이션의 정적 자산을 제공하는 역할을 합니다.

root 인수는 정적 자산의 제공을 시작하는 위치가 되는 루트 디렉토리를 지정합니다.

선택사항인 options 오브젝트는 다음과 같은 특성을 가질 수 있습니다.

특성설명유형기본값
dotfilesdotfile을 제공하기 위한 옵션입니다. 사용 가능한 값은 “allow”, “deny” 및 “ignore”입니다.문자열“ignore”
etagetag의 생성을 사용 또는 사용 안함으로 설정합니다.부울true
extensions파일 확장자 폴백을 설정합니다.배열[]
index디렉토리 인덱스 파일을 전송합니다. 디렉토리 인덱스 작성을 사용하지 않으려면 false를 설정하십시오.혼합“index.html”
lastModifiedOS에서 해당 파일이 마지막으로 수정된 날짜를 Last-Modified 헤더에 설정합니다. 사용 가능한 값은 true 또는 false입니다.부울true
maxAge밀리초 또는 ms 형식의 문자열로 Cache-Control 헤더의 max-age 특성을 설정합니다.숫자0
redirect경로 이름이 디렉토리인 경우 후미부의 “/”로 경로를 재지정합니다.부울true
setHeaders파일을 제공하도록 HTTP 헤더를 설정하기 위한 함수입니다.함수 

아래에는 상세한 옵션 오브젝트와 함께 express.static 미들웨어 함수를 사용하는 예가 표시되어 있습니다.


var options = {
  dotfiles: 'ignore',
  etag: false,
  extensions: ['htm', 'html'],
  index: false,
  maxAge: '1d',
  redirect: false,
  setHeaders: function (res, path, stat) {
    res.set('x-timestamp', Date.now());
  }
}

app.use(express.static('public', options));

다음과 같이, 하나의 앱은 2개 이상의 정적 디렉토리를 가질 수 있습니다.


app.use(express.static('public'));
app.use(express.static('uploads'));
app.use(express.static('files'));

serve-static 함수 및 그 옵션에 대한 자세한 정보는 serve-static 문서를 참조하십시오.

써드파티 미들웨어

Express 앱에 기능을 추가하려면 써드파티 미들웨어를 사용하십시오.

필요한 기능을 위한 Node.js 모듈을 설치한 후, 애플리케이션 레벨 또는 라우터 레벨에서 해당 모듈을 앱에 로드하십시오.

다음 예는 쿠키 구문 분석 미들웨어 함수인 cookie-parser의 설치 및 로드를 나타냅니다.


$ npm install cookie-parser


var express = require('express');
var app = express();
var cookieParser = require('cookie-parser');

// load the cookie-parsing middleware
app.use(cookieParser());

Express와 함께 일반적으로 사용되고 있는 써드파티 미들웨어 함수의 일부 목록을 확인하려면 써드파티 미들웨어를 참조하십시오.


ref : http://expressjs.com/ko/guide/using-middleware.html

반응형
반응형

이미지를 프로젝트에 넣고 전송하기


html 문자 보내기 예제는 여기를 참고 (http://3dmpengines.tistory.com/1860)





1. 이미지는 파일시스템 fs 로 로딩하여 보낸다


2. 이미지가 로딩이 완료 된 이후에 전송처리를 함



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 http = require('http');                 //웹서버 기능을 담당하기 위한 모듈
var server = http.createServer();           //서버 객체를 얻어옴
var fs = require('fs');
 
 
//서버에서 대기하기 위한 처리
var localHost = 'localhost';
var port = 3000;
var backLog = 50000;    //  동시에 접속 할 수 있는 클라이언트 수
server.listen(port, localHost, backLog,
    function () {
        console.log('웹서버 실행됨 :' + localHost + ':' + + port);
    }
);
 
 
server.on('connection',
    function (socket) {
        console.log('클라이언트가 접속');
    }
);
 
 
server.on('request',
    function (req, res) {
        console.log('클라이언트가 요총이 들어옴');
        //consloe.dir(req);
 
 
        var filename = 'park.jpg';
        fs.readFile(filename, //파일 읽기
            function (err, data)
            {
                //http의 헤더정보를 클라이언트쪽으로 출력
                //image/jpg : jpg 이미지 파일을 전송한다
                //write 로 보낼 내용을 입력
                res.writeHead(200, { "Context-Type""image/jpg" });//보낼 헤더를 만듬
                res.write(data);   //본문을 만들고
                res.end();  //클라이언트에게 응답을 전송한다
 
            }
        );
 
    }
);
 
 
 
 




결과 화면 : 브라우저 상단에 localhost:3000 을 입력하면 결과 이미지가 뜬것을 볼 수 있다



반응형
반응형






nodejs 로 아래 코드를 실행 시킨다음 서버를 돌리고 


브라우저를 띄워 주소창에 http://localhost:3000 입력하면 


receive response from server

이란 응답을 받을 수가 있다



클라이언트에서 접속하면 서버 내부적으로 socket 이 만들어지는데 이것을 


call-back 함수로 넘겨받게 되어있다


server.on('connection',
    function (socket) {
        console.log('클라이언트가 접속');
    }
);
 







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
var http = require('http');                 //웹서버 기능을 담당하기 위한 모듈
var server = http.createServer();           //서버 객체를 얻어옴
 
 
//서버에서 대기하기 위한 처리
var localHost = 'localhost';
var port = 3000;
var backLog = 50000;    //  동시에 접속 할 수 있는 클라이언트 수
server.listen(port, localHost, backLog,
    function ()
    {
        console.log('웹서버 실행됨 :' + localHost +':'+ + port);
    }
);
 
 
server.on('connection',
    function (socket) {
        console.log('클라이언트가 접속');
    }
);
 
 
server.on('request',
    function (req, res) {
        console.log('클라이언트가 요총이 들어옴');
        //consloe.dir(req);
 
        //http의 헤더정보를 클라이언트쪽으로 출력
        //text/html : html 파일을 전송한다
        //characterset : 문자열 셋은 utf-8
        //write 로 보낼 내용을 입력
        res.writeHead(200, { "Context-Type""text/html;characterset=utf-8" });//보낼 헤더를 만듬
        res.write('<h1> receive response from server </h1>');   //본문을 만들고
        res.end();  //클라이언트에게 응답을 전송한다
    }
);
 
 
 
 





결과 화면










반응형
반응형


옵션 중에 로그 파일이름에 날짜를 붙일 수도 있다


1
2
3
var winston = require('winston');   //로그파일
var winstonDaily = require('winston-daily-rotate-file');  //매일 다른 파일 로그를 생성하는 모듈
var moment = require('moment');     //날짜






로그를 남기는건 중요하다.

데이터는 곧 힘이 된다. 사람들이 무엇을 원하는지 알면 그들이 원하는 걸 주고 내가 원하는 걸 받을 수 있다.

데이터를 쌓는데 가장 핵심적인 일 중 하나가 로그를 꼼꼼히 남기는 일이다.

node기반의 logging라이브러리는 다양하지만 꽤 오래전부터 winston이라는 라이브러리가 패권을 잡고있다.

오늘은 winston에 대해 알아보자.

프로젝트를 생성하고 winston을 npm으로 설치한다.

npm install --save winston

임포트해보자.

기본 설정


var winston = require('winston');

var logger = new (winston.Logger)({
    transports: [
      new (winston.transports.Console)()
    ]
  });

그냥 바로 사용해도 되지만 편의상 logger를 만들어서 사용했다.

사실 벌써 끝난거나 다름없다.

logger.debug('디버그 로깅');
logger.info('인포 로깅');
logger.error('에러 로깅');

이런식으로 사용하면 로그가 출력된다.

사실 winston에서 가장 중요한건 transports라고 할 수 있는데, 형식을 정하거나 할 수 있다.

나는 로그를 file로 관리하고, 날짜별로 관리한다면 그것도 가능하다.

우선 타임스탬프부터 찍어보자.

나는 날짜별로 관리하기때문에 시간만 찍어보았다.

타임스탬프 찍기


const winston = require('winston');
const tsFormat = () => (new Date()).toLocaleTimeString();
const logger = new (winston.Logger)({
  transports: [
    new (winston.transports.Console)({
      timestamp: tsFormat
    })
  ]
});

logger.info('Hello world');

로그레벨은 기본적으로 5가지가 있다.

{ error: 0, warn: 1, info: 2, verbose: 3, debug: 4, silly: 5 }

때에 맞춰 사용하면 더 식별하기 쉬운 로그가 된다.

커스텀도 가능하지만 그건 다루지 않을거고 Winston 공식문서를 참조하자.

파일로 로그 관리하기


먼저 파일로 로그를 관리하기 위해 파일시스템 라이브러리 fs를 설치한다.

npm install --save fs

풀 코드는 이렇다.

const winston = require('winston');
const fs = require('fs');
const logDir = 'log';

if (!fs.existsSync(logDir)) {
  fs.mkdirSync(logDir);
}

const tsFormat = () => (new Date()).toLocaleTimeString();
const logger = new (winston.Logger)({
  transports: [
    new (winston.transports.Console)({
      timestamp: tsFormat,
      level: 'info'
    }),
    new (winston.transports.File)({
      level: 'info',
      filename: `${logDir}/logs.log`,
      timestamp: tsFormat,
      maxsize:1000000,
      maxFiles:5
    })
  ]
});

로그 디렉토리가 없으면 생성하고 그 아래 로그파일들을 적재하는 코드다.

maxSize를 넘어가면 새로운 파일이 생기고, maxFiles만큼만 생성된다.

logs.log 다음은 logs1.log이런식으로 생성된다.

날짜별로 로그 파일관리하기


원래는 winston안에 daily-rotate-file이 함께 있었는데, 어떤이유에서인지 분리되어 나왔다.

winston-daily-rotate-file을 설치하자

npm install --save winston-daily-rotate-file

풀 소스는 이렇다.

var winston = require('winston');
require('date-utils');
const fs = require('fs');
const logDir = 'log';

if (!fs.existsSync(logDir)) {
  fs.mkdirSync(logDir);
}

const tsFormat = () => (new Date()).toLocaleTimeString();

var logger = new (winston.Logger)({
    transports: [
      new (winston.transports.Console)({
       timestamp: tsFormat,
       colorize: true,
       level: 'info'
     }),
      new (require('winston-daily-rotate-file'))({
        level: 'info',
        filename: `${logDir}/-logs.log`,
        timestamp: tsFormat,
        datePattern: 'yyyy-MM-dd',
        prepend: true,
      })
    ]
  });

이렇게하면 2017-03-03-logs.log라는 파일에 오늘치 로그가 쌓이게 된다.

winston으로 로그관리를 간단히 할 수 있게됬다. 



ref : https://isme2n.github.io/devlog/2017/03/03/Winston-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0/

반응형
반응형


파일 Open , close  이벤트 처리


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
var fs = require('fs');
 
//파일이  없으면 만든다
fs.open('./output1.txt''w',
 
    function (err, fd)          //파일 열기 완료후 call - back
    {
        if (err) {
            console.log('파일 open 에러');
            console.dir(err);
            return;
        }
 
        //파일이 열린 이후, 팡리에다가 쓰기
        //쓸 내용을 변수로 따로 만듬
 
        //Buffer 문자열을 담아두는 객체, 길이등을 얻어올 수 있음 또는 다른 문자열과 인코딩방식을 지정해 Buffer 에 쓸 수 있음
        var buf = new Buffer('안녕\n!!!');
        fs.write(fd, buf, 0, buf.length,            //어디서부터 쓸 것인지 버퍼의 시작점과 끝점 지정
            function (err, written, buffer)         //쓰기가 완료 된 이후 실행되는 call - back
            {
                if (err) {
                    console.log('파일 쓰기 에러');
                    console.dir(err);
                    return;
                }
                console.log('쓰기 완료');
 
 
                fs.close(fd, function ()            //닫기가 완료된 이후의 call - back
                {
                    console.log('파일 닫기 완료');
                }
                );
 
            }
        );
 
 
    });




결과  :

쓰기 완료

파일 닫기 완료



output1.txt : 

안녕

!!!







스트림으로 읽어들이는 방식


위 output1.txt 파일에 써진 내용을 읽어들인다


파일을 읽는 중간 중간 data 이벤트가 발생하는데 읽은 파일이 짧던 크던 이 이벤트는 초반 처음에 한번 호출되고 

파일이 짧아 로딩 시간이 짧아지게 되면 data 이벤트는 반복하여 호출되지 않는다, 일정 크기 이상이어 중간에 한번씩 호출된다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var fs = require('fs');
var infile = fs.createReadStream('./output1.txt', { flags: 'r' });
 
//스트림으로 읽어들이는 과정 도는 읽기가 완료 됐을때 이벤트가 발생된다
 
 
// 중간 중간 읽어 들이는 중간 이벤트
infile.on('data'function (data) {
    console.log('읽어들인 데이터 : ' + data);
});
 
//읽기가 완료 됐을때의 이벤트
infile.on('end'function () {
    console.log('읽기 종료');
});


결과화면 : 





반응형
반응형
쓰기와 마찬가지로 동기 비동기가 있다


비동기 파일 쓰기 처리
 /**
     * Asynchronously writes data to a file, replacing the file if it already exists.
     * @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
     * URL support is _experimental_.
     * If a file descriptor is provided, the underlying file will _not_ be closed automatically.
     * @param data The data to write. If something other than a Buffer or Uint8Array is provided, the value is coerced to a string.
     */
    export function writeFile(path: PathLike | number, data: any, callback: (err: NodeJS.ErrnoException) => void): void;




동기식 파일 쓰기 처리
/**
     * Synchronously writes data to a file, replacing the file if it already exists.
     * @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
     * URL support is _experimental_.
     * If a file descriptor is provided, the underlying file will _not_ be closed automatically.
     * @param data The data to write. If something other than a Buffer or Uint8Array is provided, the value is coerced to a string.
     * @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag.
     * If `encoding` is not supplied, the default of `'utf8'` is used.
     * If `mode` is not supplied, the default of `0o666` is used.
     * If `mode` is a string, it is parsed as an octal integer.
     * If `flag` is not supplied, the default of `'w'` is used.
     */
    export function writeFileSync(path: PathLike | number, data: any, options?: { encoding?: string | null; mode?: number | string; flag?: string; } | string | null): void;







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var fs = require('fs');
 
 
//동기 파일 쓰기
//fs.writeFileSync
 
//비동기 파일 쓰기, 
fs.writeFile('./output.txt''hello.'function (err) {
    if (err) {
        console.log('에러발생');
        console.dir(err);
        return;
    }
    console.log('파일쓰기완료'); 
   }
);
console.log('파일 쓰기 명령');
   




결과 : 


비동기 기준임으로 파일 스기 명령이 먼저 찍힌 것을 볼 수 있다





써진 내용




반응형

+ Recent posts