๐ŸŽ„ ์„ฑ์žฅ์ผ์ง€ 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)์„ ์‹œ๋„ํ•œ ๊ฒƒ
  • ๊ณต์‹๋ฌธ์„œ์— ์–ด๋Š์ •๋„ ์ต์ˆ™ํ•ด์ง„ ๊ฒƒ
  • ์ปดํฌ๋„ŒํŠธ ํ•ฉ์„ฑ!!! ์˜ค์˜ˆ~

์˜ค๋Š˜์˜ ์•„์‰ฌ์šด ์ 

  • ๋ ˆ์ด์•„์›ƒ์ชฝ์€ ์ „๋ถ€ ๋‹ค ์™„๋ฃŒํ•˜๊ธธ ๋ฐ”๋ž๋Š”๋ฐ ์•„์ฃผ ๋‹ค ํ•˜์ง„ ๋ชปํ–ˆ๋‹ค!!!