본문 바로가기

Full Stack 교육 회고록

11/21- node.js / 오후 Kotlin

728x90
SMALL

chapter1. node.js 개요

[Contents]

1. node.js의 특징을 이해하고 설명할 수 있다

2. node.js 프로젝트를 생성할 수 있다

 

[About Node.js]

chrome v8 javascropt 엔진으로 빌드된 javascript 런타임(확장성 있는 네트워크 애플리케이션 개발에 사용되는 소프트웨어 플랫폼)

 

[node.js 등장 이전과 이후]

 

node.js 등장 이전?

- 특정 웹 브라우저(chrome, firefox,safari,exploer)안에서 동작

- 독립적으로는 사용될 수 없었음

- 웹에서 표시되는 client만 구현 가능

 

node.js 등장 이후?

- javascript 런타임 환경이 만들어져 웹 브라우저에서 독립되어 터미널 등에서 Javascript 실행 가능

- 웹 브라우저와 무관한 독립적인 프로제그램 만들 수 있음

- Server 부분에서도 javascript 사용가능

 

[node.js 특징]

 

javascript : 새로운 언어를 습득하지 않고도 javascript를 활용해 서버 기술을 향상시킬 수 있음

chrome v8 자바스크립트 엔진: 다른 javascript 엔진과는 비교할 수 없을 만큼 빠르며 오픈소스 코드로 공개되어 있음

npm(node packahe manager)을 통한 다양한 모듈(패키지)제공: npm을 이용해 필요한 라이브러리와 패키지를 검색해서 설치하고 사용가능

 

< 단일 쓰레드의 non-blocking I/O 이벤트 루프 기반 비동기 방식 >

 

단일 쓰레드 (Single Thread)?

- 하나의 프로세스에서 하나의 쓰레드를 실행하므로, 프로세스 내의 작업을 순차적으로 실행

- 유저와 상호작용하는 어플리케이션의 경우, 한 가지 작업이 끝난 뒤에야 다음 작업으로 이동하기 때문에 유저가 원하는 작업 수행이 빠르게 이루어지지 않을 수 있음

노드의 특징인 이벤트 기반, 논 블로킹 I/O 모델 구현

동기(Sync) / 비동기(Async): 처리해야 할 작업들에 대한 처리 과정

 

동기(Synchronous): 호출된 작업의 리턴하는 시간과 결과를 반환하는 시간이 일치하는 경우

비동기(Asynchrous): 호출된 작업의 리턴하는 시간과 결과를 반환하는 시간이 일치하지 않는 경우

블로킹(Blocking)/ 논블로킹(Non-Blocking):

직접 제어할 수 없는 대상을 처리하는 방법으로 이전작업이 완료될 때 까지 기다리지 않고 다음 작업이 진행되거나/되지 않도록 동작하는 패러다임

 

Blocking: 직접 제어할 수 없는 작업이 끝날 때까지 기다려야 하는 경우 호출된 함수에서 I/O 작업등을 요청했을 경우 I/O 작업이 처리되기 전까지 아무일도 하지 못함

Non-Blocking: 직접 제어할 수 없는 작업이 완료되기 전에 제어권을 넘겨주는 경우 호출된 함수에서 I/O 작업 등을 요청했을 경우 I/O 작업의 처리 여부와 관계없이 바로 다음 작업을 할 수 있음

 

동기-블로킹: 요청의 실행시간과 종료시간이 보장되며 내부의 I/O 작업 또한 종료 까지 대기 후 작업이 반환

동기-논블로킹 : 요청의 실행시간과 종료 시간이 보장되지만 작업의 반환여부와 상관없이 부가적인 작업이 이루어짐

비동기- 논블로킹: 각 작업이 순차적인 실행순서를 보장하지 않으며 요청과 작업이 호출되면 다른 작업을 받을 대기를 함

비동기- 블로킹: 비효율적이라 사용되는 모델이 많지 않음 but, Node.js+MySQL을 사용하는 경우 MySQL 드라이버가 Blocking 방식으로 동작하기 때문에 논블로킹 방식일지라도 블로팅 되는 경우가 발생할 수 있음

 

이벤트 루프(Event Loop)?

- 여러 이벤트가 동시에 발생했을 때 어떤 순서로 Callback 함수를 호출할 지 판단

Call Stack : 현재 실행중인 서브루틴에 관한 정보를 저장하는 스택 자료 구조 ->firstin lastout

TaskQueue: 이벤트 발생 후 타이머나 이벤트 리스너의 콜백들이 줄 서 있는 곳

이벤트 루프(Event Loop)?

- Call Stack에 현재 실행중인 실행 컨텍스트가 있는지, 이벤트 Queue에 대기 중인 함수가 있는지 반복해서 확인

- Call Stack이 비어있고 이벤트 Queue에 대기중인 함수가 있다면 순차적으로 Queue의 FIFO(First In First Out)특징에 따라 대기중인 함수를 Call Stack으로 이동시켜 함수가 실행되게 함

 

[node.js단점]

1. 이벤트 기반 비동기 방식으로 서버단 로직이 복잡한 경우 콜백함수의 늪에 빠질 수 있음 (ex. 요청에 의해 조회한 결과값에 따라 다른 로직을 처리해야 하는 경우)

2. 코드를 순차적으로 실행하는 것이 아니라 비동기 방식으로 이벤트를 보내므로 자바 개발 방식으로 설계하고 프로그래밍하면 큰 문제가 발생할 수 있음

3. 단일 쓰레드 이기 때문에 하나의 작업 자체가 많이 걸리는 웹서비스에는 어울리지 않음

4. 코드가 수행되어야 코드에 에러가 있는지 알 수 있음

5. 반드시 모든 케이스에 대해 소스코드를 검증해야 함

 

[node.js가 어울리는 웹서비스?]

1. 간단한 로직

2. 대용량(동시에 여러 request 처리)

3. 빠른 응답시간 요구

4. 빠른 개발 요구

5. 비동기 방식에 어울리는 서비스(네트웨크 스트리밍 서비스, 채팅 서비스 등)

ex) NETFLIX, Uber, PayPal

 

[node.js가 어울리지 않는 웹서비스?]

1. 단일 처리가 오래 걸리는 경우(싱글 쓰레드 이기 때문)

2. 서버 체크 로직이 많은 경우(call back hell)

3. 업무 복잡도/난이도가 높은 경우(에러가 나면 서버가 죽음)

 

[node.js를 사용하면 좋은 경우]

1. 간단한 요구사항이 많은 경우

ex. 채팅, CRUD 기반 서비스

기업: NETFLIX, Uber, PayPal, slack

 

[스프링을 사용하면 좋은 경우]

복잡한 요구사항이 많은 경우

ex. 실시간 게임, 영상처리

기업: trivago, udemy, CRED

 

 

[ch2.node.js 모듈과 객체]

- 모듈과 모듈시스템

 

모듈이란? 특정한 기능을 하는 함수나 변수들의 집합

모듈시스템이란? 모듈로 분리된 javascript 파일들을 불러오는 방식을 정의 한 것

 

[Ex01FirstServer.js]

const http = require('http');

http.createServer((req,res)=>{

}).listen(8888, ()=>{
    console.log('8888 포트에서 서버 연결중.....')
});

[Ex02ModuleNObject]

[func.js]

const {odd,even} = require('./var');

function checkOddOrEven(num){
    if(num%2){
        return odd;
    }else{
        return even;
    }
}

module.exports = checkOddOrEven;

[var.js]

const odd = '홀수입니다';
const even = '짝수입니다';

module.exports={
    odd,
    even,
};

//위에 아님 아래로 작성

exports.odd = '홀수입니다';
exports.even = '짝수입니다';

[index.js]

const {odd,even} = require('./var');
const checkOddEven = require('./func');

function checkStringOddEven(str){
    if(str.length %2){
        return odd;
    }else{
        return even;
    }
}

module.exports =checkStringOddEven;
console.log(checkOddEven(3));
console.log(checkStringOddEven('helloworld'));

[Ex02console.js]

//특정 레이블에 해당하는 time~timeEnd 사이의 시간 측정
console.time('전체 시간');
console.log('일반 로그');
console.error('에러 메세지');
console.table([{name:'예진', age:25},{name:'자연', age:20}]);

const obj ={
    outside : {
        inside:{
            key: 'value',
        }
    }
}

console.dir(obj, {colors : false, depth : 2}); //depth 기본값 2
console.dir(obj, {colors : true, depth :1});

console.timeEnd('전체 시간');

[Ex03Timer.js]

//setTimeout: n초후 실행
const timeout = setTimeout(()=>{
    console.log('1.5초 후 실행');
}, 1500);

//setInterval : n초마다 실행
const interval = setInterval(()=>{
    console.log('1초마다 실행');
}, 1000);

const timeout2 = setTimeout(()=>{
    console.log('실행되지 않습니다');
},3000);

setTimeout(()=>{
    clearTimeout(timeout2); //생성한 timeout 삭제
    clearInterval(interval); //생성한 interval 삭제
}, 2500);

const immediate = setImmediate(()=>{
    console.log('즉시 실행');
});

clearImmediate(immediate); //생성한 immediate 삭제

[Ex04js1]

const js2 = require('./Ex04js2');
console.log('js2 : ', js2);
module.exports = () => {
    console.log('js2', js2);
}

[Ex04js2]

const js1 = require('./Ex04js1');
console.log('js1 : ', js1);
module.exports = () => {
    console.log('js1', js1);
}

[Ex04run.js]

const js1 = require('./Ex04js1');
const js2 = require('./Ex04js2');

js1();
js2();

[Ex05nextTick.js]

setImmediate(()=>{ //3
//즉시 실행하고 싶을 때 권장하는 함수!
    console.log('immediate!');
})

setTimeout(()=>{ //2
    console.log('timeout');
},0);

process.nextTick(()=>{ //1. 이벤트루프가 다른 함수보다 우선으로 처리하도록 만듬
    console.log('nextTick');
});

[Ex06exit.js]

let i = 1;
setInterval(()=>{

    if(i===5){
        console.log('종료!');
        process.exit();
    }
    
    console.log(i);
    i++; 
},1000);

[Ex07url.js]

const {URL} = require('url');
// url 생성자 활용

const myURL = new URL('https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=0&ie=utf8&query=%EC%9B%94%EB%93%9C%EC%BB%B5+%EC%9D%BC%EC%A0%95');

console.log('searchParams : ', myURL.searchParams); //url의 전체 쿼리 확인
console.log('searchParams.get() : ', myURL.searchParams.get('query')); //특정 키의 값
//colors=red,blue,orange
//getAll(): 값이 여러개 일경우 전부 가져오기
console.log('searchParams.has() : ', myURL.searchParams.has('page'));// 특정 키를 가지고 있는지 확인(true/false)

console.log('searchParams.keys():', myURL.searchParams.keys()); //쿼리의 모든 키값
console.log('searchParams.values() :', myURL.searchParams.values()); //쿼리의 모든 벨루값

myURL.searchParams.append('key', 'value');
myURL.searchParams.append('key','value2');
console.log(myURL.searchParams.getAll('key')); // value1, value2

myURL.searchParams.set('key', 'value3');
console.log(myURL.searchParams.getAll('key')); //value3

myURL.searchParams.delete('key');
console.log(myURL.searchParams.getAll('key')); 

console.log('searchParams.toString(): ', myURL.searchParams.toString());
myURL.search = myURL.searchParams.toString();

[Ex08crypto.js]

const crypto = require('crypto');

//1. 단방향 암호화: 복화할 수 없는 암호화 방식(해시함수)

//pbkdf2 <- node에서 지원하는 비밀번호 암호화 알고리즘
//salt 라고 불리는 문자열을 붙인 후 해시 알고리즘을 반복해서 적용

//64바이트 길이 문자열 생성
crypto.randomBytes(64, (err, buf)=>{
    const salt = buf.toString('base64');
    console.log('salt: ', salt);

    //비밀번호, salt, 적용 반복 횟수, 출력바이트, 해시알고리즘
    crypto.pbkdf2('password123',salt, 100000, 64, 'sha512', (err, key)=>{
        console.log('패스워드 : ', key.toString('base64'));
    })
})

//2. 양방향 암호화: 암호화된 문자열을 복호화 할 수 있음, 키가 사용됨
const algorithm = 'aes-256-cbc';
const key = 'abcdefghijklmnopqrstuvwxtz123456';
const iv = '1234567890123456'; //암호화 시 사용되는 초기화 벡터

const cipher = crypto.createCipheriv(algorithm, key, iv);
//암호화할 문장, 인코딩, 출력인코딩(출력바이트)
let result = cipher.update('암호화할 문장', 'utf-8', 'base64');
result += cipher.final('base64'); //마지막에 출력 결과물 인코딩 넣으면 암호화 완료
console.log('암호화:',result);

const decipher = crypto.createDecipheriv(algorithm, key, iv);
//인코딩 값 순서는 암호화 때 작성한 순서 반대로!
let result2 = decipher.update(result, 'base64', 'utf-8');
result2 += decipher.final('utf-8');
console.log("복호화 : ", result2);

[Ex03FileSystem]

[Ex01readFile.js]

const fs = require('fs');

fs.readFile('./readme.txt' , (err, data)=>{
    if(err){ // 에러 발생시 예외처리
        throw err;
    }

    console.log(data); //결과물은 buffer(메모리에 저장된 데이터) 형식으로 제공
    console.log(data.toString());
})

[Ex02readFilePromise.js]

const fs = require('fs').promises;
//fs 모듈을 promise 형식으로 바꿔서 사용(비동기방식)

fs.readFile('./readme.txt')
    .then((data)=>{ //buffer
        console.log(data.toString());
    })
    .catch((err)=>{
        console.error(err);
    })

[Ex03writeFile.js]

const fs = require('fs').promises;

fs.writeFile('./writeme.txt', '새로 만든 파일!') //파일 생성
.then(()=>{ //파일이 생성이 성공하면
    return fs.readFile('./writeme.txt');
})
.then((data)=>{ //파일 리턴 성공
    console.log(data.toString());
})
.catch((err)=>{
    console.log(err);
})

[readme.txt]

readme 파일입니다!

[writeme.txt]

새로 만든 파일!

 

 

[노드 내장 객체 알아보기]

global 브라우저의 window와 같은 전역 객체/ 모든 파일에서 접근 가능/ window와 같이 생략 가능

node 에는 DOM, BOM 이 없으므로 window와 document 객체는 사용할 수 없음

console global

 

[타이머]

setTimeout: 주어진 밀리초

 

[노드 내장 모듈 알아보기]

os : 운영체제의 정보 , 가져올 수있는 모듈

path: 폴더와 파일의 경로를 쉽게 조작하도록 도와주는 모듈

url: 인터넷

 

암호화 단방향(암호화)헷/ 양방향

 


<오후수업 코틀린>

 

<ex00입력>

package ex20221121

import java.util.*

fun main() {

    //입력하는 도구를 가져오는 방법
    //Scanner sc = new Scanner(System.in)
    val sc = Scanner(System.`in`)

    //readLine() 사용해서 런창에 입력할 수 있다
    println("readLine()을 반드시 입력해야합니다 >> ")
    var num1 = readLine()?.toInt()
    // readLine은 무조건 String? 타입을 리턴

    //1. null이 발생할 수 있는 상황에 대해서 조건식 부여
    if (num1 != null) {
        print(num1 + 2)
    }
    // 2. Elvis 연산자
    // print(num1?.plus(2) ? : 실행 코드, 데이터 값)

    // 3.
    // println(num1!! +2)
    // ? x
}

<Ex00 입력>

package ex20221121

import java.util.*

fun main() {

    //입력하는 도구를 가져오는 방법
    //Scanner sc = new Scanner(System.in)
    val sc = Scanner(System.`in`)

    //readLine() 사용해서 런창에 입력할 수 있다
    println("readLine()을 반드시 입력해야합니다 >> ")
    var num1 = readLine()?.toInt()
    // readLine은 무조건 String? 타입을 리턴

    //1. null이 발생할 수 있는 상황에 대해서 조건식 부여
    if (num1 != null) {
        print(num1 + 2)
    }
    // 2. Elvis 연산자
    // print(num1?.plus(2) ? : 실행 코드, 데이터 값)

    // 3.
    // println(num1!! +2)
    // ? x
}

<Ex01 산술연산자>

package ex20221121

fun main() {

    // 1) 산술 연산자 : +,-, *, /, %

    val num1 = 30
    val num2 = 15

    var result:  Int

    result = num1 + num2
    println("+: $result")

    result = num1 - num2
    println("-: $result")

    result = num1 * num2
    println("*: $result")

    result = num1 / num2 //0 -> by zero Exception 발생
        //num2가 0이 아님을 확인하세요!
    println("/: $result")

    result = num1 % num2
    println("%: $result") // 0 -> by zero Exception 발생


}

<Ex02 대입연산자>

package ex20221121

fun main() {

    //1) 대입 연산자 (=)
    //🍎🍎🍎🍎🍎🍎 -> window + .
    var numOfApple =6 //현재 사과의 갯수

    //2) 복합 대입연산자 ( +=, -=, *=, /=, %= )
    //🍎🍎🍎🍎🍎🍎🍎🍎
    // numOfApple = numOfApple + 2
    numOfApple +=2

    // 값을 누적시킬 때!
    numOfApple -=2

}

<Ex03증감연산자>

package ex20221121

fun main() {

    //3) 증감 연산자 ( ++,--)
    // num ++, num -- : 후치 연산자: 코드가 실행된 후 +1
    // ++num, --num : 전치 연산자: +1이 된 후 코드 실행
    var num =1

    println(num++) // 1
    println(num) // 2
    println(++num) // 3
    println(num) // 3
    println(num--) // 3
    println(num) // 2
    println(--num)// 1
    println(num) // 1

}

<ex04비교연산자>

package ex20221121

fun main() {
    val a: Int = 128
    val b = a
    println(a === b)

    // ===: 참조값(주소값)이 동일한지 비교하는 연산자
    val c: Int? = a
    val d: Int? = a
    val e: Int? = c
    println(c == d)
    println(c === d)
    println(c === e)
}

<ex05 논리연산자>

package ex20221121

fun main() {
    //5) 논리 연산자 : && , ||, !

    // &&
    //: 양쪽 항이 모두 true 일 경우 결과 값으로 true를 돌려준다.

    // ||
    // : 하나라도 true일 경우 결과값으로 true를 돌려준다.

    //! (not)
    // : 부정연산자
    // !true --->false
}

<ex06 엘비스연산자>

package ex20221121

fun main() {

    // 앨비스 연산자 ( ? : )
    // NPE 발생을 예방할 수 있도록 NULL 값을 처리 해주는 연산자
    var str: String? = null

    print(str?.length?:"null입니다")
    var result = str?.length?: -1
}

 

제어문: 프로그램 실행 흐름을 개발자가 원하는 방향으로 바꿀 수 있도록 해두는 것

 

<ex07조건문>

package ex20221121

fun main() {

    // 단순 if (만약에 ~하면 ~ 한다)
    val gender = "여"
    if(gender =="여") println("여자입니다.")
    // val result2 = if(gender == "여") "여자입니다."

    // if(조건식) else
    if (gender == "여") println("여자입니다.") else println("남자입니다.")

    val result = if(gender == "여") "여자입니다." else "남자입니다."
    println(result)


}

<ex08예제>

package ex20221121

import java.lang.NumberFormatException
import java.util.*
import kotlin.random.Random
import kotlin.random.nextInt

fun main() {

    // 랜덤한 수를 가져올수있는 기능
    // Random rd = new Random();
    val rd = Random
    // 입력하는 도구 가져오기
    val sc = Scanner(System.`in`)
    // sc.nextInt()

    // 1. 랜덤한 두 수를 생성하자
    var num1 = rd.nextInt(10)+1 //1~10 랜덤한 수 생성
    var num2 = rd.nextInt(10)+1
    //2. 랜덤한 두 수를 출력하자
    println("$num1 + $num2 = ?")
    //Kotlin에서는 같은자료형이랑 만! 연산이 가능하다

    //3. 사용자로부터 정답입력 받기
    print("Enter the Answer : ")
    //val answer = readLine()?.toInt() ?:-1
    //readLne(): String?

    // readLine을 사용하게되면 사용자는 아무 문자/숫자가 입력가능한 상태
    // toInt --> "1234"  사용자가 무조건 숫자를 입력해야 형변환이 가능

    try{
        val answer = readLine()?.toInt()
        // 4. 사용자가 입력한 정답 == num1+num2 값 비교
        val result = if(num1 + num2 == answer) "정답입니다. " else "오답입니다."
        println("결과: $result")
    }catch (e: NumberFormatException){
        println("숫자를 입력해주세요! 문자는 입력할 수 없습니다.")
    }



    // Exception 잡는 방법
    // try catch ---> 예외상황
}

<ex09 when 문>

package ex20221121

fun main() {

    // when문 : Java에서 switch문과 동일
    // when(변수){
    // 값1 -> 실행코드1
    // 값2 -> 실행코드2
    // .........
    // else -> 실행코드n
    // }

    val a = 2
    when(a){
        // 여러가지 값의 실행코드가 같을 경우
        // a가 1또는 2일 경우 -> 실행코드를 실행
        1,2 -> println("a는 1,2입니다.")
        // 2 -> println("a는 1,2입니다.")
        else -> println("a는 1,2가 아닙니다.")
    }
    // 식
    when(a%2){
        1 -> println("홀수입니다.")
        0 -> println("짝수입니다.")
        else -> println("")
    }
    //in .. (범위를 설정하는 키워드)
    when(a){
        in 0.. 10 -> println("0~10")
        in 11..20 -> println("11~20")
        else -> println(a)

    }

    //객체/변수의 데이터 타입을 확인할때 가장많이 사용합니다.!!!
        // Any , is, when
    //is : 데이터 타입 확인 사용하는 키워드
    // Any: Java Object (최상위 클래스)
    // when: 조건식의 일종

    //반복문
    //**함수
    // +람다식
}
728x90
LIST