Vanilla JavaScript SPA

Take!·2024년 9월 29일

JavaScript

목록 보기
7/12

Vanilla JavaScript로 SPA 만들기[0]

Core 프로젝트 구조

  • View class, Router class를 구현
  • loginView, mainView, profileView, errorView 등은 View class를 상속 받아 구현
    - loginView, mainView, profileView, errorView는 각각의 template 파일을 렌더링.

Class vs Function

아무 생각 없이 당연하다는듯이 Class로 진행을 했지만, 정작 왜 Class를 선택 했고, Function에 비해 어떤 부분이 더 이점을 가지는지 몰랐다.
반성(?)을 하는 차원에서 글을 다루고 SPA 프로젝트 진행에 대한 글쓰기를 이어나가보려고 한다.

1. 기본 사용 방법
	- 기본 사용 방법은 다음과 같다
      class TodoModel {
              constructor(data) {
                  this.todos = [];
                  this.data = data;
              }

              addData() {
                  console.log(`${data} add Data`);
              }

              add() {
                  console.log('add');
              }
          }

      export default TodoModel;

      const todoModel = new TodoModel('input');
      todoModel.addData();
- Factory Function
 	function TodoModel(data) {
     	const todos = [];
         
         function addData() {
 			console.log(`${data} addData`);
     	}

     	function add() { console.log('add'); }

         return Object.freeze({
           addData,
         });
     }
    
   export default TodoModel;
   
   
   const todoModel = TodoModel('input');
   todoModel.addData();
2. 캡슐화
	- 내부 변수 또는 감추고 싶은 함수에 접근이 가능 여부
    - 캡슐화가 안되면 _보안 이슈 가능성 농후!_
  	- 기본적으로 function은 캡슐화가 되지만, class는 캡슐화가 되지 않았었다. 그러나! nodejs 12.0.0	버전부터는 Private class fields를 사용하면 class도 캡슐화 가능!
    
	class TodoModel {
    	#todos;
        constructor(data) {
        	this.#todos = [];
            this.data = data;
        }
        //	이하 생략
    }
3. 불변성
	- 정의된 함수를 변경할 수 있는가! 를 말한다.
    - 보안을 위해 함수가 변경되지 않는 것이 좋다. (특수한 상황에 따라서 변경이 필요할 수는 있으나, 권장되는 방식은 아님!)
    - class에서는 재할당을 통해 함수 변경이 가능하나, function에서는 불가능함. 그러나 static을 사용하면 class에서 개선이 가능하지만, 인스턴스화 되지 않으므로 사용법에 주의가 필요하다.
    
class TodoModel {
	#todos;
    constructor(data) {
    	this.#todos = [];
        this.data = data;
    }
    
    addData() {
    	console.log('addData');
    }
    static add() {
    	console.log('add');
    }
}

TodoModel.add();	//	add
TodoModel.add = function() {
	console.log("a new add") 	
}	//	Invalid left-hand side in assignment
4. 상속과 구성
	- class에서는 상위 class로부터 상속을 받으면 상속 받은 모든 method를 사용해야 하지만, factory는 구성을 하기 때문에 선별적으로 사용할 수 있다.
  • class의 상속
class Person {
  eat() {
    console.log('I am eating');
  }
  breathe() {
    console.log('I am breathing');
  }    
  swim() {
    console.log('I am swimming');
  } 
}
class Wizard extends Person {
  trick() {
    console.log('I am doing a trick');
  }
}
const harry = new Wizard();
const ron = new Wizard();

// Harry can:
harry.eat();          // I am eating
harry.breathe();      // I am breathing
harry.swim();         // I am swimming
harry.trick();        // I am doing a trick

// Ron can:
ron.eat();        // I am eating
ron.breathe();    // I am breathing
ron.swim();       // I am swimming
ron.trick();      // I am doing a trick
  • function 의 구성
const Person = () => {
  return {
    eat: () => {
      console.log('I am eating');
    },
    breathe: () => {
      console.log('I am breathing');
    },
    swim: () => {
      console.log('I am swimming');
    },
  };
};
const Trick = () => {
  return {
    trick: () => {
      console.log('I am doing a trick');
    },
  };
};

const Wizard = () => {
  return {
    eat: Person().eat,
    breathe: Person().breathe,
    trick: Trick().trick,
  };
};
const Muggle = () => {
  return {
    eat: Person().eat,
    breathe: Person().breathe,
    swim: Person().swim,
  };
};

// Harry can:
const harry = Wizard();
harry.eat();            // I am eating
harry.breathe();        // I am breathing
harry.trick();          // I am doing a trick

// Ron can:
const ron = Muggle();
ron.eat();            // I am eating
ron.breathe();        // I am breathing
ron.swim();           // I am swimming
5. this
	- class에서는 this 문법을 사용할 수 있으나 factory function에서는 this 문법을 사용할 수 없다!!!
    - this 문법을 사용할 때에는 컨텍스트 손실 문제가 발생할 수 있기 때문에 사용에 유의가 필요하다.
    
  • Context 손실 문제란?
    - this가 기대한 객체를 참조하지 않을 때 발생하는 문제, 자바스크립트의 함수는 호출 방식에 따라 this가 결정된다. 이러한 문제는 주로 콜백함수나 이벤트 핸들러를 사용할 때 빈번하게 발생된다. => bind method를 사용하여 this값을 명시적으로 지정해주거나, 화살표 함수 이용 권장.
class TodoModel() {
	constructor() {
    	this.todos = [];
    }
    reload() {
    	setTimeout(function log() {
        	console.log(this.todos)
        }, 0);
    }
}

todoModel.reload();		//	undefined
6. 메모리
	- class의 모든 메서드는 프로토 타입 객체에서 한 번 생성되고 모든 인스턴스에서 공유된다. 그러나! 여러 동일한 객체를 만들 때 function의 경우 많은 메모리 비용이 필요하다.
    
7. 결론
	- 메모리 사용을 고려한 프로젝트인가 아니면 보안성이 우선시되는 프로젝트인가에 따라 다를 듯 하다.(class도 보안 요소 추가 가능)
    

이 글이 누군가에게는 도움이 되길 바라며...

profile
확장성 있는 설계와 유지보수가 용이한 클린 코드 지향하는 개발자입니다.

0개의 댓글