delete 뒤에 객체의 속성 값을 입력하면 해당 속성을 제거한다.

 

let test = {a:0, b:1, c:2};
delete test.a;

console.log(test); // { b: 1, c: 2 }

 

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/delete

 

delete 연산자 - JavaScript | MDN

**delete**는 객체의 속성을 제거합니다. 속성의 값이 객체이고 더 이상 그 객체에 대한 참조가 없다면, 해당 객체는 결국 자동으로 메모리에서 해제됩니다.

developer.mozilla.org

 

Prettier

 

Prettier는 코드 서식을 관리 해주는 패키지다

 

Prettier 사용 준비

# Prettier를 debDependency로 설치합니다.
yarn add prettier -D

 

위 명령어를 터미널에 입력해 prettier를 설치한다. ( D = 개발 환경 전용 )

 

Prettier 설정파일 추가

.prettierrc.json 기본 설정

{
  "printWidth": 80,
  "tabWidth": 2,
  "singleQuote": false,
  "trailingComma": "all",
}

 

  • printwidth : number ( 한 줄에 최대 글자수를 정의 )
  • tabWidth : number ( Tab에 대한 스페이스 수를 정의 )
  • singleQuote : bool ( 따옴표를 쌍 따옴표 (") 사용 여부 )
  • trailingComma : "all" ( 여러 줄을 사용할 때, 후행 콤마 사용 )

스크립트 추가

Prettier를 보다 편리하게 사용할 수 있도록 package.json 파일에 스크립트를 추가한다.

이를 통해 터미널에서 간단한 명령만으로 Prettier를 실행할 수 있다.

 

"scripts": {
  "format": "prettier --write *.js **/*.js"
},

 

위 코드를 package.json에 입력한다. 이 스크립트를 실행하면 프로젝트 내의 모든 .js 파일을 대상으로 .prettierrc.js에 설정된 값을 바탕으로 Prettier를 실행하게 된다.

 

Prettier 실행

# package.json에 작성된 format 스크립트를 실행합니다.
yarn run format

 

위 명령어를 터미널에 입력하면 yarn run이 package.json에 작성한 스크립트를 실행한다. ( format은 package.json에 추가한 스크립트 이름 )

미들웨어

 

  • 미들웨어는 서버의 요청 ( Request ) - 응답 ( Response ) 과정에서 중간에 위치해 특정 기능을 수행하는 함수라고 볼 수 있다.
  • 예를 들어, 모든 요청에 대해 로그를 남기거나, 특정 사용자만 API를 접근하게 하고 싶을 경우에도 미들웨어를 사용한다.

 

Express.js의 미들웨어 

// 전역으로 미들웨어 등록
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
  • urlencoded : form-urlencoded 라는 규격의 body 데이터를 손쉽게 코드에서 사용할 수 있게 도와주는 미들웨어
  • json : JSON 규격의 body 데이터를 손쉽게 코드에서 사용할 수 있게 도와주는 미들웨어

 

Express.js에서 미들웨어 작성

app.use((req, res, next) => {
  // 필요한 코드
});

위 형태에서 req, res, next는 각자 역할을 지니고 있는 인자다

  • req : 요청 ( Request )에 대한 정보가 담겨있는 객체다. ( HTTP Headers, Query Parameters, URL 등 브라우저가 서버로 보내는 정보들이 담겨 있다. )
  • res : 응답 ( Response )을 위한 기능이 제공된다. ( 어떤 HTTP Status Code로 응답 할지, 어떤 데이터 형식으로 응답 할지, 헤더는 어떤 값을 넣어 응답 할지 다양한 기능을 제공한다. )
  • next : 다음 스택으로 정의된 미들웨어를 호출한다.

 

미들웨어 작성해보기

app.use((req, res, next) => {
    console.log('Request URL:', req.originalUrl, ' - ', new Date());
    next();
});
  • 위 코드를 작성하고 서버를 실행한 후 메인페이지로 접속하면 터미널에 로그가 남겨지는 것을 확인할 수 있다.

 

미들웨어 동작 방식

다음 미들웨어로 진행하지 않고 중간에 응답할 경우의 상황

 

  • 미들웨어는 어디에 위치시키느냐에 따라 다르게 동작한다. 일반적으로는 어플리케이션에 등록된 순서대로 실행된다.
  • 여러개의 미들웨어가 겹치는 경우, 이는 첫번째 미들웨어부터 순차적으로 진입한다.
app.use((req, res, next) => {
    console.log('첫번째 미들웨어');
    next();
});

app.use((req, res, next) => {
    console.log('두번째 미들웨어');
    next();
});

app.use((req, res, next) => {
    console.log('세번째 미들웨어');
    next();
});

// print: 첫번째 미들웨어
// print: 두번째 미들웨어
// print: 세번째 미들웨어

 

예를 들어

  • 위 그림처럼 순차적으로 미들웨어를 통과하고 중간에 응답을해 종료가 되는 경우
  • 위 코드처럼 순차적으로 다음 미들웨어로 넘어가는 경우
  • 중간에 next()를 실행하지 않으면 다음 미들웨어는 실행되지 않는다.
  • 당연히 현재 미들웨어에서 응답을 보내는 경우, 즉 res.send() 나 res.json() 등의 메서드를 호출하는 경우 next()를 호출하면 안된다. 이렇게 하지 않으면 이미 요청이 종료된 상태에서 다른 미들웨어가 응답을 보내려고 해서 중복된 요청이 전달되는 문제가 발생한다.

 

라우터와 미들웨어 차이

  • 라우터와 미들웨어는 서로 다른 방식처럼 보이지만 라우터는 미들웨어 기반으로 구현된 객체라서 미들웨어와 동일한 방식으로 작동된다.
  • 라우터는 미들웨어 함수를 특정 경로에 바인딩하는 역할을 하고, 요청이 들어온 URL 경로에 따라 서로 다른 미들웨어를 실행시킬 수 있게 도와준다.
app.use(Middleware) : 모든 요청에서 미들웨어가 실행된다.
app.use('/api', Middleware) : /api로 시작하는 모든 요청에서 미들웨어를 실행한다.
app.post('/api', Middleware, (req,res)=>{}) : /api로 시작하는 POST 요청에서 미들웨어를 실행한다.

 

Request, Response

Request

  • Request란 클라이언트가 서버에게 전달하려는 정보나 메세지를 담은 객체를 의미한다.
  • Request의 세부 사항에는 URL, http method, 헤더( header ), 쿼리 파라미터 ( query parameter ), 바이 데이터 ( body data ) 등이 포함 된다.

 

Response

  • Response란 서버에서 클라이언트로 응답 메세지를 전송시켜주는 객체다.
  • Response의 세부 사항에는 상태 코드 ( status code ), 응답 데이터 ( response data ), 응답 헤더 ( response header ) 등이 포함된다.

서버 모듈

  • Node.js의 서버 모듈에는 대표적으로 http 모듈과 Express.js가 존재한다. ( http 모듈은 Node.js에서 기본 제공하는 http 서버 모듈이다 )
  • Express.js는 http 모듈을 확장해 제공한다.
  • Express.js는 기존 http 모듈의 메서드도 사용할 수 있지만, Express.js가 추가 제공하는 메서드나 속성들을 사용할 수 있다.

 

Express.js 통신 흐름

  • 클라이언트는 특정 URL과 데이터를 담은 요청 ( Request )을 서버에 전송한다.
  • 서버는 받은 데이터에 따라 필요한 비즈니스 로직을 수행한다.
  • 서버는 처리된 결과를 클라이언트에게 응답 ( Response )으로 보내준다.

 

예제 ) 

 

app.js

// app.js

import express from 'express';
import goodsRouter from './routes/goods.js';
import newsRouter from './routes/news.js';

const app = express();
const PORT = 3000; // 서버를 열 때 사용할 포트 번호

app.get('/', (req, res) => {
  res.send('Hello World!');
});

// 1. Express.js의 서버를 엽니다.
app.listen(PORT, () => {
  console.log(PORT, '포트로 서버가 열렸어요!');
});

// localhost:3000/api -> goodsRouter
// localhost:3000/api -> newsRouter
// 2. 라우터를 등록 합니다.
// app.use 미들웨어를 사용해 /api로 접속하면 goodsRouter와 newsRouter를 연결(등록)한다 
app.use('/api', [goodsRouter, newsRouter]);

 

1. 서버시작

 app.listen을 통해 3000 포트로 웹 서버를 연다.

 

2. 라우터 등록

 app.use 미들웨어를 사용해 /api 주소에 goodsRouter와 newRouter를 연결(등록)한다.

 

news.js

// routes/news.js


import express from 'express';

const router = express.Router();

// req : 클라이언트가 전달한 Path Params
// res : 서버가 클라에게 전달할 데이터 ( json 형태로 전달 )

/** 뉴스 목록 조회 API **/
// 3. HTTP Method와 URL을 지정한 API를 정의합니다.
// 만약, localhost:3000/api/news 라는 URL로 GET 요청이 들어온다면 해당 코드를 실행합니다.
router.get('/news', (req, res) => {
  // 4. 사용자의 요청에 맞는 데이터를 반환합니다.
  return res // Express.js의 res 객체를 반환합니다.
    .status(200) // API의 상태 코드를 200번으로 전달합니다.
    .send('뉴스 목록 조회 API 입니다.'); // API의 결과값을 '뉴스 목록 조회 API 입니다.'로 전달합니다.
});

/** 뉴스 세부 조회 API **/
// 3. HTTP Method와 URL을 지정한 API를 정의합니다.
// 만약, localhost:3000/api/news/:newsId 라는 URL로 GET 요청이 들어온다면 해당 코드를 실행합니다.
router.get('/news/:newsId', (req, res) => {
  // 클라이언트가 전달한 Path Params 데이터를 받아옵니다.
  const params = req.params;

  // Path Params 데이터 중 newsId를 추출합니다.
  const newsId = params.newsId;

  // 서버 콘솔에 클라이언트가 전달한 newsId를 출력합니다.
  console.log('클라이언트로 부터 전달받은 뉴스 ID:', newsId);

  // 4. 사용자의 요청에 맞는 데이터를 json 형태로 반환합니다.
  return res.status(200).json({
    data: '뉴스 세부 조회 API 입니다.',
  });
});

// Express 라우터를 외부로 전달합니다.
export default router;

 

3. API 정의 

등록된 각 라우터를 순서대로 검토하고, HTTP Method와 URL이 일치하는 함수를 실행한다.

 -URL /api/news로 GET 요청이 들어오면 router.get('/new' ~ )을 실행한다.

   

 -URL /api/news/:newsId로 GET 요청이 들어오면 router.get('/new/:newsId' ~)을 실행한다.

  • 여기서 중요한 부분은 :newId에 해당하는 경로 변수다. 이는 req.params을 통해 들어온 변수를 읽어들일 수 있다. 
  • 위 코드에서는 req.params을 통해 들어온 변수를 params에 저장하고 params.newsId를 통해 해당 변수를 읽어오고 출력해주는 형태다

4. 결과 반환

API에서 모든 로직 처리가 완료된 후, 클라이언트에게 결과를 전달한다.

 

 

 

'Javascript' 카테고리의 다른 글

[Javascript][Node.js] Mongo DB  (0) 2024.09.02
[Javascript][Node.js] Express.js - req, res 객체  (0) 2024.08.30
[Javascript] API Client ( Insomnia API Client )  (0) 2024.08.30
[Javascript] API  (0) 2024.08.29
[Javascript] Module  (0) 2024.08.29

API

 

API는 서로 다른 다른 소프트웨어나 어플리케이션 간을 연결해주는 매개체이자 약속이라고 볼 수 있다.

 

API를 작성한다는 의미

  • 웹 어플리케이션에서 원하는 기능을 수행하는 URL과 인터페이스를 제공한다는 의미다.
  • API에서 원하는 데이터를 받아 DB에 데이터를 저장하고, 저장되어 있는 데이터를 읽어 웹 어플리케이션에 데이터를 제공하는 행위를 통해 사용자가 원하는 목적을 이룰 수 있게 해야 한다.

REST API

REST API ( 출처 : https://mannhowie.com/rest-api )

 

  • REST는 'Representational State Transfer'의 줄임 말로, 월드 와이드 웹과 같은 분산 하이퍼미디어 시스템을 위해 네트워크 상에서 자원을 쉽고 명확하게 식별하고 조작할 수 있게 도와주는 소프트웨어 아키텍처의 한 형식이다.
  • URL, Headers, Method 등 네트워크 표현 수단을 이해하기 쉬운 표현으로 정의하는 것을 말하고, 'REST 아키텍쳐'는 쉽게 이해할 수 있도록 '자원'을 정의하고 이 '자원'을 중심으로 표현을 구성하는 원칙을 제시한다.
  • REST API는 HTTP를 통해 웹 서비스의 자원에 접근하는 방식을 'REST 아키텍쳐'의 규칙을 따라 구현된 API라고 생각하면 된다.

REST API의 구성 요소

REST API의 구성은 크게 세 가지로 이루어 진다.

1. 자원 ( Resource ) - URL

  • 소프트웨어가 관리하는 모든 것을 자원으로 표현할 수 있다.

2. 행위 - HTTP method

  • http method인 GET, POST 등으로 자원에 대한 행위를 표현할 수 있다. ( 예를 들어, GET 메서드는 '조회'와 관련이 있어서 데이터를 읽는 작업을 수행하고, POST 메서드는 '생성'과 관련이 있어서 새로운 데이터를 생성하는 작업을 수행한다. )
  • 자원에 대한 생성/조회/수정/삭제를 각각의 method로 나누어 놓고, 이를 보통 CRUD라 한다.
Create : 생성(POST)
Read : 조회(GET)
Update : 수정(PUT),(PATCH)
Delete : 삭제(DELETE)

 

3. 표현

  • 해당 자원을 어떻게 표현할지에 대한 방법으로, 보통 JSON, XML 같은 형식을 이용해 자원을 표현한다.
  • HTTP에서는 Content-Type 이라는 헤더를 통해 표현 방법을 서술한다.

REST API 예시

router.get('/books', (req, res) => {
	res.json({ success: true, data: getAllBooks() });
});
  • 위 예시코드는 /books 라는 URL을 통해 전체 책 목록을 불러와 응답해 주는 역할을 하는 API다.
  • http 메서드인 GET은 리소스를 조회하는 역할을 담당하므로, 위 코드는 전체 책 목록을 조회하고, 그 결과를 JSON 형식으로 반환한다. 이렇게 API가 "REST 원칙"에 따라 구현되었으므로, 이 API는 RESTful 하다고 볼 수 있다.

Routing의 이해

Routing은 클라이언트의 요청 조건( http 메서드, 주소 등)에 대응해 응답하는 방식을 말한다.

여기서 말하는 Router는 클라이언트의 요청을 쉽게 처리 할 수 있게 도와주는 Express.js의 기본 기능중 하나다.

  • 일반적으로 Router는 아래와 같은 구조를 가진다.
router.METHOD(PATH, HANDLER);
  • router : Express.js의 라우터를 정의하기 위해 사용한다
  • METHOD : http method를 나타낸다. ( 예 : get, post, put, patch, delete, ... )
  • PATH : 실제 서버에서 API를 사용하기 위한 경로를 나타낸다. ( 예 : users, posts, URL, ... )
  • HANDLER : 라우트가 일치할 때 실행되는 함수다.

 

'Javascript' 카테고리의 다른 글

[Javascript][Node.js] Request, Response  (0) 2024.08.30
[Javascript] API Client ( Insomnia API Client )  (0) 2024.08.30
[Javascript] Module  (0) 2024.08.29
[Javascript] Express.js 프레임 워크  (0) 2024.08.28
[Javascript] Node.js  (0) 2024.08.27

모듈 ( 출처 : hacks.mozilla.org )

 

모듈은 Javascript를 파일 단위로 분리된 코드 덩어리를 말한다.

모듈은 하나의 모듈에서 다른 모듈을 호출해 사용할 수 있다.

모듈은 대개 클래스 하나 혹은 특정한 목적을 가진 복수의 함수로 구성된 라이브러리 하나로 구성된다.

 

모듈의 필요성

  • 코드 베이스를 분리할 수 있고, 이를 통해 코드를 구조적으로 관리할 수 있다.
  • 코드를  재사용 가능하게 만들어준다. ( = 모듈화 )
  • 코드의 함수와 변수중 일부만 외부에서 사용하도록 노출시킬 수 있다. ( 즉, 모듈 내부의 코드 세부사항을 외부로 부터 은닉하는 정보은닉을 표현할 수 있다. )
  • 해당 모듈이 참조하고 있는 다른 모듈에 대한 종속성을 관리하는 역할을 담당한다.

 

CJS ( CommonJS )

Node.js 환경에서 기본적으로 사용되는 모듈 시스템이다.

설정을 따로 추가하지 않은 이상, Node.js에서는 CommonJS를 기본으로 사용한다.

require 함수를 사용하여 다른 모듈을 불러올 수 있다.

require 함수는 경로 혹은 문자열을 가지고 내부 알고리즘을 통해 모듈을 가져오고 종속성을 처리한다.

 

ESM ( ECMA Script Module )

최신 Javascript에서 지원하는 모듈 시스템이다.

모든 Javascript 환경에서 통합적인 인터페이스를 제공하기 위해 시작된 체계다.

CommonJS 와는 다르게 정적으로 모듈을 가져오며 비동기적 모듈 로딩과 순환 종속을 처리한다.

 


모듈의 사용법

모듈 사용법 ( 출처 : hacks.mozilla.org )

 

export 명령어를 변수나 함수 앞에 붙이면 외부 모듈에서 해당 변수나 함수에 접근할 수 있다. 

import, require 명령어를 사용해 외부 모듈의 기능을 가져올 수 있다.

 

 ● import는 ES6( ES2015 )로 모듈 시스템을 관리할 때 사용한다.

  • 이 방식은 정적 로딩을 지원한다.
  • import 문은 코드의 최상위에 위치해야 한다

 ● require는 CommonJS로 모듈시스템을 관리할 때 사용한다.

  • 이 방식은 동적 로딩을 지원한다.
  • require 문은 코드의 어디에서든 사용할 수 있다.

 

ES6 Module 사용

// 📁 sayHi.js
export function sayHi(user) {
  console.log(`Hello, ${user}!`);
}

 

export 지시자를 사용해 sayHi.js 내부의 함수 sayHi를 외부로 내보낸다.

 

// 📁 main.js
import {sayHi} from './sayHi.js';

console.log(sayHi); // function
sayHi('John'); // Hello, John!

 

import 지시자를 사용해 상대 경로 ( ./sayHi.js ) 기준으로 모듈을 가져오고 sayHi.js 에서 내보낸 함수 sayHi를 상응하는 변수에 할당한다.

 

상대 경로

import {sayHi} from './sayHi.js';

 

위 코드에서 ./sayHi는 파일 경로를 나타내는데, ./ 으로 시작하는 경로는 '상대 경로' 라는 것을 나타낸다.

여기서, '상대 경로'란 현재 파일의 위치에 따라 다르게 해석되는 파일 또는 디렉토리의 위치는 나타내는 방식이다.

즉, ./sayHi.js 는 현재 파일이 위치한 디렉토리에서 sayHi.js라는 이름의 파일을 찾는 것을 의미한다.

상위 디렉토리에서 파일을 찾으려면 ../ 을 이용하면 된다. 

즉, ../sayHi.js 라고 상대경로를 설정하면 현재 파일이 위치한 디렉토리의 상위 디렉토리에서 sayHi.js 를 찾는 것을 의미한다.

 

화살표 함수 export, import

/** 화살표 함수 export **/

// 모듈을 호출했을 때, addArrowFunction 키 값에는 addArrowFunction 변수 함수가 가지고 있는 값이 할당된다.
export const addArrowFunction = (a, b) => {
  return a + b;
}

 

/** 화살표 함수 import **/

import { addArrowFunction } from './math.js'

console.log(addArrowFunction(5, 3));

// Print: 8

 

'Javascript' 카테고리의 다른 글

[Javascript] API Client ( Insomnia API Client )  (0) 2024.08.30
[Javascript] API  (0) 2024.08.29
[Javascript] Express.js 프레임 워크  (0) 2024.08.28
[Javascript] Node.js  (0) 2024.08.27
[Javascript] 자료형  (0) 2024.08.24

자바스크립트에서 값은 항상 문자열이나 숫자형 같은 특정한 자료형에 속한다.

자바스크립트에는 8가지 기본 자료형이 있다.

 

숫자형

let n = 123;
n = 12.345;

 

숫자형은 정수 및 부동소수점 숫자를 나타낸다.

숫자형과 관련된 연산은 다양한데, 곱셉, 나눗셈, 덧셈, 뺄셈 등이 대표적이다.

숫자형엔 일반적인 숫자 외에 Infinity, -Infinity, NaN 같은 특수 숫자 값이 포함된다.

 

Infinity는 무한대를 나타낸다.

일반적으로 0으로 나누면 무한대를 얻을 수 있다.

console.log( 1 / 0 );
console.log( Infinity );

 

NaN은 계산 중 에러가 발생했다는 것을 나타내주는 값이다.

부정확하거나 정의되지 않은 수학 연산을 사용하면 계산 중 에러가 발생하는데, 이때 NaN이 반환된다.

console.log( "글자" / 2 ); // NaN

 

 

NaN은 웬만해선 바뀌지 않는다. NaN에 어떤 추가 연산을 해도 결국 NaN이 반환된다.


BigInt

자바스크립트에선 내부 표현 방식 때문에 (2^53 - 1)(9007199254740991) 보다 큰 값 또는

-(2^53-1) 보다 작은 정수는 숫자형을 사용해 나타낼 수 없다.

BigInt 형은 길이에 상관없이 정수를 나타낼 수 있다.

BigInt 형 값은 정수 리터럴 끝에 n을 붙이면 만들 수 잇다. 

 

// 끝에 'n'이 붙으면 BigInt형 자료입니다.
let bigInt = 1234567890123456789012345678901234567890n;

문자형

자바스크립트에선 문자열을 따옴표로 묶는다.

let str = "Hello";
let str2 = 'Single quotes are ok too';
let phrase = `can embed another ${str}`;

 

따옴표는 세 종류가 있다.

1. 큰따옴표 : "Hello"

2. 작은따옴표 : 'Hello'

3. 역 따옴표( 백틸, backtick ) : `Hello`

 

큰따옴표와 작은따옴표는 기본적인 값으로, 자바스크립트에서는 이 둘에 차이를 두지 않는다.

역 따옴표로 변수나 표현식을 감싼 후 ${...} 안에 넣어주면, 다음과 같이 원하는 변수나 표현식을 

문자열 중간에 손쉽게 넣을 수 있다.

 

let name = "John";

// 변수를 문자열 중간에 삽입
console.log( `Hello, ${name}!` ); // Hello, John!

// 표현식을 문자열 중간에 삽입
console.log( `the result is ${1 + 2}` ); // the result is 3

Boolean 형

boolean형은 ture와 false 두 가지 값밖에 없는 자료형 이다.

boolean형은 긍정이나 부정을 나타내는 값을 저장할 때 사용한다.

let nameFieldChecked = true; 
let ageFieldChecked = false;

null 값

null 값은 지금까지 소개한 자료형 중 어느 자료형에도 속하지 않는 값이다.

null 값은 오로지 null 값만 포함하는 별도의 자료형이다.

let age = null;

 

 

자바스크립트의 null은 다른 언어에서의 null과는 성격이 다르다.

다른 언어에서는 null을 존재하지 않는 객체에 대한 참조널 포인터를 나타낼 때 사용한다.

하지만 자바스크립트에서 null은 존재하지 않는 값, 비어 있는 값, 알 수 없는 값을 나타내는 데 사용한다.

 

위 예시를 들어 설명하자면 let age = null; 은 나이를 알 수 없거나 그 값이 비어있음을 보여준다. ( 해석의 영역 )


undefined 값

undefined 값도 null 값처럼 자신만의 자료형을 형성한다.

undefined는 값이 할당되지 않은 상태를 나타낼 때 사용한다.

변수는 선언했으나, 값을 할당하지 않았다면 해당 변수에 undefined가 자동으로 할당된다.

let age;

console.log(age); // 'undefined'가 출력됩니다.

 

변수에 undefined를 명시적으로 할당하는 것도 가능하다.

let age = 100;

// 값을 undefined로 바꿉니다.
age = undefined;

console.log(age); // "undefined"

 

하지만 이렇게 undefined를 직접 할당하는 것은 권장되지 않는다.

변수가 비어있거나 알 수 없는 상태라는 걸 나타낼 때는 null을 사용하는 것이 좋다.

undefined는 값이 할당되지 않은 변수의 초기값을 위해 예약어로 남겨두는 편이 낫다.


typeof 연산자

typeof 연산자는 인수의 자료형을 반환한다. 자료형에 따라 처리 방식을 다르게 하고 싶을 경우와

변수의 자료형을 빠르게 알아내고자 할 때 유용하다.

 

typeof 연산자는 두 가지 형태의 문법을 지원한다.

1. 연산자 : typeof x

2. 함수 : typeof(x)

 

typeof undefined // "undefined"

typeof 0 // "number"

typeof 10n // "bigint"

typeof true // "boolean"

typeof "foo" // "string"

typeof Symbol("id") // "symbol"

 

참고 : https://ko.javascript.info/types

 

자료형

 

ko.javascript.info

 

'Javascript' 카테고리의 다른 글

[Javascript] Express.js 프레임 워크  (0) 2024.08.28
[Javascript] Node.js  (0) 2024.08.27
[Javascript] 화살표함수  (0) 2024.08.22
[Javascript] 프로토타입 ( Prototype )  (0) 2024.08.22
[Javascript] Random - 난수 생성하기  (0) 2024.08.21

prototype 프로퍼티는 자바스크립트 내부에서 광범위하게 사용된다.

모든 내장 생성자 함수에서 prototype 프로퍼티를 사용한다.


Object.prototype

빈 객체를 생성해보자.

let obj = {};
alert( obj ); // "[object Object]" ?

 

"[Object Object]" 문자열을 생성하는 코드는 어디에 있는걸까?

obj는 비어 있는데 말이다.

obj = new Object()를 줄이면 obj = {} 가 된다.

여기서 Object는 내장 객체 생성자 함수인데, 이 생성자 함수의 prototype은 toString을 비롯한 다양한 메서드가 구현되어 있는 거대한 객체를 참조한다.

Object의 prototype이 Object.prototype을 참조하는 그림

 

 

new Object()를 호출하면 새롭게 생성된 객체의 Prototype 은 Object.prototype을 참조한다.

new Object()를 사용해 생성된 객체의 Prototype이 Object.prototype을 참조하는 그림

 

 

따라서 obj.toString()을 호출하면 Object.prototype에서 해당 메서드를 가져오게 된다.

예시를 통해 확인해 보자.

let obj = {};

console.log(obj.__proto__ === Object.prototype); // true

console.log(obj.toString === obj.__proto__.toString); //true
console.log(obj.toString === Object.prototype.toString); //true

 

다양한 내장 객체의 프로토타입

Array, Date, Function을 비롯한 내장 객체들 역시 프로토타입에 메서드를 저장해 놓는다.

배열 [1, 2, 3]을 만들면 new Array() 의 디폴트 생성자가 내부에서 동작하여 Array.prototype이 배열 [1, 2, 3]의 프로토타입이 되고 개발자는 Array.prototype을 통해 배열 메서드를 사용할 수 있다.

 

명세서에선 모든 내장 프로토타입의 상속 트리 꼭대기엔 Object.prototype이 있어야 한다고 규정한다.

세 내장 객체를 이용해 지금까지 설명한 내용을 그려보면 다음과 같다.

 

 

이번엔 코드로 각 내장 객체의 프로토타입을 직접 확인해 보자.

let arr = [1, 2, 3];

// arr은 Array.prototype을 상속받았나요?
console.log( arr.__proto__ === Array.prototype ); // true

// arr은 Object.prototype을 상속받았나요?
console.log( arr.__proto__.__proto__ === Object.prototype ); // true

// 체인 맨 위엔 null이 있습니다.
console.log( arr.__proto__.__proto__.__proto__ ); // null

 

 

체인 상의 프로토타입엔 중복 메서드가 있을 수 있다.

Array.prototype엔 요소 사이에 쉼표를 넣어 요소 전체를 합친 문자열을 반환하는 자체 메서드 toString이 있다.

let arr = [1, 2, 3]
console.log(arr); // 1,2,3 <-- Array.prototype.toString의 결과

 

 

그런데 Object.prototype에도 메서드 toString이 있다. 이렇게 중복 메서드가 있을 때는 체인 상에서 가까운 곳에 있는 메서드가 사용된다. Array.prototype 이 체인 상에서 더 가깝기 때문에 예시에서는 Array.prototype의 toString이 사용된다.

 

 

Chrome 개발자 콘솔과 같은 도구를 사용해 console.dir를 사용하면 내장 객체의 상속 관계를 확인할 수 있다.

 

 

배열이 아닌 다른 내장 객체들 또한 같은 방법으로 동작한다. 

함수도 마찬가지며 call, apply를 비롯한 함수에서 사용할 수 있는 메서드는 Function.prototype에서 받아온다.

function f() {}

console.log(f.__proto__ == Function.prototype); // true
console.log(f.__proto__.__proto__ == Object.prototype); // true, 객체에서 상속받음

 

'Javascript' 카테고리의 다른 글

[Javascript] 자료형  (0) 2024.08.24
[Javascript] 화살표함수  (0) 2024.08.22
[Javascript] Random - 난수 생성하기  (0) 2024.08.21
[Javascript] Map  (0) 2024.08.19
[Javascript] 소수 올림, 내림, 반올림  (0) 2024.08.19

클래스는 객체를 생성하기 위한 템플릿으로 생각하면 된다.

클래스를 생성하기 위해서는 class 키워드를 사용한다.


기본 문법

class MyClass {
  // 여러 메서드를 정의할 수 있음
  constructor() { ... }
  method1() { ... }
  method2() { ... }
  method3() { ... }
  ...
}

 

위처럼 클래스를 만들고 new Myclass()를 호출하면 객체가 생성된다.

 

constructor()는 생성자로 new에 의해 자동으로 호출되고, 객체의 기본 상태를 설정해준다.

 

class User {
  constructor(name) {
    this.name = name;
  }

  sayHi() {
    console.log("안녕하세요");
  }
}

// 사용법:
let user = new User("Yam");
user.sayHi();

 

위처럼 new User("Yam")를 호출하면, 새로운 객체가 생성되고,

넘겨받은 매개변수와 함께 constructor가 자동으로 실행된다.

 

자바스크립트에서 클래스는 함수의 한 종류로 취급한다.

class User {
  constructor(name) { this.name = name; }
  sayHi() { console.log(this.name); }
}

// User가 함수라는 증거
console.log(typeof User); // function

 

class User 문법 구조가 하는일은 다음과 같다.

1. User라는 이름을 가진 함수를 만들고, 함수 본문은 constructor에서 가져온다.

    constructor가 없으면 본문이 비워진 채로 함수가 만들어진다.

2. sayHi와 같은 메서드를 User.prototype에 저장한다.

 

new User를 호출해 객체를 만들고, 객체의 메서드를 호출하면 메서드를 prototype 프로퍼티를 통해 가져온다.

이 과정이 있어서 객체에서 메서드에 접근할 수 있다.

 

class User {
  constructor(name) { this.name = name; }
  sayHi() { alert(this.name); }
}

// 클래스는 함수다.
console.log(typeof User); // function

// 정확히는 생성자 메서드와 동일하다.
console.log(User === User.prototype.constructor); // true

// 클래스 내부에서 정의한 메서드는 User.prototype에 저장된다.
console.log(User.prototype.sayHi); // console.log(this.name);

// 현재 프로토타입에는 메서드가 두 개다.
console.log(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi

 

 

class라는 키워드 없이도 클래스 역할을 하는 함수를 선언할 수 있다.

 

// class User와 동일한 기능을 하는 순수 함수를 만들어보자.

// 1. 생성자 함수를 만든다.
function User(name) {
  this.name = name;
}

// 모든 함수의 프로토타입은 'constructor' 프로퍼티를 기본으로 갖고 있기 때문에
// constructor 프로퍼티를 명시적으로 만들 필요가 없다.

// 2. prototype에 메서드를 추가한다.
User.prototype.sayHi = function() {
  console.log(this.name);
};

// 사용법:
let user = new User("John");
user.sayHi();

 

위 처럼 순수 함수로 클래스 역할을 하는 함수를 선언하는 방법과 class 키워드를 사용하는 방법의 결과는 거의 같다.

 

이 두 방법에는 중요한 차이가 몇가지 있다.

1. class로 만든 함수엔 특수 내부 프로퍼티인 IsClassConstructor : true 가 이름표처럼 붙는다.

    이것만으로도 두 방법엔 분명한 차이가 있음을 알 수 있다.

 

class User {
  constructor() {}
}

console.log(typeof User); // User의 타입은 함수이긴 하지만 그냥 호출할 수 없다
User(); // TypeError: Class constructor User cannot be invoked without 'new'

 

자바스크립트는 다양한 경우 IsClassConstructor : true를 활용한다.

클래스 생성자를 new와 함께 호출하지 않으면 에러가 발생하는데 이 때 IsClassConstructor : true 가 사용된다.

 

또 다른 차이점으로는

2. 클래스에 정의된 메서드는 열거할 수 없다.

    클래스의 prototype 프로퍼티에 추가된 메서드의 enumerable 플래그는 false 이기 때문.

    for in 으로 객체를 순회할 때, 메서드는 순회 대상에서 제외하고자 하는 경우가 많아 이 특징은 꽤 유용하다.

 

3. 클래스는 항상 엄격 모드로 실행된다. 클래스 생성자 안 코드 전체에 자동으로 엄격 모드가 적용된다.


클래스 표현식

함수처럼 클래스도 다른 표현식 내부에서 정의, 전달, 반환, 할당할 수 있다.

 

클래스 표현식을 만들어보자.

let User = class {
  sayHi() {
    console.log("안녕하세요.");
  }
};

 

 

기명 함수 표현식과 유사하게 클래스 표현식에도 이름을 붙일 수 있다.

클래스 표현식에 이름을 붙이면, 이 이름은 오직 클래스 내부에서만 사용할 수 있다.

// 기명 클래스 표현식(Named Class Expression)
// (명세서엔 없는 용어이지만, 기명 함수 표현식과 유사하게 동작한다.)
let User = class MyClass {
  sayHi() {
    console.log(MyClass); // MyClass라는 이름은 오직 클래스 안에서만 사용할 수 있다.
  }
};

new User().sayHi(); // 원하는대로 MyClass의 정의를 보여준다.

console.log(MyClass); // ReferenceError: MyClass is not defined, MyClass는 클래스 밖에서 사용할 수 없다.

getter와 setter

클래스는 getter와 setter를 지원한다.

get과 set을 이용해 user.name을 조작해보자!

class User {

  constructor(name) {
    // setter를 활성화합니다.
    this.name = name;
  }

  get name() {
    return this._name;
  }

  set name(value) {
    if (value.length < 4) {
      console.log("이름이 너무 짧습니다.");
      return;
    }
    this._name = value;
  }

}

let user = new User("성원");
console.log(user.name); // 성원

user = new User(""); // 이름이 너무 짧습니다.

 

참고로 getter와 setter는 User.prototype에 정의된다.


클래스 필드

클래스 필드라는 문법을 사용하면 어떤 종류의 프로퍼티도 클래스에 추가할 수 있다.

클래스 User에 name 프로퍼티를 추가해보자.

class User {
  name = "성원";

  sayHi() {
    console.log(`${this.name}님 안녕하세요!`);
  }
}

new User().sayHi(); // 성원님 안녕하세요!

 

 

클래스를 정의할 때 <프로퍼티 이름> = <값> 을 써주면 간단히 클래스 필드를 만들 수 있다.

클래스 필드의 중요한 특징 중 하나는 User.prototype이 아닌 개별 객체에만 클래스 필드가 설정된다는 점이다.

class User {
  name = "성원";
}

let user = new User();
console.log(user.name); // 성원
console.log(User.prototype.name); // undefined

 

 

 

 

참고 : https://ko.javascript.info/class

 

클래스와 기본 문법

 

ko.javascript.info

 

Set은 원시 값이나 객체 참조 값 등 모든 유형의 고유 값을 저장할 때 사용하는 객체다.

 

선언

let mySet = new Set();

 

add ( 데이터 넣기 )

Set에 데이터를 넣는다. 해당 값이 중복되면 데이터가 저장되지 않는다.

let mySet = new Set();

// 데이터 넣기
mySet.add(1);
mySet.add(2);
mySet.add(2); // 데이터가 중복되므로 저장되지 않는다.

 

delete ( 데이터 삭제 )

Set에서 데이터를 삭제한다. 데이터 삭제에 성공하면 true를 반환하고 실패하면 false를 반환한다.

let mySet = new Set();

// 데이터 넣기
mySet.add(1);
mySet.add(2);

// 데이터 삭제하기
mySet.delete(1); // true
mySet.delete(3); // false

 

clear ( 데이터 모두 삭제 )

Set에 저장되어 있는 데이터 전부를 삭제한다. 삭제에 성공하면 true, 실패하면 false를 반환한다.

let mySet = new Set();

// 데이터 넣기
mySet.add(1);
mySet.add(2);

// 데이터 모두 삭제하기
mySet.clear(); // true

 

Set 순회하기

let mySet = new Set();

mySet2.add(1);
mySet2.add(2);

// 데이터 순회하기
for (let item of mySet) {
  console.log(item);
}

for (let item of mySet.values()) {
  console.log(item);
}

 

 

 

참고 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Set

 

Set - JavaScript | MDN

Set 객체는 원시값이나 객체 참조 값 등 모든 유형의 고유 값을 저장할 때 사용할 수 있습니다.

developer.mozilla.org

 

+ Recent posts