JavaScript, NodeJS 기초 (2) - [AI + 웹개발 취업캠프, 정보통신산업진흥원(NIPA)]

wish17·2023년 7월 25일
0

[NIPA] Ai + 웹개발

목록 보기
7/23

JavaScript

연산자

산술 연산자

산술 연산자 설명
+ 더하기
- 빼기
* 곱하기
/ 나누기
% 왼쪽 피연산자의 값을 오른쪽 피연산자의 값으로 나눈 후, 그 나머지를 반환
let a = 10;
let b = 5;

console.log(a + b); // 15
console.log(a - b); // 5
console.log(a * b); // 50
console.log(a / b); // 2
console.log(a % b); // 0

할당 연산자

let a = 10;

a += 5; // a = a + 5
console.log(a); // 15

a -= 5; // a = a - 5
console.log(a); // 10

a *= 2; // a = a * 2
console.log(a); // 20

a /= 2; // a = a / 2
console.log(a); // 10

a %= 3; // a = a % 3
console.log(a); // 1

비교 연산자

let a = 10;
let b = 5;

console.log(a == b); // false
console.log(a === '10'); // false
console.log(a != b); // true
console.log(a !== '10'); // true
console.log(a < b); // false
console.log(a > b); // true
console.log(a <= b); // false
console.log(a >= b); // true

논리 연산자

let a = true;
let b = false;

console.log(a && b); // false
console.log(a || b); // true
console.log(!a); // false
console.log(!b); // true

스프레드(전개) 연산자

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const arr3 = [...arr1, ...arr2];
console.log(arr3); // [1, 2, 3, 4, 5, 6]

const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const obj3 = { ...obj1, ...obj2 };
console.log(obj3); // {a: 1, b: 2, c: 3, d: 4}

function sum(a, b, c) {
  return a + b + c;
}
const arr = [1, 2, 3];
console.log(sum(...arr)); // 6

연산자 우선순위

우선순위 연산자 설명 결합 방향
1 () 묶음(괄호) -
2 . 멤버 접근 왼쪽에서 오른쪽으로
  new 인수 있는 객체 생성 -
3 () 함수 호출 왼쪽에서 오른쪽으로
  new 인수 없는 객체 생성 오른쪽에서 왼쪽으로
4 ++ 후위 증가 연산자 -
  -- 후위 감소 연산자 -
5 ! 논리 NOT 연산자 오른쪽에서 왼쪽으로
  ~ 비트 NOT 연산자 오른쪽에서 왼쪽으로
  + 양의 부호 (단항 연산자) 오른쪽에서 왼쪽으로
  - 음의 부호 (단항 연산자) 오른쪽에서 왼쪽으로
  ++ 전위 증가 연산자 오른쪽에서 왼쪽으로
  -- 전위 감소 연산자 오른쪽에서 왼쪽으로
  typeof 타입 반환 오른쪽에서 왼쪽으로
  void undefined 반환 오른쪽에서 왼쪽으로
  delete 프로퍼티의 제거 오른쪽에서 왼쪽으로
6 ** 거듭제곱 연산자 오른쪽에서 왼쪽으로
  * 곱셈 연산자 왼쪽에서 오른쪽으로
  / 나눗셈 연산자 왼쪽에서 오른쪽으로
  % 나머지 연산자 왼쪽에서 오른쪽으로
7 + 덧셈 연산자 (이항 연산자) 왼쪽에서 오른쪽으로
  - 뺄셈 연산자 (이항 연산자) 왼쪽에서 오른쪽으로
8 << 비트 왼쪽 시프트 연산자 왼쪽에서 오른쪽으로
  >> 부호 비트를 확장하면서 비트 오른쪽 시프트 왼쪽에서 오른쪽으로
  >>> 부호 비트를 확장하지 않고 비트 오른쪽 시프트 왼쪽에서 오른쪽으로
9 < 관계 연산자(보다 작은) 왼쪽에서 오른쪽으로
  <= 관계 연산자(보다 작거나 같은) 왼쪽에서 오른쪽으로
  > 관계 연산자(보다 큰) 왼쪽에서 오른쪽으로
  >= 관계 연산자(보다 크거나 같은) 왼쪽에서 오른쪽으로
  instanceof 인스턴스 여부 판단 왼쪽에서 오른쪽으로
10 == 동등 연산자 왼쪽에서 오른쪽으로
  === 일치 연산자 왼쪽에서 오른쪽으로
  != 부등 연산자 왼쪽에서 오른쪽으로
  !== 불일치 연산자 왼쪽에서 오른쪽으로
11 & 비트 AND 연산자 왼쪽에서 오른쪽으로
12 ^ 비트 XOR 연산자 왼쪽에서 오른쪽으로
13 | 비트 OR 연산자 왼쪽에서 오른쪽으로
14 && 논리 AND 연산자 왼쪽에서 오른쪽으로
15 || 논리 OR 연산자 왼쪽에서 오른쪽으로
16 ? : 삼항 연산자 오른쪽에서 왼쪽으로
17 = 대입 연산자
(=, +=, -=, *=, /=, %=, <<=, >>=, >>>=, &=, ^=, |=)
오른쪽에서 왼쪽으로
18 ... 전개 -
19 , 쉼표 연산자 왼쪽에서 오른쪽으로

조건문

if문

if (조건식) {
  // 조건식이 참일 때 실행될 코드
}

let num = 5;

if (num < 0) {
  console.log("음수입니다.");
} else if (num == 0) {
  console.log("0입니다.");
} else if (num < 10) {
  console.log("한 자리 양수입니다.");
} else {
  console.log("두 자리 이상의 양수입니다.");
}

switch-case

  • 특정 값에 대한 여러 가지 조건을 비교하고 분기할 때 주로 사용

  • if문과 유사하지만, 하나의 변수에 대해 많은 조건을 비교하는 경우에는 if문보다 switch문이 더 가독성이 좋고 간결한 코드를 작성할 수 있다.

switch (변수) {
  case1:
    // 값1일 때 실행할 코드
    break;
  case2:
    // 값2일 때 실행할 코드
    break;
  default:
    // 모든 case에 해당하지 않을 때 실행할 코드
}

반복문

for

for (초기식; 조건식; 증감식) {
  // 실행할 코드 블록
}
let sum = 0;
for (let i = 1; i <= 10; i++) {
  sum += i;
}
console.log(sum); // 55

for-of

  • 배열과 같은 iterable한 객체를 순회할 때 사용

  • java의 향상된 for문 같은거

for (variable of iterable) {
  // 반복 실행될 코드
}
const arr = [1, 2, 3];

for (let num of arr) {
  console.log(num); // 1, 2, 3이 차례대로 출력됨
}

for-in

  • 객체의 속성을 열거할 때 사용하는 반복문
for (variable in object) {
  // code to be executed
}
const person = {
  name: "Alice",
  age: 30,
  gender: "female",
};

for (let key in person) {
  if (person.hasOwnProperty(key)) {
    console.log(`${key}: ${person[key]}`);
  }
}

while

let i = 1;
while (i <= 5) {
  console.log(i);
  i++;
}

do-while

  • while문과는 달리 조건을 먼저 검사하지 않고, do{} 블록 내부의 코드를 최소한 한 번은 실행한 후 조건을 검사한다.

  • 그냥 간단하게 while문 순서 뒤집힌거~

do {
  // 반복 실행될 코드
} while (조건);
let i = 1;

do {
  console.log(i);
  i++;
} while (i <= 10);

자료구조(Data structure)

배열(Array)

배열 선언 및 초기화

let arr = []; // 빈 배열 선언
let arr2 = [1, 2, 3]; // 원소가 있는 배열 선언

원소 추가 및 삭제

let arr = [1, 2, 3];
arr.push(4); // 마지막에 원소 추가
arr.pop(); // 마지막 원소 삭제
// cf. 파이썬처럼 pop(-1) 안된다. 자바스크립트의 pop()은 매개변수를 받지 않음
arr.unshift(0); // 첫번째 위치에 원소 추가
arr.shift(); // 첫번째 원소 삭제

원소 접근

let arr = [1, 2, 3];
console.log(arr[2]); // 3

배열 순회

let arr = [1, 2, 3];

// for문을 사용한 순회
for (let i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}

// forEach 메서드를 사용한 순회
arr.forEach(function(element) {
  console.log(element);
});

// for-of문을 사용한 순회
for (let element of arr) {
  console.log(element);
}

배열 복사

  • 얕은 복사
    • 주소값 참조 => 복사한 배열의 요소가 바뀌면 원본도 바뀐다.
let arr = [1, 2, 3];

// 배열 전체를 복사
let arr2 = arr.slice();

// 일부 원소만 복사
let arr3 = arr.slice(1, 2); // [2]

// ES6에서 추가된 전개 연산자(...)를 사용한 복사
let arr4 = [...arr];
  • 깊은 복사
let arr = [[1], [2], [3]];
let deepCopiedArr = JSON.parse(JSON.stringify(arr));
- 위 방법의 단점
	- 메서드는 원본 배열에서 함수, undefined, 심볼 등을 제거한다.
	- 원본 배열이 순환 참조를 포함하고 있으면, 이 방법은 에러를 발생시킨다.
	- 성능 측면에서 비효율적일 수 있습니다. 큰 배열을 복사할 때 특히 그렇다.

따라서 아래방법을 사용하자

let arr = [[1], [2], [3]];
let deepCopiedArr = _.cloneDeep(arr);

배열 정렬

let arr = [3, 1, 2];

// 오름차순 정렬
arr.sort(function(a, b) {
  return a - b;
});

// 내림차순 정렬
arr.sort(function(a, b) {
  return b - a;
});

배열 검색

let arr = [1, 2, 3];

// 배열에서 원소 검색
console.log(arr.indexOf(2)); // 1

// 조건에 맞는 원소 검색
console.log(arr.find(function(element) {
  return element > 1;
})); // 2(1보다 큰 첫번째 숫자)
//find대신 filter를 쓰면 1보다 큰 모든 숫자를 반환

해시(Hash)와 객체(Object)

해시와 객체 선언 및 초기화

let obj = {}; // 빈 객체 선언
let obj2 = {key1: 'value1', key2: 'value2'}; // 속성이 있는 객체 선언

속성 추가 및 삭제

let obj = {key1: 'value1', key2: 'value2'};
obj.key3 = 'value3'; // 속성 추가
delete obj.key3; // 속성 삭제

속성 접근

let obj = {key1: 'value1', key2: 'value2'};
console.log(obj.key1); // 'value1'

객체 순회

let obj = {key1: 'value1', key2: 'value2'};

// for-in 문을 사용한 순회
for (let key in obj) {
  console.log(key); // 키 출력
  console.log(obj[key]); // 값 출력
}

// Object.keys를 사용한 순회
Object.keys(obj).forEach(function(key) {
  console.log(key); // 키 출력
  console.log(obj[key]); // 값 출력
});

// Object.entries를 사용한 순회
for (let [key, value] of Object.entries(obj)) {
  console.log(key, value); // 키와 값 동시 출력
}

객체 복사

  • 얕은 복사
let obj = {key1: 'value1', key2: 'value2'};

// Object.assign을 사용한 복사
let obj2 = Object.assign({}, obj);

// ES6에서 추가된 전개 연산자(...)를 사용한 복사
let obj3 = {...obj};
  • 깊은 복사
let obj = {key1: {subkey1: 'subvalue1'}, key2: 'value2'};
let deepCopiedObj = _.cloneDeep(obj);

객체 속성 검색

let obj = {key1: 'value1', key2: 'value2'};

// 객체에서 Key 검색
console.log(obj.hasOwnProperty('key2'));

// 객체에서 Value 검색
console.log(Object.values(obj).includes('value2'));

실습 - 오목게임

어제 학습내용에 이어서 진행했습니다.

오늘 추가된 내용

1. 승패가 계속 나지 않을 경우 실행 후 5분이 지나면 자동 종료시키는 기능 추가

setTimeout()

  • n초 뒤 동작을 지정할 수 있는 메서드

2. 시간복잡도 O(n^4) -> O(n^2) 개선

// 파이썬의 input() 함수 역할을 하는 사용자 입력을 받는 Node.js 기능
const readline = require('readline');
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

// 5분 지나면 입력 종료되는 기능
let countingTime = setTimeout(function() {
    console.log('5분이 지났습니다. 게임이 종료됩니다.');
    rl.close();
}, 5 * 60 * 1000);

console.log('행, 열 <- 왼쪽과 같은 양식으로 좌표값을 입력해주세요.')
console.log('ex) 1,1 or 1, 1 or 7, 3 or 7,3 등')

let arr = new Array(30);
for (let i = 0; i < arr.length; i++) {
    arr[i] = new Array(30).fill('');
}

let turn = 0;

// 입력 받고 최신화 된 보드 출력해주는 메서드
function printBoard() {
  for(let i = 0; i < 30; i++) {
      console.log(arr[i].map(cell => cell === '' ? '*' : cell === '흑' ? 1 : 0).join(' '));
  }
}

/*
 이긴사람 있는지 확인하는 메서드
 가로, 세로, 대각석 탐색
*/
function checkWin(x, y) {
    const directions = [[0, 1], [1, 0], [1, 1], [-1, 1]];

    for(let direction of directions) {
      if(checkLine(x, y, direction)) {
        return true;
      }
    }
  return false;
}


// 한 방향(라인)에 대해 오목이 완성되었는지 확인하는 메서드
function checkLine(x, y, direction) {
    let i = x, j = y, count = 0, xyColor = arr[x][y], used = 0;

    for (let k = 0; k < 5; k++) {
        if (arr[i][j] === xyColor){
            count++;
            i += direction[0];
            j += direction[1];
        }else {
            used = k;
            break;
        }
        if (overRange(i, j)) {
            used = k;
            break;
        }
    }

    i = x - direction[0], j = y - direction[1]
    if (overRange(i,j)) {
        return count == 5;
    }

    for (let k = 0; k < 5 - used; k++) {
        if (arr[i][j] === xyColor){
            count++;
            i -= direction[0];
            j -= direction[1];
        }else {
            break;
        }
        if (overRange(i, j)) {
            break;
        }
    }


    return count === 5;
}

// 확인하려는 좌표가 Board 범위를 초과됐는지 확인하는 메서드
function overRange(x, y) {
    if (x < 0 || x >= 30 || y < 0 || y >= 30) {
        return true;
    }
    return false;
}


/*
    입력값 받아서 보드에 넣는 실질적인 게임 메서드
    + 예외처리
*/
function play() {
    let player = turn % 2 == 0 ? '백' : '흑'; // w for white, b for black
    rl.question(`${player === '흑' ? '흑' : '백'}색 돌을 놓을 좌표를 입력하세요 :`, (inputValue) => {
        let coords = inputValue.split(',');
        let x = parseInt(coords[0]);
        let y = parseInt(coords[1]);

        // 입력값 범위 초과에 대한 예외처리
        if(x < 0 || x >= 30 || y < 0 || y >= 30) {
            console.log("0이상 30미만 값을 입력해주세요.");
            play();
            return;
        }

        // 이미 둔 자리 or 잘못된 입력양식에 대한 예외처리
        if(arr[x][y] !== '') {
            if(arr[x][y] === '흑' || arr[x][y] === '백') {
                console.log("이미 돌을 놓은 자리입니다.");
            }else {
                console.log("올바른 좌표값을 입력하세요.");
                console.log("예시: 1,3 or 1, 3 or 10, 15 등등");
                console.log("잘못된 예시: [1,3] or 1,     2 or 1.2");
            }
            play();
            return;
        }

        arr[x][y] = player;
        printBoard();

        if(checkWin(x, y)) {
            console.log('Game over')
            console.log(`${player === '흑' ? '흑' : '백'}색돌이 승리하였습니다!!`);
            rl.close();
            clearTimeout(countingTime);
        } else {
            turn++;
            play();
        }
    });
}

play();

3. 문자열 등 잘못된 입력값에 대한 예외처리 추가 + 예외처리 기능 분리

// 파이썬의 input() 함수 역할을 하는 사용자 입력을 받는 Node.js 기능
const readline = require('readline');
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

// 5분 지나면 입력 종료되는 기능
let countingTime = setTimeout(function() {
    console.log('5분이 지났습니다. 게임이 종료됩니다.');
    rl.close();
}, 5 * 60 * 1000);

console.log('행, 열 <- 왼쪽과 같은 양식으로 좌표값을 입력해주세요.')
console.log('ex) 1,1 or 1, 1 or 7, 3 or 7,3 등')

let arr = new Array(30);
for (let i = 0; i < arr.length; i++) {
    arr[i] = new Array(30).fill('');
}

let turn = 0;

// 입력 받고 최신화 된 보드 출력해주는 메서드
function printBoard() {
  for(let i = 0; i < 30; i++) {
      console.log(arr[i].map(cell => cell === '' ? '*' : cell === '흑' ? 1 : 0).join(' '));
  }
}

/*
 이긴사람 있는지 확인하는 메서드
 가로, 세로, 대각석 탐색
*/
function checkWin(x, y) {
    const directions = [[0, 1], [1, 0], [1, 1], [-1, 1]];

    for(let direction of directions) {
      if(checkLine(x, y, direction)) {
        return true;
      }
    }
  return false;
}


// 한 방향(라인)에 대해 오목이 완성되었는지 확인하는 메서드
function checkLine(x, y, direction) {
    let i = x, j = y, count = 0, xyColor = arr[x][y], used = 0;

    for (let k = 0; k < 5; k++) {
        if (arr[i][j] === xyColor){
            count++;
            i += direction[0];
            j += direction[1];
        }else {
            used = k;
            break;
        }
        if (overRange(i, j)) {
            used = k;
            break;
        }
    }

    i = x - direction[0], j = y - direction[1]
    if (overRange(i,j)) {
        return count == 5;
    }

    for (let k = 0; k < 5 - used; k++) {
        if (arr[i][j] === xyColor){
            count++;
            i -= direction[0];
            j -= direction[1];
        }else {
            break;
        }
        if (overRange(i, j)) {
            break;
        }
    }


    return count === 5;
}

function overRange(x, y) {
    if (x < 0 || x >= 30 || y < 0 || y >= 30) {
        return true;
    }
    return false;
}

// 입력값에 대한 예외처리
function validateInput(inputValue) {
    let coords = inputValue.split(',');
    let x = parseInt(coords[0]);
    let y = parseInt(coords[1]);

    if(isNaN(x) || isNaN(y)) {
        console.log("숫자를 입력해주세요.");
        return null;
    }

    if(x < 0 || x >= 30 || y < 0 || y >= 30) {
        console.log("0이상 30미만 값을 입력해주세요.");
        return null;
    }

    if(arr[x][y] !== '') {
        if(arr[x][y] === '흑' || arr[x][y] === '백') {
            console.log("이미 돌을 놓은 자리입니다.");
        }else {
            console.log("올바른 좌표값을 입력하세요.");
            console.log("예시: 1,3 or 1, 3 or 10, 15 등등");
            console.log("잘못된 예시: [1,3] or 1,     2 or 1.2");
        }
        return null;
    }

    return [x, y];
}


/*
    입력값 받아서 보드에 넣는 실질적인 게임 메서드
*/
function play() {
    let player = turn % 2 == 0 ? '백' : '흑'; // w for white, b for black
    rl.question(`${player === '흑' ? '흑' : '백'}색 돌을 놓을 좌표를 입력하세요 :`, (inputValue) => {
        let coords = validateInput(inputValue);
        if(coords === null) {
            play();
            return;
        }
        let x = parseInt(coords[0]);
        let y = parseInt(coords[1]);

        arr[x][y] = player;
        printBoard();

        if(checkWin(x, y)) {
            console.log('Game over')
            console.log(`${player === '흑' ? '흑' : '백'}색돌이 승리하였습니다!!`);
            rl.close();
            clearTimeout(countingTime);
        } else {
            turn++;
            play();
        }
    });
}

play();

본 후기는 정보통신산업진흥원(NIPA)에서 주관하는 <AI 서비스 완성! AI+웹개발 취업캠프 - 프론트엔드&백엔드> 과정 학습/프로젝트/과제 기록으로 작성 되었습니다.
#정보통신산업진흥원 #NIPA #AI교육 #프로젝트 #유데미 #IT개발캠프 #개발자부트캠프 #프론트엔드 #백엔드 #AI웹개발취업캠프 #취업캠프 #개발취업캠프

0개의 댓글