본문 바로가기
코딩과 알고리즘

node.js express | 클래스? (Class)

중학교 영어시간에 이런 예문을 보신 적이 있으신가요?
We were in the same class at school. ( 우리는 학교에서 같은 반이었다. )

영어회화에서 class 는 대부분 학급, 수업 등의 의미로 사용되는데요.
컴퓨터 언어에서는 살짝 의미가 다릅니다.
근본적으로는 묶어준다는 점에서 동일한 개념이긴 하지만요.

오늘은 컴퓨터 언어에서의 클래스에 대해 살펴보도록 하겠습니다.

참고로 지난 시간에는 node.js 에서 기다려주는 기능, await 에 대해서 살펴보았습니다.

https://itadventure.tistory.com/445

 

node.js express | 템플릿쪽지함 #8. 기다려! await!

지난 스토리에서는 mysql2 모듈을 사용할 때 프로미스에 대해서 알아보았는데요. https://itadventure.tistory.com/444 node.js express | #7. mysql2 프로미스 지난 스토리에서 다루었던 쪽지 템플릿에는 MYSQL..

itadventure.tistory.com

 

node.js 에서 클래스(Class)란 무엇일까요?


다른 언어도 마찬가지지만 개념은 간단합니다. 설계도입니다.

예를 들어 컴퓨터를 만들 수 있는 설계도가 있다고 칩시다.
그러면 재료와 만들수 있는 시설이 있다면 컴퓨터를 얼마든지 찍어낼 수 있겠지요?

설계도가 바로 클래스입니다.

그리고 만들어낸 컴퓨터오브젝트(Object)라고 부르는데요.
컴퓨터의 설계도는 1개지만 그로 인해 컴퓨터는 무한으로 만들어낼 수 있는 것이지요.

컴퓨터에는 여러가지 부속들이 있겠지요?
- 키보드, 마우스, CPU. 메모리, SSD 드라이브 등등..

컴퓨터로 할 수 있는 일도 여러가지가 있겠지요?
- 인터넷으로 내 마음에 드는 상품 쇼핑을 한다.
- 온라인 게임을 한다.
- 넷플릭스를 보며 영어리스닝 공부를 한다.
- 힐링 음악을 들으며 여가를 즐긴다.

이러한 부품이나 기능들은 모두 설계도 안에 들어 있다고 생각해 보도록 하죠.
이 설계도를 이용해 찍어낸 컴퓨터는 이러한 부품과 기능이 모두 내장되어 있습니다.

이러한 개념이 바로 클래스와 오브젝트입니다.

개념으로만 설명드리면 이해가 어려우실 테니 실제 코딩으로 예시를 들어보도록 하지요.
지난 번에 만들었던 쪽지함을 클래스로 구성해 보도록 합시다.

 

클래스 생성과 오브젝트 생성

클래스와 오브젝트를 만드는 방법은 아래와 같은데요.
여기서 클래스이름란은 영문 또는 언더바 ( _ ) 기호를 사용하셔야 합니다.

class 클래스이름 {
    : // 이 곳에 클래스를 구성하는 코드를 넣습니다.
}
const 오브젝트이름 = new 클래스이름();


먼저 메모 클래스 이름을 memoClass 라고 정해주도록 합시다.

class memoClass {
}


그리고 이 클래스를 이용하여 오브젝트를 생성해주면 되는데요.
코드는 아래와 같습니다. memoClass 구조의 설계도를 새로 만들어 memo 라는 오브젝트를 추가해준다는 의미입니다.

const memo = new memoClass();


참고로 설계도는 재사용 가능합니다.
만약 쪽지함2를 만들고 싶다면, 아래와 같이 하나의 코드를 더 적어주시면 됩니다.
그러면 memo 와는 다른 또 하나의 쪽지함 오브젝트 memo2가 생겨나는 것이지요.

const memo2 = new memoClass();


이렇게 쪽지함 클래스와 오브젝트를 생성하는 기본틀의 소스가 준비되었는데요.
이제 여기에 부속을 심어주도록 합시다.

 

클래스 생성자 함수

 

우선 쪽지함 안에는 쪽지가 들어 있어야 겠지요?
매번 MYSQL 데이터베이스에서 직접 불러와도 되긴 하겠지만
여기서는 맨 처음에 한번만 데이터베이스에서 쪽지를 가지고 와 저장하도록 합시다.

그러러면 쪽지함 클래스 안에 쪽지를 보관할 변수를 정의해야 합니다.
코드는 아래와 같은데요.

class memoClass {
    constructor(){
        this.list=Array();
    }
}


constructor() 란 생성자 함수라고 해서 클래스를 통해 오브젝트를 만들 때 자동으로 실행되는 함수입니다.
바로 아래 코드가 실행되는 순간에 동시에 실행됩니다.

const memo2 = new memoClass();


constructor() 함수 내에는 아래와 같은 코드가 들어 있는데요.

constructor(){
    this.list=Array();
}

여기서 this는 클래스로 생성된 오브젝트 자신을 말합니다.
만일 클래스로 2개의 오브젝트를 만들었다면 이 코드가 실행되는 시점에
각각의 오브젝트 자신를 의미하는 것이지요.

그리고 this.list 는 오브젝트 내 list 라는 이름의 변수를 의미하는데요.
원래부터 이 변수가 들어있는건 아닙니다.
node.js 는 다른 컴퓨터 언어와는 다르게 미리 오브젝트 안에 변수를 정의할 필요가 없습니다.
그냥 원래 있었던 것처럼 사용하면 되는 자유로운 코딩이 가능합니다.

이어서 Array() 를 이용하여 내용이 전혀 들어있지 않은 공백 배열을 만들어 this.list 변수에 입력해 줍니다.

this.list=Array();

 

이 코드는 사실상 왼쪽과 오른쪽이 같다라는 뜻이 아니고
오른쪽 내용을 왼쪽에 담는다는 의미를 담고 있습니다.

this.list ← Array(); // Array() 로 배열을 만들어 this.list 에 담기


이렇게 오브젝트 내에 list 라는 변수가 추가되었습니다,
그러면 이제 쪽지를 불러오는 기능에 대한 함수를 넣어보도록 할까요?

 

쪽지 불러오기 함수 구성

 

함수 또한 기능은 클래스 안에 넣고, 사용은 오브젝트에서 하면 되는데요.
loading() 이라는 함수를 만들도록 하겠습니다.
그 방법은 아래와 같습니다.

// 클래스 내에 함수 정의
class 클래스명 {
     :
	함수명(파라미터){		
		함수처리 내용
	}
     :
}

// 클래스로 오브젝트를 생성
const 오브젝트명 = new 클래스명();

// 오브젝트에서 함수를 사용
오브젝트명.함수명(파라미터);


클래스 안에 쪽지를 불러오는 함수는
클래스 내에 아래와 같이 작성하거나 또는

loading(db){		
  db.query(
    'SELECT x, y, r, memo FROM memolist'
  ).
  then((data)=>{
    let result=data[0];

    for(var i=0;i<result.length;++i)
      this.list.push({
        x: result[i].x, 
        y: result[i].y, 
        r: result[i].r, 
        memo: result[i].memo
      });
    console.log(this.list);
    console.log(
      "[ " + result.length 
      + " ] 개의 쪽지가 로딩되었습니다."
    );
  });
}


아래와 같이 작성하면 되는데요.
지난 시간에 다루었던 await 기다려! 방식이고, 코드 흐름 상 이쪽이 더 이해가 수월하실 겁니다.
이 코드로 설명드리도록 하겠습니다.

async loading(db){		
  try {
    const data = await db.query(
    'SELECT x, y, r, memo FROM memolist'
    );
    let result=data[0];

    for(var i=0;i<result.length;++i)
      this.list.push({
        x: result[i].x, 
        y: result[i].y, 
        r: result[i].r, 
        memo: result[i].memo
      });
    console.log(this.list);
    console.log(
      "[ " + result.length 
      + " ] 개의 쪽지가 로딩되었습니다."
    );
  } catch (err) {
    console.log(err.message);
  }
}


우선 함수 안에서 await 를 사용하시려면 반드시 함수가 async 로 정의되어야 하는데요.
아래와 같습니다.

async 함수명()  //  await 를 사용하려면 async 정의 필수
{
    :
  await 프로미스함수();
    :
}


async 로 함수를 정의할 경우 이점이 있습니다.
바로 그것은 async 함수 내에서 코드는 모두 순서대로 실행된다는 것입니다.
물론 이 것은 기본 옵션이고, 속도를 위해 원래 방식대로 혼용도 가능합니다.

먼저 아래는 프로미스 함수를 await 방식으로 기다리게 작동하게 하는 함수를 정의하는 코드입니다.

async loading(db){
     :
}


함수를 실행할 때 db 모듈을 파라미터로 전달받는데요.
db 는 아래와 같이 사전에 정의된 모듈을 사용합니다.

 

const db = require('./db');


그리고 함수 내에서 아래 코드가 보이는데요.
try { }  catch { } 란 try 코드영역을 먼저 실행하고 오류가 발생할 경우 오류 처리를 하는 catch 코드영역을 실행해주는 예외 처리 코드입니다.
만일 try 코드 영역에서 오류가 발생하지 않으면 catch 코드 영역은 실행되지 않습니다.

async loading(db){
  try {
    : // try 코드 영역
  } catch (err) {
    : // catch 코드 영역
  }
}


try 코드 영역에서는 첫번째로 MYSQL 데이터베이스에서 쪽지를 모두 불러오는 쿼리를 실행하고, 그 결과를 받아올 떄까지 잠깐 대기합니다.
await 를 프로미스 함수 앞에 써주면 프로미스 함수의 실행이 끝날때까지 기다려주거든요.

try {
  const data = await db.query(
    'SELECT x, y, r, memo FROM memolist'
  );


data[0]과 data[1] 2개의 값이 배열로 반환되는데요
쪽지내용들은 모두 data[0]에 들어 있습니다.
result 에 data[0] 값을 받아옵니다.

let result=data[0];


모든 쪽지를 쪽지함 오브젝트에 보관하기 위해, 쪽지배열을 반복문을 돌리면서

for(var i=0;i<result.length;++i)


쪽지를 하나 하나 배열에 추가해 줍니다.
그러면 쪽지함 클래스의 list 변수에는 쪽지목록이 배열로 차곡 차곡 저장됩니다.

for(var i=0;i<result.length;++i)
  this.list.push({
    x: result[i].x, 
    y: result[i].y, 
    r: result[i].r, 
    memo: result[i].memo
  });


그리고 그 결과를 서버의 콘솔 화면에 바로 출력해 주는데요.

console.log(this.list);
console.log(
  "[ " + result.length 
  + " ] 개의 쪽지가 로딩되었습니다."
);

서버에 아래와 같은 결과 화면이 출력되게 합니다.


하지만 만약 이 코드들 중 한군데라도 오류가 발생하는 경우라면,
catch 코드 영역이 실행되는데요.

} catch (err) {
  console.log(err.message);
}


코드를 잠깐 바꿔서 일부로 오류를 내봤습니다.
SQL 문을 아래와 같이 바꾸면,

'SELECT x, y, r, memo, z FROM memolist'

이런 결과 화면을 보여주지요. z 라는 컬럼 항목이 없다는 오류 메시지를 의미하지요.

이 것으로 메모클래스의 loading() 함수 설계가 끝났습니다만, 
loading()함수는 자동으로 실행되지는 않습니다.
오브젝트를 생성한 다음, 오브젝트에서 해당 함수를 실행하는 순간에 작동하는데요.
아래 코드가 바로 이 함수를 실행하는 부분입니다.

const memo = new memoClass();
memo.loading(db); // 이 때 loading() 함수가 실행


추가로 알아두실 부분은, 클래스 내의 함수(Function) 와 변수(variable)는 대부분 전용 명칭이 있는데요.
함수는 메소드(Method:)라고 보통 부르고, 변수는 프로퍼티(property) 또는 한글로 속성(변수)라고도 부른다는 점입니다.
쉬운 말로는 클래스함수, 클래스변수라고도 부르기도 하니 다른 서적이나 인터넷 게시글, 영상을 보실 때 혼동 없으시기 바랍니다.

 

샘플 전체소스



이 샘플 코드의 전체 소스는 아래와 같습니다.

const express=require('express');
const bodyParser = require('body-parser');
const ejs=require("ejs");
const app=express();
const db = require('./db');

class memoClass {
  constructor(){
    this.list=Array();
  }

  async loading(db){		
    try {
      const data = await db.query(
      'SELECT x, y, r, memo FROM memolist'
      );
      let result=data[0];

      for(var i=0;i<result.length;++i)
        this.list.push({
          x: result[i].x, 
          y: result[i].y, 
          r: result[i].r, 
          memo: result[i].memo
        });
      console.log(this.list);
      console.log(
        "[ " + result.length 
        + " ] 개의 쪽지가 로딩되었습니다."
      );
    } catch (err) {
      console.log(err.message);
    }
  }
}
const memo = new memoClass();
memo.loading(db);


이와 같이 쪽지함에 쪽지를 불러와 저장하는 부분을 다루어 보았습니다.
다음 스토리에서는 웹페이지에서 쪽지를 추가하는 부분을
클래스 함수에 포함시키고 사용하는 방법, 그리고 클래스를 모듈화시키는 부분을 다루어보도록 하겠습니다.

독자분의 마음을 움직이는 글이었다면 공감( ) 버튼을,
소통하시고 싶으시면 댓글 남겨주세요 :)

오늘도 여기까지 읽어주셔서 감사합니다.


다음 스토리 : https://itadventure.tistory.com/458

 

node.js express 클래스 파일 모듈화

프로그램은 쪼갤수록 단순해진다! 이 개념을 아시나요? 지난 시간에 다루었던 클래스도 예외가 아닌데요. 이번 시간에는 클래스를 모듈로 분리하는 방법과 쪽지 추가 기능에 대해 점진적인 개

itadventure.tistory.com