230316(๋ชฉ)
๐ ์ฑ์ฅ์ผ์ง 3.2
์ฑ
ํ๋ณตํ ์ด๊ธฐ์ฃผ์์(์จ์ธ ๋ค์ด์ด)
์ ๋ด์ฉ์ ์๊ทน๋ฐ์ ์์ํ๋ ์๋ฐํ ์ฑ์ฅ๊ธฐ๋ก
์ด์์๋ ๊ฝ๊ณผ ์ฃฝ์ ๊ฝ์ ์ด๋ป๊ฒ ๊ตฌ๋ณํ๋๊ฐ?
์ฑ์ฅํ๊ณ ์๋ ๊ฒ์ด ์ด์ ์๋ ๊ฒ์ด๋ค.
์๋ช ์ ์ ์ผํ ์ฆ๊ฑฐ๋ ์ฑ์ฅ์ด๋ค!
๐ณ ํค์๋ (1.0)
์ต๋ํ ๊ฐ๋จํ๊ฒ ์ ๋ฆฌ, ์ถํ์ ๋ณด๋ฉด์ ์ค์ค๋ก ์ค๋ช
๐ ๊ฒฝํ ์์ฃผ๋ก (2.0)
๋จ์ ์ ๋ณด๋ฅผ ์ ๋ฌํ๊ธฐ๋ณด๋ค ๋ฌด์์ ๋ฐฐ์ ๊ณ ์ด๋ป๊ฒ ํด๊ฒฐํ๋์ง ์งง๊ณ ๊ฐ๋จํ๊ฒ ์์ฑ
โ๏ธ ์ ํด์ง ํ ํ๋ฆฟ์ ๋ง์ถฐ์ (3.0)
ํค์๋, ๊ฒฝํ ๋ชจ๋ ์ข๋ค. ๋ค๋ง ๋งค์ผ ์์ฑํ๊ธฐ๋ก ๋ง์ ๋จน์๋งํผ ํต์ฌ๋ง ๊ฐ๊ฒฐํ๊ฒ ์ ๋ฆฌํ ์ ์๊ฒ ํ ํ๋ฆฟ์ ์์ฑ
(3.1) 230102๋ถํฐ ์์๋๋ ํ์ต์ ๊ดํ ๋ด์ฉ ์ถ๊ฐ
(3.2) 230313๋ถํฐ ์ข๋ ๊ฒฝํ, ๊ฐ์ ์์ฃผ์ ๋ด์ฉ๋ ๋ด๊ธฐ!
๐ ์ค๋์ ํค์๋
์ปดํฌ๋ํธ ํฉ์ฑํ์ฌ ๋ ํฐ ์ปดํฌ๋ํธ ๋ง๋ค๊ธฐ(feat. TS, Vanilla Extract)
๋จผ์ ์๋์ ๊ฐ์ด Base ์ญํ ์ ํด์ฃผ๋ component๋ฅผ ๋ง๋ค์ด์ค๋ค. ์ด component๋ ์ ๋ฌ๋ฐ์ html string์ element ํํ๋ก ๊ฐ๊ณ ์๊ณ
๋ถ๋ชจ element์ ์ํ๋ ์์น์ ์ค์ค๋ก๋ฅผ ์์ element๋ก ๋ฃ์ ์ ์๋ attachTo
๋ฉ์๋๋ฅผ ๊ฐ๊ณ ์๋ค.
export interface Base {
attachTo(parent: HTMLElement, position?: InsertPosition): void;
}
export class BaseComponent<T extends HTMLElement> implements Base {
protected readonly element: T;
constructor(htmlString: string) {
const template = document.createElement('template');
template.innerHTML = htmlString;
this.element = template.content.firstElementChild! as T;
}
attachTo(parent: HTMLElement, position: InsertPosition = 'afterbegin') {
parent.insertAdjacentElement(position, this.element);
}
}
์์ Base๋ฅผ ๋ฐํ์ผ๋ก TextComponent๋ฅผ ๊ตฌํํ๋ค.
import { BaseComponent } from '../Base';
import { TextComponentStyle } from '../../../style/components/basic/TextComponent.css';
export class TextComponent extends BaseComponent<HTMLSpanElement> {
constructor(
text: string,
color: string = '',
fontSize: string = '',
fontWeight: string = '',
) {
super(`<span class='${TextComponentStyle}'>${text}</span>`);
this.element.style.color = color;
this.element.style.fontSize = fontSize;
this.element.style.fontWeight = fontWeight;
}
}
์ด ๋, vanilla extract์ผ๋ก ์์ฑ๋ TextComponent.css.ts
์ ์๋์ ๊ฐ๋ค.
import { style } from '@vanilla-extract/css';
export const TextComponentStyle = style({
display: 'block',
color: 'var(--color-white)',
fontSize: 'var(--font-md)',
fontWeight: 'var(--weight-regular)',
textAlign: 'center',
});
์์ ๋ณ์๋ฅผ component์ class์ ์ ๋ฌํด์ฃผ๋ฉด ํด๋น style๋ค์ด ์ ์ฉ๋๋ค.
์ด์ ๊ฐ๋จํ(์ ๋ง ์์ ๋จ์์) ์ปดํฌ๋ํธ๋ ๊ตฌ์ฑํ ์ ์๊ฒ ๋์๋ค. ์ด๋ฅผ ๋ฐํ์ผ๋ก ๊ฐ component๋ฅผ ํฉ์ฑํ์ฌ ๋ ํฐ navbar-main component๋ฅผ ๊ตฌํํ๋ค.
import { BaseComponent } from '../../Base';
import { ImageComponent } from '../../basic/ImageComponent';
import { SearchBarComponent } from './SearchBarComponent';
import { TwoRowTextComponent } from './TwoRowTextComponent';
import { SymbolTextComponent } from '../SymbolTextComponent';
import { NavBarMainComponentStyle } from '../../../../style/components/navbar/main/NavBarMainComponent.css';
export class NavBarMainComponent extends BaseComponent<HTMLElement> {
constructor() {
super(`<section class='${NavBarMainComponentStyle}'></section>`);
const logo = new ImageComponent(
'assets/nav-bar/logo.svg',
'6rem',
'2.5rem',
);
const shippingAddress = new TwoRowTextComponent('๋ฐฐ์ก์ฒ', '๋ํ๋ฏผ๊ตญ');
const searchBar = new SearchBarComponent();
const nation = new SymbolTextComponent('assets/nav-bar/flag-un.svg', 'UN');
const login = new TwoRowTextComponent('์๋
ํ์ธ์, ๋ก๊ทธ์ธ', '๊ณ์ ๋ฐ ๋ชฉ๋ก');
const myPage = new TwoRowTextComponent('๋ฐํ', '& ์ฃผ๋ฌธ');
const cart = new SymbolTextComponent('assets/nav-bar/cart.svg', '์ฅ๋ฐ๊ตฌ๋');
cart.attachTo(this.element);
myPage.attachTo(this.element);
login.attachTo(this.element);
nation.attachTo(this.element);
searchBar.attachTo(this.element);
shippingAddress.attachTo(this.element);
logo.attachTo(this.element);
}
}
์์งํ ์์ง๋ ๋ฆฌํํ ๋งํด์ผํ ์์๋ค์ด ๋ณด์ด์ง๋ง, ์์ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค๊ณ ์ ์ด๋ป๊ฒ ํฉ์ฑํ ์ง ๊ณ์ ๊ณ ๋ฏผํ๋์ง๋ผโฆ ๋๋ฌด ๊ธฐ๋ปค๋ค ใ
ใ
ใ
์ง์ง ๊ฐ๊ฒฉโฆ
NavBarMainComponent์ style์ ์๋์ ๊ฐ์ด ๊ตฌํํ๋ค.
import { style } from '@vanilla-extract/css';
export const NavBarMainComponentStyle = style({
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
width: '100%',
height: '3.5rem',
padding: '.5rem 1rem',
backgroundColor: 'var(--color-black)',
});
์ด๋ ๊ฒ ํ๋ํ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค์ด์ ํฉ์ฑํ๋ ์ค์ด๋ค. ์ด์ ๋ค์ ๊ณ ๋น(?)๋ event์ ๊ด๋ จ๋ ๋ถ๋ถ์ผํ ๋ฐโฆ ์ด๊ฒ ๋ ๊ณ ๋ฏผ์ด๋ค. ์ด event์ ๊ด๋ จ๋ ๋ถ๋ถ๋ component๋ก ๋ง๋ค์ด์ ์ฒ๋ฆฌํ๋์ง, ์๋๋ฉด ๊ทธ๋ฅ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ component์์ ๋ฐ๋ก ์ฒ๋ฆฌํ๋์ง..! ์๋๋ฉด event๋ฅผ ๋ณ์๋ก ์ ๋ฌํด์ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ๋ ์์ ๊ฒ ๊ฐ๋ค! ์ด ๋ถ๋ถ์ ์ฒ์ฒํ ์ด๋ฒ์ฃผ๊น์ง ์ ๋ถ ์๋ฃํด์ผ๊ฒ ๋ค.
์ฐธ๊ณ
๐ ์์ฝ ๋ฐ ํ๋ฃจ ๊ฐ๋จ ํ๊ณ
์ง์ง ์กฐ๊ธ์ฉ ์์ฃผ ์ฒ์ฒํ ๊ฐ์ด ์จ๋ค..! ์ปดํฌ๋ํธ ๊ธฐ๋ฐ ์ค๊ณ๊ฐ ์ฝ์ง๋ ์๊ณ ์ง๊ธ ์ด๊ฒ ์ ๋๋ก ๊ฐ๊ณ ์๋๊ฑด์ง๋ ์กฐ๊ธ ํท๊ฐ๋ฆฌ์ง๋งโฆ! ๋๋ฌด ์ฌ๋ฏธ์๋คใ ใ ใ ใ ใ ์ผ๋จ ํ์คํ component๋ ๊ฒฐ๊ตญ ํจ์์ธ์ง๋ผ, ํจ์๋ค์ ๋ง๋ค์ด์ ์น์ ๊ตฌ์กฐ๋ฅผ ์ง๋ค๋ณด๋ ๋ญ๊ฐ ์ฌ์ฌ์ฉ์ฑ๊ณผ ๋ถ๋ฆฌ๋๊ฐ ๋์์ง๋ ๊ธฐ๋ถ์ด ๋ค์ด์ ๋๋ฌด ์ข๋ค. ๊ทธ๋ฆฌ๊ณ ์ ์ฐจ ์๋ก ์ ํ๋ ๊ฒ๋ค๋ ๊ณต์๋ฌธ์๋ฅผ ํตํด์ ๋ด๊ฐ ํ๋ํ๋ ์ฐพ์๊ฐ๋ฉฐ ๊ตฌํํ๊ณ ์๊ธฐ์ ๋ ์๋ฏธ์๋ค๊ณ ๋๊ปด์ง๋ค.
์ค๋์ ์ํ ์
- ์๋ก์ด ๊ฒ(vanilla extract, ts component)์ ์๋ํ ๊ฒ
- ๊ณต์๋ฌธ์์ ์ด๋์ ๋ ์ต์ํด์ง ๊ฒ
- ์ปดํฌ๋ํธ ํฉ์ฑ!!! ์ค์~
์ค๋์ ์์ฌ์ด ์
- ๋ ์ด์์์ชฝ์ ์ ๋ถ ๋ค ์๋ฃํ๊ธธ ๋ฐ๋๋๋ฐ ์์ฃผ ๋ค ํ์ง ๋ชปํ๋ค!!!