01. 자바스크립트
1. 객체의 형식 - 배열 vs 객체
1) 배열: 순서가 있는 정보
- 순서는 인덱스로 구성
- 인덱스를 통해 접근
2) 객체: 순서가 없는 정보
- Property: 키-값으로 이루어진 쌍
- 키를 통해 접근
3) 선언 및 접근
- 배열: 대괄호[ ]로 생성, arr[index]로 접근
- 객체: 중괄호{ }로 생성, obj.key / obj[key]로 접근
4) 배열과 객체의 구별
- typeof()는 구분 불가능
배열도 객체의 일종이기 때문에 객체 판정이 나온다.
- Array.isArray()로 구분 가능
T가 나오면 배열, F가 나오면 배열이 아니다.
이를 이용해 순회가 필요할때 Array/Object에 따라 순회방법을 다르게 넣는다.
length를 통해 배열의 전체크기를 얻어 for/while 반복문으로 순회한다.
이때 객체의 길이는 얻을 수 없다. 그렇다면 어떻게 할까?
5) 데이터 순회
- 배열: 배열의 길이(.length)를 활용
- 객체: in 키워드를 사용
변수 in 객체이름: 객체에서 키값을 하나씩 꺼내온다.
2. 객체: 값으로서의 함수
대입 연산자를 통해(변수 = 값) 값으로 판정되는지 확인할 수 있다.
- 다음의 if문의 경우: 불가능. 오류가 뜬다.
- 함수의 경우: 가능.
값을 넣어야 하는 자리에 함수를 대입할 수 있다.
- 배열
1) 배열에 요소로 삽입할 수 있다.
2) 배열 인덱스 접근을 통해 함수를 호출할 수 있다.
배열로 접근하는 경우 ()를 붙여서 실행한다.
- 객체
1) 객체에 property로 삽입할 수 있다.
2) 객체 접근을 통해 함수를 호출할 수 있다.
이때 배열/객체 모두 ()를 붙여서 함수를 사용한다.
o['func'](); 로도 접근이 가능하다.
결론: 함수는 값으로 할당 가능하며, 배열/객체에 넣어서 사용할 수 있다.
3. 객체 지향
- 객체 지향 접근 방식
장점: 코드의 유지보수가 편리하다.
단점: 코드의 이름이 특별해야 한다. (중복 이름이 불가능한데 코드가 길어지면 힘들다.)
-> 해결하기 위해 함수까지 객체 멤버로 사용한다.
o라는 오브젝트 할당, 함수 안에서 o에 접근.
<-> o로만 할당받지 않고 변수 이름 변경에 따라 값이 자동으로 변경되는게 좋다.
this 사용: 자신의 이름에 종속적이지 않도록 한다.
4. 화살표 함수
새로운 방식의 함수 선언 방법.
원래는 function 함수이름(매개변수) {함수 선언문 명시};
-> 간결하고 읽기 좋게 하기 위해 화살표 함수를 사용.
let printName = function printName(name) => 실행내용.
비교시: 밑이 훨씬 간결하다.
- 기본 문법
매개변수가 하나가 아니고 여러개일 때 소괄호( )로 묶어준다.
=> 중괄호{ }로, 함수가 여러개의 선언으로 이루어진 경우, 묶어준다.
바로 어떤 값을 리턴하는 경우 => expression 으로. 다음에 중괄호로 묶은 것과 동일한 의미.
num => num+1
num을 매개변수로 받아 num+1을 리턴하는 함수와 동일.
매개변수가 하나인 경우에는 괄호 자체도 생략이 가능.
매개변수가 없는 경우 꼭 소괄호( )를 사용해줘야 한다. ( ) => 해줘야 화살표 함수라는 것을 이해한다.
02. Node.js 모듈 생성
간단한 웹서버를 만들어볼 예정.
간단한 소스코드일때는 문제가 되지 않는다(그동안의 실습들이 예시).
그러나 코드가 커지면 한눈에 파악하기 어려워지며, 함수 수정시 - 어느 위치에 있는지 찾는것도 힘들어진다.
객체로 한번 정리할수는 있지만, 그것만으로는 부족하다.
때문에 많은 자바스크립트 파일로 나누어서 작성한다.
하나의 소스코드 파일 안에 모든 내용을 넣을수는 없다 - 여러개의 파일로 구성한다.
모듈이라는 단위로 정리(묶)한다.
모듈: 자바스크립트 파일/폴더의 묶음. 일종의 코드 라이브러리가 들어있는 모듈.
- 과정
1) 모듈 안에서 선언한 함수/변수를 외부에서 접근할 수 있도록: module.exports(이것 또한 객체)를 사용.
2) require(): (사용하는 쪽에서) 명령을 활용해 해당 모듈을 불러오는 작업을 한다.
해당 모듈이 파일 안에 있는 것처럼 사용한다.
1. 새로운 Node.js 모듈 생성
단순한 배열 생성.
이를 외부로 export하기 위해서는?
- exports로 단축해서 사용 가능.
obj라는 객체가 있다고 가정했을때, let obj = {'a':'b'};
obj.bc = 'bc'; 로 할당하면
객체에 원래 존재하지 않았지만, 객체에 자동으로 삽입된다.
메세지라는 것이 실제로 존재하지 않는다면 - 추가할 수 있다.
message가 키, 뒤의 배열이 vaule.
exports라는 객체에 message가 추가된 것. exports를 외부에서 접근 가능하다면 자동으로 메세지도 접근 가능하다.
- 사용자 측에서 require()를 통해 불러와야 한다.
forEach: 하나하나 접근하는 함수.
메세지 모듈 선언. require() 호출하면서 현재 경로의 message를 찾는다. (그 이름의 자바스크립트 모듈을 검색한다.)
messageModule = exports가 대입된다.
messageModule.message 에서 forEach사용 -> m(매개변수: 인덱스에 할당된 값)
message에 배열이 들어가있지만, 함수도 들어가있을 수 있다.
2. npm 활용
모든 모듈을 처음부터 만들 필요는 없다. 다른 사람들이 제공한 라이브러리를 가져다가 사용.
- npm 활용: node.js package manager의 약자.
- 패키지: 하나의 모듈이 아니라 여러개의 모듈을 하나로 묶어 제공.
- Node.js 패키지 매니저: 패키지들의 설치/제거/수정에 활용.
1) npm install <package>
2) npm uninstall <package>
3) 옵션
(1) --save(-S): 애플리케이션에만 추가하는 모듈. npm 인스톨을 하는 경로에 있는 애플리케이션에서만 사용 가능.
(2) -- global(-g): 어떤 곳에서든 사용할 수 있는 패키지를 설치.
npm | Home
Bring the best of open source to you, your team, and your company Relied upon by more than 17 million developers worldwide, npm is committed to making JavaScript development elegant, productive, and safe. The free npm Registry has become the center of Java
www.npmjs.com
3. Node.js 애플리케이션의 초기화
- package.json 파일
: 현재 작업하고 있는 프로젝트와 관련된 정보를 모두 저장하고 있다.
1) 현재 릴리즈 버전
2) 애플리케이션 이름
3) 메인 애플리케이션 파일(진입로 - 메인함수, 기본적으로 사용하게 될 파일)
4) 의존 패키지 정보(어떤 패키지들을 설치/사용해야 하는지)
5) 프로젝트 루트 레벨에 존재하는 파일
우리가 지금까지 작업해온 파일에는 존재하지 않는다. 없다고 해서 실행할 수 없는건 아니다.
하지만 node.js를 배포하고자 한다면 필수이다.
1) package.son 파일의 생성
- npm init
여러가지 입력할 수 있는 실행창이 뜬다. 패키지 이름/릴리즈 버전/내용/진입 포인트/테스트 커멘드/기타 등등 입력.
pakage.json 입력 완료.
- Cities 설치
npm install cities --save
node_modules 디렉토리 내부에 여러가지 패키지가 설치되어 있는 것을 확인 가능.
이때 다른 패키지가 있는 것: cities가 다른 패키지를 참조하기 때문에 연쇄적으로 설치.
cities에 package.json 파일이 존재.
이때 --save 옵션을 사용했기 때문에 해당 디렉토리 내부에 설치되었다.
다음이 추가된것을 확인 가능.
cities(강의자료 이름은 다름)와 의존관계라고 입력.
이런 식으로 입력되어 있다면 -> Cities만 remove 했을때, dependencies에만 입력되어 있는 상태가 된다.
그런 경우 npm install --save로 패키지 이름을 명시하지 않아도, 자동으로 필요한 의존성 패키지들을 설치해준다.
때문에 package.json을 잘 설정해야 사용자는 npm install --save만으로 필요한 패키지를 설치하고 즉각 사용할 수 있다.
- 정리
1) 프로젝트 폴더 하나 만듦.
2) 시작점이 되는 자바스크립트 파일 만듦.
3) 패키지 종속정보 등을 포함하는 package.json을 만듦
-> node_modules에 필요한 외부 패키지가 모두 저장된다.
- node_modules: 모든 외부 패키지가 다운로드되는 장소.
실행에만 필요하다.
실행에는 반드시 필요하지만, 일반적으로 소스코드 관리시 외부 패키지의 소스코드까지 다운받을 필요는 없다.
git으로 소스코드를 관리할 경우: gitinore 파일 - node_modules 디렉토리 추가 - git에서 제외.
실행때 npm install 명령을 통해 얼마든지 필요한 모듈 설치가 가능하다.
-> 소스코드 관리시에는 node_modulues 소스코드까지 함께 관리할 필요가 없다.
- 외부 패키지의 활용
cities에 접근 가능하도록 require - 모듈 이름 명시.
10016에 대한 우편정보 출력 요청.
필요한 모듈을 설치한 다음에는 node main.js로 실행 가능.
정리: 외부 모듈을 설치받아 참조해서 활용할 수 있다.
03. Node.js에서 웹 서버 만들기
1. 웹 서버의 이해
- 클라이언트(웹 브라우저) 와 웹 서버: HTTP 프로토콜을 통해 서로 통신한다.
-> 메소드
- GET: 서버로부터 정보를 요청할때.
- POST: 클라이언트가 서버로 정보를 전송할때.
1) 브라우저에 URL 입력 - GET 메소드 활용. 웹 브라우저의 정보를 가져온다.
2) URL이 서버에 전달.
3) 서버에서 분석한다.
요청된 정보를 서버 or DB에서 가져온다.
4) HTML/json/일반 텍스트/포맷 등의 요청된 형태로 전달된다.
5) 웹 브라우저 창으로 결과를 띄운다.
HTTP 프로토콜을 사용해 동작. 그 내부에 여러 메소드가 있는데 GET/POST가 가장 중요하다.
2. 기본 웹 서버의 생성
1) npm init을 통해 package.json을 생성한다.
2) http-status-code 패키지를 설치한다.
3) 웹서버를 작성한다. (main.js에)
- port 넘버를 80(일반적으로 http 프로토콜을 사용해서 웹브라우저에 접근할때 자동으로 사용하도록 설정되어 있는 넘버)으로 설정한다.
-> 웹 서버쪽의 포트 넘버. 웹 서버가 어떤 포트를 기다리고 있는지 중요.
80번 포트를 사용한다는 것 = HHTP 프로토콜을 사용한다는 것 - 웹서버에 접근한다는 것.
! 443: HHTPS 넘버.
3000/8080: 개발용으로 사용.
- require 2번.
내부 패키지를 불러오고 있다.
! 이때 const가 전부 앞에 붙기 때문에 약간의 띄어쓰기가 보인다.
- .createServer 함수: request, responce를 매개변수로 => 함수 실행.
이때 createServer의 매개변수는 (request, responce)가 아니라, 함수가 들어간 것이다.
실제로 createServer의 매개변수는 콜백 함수이다.
콜백 함수는 서버에서 어떤 이벤트가 발생할때마다 동작하게 되는 함수.
이 함수를 등록했다는 것 - request를 받을 때마다 이 함수를 호출하도록 등록되었다는 것. app이라는 서버는 이벤트 발생때마다 실행된다.
- .writeHead: 헤더부분의 기본적 속성을 정의하고 있다.
httpStatus.OK = 200과 동일. (=status code)
- response.write: 본문을 채워 넣는 것. 헤더 부분 이외의 내용 = 본문.
- response.end: 응답 종료. 최종적으로 호출해야만 응답이 종료된다.
종료되어야만 커넥션이 끊어진다. 하지 않으면 클라이언트는 계속해서 서버에서 보낼 것이 있다고 생각하고 대기한다.
- app.listen(port): 해당 포트(위에서 세팅한 80번)를 수신하도록 설정. 이 포트로 요청이 들어올때마다 콜백함수가 실행된다. listen을 실행한 다음부터 동작한다.
3. 콜백 함수: 이름이 없는 함수 = 익명 함수.
다른 함수가 종료될때 자동으로 실행되는 함수.
비동기적으로 실행되는 함수: 다 끝날때까지 기다릴 필요 없이, 다른 코드를 실행할 수 있다.
1) 여러개의 클라이언트가 서버에게 요청을 연달아 보내고 있는 상황 가정.
2) 요청들은 순서대로 도착하지 않는다. 즉, 이 요청들은 비동기 방식으로 처리된다.
3) 큐에다가 요청들을 쌓아두고, 요청마다 시간을 쪼개서 진행한다. 최종적으로 응답이 준비되면 콜백이 신호를 보낸다.
4) 이때 처리되는 순서가 어떻게 될지는 모른다. 빨리 처리된 것부터 전송된다.
5) 요청 처리에 걸린 시간 순으로 클라이언트는 전달받는다.
4. 애플리케이션 실행
-> 실행해보면? sudo node main.js 하면 실행되는 상태가 된다.
VM instance에 들어가서 외부 IP주소 복사, URL에 넣어보면 결과가 나온다.
인스턴스 내에서 웹서버를 실행.
웹브라우저에서 인스턴스 내의 서버에 접근함.
간단하게 웹서버를 만들어봤다.
04. 수신 데이터 다루기
1. 이벤트 리스너를 추가한 간단한 웹 서버
1) 초기 설정(이전과 동일)
- npm으로 애플리케이션 초기화
- http-status-code 패키지 설치
2) "request" 이벤트가 트리거 될 때마다 호출되는 콜백 함수의 등록
이전에는 createServer할때 콜백을 추가.
이번에는 그렇게 하지 않고, 이벤트가 트리거가 될때마다 호출되는 콜백 함수 등록이 가능.
사실상 createServer에 콜백 함수를 추가한 것과 작동 방식은 다르지 않다(동일하다).
- app.on 함수: 콜백 함수 등록 가능.
"request"라는 이벤트가 발생하면, req/res를 전달해 매개변수로 활용할 수 있게 한다.
매개변수가 전달되면 - 함수 실행
(1) writeHead 함수가 실행
(2) responceMessage 작성
(3) res.end( ); 실행
! 이때 req/res는 createServer에서 만든 서버가 내부적으로 가지고 있고, 요청이 있으면 생성된다.
3) 요청 데이터의 분석
(1) request는 기본적으로 접근할 수 있는 정보가 있다.
-> method/url/heards.
결과:
HET
/
헤더 정보
쭉 출력된다.
! URL에 입력되는 것: IP주소(=호스트 네임), 뒤쪽 /(루트)부터 시작되는게 웹서버 경로.
아무것도 입력되지 않았다면 자동으로 루트가 붙는다.
실제로 홈페이지를 의미한다.
(2) JSON.stringify() 메소드 활용
- JSON: 자바스크립트 오브젝트 노테이션.
객체를 만들때 계속 선언한 것.
웹브라우저와 서버 사이에 데이터를 주고 받을 때 활용하는 데이터 방식.
꼭 그때에만 사용되지 않으며, 여러가지 프로그램에서 활용된다.
가독성이 좋고, 데이터를 주고받을때 편리한 포맷 방식.
- JSON.stringify(value, replacer, space): JSON파일을 string 형식으로 출력하는 함수.
세개의 매개변수를 받으며, value 부분 - 자바스크립트 값, 객체를 JSON 문자열로 변환한다.
중첩 객체가 있어도 알아서 문자열로 변환해준다는 장점이 있다.
meetup에서 객체 안에 객체가 있어도 자연스럽게 변환해준다.
(3) JSON.stringfiy() 메소드의 활용
- getJSONString = obj가 주어지면 함수 실행 - return JSON.stringify(obj, null, 2).
-> 출력할 수 있는 문자열을 갖게 된다.
결과물: 아까보다 가독성이 훨씬 좋아진다. " "로 묶어 구분된다.
(4) 서버에 데이터를 보내는 경우 (POST 요청)
GET뿐만 아니라 POST도 사용.
클라이언트가 서버에 데이터를 보낼 때 활용.
1) 클라이언트가 서버로 POST 요청을 보낸다.
2) 서버 입장에서는 클라이언트가 보낸 데이터의 끝이 어딘지를 미리 알지 못한다.
- chunked 형태로 데이터를 호스트하게 되면 데이터가 쪼개져서 보내지는데, 맨 마지막을 받아봐야 끝을 알 수 있다. 즉, 들어오기 전까지는 데이터의 끝을 알 수 없다.
서버는 일단 들어오는 순서대로 저장한다. 마지막 청크가 들어왔다는 것을 확인하면 합친다.
3) 서버는 청크를 버퍼에 저장해놔야 한다.
4) 서버는 데이터를 확인하고, 클라이언트에게 요청할 수 있다.
이렇게 하는 이유는, 전송되는 데이터의 끝을 알 수 없기 때문이다.
이것을 서버는 어떻게 받을까?
app.on에 request가 들어와서 데이터 수신이라는 이벤트가 발생했을 때,
뒤에 선언이 된 콜백 함수를 호출한다. 이를 위해 호출 함수를 등록하고 있다.
- req.on("data"): 데이터를 수신했을 때.
body[ ]: 받을 수 있는 배열을 미리 선언.
매개변수로 들어온다면, bodyData를 body에 추가한다.
청크가 들어올수록 배열에 쌓인다.
- req.on("end"): 데이터 수신이 끝났을 때.
body를 하나로 이어 붙여서, string으로 변환한다.
string 형태로 출력이 가능하다.
이를 테스트하기 위해서는 POST 요청이 필요하다.
웹브라우저에서 POST 요청을 보내기 위해서는 GUI 버튼으로 구현되어야 하는데, 없으므로 curl 명령어로 대체한다.
- curl: 웹 브러우저를 대신해서 서버에 요청을 할 수 있는 커맨드 라인 명령도구.
다른 터미널을 띄우고
curl --data "username=Jon&password=secret" http://<IP 주소>
-> 웹서버 쪽에서 Request Body Contents가 하나로 합쳐져서 들어왔다는 알림이 뜬다.
2. 웹 애플리케이션에 라우트 붙이기
POST만 확인했지만 GET도 개선이 가능.
현재 웹 서버의 라우트: 모든 요청에 대해서 똑같이 응답.
localhost/testing = local/contact = /(루트 홈페이지) 모두 동일한 응답이 돌아온다.
-> 개선시키기 위해서는?
어떤 URL이 들어가냐에 따라서 - 애플리케이션이 어떻게 응답할지를 정해줘야 한다: 라우트를 사용.
1) 요청에 따른 라우트의 매핑 정의
- key: value 형태.
- 내용은 URL : 출력할 html
2) 요청 라우트가 정의된 맵에 있는지 체크
if문으로 routeResponseMap에서 req.url로 참조.
있는 경우: 해당 메세지 전달.
없는 경우: 기본 메세지 전달.
'강의 정리 > 서버시스템 구축 실습' 카테고리의 다른 글
서버시스템구축실습 (8) Express.js를 통한 웹 개발 (1) (1) | 2024.05.04 |
---|---|
서버시스템구축실습 (6) Node.js 기초 (2) (1) | 2024.05.03 |
서버시스템구축실습 (4) 자바스크립트 기초 (0) | 2024.04.02 |
서버시스템구축실습 (2) 웹서버와 데이터베이스 개요 (0) | 2024.03.19 |
서버시스템구축실습 (3) 데이터베이스 모델링과 설계 (0) | 2024.03.19 |