230424(์)
๐ ์ฑ์ฅ์ผ์ง 4.0
์ฑ
ํ๋ณตํ ์ด๊ธฐ์ฃผ์์(์จ์ธ ๋ค์ด์ด)
์ ๋ด์ฉ์ ์๊ทน๋ฐ์ ์์ํ๋ ์๋ฐํ ์ฑ์ฅ๊ธฐ๋ก
์ด์์๋ ๊ฝ๊ณผ ์ฃฝ์ ๊ฝ์ ์ด๋ป๊ฒ ๊ตฌ๋ณํ๋๊ฐ?
์ฑ์ฅํ๊ณ ์๋ ๊ฒ์ด ์ด์ ์๋ ๊ฒ์ด๋ค.
์๋ช ์ ์ ์ผํ ์ฆ๊ฑฐ๋ ์ฑ์ฅ์ด๋ค!
๐ณ (1.0)ํค์๋
์ต๋ํ ๊ฐ๋จํ๊ฒ ์ ๋ฆฌ, ์ถํ์ ๋ณด๋ฉด์ ์ค์ค๋ก ์ค๋ช
๐ (2.0)๊ฒฝํ ์์ฃผ๋ก
๋จ์ ์ ๋ณด๋ฅผ ์ ๋ฌํ๊ธฐ๋ณด๋ค ๋ฌด์์ ๋ฐฐ์ ๊ณ ์ด๋ป๊ฒ ํด๊ฒฐํ๋์ง ์งง๊ณ ๊ฐ๋จํ๊ฒ ์์ฑ
โ๏ธ (3.0)์ ํด์ง ํ ํ๋ฆฟ์ ๋ง์ถฐ์
ํค์๋, ๊ฒฝํ ๋ชจ๋ ์ข๋ค. ๋ค๋ง ๋งค์ผ ์์ฑํ๊ธฐ๋ก ๋ง์ ๋จน์๋งํผ ํต์ฌ๋ง ๊ฐ๊ฒฐํ๊ฒ ์ ๋ฆฌํ ์ ์๊ฒ ํ ํ๋ฆฟ์ ์์ฑ
(3.1)230102๋ถํฐ ์์๋๋ ํ์ต์ ๊ดํ ๋ด์ฉ ์ถ๊ฐ
(3.2)230313๋ถํฐ ์ข๋ ๊ฒฝํ, ๊ฐ์ ์์ฃผ์ ๋ด์ฉ๋ ๋ด๊ธฐ!
๐พ (4.0)ํ์ต ํค์๋์์ ์ต๋ํ ๊ฐ๋จํ ์ ๋ณด ์ ๊ณต, ๊ณ ๋ฏผ์์ ๋ด ๊ฒฝํ์ ์์ธํ ์ ์!
๐ง ๊ณ ๋ฏผ ์ฌํญ
๐ ์ค๋์ ํ์ต ํค์๋
- ๋ฆฌํฉํ ๋ง
๐ฅณ ํ์ต ๋ด์ฉ
๋ฆฌํฉํ ๋ง ์ฑ๊ณต?!
๋๋์ดโฆ ๋ช์ผ๋์ ํผ์ ๋๋๊ฑฐ๋ฆฌ๋ ๋ฆฌํฉํ ๋ง์ ์ฑ๊ณตํ๋ค!!! ์์ฃผ ๊ฐ๋จํ Header๋ง ๊ธฐ์กด๊ณผ ๋น๊ตํด๋ณด์๋ฉด Header๋ Model, Component, View ์ด 3๊ฐ์ง๋ก ๊ตฌ์ฑ๋์ด์๋ค.
Model์ ํฐ ๋ณํ๊ฐ ์๊ธฐ์ View์ Component๋ง ์ดํด๋ณด๋ ค ํ๋ค.
๋ฆฌํฉํ ๋ง ์ ์ฝ๋
View
import { State } from '@custom-types/types';
import { AbstractView } from '@custom-types/abstracts.js';
export class HeaderView extends AbstractView {
constructor() {
super();
}
protected setWrapper() {
this._wrapperElement.innerHTML = `<header class="h-1/6 bg-green-100 border border-green-500 text-3xl text-gray-500 grid place-content-center">Header</header>`;
}
render(state: State) {
return;
}
}
Component
import { Props, State } from '@custom-types/types';
import { Component } from '@custom-types/interfaces';
import { HeaderModel } from '@components/header/HeaderModel.js';
import { HeaderView } from '@components/header/HeaderView.js';
export class HeaderComponent implements Component {
private _model: HeaderModel;
private _view: HeaderView;
constructor(props?: Props) {
this._model = new HeaderModel();
this._view = new HeaderView();
}
get element() {
return this._view.element;
}
get state() {
return this._model.state;
}
private setState(state: State) {
this._model.setState(state);
this._view.render(this._model.state);
}
attachTo(component: Component, position: InsertPosition = 'beforeend') {
component.element.insertAdjacentElement(position, this.element);
}
}
์์์ ๋ฌธ์ ๋ View์ render ๋ฉ์๋๊ฐ ๋จ์ํ ์ด๋ฏธ ๋ง๋ค์ด์ง ํ ํ๋ฆฟ์ ์ด๋ฒคํธ๋ฅผ ๋ถ์ด๊ฑฐ๋ dom api๋ฅผ ํตํ ์ง์ ์ ๊ทผ์ผ๋ก ๋ฐ๋ state๋ฅผ ์ ๋ฌํ๊ณ ui์ ๋ชจ์ต์ด ๋ณํ๋ค๋ ์ ์ด๋ค. ๋, Component์์ ๊ตฌํ๋ attachTo๋ผ๋ ๋ฉ์๋๋ ๊ฐ๋ ์ฑ์ ์ข์ง๋ง ๋ถ๋ชจ์ ํ๋ฒ element ํํ๋ก ๋ถ์ฌ๋ฒ๋ฆฌ๋ฉด ์ดํ์ ์ด element์ innerHTML ํํ๋ก ์๋ก์ด state๋ฅผ ๋๊ธด template literal์ ์ ๋ฌํ ์ ์๊ฒ ๋๋ค.(๋ถ๋ชจ์ ๋ถ์ธ ์๊ฐ ์ด๋ฏธ ์ ์ ์ธ element๊ฐ ๋ถ์ด๋ฒ๋ฆฌ๊ณ ๊ทธ ๋ค์ ๊ฐ์ ๋ฐ๊พผ๋ค๊ณ ๋ถ๋ชจ์ ๋ถ์ element๊ฐ ๋ณํ์ง ์๊ธฐ ๋๋ฌธ์ด๋ค.) ๊ทธ๋ฆฌ๊ณ ๊ฐ์ฅ ํฐ ๋ฌธ์ ๋ ์ฒ์ ๋ด๊ฐ ์ค๊ณํ๋ ์ปดํฌ๋ํธ๋ง๋ค Model, View๋ฅผ ๊ฐ๊ณ ์๋ ๋ฆฌ์กํธ์ค๋ฌ์ด ๋๋์ด ์๋๋ผ๋ ๊ฒ์ด๋ค. setState๊ฐ ์ผ์ด๋ ๋๋ง๋ค render ๋ฉ์๋๊ฐ ์คํ๋๋ฉด์ ์๋ก์ด state๊ฐ ๋ฐ์๋ ui๋ก ๋ณ๊ฒฝ๋์ด์ผ ํ๋๋ฐ ์ ์ฝ๋๋ ์์ ๋งํ ๋ฌธ์ ๋ค๋ก ๋์ง ์๋๋ค.
๊ทธ๋ผ ์ด์ ์๋ก์ด ์ฝ๋๋ฅผ ์ดํด๋ณด์..!
๋ฆฌํฉํ ๋ง ํ ์ฝ๋
View
import { State } from '@custom-types/types';
import { TempAbstractView } from '@custom-types/abstracts.js';
export class HeaderView extends TempAbstractView {
constructor($target: HTMLElement) {
super($target);
}
template(state: State) {
return `<header class="h-full bg-green-100 border border-green-500 text-3xl text-gray-500 grid place-content-center">Header</header>`;
}
render(state: State) {
this.$target.innerHTML = this.template(state);
this.addChildren(state);
this.setEvents(state);
}
setEvents(state: State) {
return;
}
addChildren(state: State) {
return;
}
}
Component
import { Props, State } from '@custom-types/types';
import { TempComponent } from '@custom-types/interfaces';
import { HeaderModel } from '@components/header/HeaderModel.js';
import { HeaderView } from '@components/header/HeaderView.js';
export class HeaderComponent implements TempComponent {
private _model: HeaderModel;
private _view: HeaderView;
$target: HTMLElement;
constructor(targetElement?: HTMLElement, props?: Props) {
this.$target = targetElement as HTMLElement;
this._model = new HeaderModel();
this._view = new HeaderView(this.$target);
}
get state() {
return this._model.state;
}
private setState(state: State) {
this._model.setState(state);
this._view.render(this._model.state);
}
}
์์ Header ์ปดํฌ๋ํธ๋ ๋ฐ๋ก ์์ ์ปดํฌ๋ํธ๊ฐ ์์ด์ props๋ฅผ ์ ๋ฌํ๊ฑฐ๋ ์์์ ๋ถ์ผ ์ผ์ด ์๋ค. ์์์ ํต์ฌ์ ๋ถ๋ชจ(target)์ ์ ๋ฌํ์ฌ ์์์์ ๋ถ๋ชจ์ element์ ์ ๊ทผ์ด ๊ฐ๋ฅํ๊ฒ ํจ์ผ๋ก์จ innerHTML๋ก ์๋ก์ด state์ ๋ฐ๋ฅธ ui๋ฅผ ๋ณ๊ฒฝํ ์ ์๊ฒ ํ ์ ์ด๋ค.
์์ ๋ด์ฉ๋ค์ ์ถํ์ ๋ ์์ธํ ๊ธธ๊ฒ ๋ค๋ค๋ณผ ์์ ์ด๋ค.(๋ฆฌํฉํ ๋ง ์ ๋ง ํ๋ค์๋คโฆใ ๋ฌผ๋ก ์ด์ ์์ผ ์์ผ๋ฉด์ ํ ์ ์๊ฒ ๋์์ง๋ง..!)