์น ์ปดํฌ๋ํธ๋ฅผ ์ํ ๊ฒฉ๋ฆฌ๋ ์ปดํฌ๋ํธ ํ ์คํธ ํ๋ ์์ํฌ๋ฅผ ํ์ํ์ธ์. ๋ชจ๋ฒ ์ฌ๋ก์ ๋๊ตฌ๋ฅผ ํตํด ํ์ง์ ํฅ์์ํค๊ณ ๋ฒ๊ทธ๋ฅผ ์ค์ด๋ฉฐ ์ผ๊ด๋ ์ฌ์ฉ์ ๊ฒฝํ์ ๋ณด์ฅํฉ๋๋ค.
์น ์ปดํฌ๋ํธ ํ ์คํธ ํ๋ ์์ํฌ: ๊ฒฉ๋ฆฌ๋ ์ปดํฌ๋ํธ ๊ฒ์ฆ ์์คํ
์น ์ปดํฌ๋ํธ๋ ํ๋ก ํธ์๋ ๊ฐ๋ฐ์ ํ๋ช ์ ์ผ์ผ์ผฐ์ผ๋ฉฐ, ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ๊ณ ์บก์ํ๋ UI ์์๋ฅผ ๊ตฌ์ถํ๋ ๊ฐ๋ ฅํ ์ ๊ทผ ๋ฐฉ์์ ์ ๊ณตํฉ๋๋ค. ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณต์ก์ฑ์ด ์ฆ๊ฐํจ์ ๋ฐ๋ผ ์ด๋ฌํ ์ปดํฌ๋ํธ์ ํ์ง๊ณผ ์ ๋ขฐ์ฑ์ ๋ณด์ฅํ๋ ๊ฒ์ด ๋ฌด์๋ณด๋ค ์ค์ํด์ก์ต๋๋ค. ์ด ๊ธ์์๋ ์น ์ปดํฌ๋ํธ ํ ์คํธ ํ๋ ์์ํฌ์ ์ธ๊ณ๋ฅผ ๊น์ด ํ๊ณ ๋ค์ด ๊ฒฉ๋ฆฌ๋ ์ปดํฌ๋ํธ ๊ฒ์ฆ ์์คํ ์ ๊ฐ๋ , ๊ทธ ์ด์ , ๊ทธ๋ฆฌ๊ณ ์ด๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ง์ค์ ์ผ๋ก ๋ค๋ฃน๋๋ค.
์น ์ปดํฌ๋ํธ๋ ๋ฌด์์ธ๊ฐ?
ํ ์คํธ์ ๋ํด ์์๋ณด๊ธฐ ์ ์, ์น ์ปดํฌ๋ํธ๊ฐ ๋ฌด์์ธ์ง ๊ฐ๋จํ ๋ณต์ตํด ๋ณด๊ฒ ์ต๋๋ค. ์น ์ปดํฌ๋ํธ๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ปค์คํ HTML ์์๋ฅผ ์บก์ํ๋ ๋ก์ง๊ณผ ์คํ์ผ๋ง์ผ๋ก ๋ง๋ค ์ ์๊ฒ ํด์ฃผ๋ ์น ํ๋ซํผ API์ ์งํฉ์ ๋๋ค. ์ด๋ ์ธ ๊ฐ์ง ์ฃผ์ ๊ธฐ์ ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค:
- ์ปค์คํ ์์(Custom Elements): ์๋ก์ด HTML ํ๊ทธ์ ๊ทธ ๋์์ ์ ์ํฉ๋๋ค.
- ์๋ DOM(Shadow DOM): ์ปดํฌ๋ํธ์ ๋ด๋ถ ๊ตฌ์กฐ์ ์คํ์ผ๋ง์ ์จ๊ฒจ ์บก์ํ๋ฅผ ์ ๊ณตํฉ๋๋ค.
- HTML ํ ํ๋ฆฟ(HTML Templates): ๋ณต์ ํ์ฌ DOM์ ์ฝ์ ํ ์ ์๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ HTML ์กฐ๊ฐ์ ๋๋ค.
์ด๋ฌํ ๊ธฐ์ ์ ํ์ฉํจ์ผ๋ก์จ ๊ฐ๋ฐ์๋ ๋ชจ๋์์ด๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ ์ฝ๋๋ฒ ์ด์ค๋ฅผ ๋ง๋ค ์ ์์ผ๋ฉฐ, ์ฌ์ฌ์ฉ์ฑ์ ๋์ด๊ณ ์ค๋ณต์ ์ค์ผ ์ ์์ต๋๋ค. ๋ฒํผ ์ปดํฌ๋ํธ๋ฅผ ์๊ฐํด ๋ณด์ธ์. ์ธํ, ๋์(ํด๋ฆญ ํธ๋ค๋ฌ, ํธ๋ฒ ์ ์คํ์ผ๋ง), ์์ฑ์ ํ ๋ฒ ์ ์ํ ๋ค์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฒด์์ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด ์ ๊ทผ ๋ฐฉ์์ ์ค๋ณต ์ฝ๋๋ฅผ ์ต์ํํ๊ณ ์ ์ง๋ณด์๋ฅผ ๋จ์ํํฉ๋๋ค.
์ ์น ์ปดํฌ๋ํธ๋ฅผ ๊ฒฉ๋ฆฌํ์ฌ ํ ์คํธํด์ผ ํ๋๊ฐ?
์ ํต์ ์ธ ํ ์คํธ ๋ฐฉ๋ฒ๋ก ์ ์ข ์ข ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์ ์ ๋งฅ๋ฝ ์์์ ์ปดํฌ๋ํธ๋ฅผ ํ ์คํธํ๋๋ฐ, ์ด๋ ์ฌ๋ฌ ๊ฐ์ง ์ด๋ ค์์ ์ผ๊ธฐํฉ๋๋ค:
- ๋ณต์ก์ฑ: ๋๊ท๋ชจ ์ ํ๋ฆฌ์ผ์ด์ ๋ด์์ ์ปดํฌ๋ํธ๋ฅผ ํ ์คํธํ๋ ๊ฒ์ ๋ณต์กํ ์ ์์ผ๋ฉฐ, ์คํจ์ ๊ทผ๋ณธ ์์ธ์ ๋ถ๋ฆฌํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ญ๋๋ค.
- ์์กด์ฑ: ์ปดํฌ๋ํธ๊ฐ ์ธ๋ถ ์์กด์ฑ์ ์์กดํ ์ ์์ด ํ ์คํธ๊ฐ ์์ธก ๋ถ๊ฐ๋ฅํ๊ณ ๋ถ์์ฉ์ด ๋ฐ์ํ๊ธฐ ์ฝ์ต๋๋ค.
- ๋๋ฆฐ ํผ๋๋ฐฑ ๋ฃจํ: ์๋ํฌ์๋ ํ ์คํธ๋ฅผ ์คํํ๋ ๋ฐ ์๊ฐ์ด ๋ง์ด ์์๋ ์ ์์ด ์ ์ํ ๊ฐ๋ฐ๊ณผ ๋ฐ๋ณต์ ์ธ ํ ์คํธ๋ฅผ ๋ฐฉํดํฉ๋๋ค.
- ์ทจ์ฝ์ฑ: ์ ํ๋ฆฌ์ผ์ด์ ์ ํ ๋ถ๋ถ์์์ ๋ณ๊ฒฝ์ด ๊ด๋ จ ์๋ ์ปดํฌ๋ํธ์ ํ ์คํธ๋ฅผ ์๋์น ์๊ฒ ๊นจ๋จ๋ฆด ์ ์์ต๋๋ค.
๊ฒฉ๋ฆฌ๋ ์ปดํฌ๋ํธ ํ ์คํธ๋ ํต์ ๋ ํ๊ฒฝ์์ ๊ฐ๋ณ ์ปดํฌ๋ํธ๋ฅผ ๊ฒ์ฆํ๋ ๋ฐ ์ง์คํจ์ผ๋ก์จ ์ด๋ฌํ ๋ฌธ์ ๋ค์ ํด๊ฒฐํฉ๋๋ค. ์ปดํฌ๋ํธ๋ฅผ ๊ฒฉ๋ฆฌํจ์ผ๋ก์จ ๋ค์๊ณผ ๊ฐ์ ์ด์ ์ ์ป์ ์ ์์ต๋๋ค:
- ํ ์คํธ ๋จ์ํ: ๋จ์ผ ์ฝ๋ ๋จ์์ ์ง์คํ์ฌ ๋ณต์ก์ฑ์ ์ค์ ๋๋ค.
- ์ ๋ขฐ์ฑ ํฅ์: ์ธ๋ถ ์์กด์ฑ๊ณผ ๋ถ์์ฉ์ ์ ๊ฑฐํ์ฌ ๋ ์ ๋ขฐํ ์ ์๋ ํ ์คํธ ๊ฒฐ๊ณผ๋ฅผ ์ป์ต๋๋ค.
- ๊ฐ๋ฐ ๊ฐ์ํ: ๋ ๋น ๋ฅธ ํผ๋๋ฐฑ ๋ฃจํ๋ฅผ ํตํด ์ ์ํ ๋ฐ๋ณต๊ณผ ๋๋ฒ๊น ์ด ๊ฐ๋ฅํด์ง๋๋ค.
- ์ ์ง๋ณด์์ฑ ํฅ์: ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ค๋ฅธ ๋ถ๋ถ์ ๋ณ๊ฒฝ์ ๋ํด ํ ์คํธ๊ฐ ๋ ํ๋ ฅ์ ์ผ๋ก ๋ง๋ค์ด์ง๋๋ค.
๊ฒฉ๋ฆฌ๋ ํ๊ฒฝ์์์ ํ ์คํธ๋ ์ ์ฒด ๊ตฌ์กฐ๋ฌผ์ ์ง๊ธฐ ์ ์ ๊ฑด๋ฌผ์ ๊ฐ ๋ฒฝ๋์ ๊ฐ๋ณ์ ์ผ๋ก ๊ฒ์ฌํ๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค. ์ด๋ ๊ฐ ๋ฒฝ๋์ด ํผํผํ๊ณ ์๊ตฌ ์ฌ์์ ์ถฉ์กฑํ๋์ง ํ์ธํ์ฌ, ์ต์ข ์ ํ์ด ๋ ๊ฒฌ๊ณ ํ๊ณ ์์ ์ ์์ ๋ณด์ฅํฉ๋๋ค. ํ์ค ์ธ๊ณ์ ๋น์ ๋ก๋ ์๋์ฐจ ์ฐ์ ์์ ์ฐพ์ ์ ์๋๋ฐ, ์์ง, ๋ธ๋ ์ดํฌ ์์คํ , ์์คํ์ ๊ณผ ๊ฐ์ ๊ฐ๋ณ ๋ถํ๋ค์ด ์์ ํ ์ฐจ๋์ ํตํฉ๋๊ธฐ ์ ์ ๊ฒฉ๋ฆฌ๋ ์ํ์์ ์๊ฒฉํ๊ฒ ํ ์คํธ๋ฉ๋๋ค.
์น ์ปดํฌ๋ํธ ํ ์คํธ์ ์ข ๋ฅ
ํ๋ ์์ํฌ๋ฅผ ์ ํํ๊ธฐ ์ ์, ์น ์ปดํฌ๋ํธ์ ์ ์ฉํ ์ ์๋ ๋ค์ํ ์ ํ์ ํ ์คํธ๋ฅผ ์ดํดํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค:
- ๋จ์ ํ ์คํธ(Unit Tests): ๋ฉ์๋, ์์ฑ, ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ๊ฐ์ ์ปดํฌ๋ํธ์ ๋ด๋ถ ๋ก์ง์ ๊ฒ์ฆํ๋ ๋ฐ ์ค์ ์ ๋ก๋๋ค. ์ด ํ ์คํธ๋ ์ปดํฌ๋ํธ๊ฐ ๊ฒฉ๋ฆฌ๋ ์ํ์์ ์์๋๋ก ๋์ํ๋์ง ํ์ธํฉ๋๋ค.
- ํตํฉ ํ ์คํธ(Integration Tests): ์ ํ๋ฆฌ์ผ์ด์ ๋ด์ ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ ๋ชจ๋ ๊ฐ์ ์ํธ ์์ฉ์ ํ์ธํฉ๋๋ค. ์น ์ปดํฌ๋ํธ์ ๊ฒฝ์ฐ, ์ด๋ ์ปค์คํ ์์๊ฐ ๋ถ๋ชจ ๋๋ ์์ ์์์ ์ด๋ป๊ฒ ์ํธ ์์ฉํ๋์ง ํ ์คํธํ๋ ๊ฒ์ ํฌํจํ ์ ์์ต๋๋ค.
- ์๊ฐ์ ํ๊ท ํ ์คํธ(Visual Regression Tests): ์ปดํฌ๋ํธ์ ์ฌ๋ฌ ์ํ์ ๋ํ ์คํฌ๋ฆฐ์ท์ ์บก์ฒํ๊ณ ๊ธฐ์ค ์ด๋ฏธ์ง์ ๋น๊ตํ์ฌ ์๊ฐ์ ํ๊ท๋ฅผ ๊ฐ์งํฉ๋๋ค. ์ด ํ ์คํธ๋ ์ปดํฌ๋ํธ๊ฐ ๋ค๋ฅธ ๋ธ๋ผ์ฐ์ ์ ์ฅ์น์์ ์ฌ๋ฐ๋ฅด๊ฒ ๋ ๋๋ง๋๋์ง ํ์ธํฉ๋๋ค.
- ์๋ํฌ์๋(E2E) ํ ์คํธ(End-to-End (E2E) Tests): ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ์ ์ฌ์ฉ์ ์ํธ ์์ฉ์ ์๋ฎฌ๋ ์ด์ ํ์ฌ, ์ปดํฌ๋ํธ๊ฐ ์ ์ฒด ์ฌ์ฉ์ ํ๋ฆ ๋ด์์ ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ๋์ง ํ์ธํฉ๋๋ค. ์ด ํ ์คํธ๋ ์ผ๋ฐ์ ์ผ๋ก ๋ค๋ฅธ ์ ํ์ ํ ์คํธ๋ณด๋ค ๋๋ฆฌ๊ณ ๋ณต์กํฉ๋๋ค.
๊ฒฉ๋ฆฌ๋ ์ปดํฌ๋ํธ ๊ฒ์ฆ ์์คํ ์ ์ฃผ์ ํน์ง
ํจ๊ณผ์ ์ธ ๊ฒฉ๋ฆฌ๋ ์ปดํฌ๋ํธ ๊ฒ์ฆ ์์คํ ์ ๋ค์๊ณผ ๊ฐ์ ์ฃผ์ ํน์ง์ ๊ฐ์ ธ์ผ ํฉ๋๋ค:
- ์ปดํฌ๋ํธ ๊ฒฉ๋ฆฌ: ์ ํ๋ฆฌ์ผ์ด์ ์ ๋๋จธ์ง ๋ถ๋ถ์ผ๋ก๋ถํฐ ์ปดํฌ๋ํธ๋ฅผ ๊ฒฉ๋ฆฌํ์ฌ ํต์ ๋ ํ ์คํธ ํ๊ฒฝ์ ๋ง๋๋ ๋ฅ๋ ฅ. ์ด๋ ์ข ์ข ์๋ DOM ์ฌ์ฉ ๋ฐ ์์กด์ฑ ๋ชจ์(mocking)์ ๊ฐ์ ๊ธฐ์ ์ ํฌํจํฉ๋๋ค.
- ๋จ์ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(Assertion Library): ์ปดํฌ๋ํธ ๋์, ์์ฑ, ์ดํธ๋ฆฌ๋ทฐํธ, ์คํ์ผ์ ๊ฒ์ฆํ๊ธฐ ์ํ ํ๋ถํ ๋งค์ฒ(matcher) ์ธํธ๋ฅผ ์ ๊ณตํ๋ ํฌ๊ด์ ์ธ ๋จ์ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ.
- ํ ์คํธ ์คํ๊ธฐ(Test Runner): ์ผ๊ด๋๊ณ ์ ๋ขฐํ ์ ์๋ ๋ฐฉ์์ผ๋ก ํ ์คํธ๋ฅผ ์คํํ๊ณ ์์ธํ ๋ณด๊ณ ์์ ํผ๋๋ฐฑ์ ์ ๊ณตํ๋ ํ ์คํธ ์คํ๊ธฐ.
- ๋ชจ์ ๊ธฐ๋ฅ(Mocking Capabilities): ์์ธก ๊ฐ๋ฅํ ํ ์คํธ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฅํ๊ธฐ ์ํด API ํธ์ถ ๋ฐ ์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ฐ์ ์ธ๋ถ ์์กด์ฑ์ ๋ชจ์ํ๋ ๋ฅ๋ ฅ.
- ์๊ฐ์ ํ ์คํธ ์ง์: ์๊ฐ์ ํ๊ท๋ฅผ ๊ฐ์งํ๊ธฐ ์ํด ์ปดํฌ๋ํธ์ ์คํฌ๋ฆฐ์ท์ ์บก์ฒํ๊ณ ๋น๊ตํ๋ ์๊ฐ์ ํ ์คํธ ๋๊ตฌ์์ ํตํฉ.
- ๋ธ๋ผ์ฐ์ ์ง์: ๋ค์ํ ํ๋ซํผ์์ ์ผ๊ด๋ ๋์์ ๋ณด์ฅํ๊ธฐ ์ํ ๊ด๋ฒ์ํ ๋ธ๋ผ์ฐ์ ํธํ์ฑ.
- ๋๋ฒ๊น ๋๊ตฌ: ์ค๋จ์ , ์ฝ์ ๋ก๊น , ์ฝ๋ ์ปค๋ฒ๋ฆฌ์ง ๋ถ์๊ณผ ๊ฐ์ ํ ์คํธ ๋ฐ ์ปดํฌ๋ํธ ๋๋ฒ๊น ์ ์ํ ๋๊ตฌ.
์ธ๊ธฐ ์๋ ์น ์ปดํฌ๋ํธ ํ ์คํธ ํ๋ ์์ํฌ
์ฌ๋ฌ ํ๋ ์์ํฌ๊ฐ ์น ์ปดํฌ๋ํธ ํ ์คํธ์ ํน์ ์๊ตฌ ์ฌํญ์ ์ถฉ์กฑ์ํค๋ฉฐ ๋ค์ํ ๊ธฐ๋ฅ๊ณผ ์ ๊ทผ ๋ฐฉ์์ ์ ๊ณตํฉ๋๋ค. ๋ค์์ ๋ช ๊ฐ์ง ์ธ๊ธฐ ์๋ ์ต์ ์ ๋ํ ๊ฐ์์ ๋๋ค:
1. Storybook
Storybook์ ์ธ๊ธฐ ์๋ UI ์ปดํฌ๋ํธ ๊ฐ๋ฐ ๋๊ตฌ๋ก, ํ๋ฅญํ ํ ์คํธ ํ๊ฒฝ ์ญํ ๋ ํฉ๋๋ค. UI ์ปดํฌ๋ํธ๋ฅผ ๊ฒฉ๋ฆฌ, ๋ฌธ์ํ ๋ฐ ์ ์ํ ์ ์๋ ํ๋ซํผ์ ์ ๊ณตํฉ๋๋ค. ์๋ฐํ ๋งํด ํ ์คํธ ํ๋ ์์ํฌ๋ ์๋์ง๋ง, ๊ฒฉ๋ฆฌ๋ ํ๊ฒฝ๊ณผ Chromatic๊ณผ ๊ฐ์ ์ ๋์จ ๋๋ถ์ ์๊ฐ์ ๋ฐ ์ํธ ์์ฉ ํ ์คํธ์ ๋งค์ฐ ์ ์ฉํฉ๋๋ค.
์ฅ์ :
- ๊ฒฉ๋ฆฌ๋ ํ๊ฒฝ: Storybook์ ์ปดํฌ๋ํธ๋ฅผ ๊ฒฉ๋ฆฌํ์ฌ ๊ฐ๋ฐํ๊ณ ํ ์คํธํ ์ ์๋ ์๋๋ฐ์ค ํ๊ฒฝ์ ์ ๊ณตํฉ๋๋ค.
- ์๊ฐ์ ํ ์คํธ: ์๊ฐ์ ํ๊ท ํ ์คํธ๋ฅผ ์ํด Chromatic๊ณผ ์ํํ๊ฒ ํตํฉ๋ฉ๋๋ค.
- ์ํธ ์์ฉ ํ ์คํธ: ๊ฐ๋ฐ์๊ฐ ์ปดํฌ๋ํธ์ ์ํธ ์์ฉํ๊ณ ๊ทธ ๋์์ ํ ์คํธํ ์ ์๋๋ก ํฉ๋๋ค.
- ๋ฌธ์ํ: ์ปดํฌ๋ํธ์ ๋ํ ๋ฌธ์๋ฅผ ์์ฑํ์ฌ ์ดํดํ๊ณ ์ฌ์ฌ์ฉํ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค.
- ๋์ ์ฑํ๋ฅ : ๋๊ท๋ชจ ์ปค๋ฎค๋ํฐ์ ๊ด๋ฒ์ํ ์ ๋์จ ์ํ๊ณ๋ฅผ ๊ฐ์ถ๊ณ ์์ต๋๋ค.
์์ :
Storybook์ ์ฌ์ฉํ์ฌ ์น ์ปดํฌ๋ํธ์ ๋ค์ํ ์ํ์ ๋ณํ์ ๋ณด์ฌ์ฃผ๋ ์คํ ๋ฆฌ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. ์ด๋ฌํ ์คํ ๋ฆฌ๋ ์๊ฐ์ ํ ์คํธ ๋ฐ ์ํธ ์์ฉ ํ ์คํธ์ ์ฌ์ฉ๋ ์ ์์ต๋๋ค.
// Button.stories.js
import { html } from 'lit-html';
import './button.js';
export default {
title: 'Components/Button',
component: 'my-button',
};
const Template = (args) => html` `;
export const Primary = Template.bind({});
Primary.args = {
label: 'Primary Button',
onClick: () => alert('Primary Button Clicked!'),
};
2. Testing Library
Testing Library๋ ์ฌ์ฉ์๊ฐ ์ปดํฌ๋ํธ์ ์ํธ ์์ฉํ๋ ๋ฐฉ์์ ์ค์ ์ ๋ ํ ์คํธ ์์ฑ์ ์ฅ๋ คํ๋ ๊ฒฝ๋์ ์ฌ์ฉ์ ์ค์ฌ ํ ์คํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. ์ ๊ทผ์ฑ์ ์ฆ์ง์ํค๊ณ ๊ตฌํ ์ธ๋ถ ์ฌํญ์ ํ ์คํธํ๋ ๊ฒ์ ํผํฉ๋๋ค.
์ฅ์ :
- ์ฌ์ฉ์ ์ค์ฌ ์ ๊ทผ ๋ฐฉ์: ์ฌ์ฉ์๊ฐ ์ปดํฌ๋ํธ์ ์ํธ ์์ฉํ๋ ๋ฐฉ์ ํ ์คํธ์ ์ค์ ์ ๋์ด ์ ๊ทผ์ฑ๊ณผ ์ฌ์ฉ์ฑ์ ์ฆ์ง์ํต๋๋ค.
- ๊ฐ๋จํ API: ํ ์คํธ ์์ฑ์ ์ํ ๊ฐ๋จํ๊ณ ์ง๊ด์ ์ธ API๋ฅผ ์ ๊ณตํฉ๋๋ค.
- ํ๋ ์์ํฌ์ ๊ตฌ์ ๋ฐ์ง ์์: React, Angular, Vue.js๋ฅผ ํฌํจํ ๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ ํ๋ ์์ํฌ์ ํจ๊ป ์ฌ์ฉํ ์ ์์ต๋๋ค.
- ์ข์ ๊ดํ ์ฅ๋ ค: ๊ตฌํ ์ธ๋ถ ์ฌํญ์ ๋ณ๊ฒฝ์ ํ๋ ฅ์ ์ธ ํ ์คํธ ์์ฑ์ ์ฅ๋ คํฉ๋๋ค.
์์ :
// button.test.js
import { render, screen, fireEvent } from '@testing-library/dom';
import './button.js';
test('renders a button with the correct label', () => {
render(' ');
const buttonElement = screen.getByText('Click Me');
expect(buttonElement).toBeInTheDocument();
});
test('calls the onClick handler when the button is clicked', () => {
const onClick = jest.fn();
render(' ');
const buttonElement = screen.getByText('Click Me');
fireEvent.click(buttonElement);
expect(onClick).toHaveBeenCalledTimes(1);
});
3. Web Test Runner
Web Test Runner๋ ์น ์ปดํฌ๋ํธ๋ฅผ ์ํด ํน๋ณํ ์ค๊ณ๋ ์ต์ ํ ์คํธ ์คํ๊ธฐ์ ๋๋ค. Mocha, Chai, Jasmine๊ณผ ๊ฐ์ ๋ค์ํ ํ ์คํธ ํ๋ ์์ํฌ๋ฅผ ์ง์ํ๋ฉฐ, ์ค์๊ฐ ๋ฆฌ๋ก๋ฉ, ์ฝ๋ ์ปค๋ฒ๋ฆฌ์ง, ๋ธ๋ผ์ฐ์ ์ง์๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
์ฅ์ :
- ์น ์ปดํฌ๋ํธ ํนํ: ์น ์ปดํฌ๋ํธ๋ฅผ ์ผ๋์ ๋๊ณ ์ค๊ณ๋์ด ์ปค์คํ ์์ ๋ฐ ์๋ DOM ํ ์คํธ์ ๋ํ ํ๋ฅญํ ์ง์์ ์ ๊ณตํฉ๋๋ค.
- ์ต์ ๊ธฐ๋ฅ: ์ค์๊ฐ ๋ฆฌ๋ก๋ฉ, ์ฝ๋ ์ปค๋ฒ๋ฆฌ์ง, ๋ธ๋ผ์ฐ์ ์ง์๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
- ์ ์ฐ์ฑ: ๋ค์ํ ํ ์คํธ ํ๋ ์์ํฌ์ ๋จ์ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ง์ํฉ๋๋ค.
- ์ฌ์ด ๊ตฌ์ฑ: ๊ฐ๋จํ๊ณ ์ง๊ด์ ์ธ ๊ตฌ์ฑ.
์์ :
// web-test-runner.config.js
import { fromRollup } from '@web/rollup-plugin';
import { rollupPluginHTML } from '@web/rollup-plugin-html';
import { resolve } from 'path';
export default {
files: ['src/**/*.test.js'],
nodeResolve: true,
reporters: ['spec'],
browsers: ['chrome', 'firefox'],
plugins: [
fromRollup(rollupPluginHTML(), {
exclude: null,
}),
],
};
// src/my-component.test.js
import { expect } from '@open-wc/testing';
import { MyComponent } from './my-component.js';
import './my-component.js';
describe('MyComponent', () => {
it('should render', async () => {
const el = await fixture(html` `);
expect(el).to.exist;
});
it('should have a default name "World"', async () => {
const el = await fixture(html` `);
expect(el.name).to.equal('World');
});
it('should update the name when a new value is provided', async () => {
const el = await fixture(html` `);
expect(el.name).to.equal('Test');
});
});
4. Open Web Components ๊ถ์ฅ ์ฌํญ
Open Web Components(OWC)๋ ์น ์ปดํฌ๋ํธ ๊ฐ๋ฐ์ ์ํ ๊ถ์ฅ ์ฌํญ๊ณผ ๋๊ตฌ๋ฅผ ์ ๊ณตํ๋ ์ปค๋ฎค๋ํฐ ์ฃผ๋ ์ด๋์ ํฐ๋ธ์ ๋๋ค. ํ ์คํธ ๋ชจ๋ฒ ์ฌ๋ก์ ๋ํ ์ง์นจ์ ์ ๊ณตํ๊ณ `@open-wc/testing` ๋ฐ `@open-wc/visualize`์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ๊ณตํ์ฌ ํ ์คํธ ์ํฌํ๋ก์ฐ๋ฅผ ๋จ์ํํฉ๋๋ค.
์ฅ์ :
- ๋ชจ๋ฒ ์ฌ๋ก: Open Web Components ์ปค๋ฎค๋ํฐ์ ๊ถ์ฅ ์ฌํญ์ ๋ฐ๋ฆ ๋๋ค.
- ์ ํธ๋ฆฌํฐ: ์ผ๋ฐ์ ์ธ ํ ์คํธ ์์ ์ ์ํ ์ ํธ๋ฆฌํฐ ํจ์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ๊ณตํฉ๋๋ค.
- ํตํฉ: ๋ค๋ฅธ ํ ์คํธ ํ๋ ์์ํฌ ๋ฐ ๋๊ตฌ์ ์ ํตํฉ๋ฉ๋๋ค.
- ์๊ฐํ: ์ปดํฌ๋ํธ ์ํ ๋ฐ ์ํธ ์์ฉ์ ์๊ฐํํ๋ ๋๊ตฌ๋ฅผ ์ ๊ณตํฉ๋๋ค.
์์ :
// my-element.test.js
import { html, fixture } from '@open-wc/testing';
import { MyElement } from './my-element.js';
import './my-element.js';
describe('MyElement', () => {
it('renders with default values', async () => {
const el = await fixture(html` `);
expect(el.title).to.equal('Hey there');
expect(el.counter).to.equal(5);
});
it('increases the counter on button click', async () => {
const el = await fixture(html` `);
el.shadowRoot.querySelector('button').click();
expect(el.counter).to.equal(6);
});
});
๊ฒฉ๋ฆฌ๋ ์ปดํฌ๋ํธ ๊ฒ์ฆ ์์คํ ๊ตฌํํ๊ธฐ: ๋จ๊ณ๋ณ ๊ฐ์ด๋
Web Test Runner์ Testing Library๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒฉ๋ฆฌ๋ ์ปดํฌ๋ํธ ๊ฒ์ฆ ์์คํ ์ ์ค์ ํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์ค์ฉ์ ์ธ ๊ฐ์ด๋์ ๋๋ค:
- ํ๋ก์ ํธ ์ค์ :
- ์ ํ๋ก์ ํธ ๋๋ ํ ๋ฆฌ๋ฅผ ๋ง๋ญ๋๋ค.
- ์ npm ํ๋ก์ ํธ๋ฅผ ์ด๊ธฐํํฉ๋๋ค:
npm init -y - Web Test Runner์ Testing Library๋ฅผ ์ค์นํฉ๋๋ค:
npm install --save-dev @web/test-runner @testing-library/dom - ์ง์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํฉ๋๋ค:
npm install --save-dev @open-wc/testing jest
- ์น ์ปดํฌ๋ํธ ์์ฑ:
- `my-component.js`๋ผ๋ ์ด๋ฆ์ ํ์ผ์ ๋ค์ ๋ด์ฉ์ผ๋ก ์์ฑํฉ๋๋ค:
// my-component.js import { LitElement, html, css } from 'lit'; export class MyComponent extends LitElement { static styles = css` p { color: blue; } `; static properties = { name: { type: String }, }; constructor() { super(); this.name = 'World'; } render() { return html`Hello, ${this.name}!
`; } _changeName(e) { this.name = e.target.value; } } customElements.define('my-component', MyComponent);
- `my-component.js`๋ผ๋ ์ด๋ฆ์ ํ์ผ์ ๋ค์ ๋ด์ฉ์ผ๋ก ์์ฑํฉ๋๋ค:
- ํ
์คํธ ํ์ผ ์์ฑ:
- `my-component.test.js`๋ผ๋ ์ด๋ฆ์ ํ์ผ์ ๋ค์ ๋ด์ฉ์ผ๋ก ์์ฑํฉ๋๋ค:
// my-component.test.js import { html, fixture } from '@open-wc/testing'; import { MyComponent } from './my-component.js'; import './my-component.js'; import { expect } from '@esm-bundle/chai'; describe('MyComponent', () => { it('renders with a default name', async () => { const el = await fixture(html``); expect(el.shadowRoot.querySelector('p').textContent).to.equal('Hello, World!'); }); it('updates the name when input changes', async () => { const el = await fixture(html` `); const input = el.shadowRoot.querySelector('input'); input.value = 'Test'; input.dispatchEvent(new Event('input')); await el.updateComplete; expect(el.shadowRoot.querySelector('p').textContent).to.equal('Hello, Test!'); }); });
- `my-component.test.js`๋ผ๋ ์ด๋ฆ์ ํ์ผ์ ๋ค์ ๋ด์ฉ์ผ๋ก ์์ฑํฉ๋๋ค:
- Web Test Runner ๊ตฌ์ฑ:
- ๋ฃจํธ ๋๋ ํ ๋ฆฌ์ `web-test-runner.config.js`๋ผ๋ ์ด๋ฆ์ ํ์ผ์ ์์ฑํฉ๋๋ค:
// web-test-runner.config.js import { playwrightLauncher } from '@web/test-runner-playwright'; export default { files: ['**/*.test.js'], browsers: [ playwrightLauncher({ product: 'chromium', }), playwrightLauncher({ product: 'firefox', }), playwrightLauncher({ product: 'webkit', }), ], };
- ๋ฃจํธ ๋๋ ํ ๋ฆฌ์ `web-test-runner.config.js`๋ผ๋ ์ด๋ฆ์ ํ์ผ์ ์์ฑํฉ๋๋ค:
- ํ
์คํธ ์คํฌ๋ฆฝํธ ์ถ๊ฐ:
- `package.json` ํ์ผ์ ํ
์คํธ ์คํฌ๋ฆฝํธ๋ฅผ ์ถ๊ฐํฉ๋๋ค:
{ "scripts": { "test": "web-test-runner" } }
- `package.json` ํ์ผ์ ํ
์คํธ ์คํฌ๋ฆฝํธ๋ฅผ ์ถ๊ฐํฉ๋๋ค:
- ํ
์คํธ ์คํ:
- ๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ํ
์คํธ๋ฅผ ์คํํฉ๋๋ค:
npm test - Web Test Runner๊ฐ ๊ตฌ์ฑ๋ ๋ธ๋ผ์ฐ์ ์์ ํ ์คํธ๋ฅผ ์คํํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ํ์ํฉ๋๋ค.
- ๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ํ
์คํธ๋ฅผ ์คํํฉ๋๋ค:
์น ์ปดํฌ๋ํธ ํ ์คํธ ๋ชจ๋ฒ ์ฌ๋ก
์น ์ปดํฌ๋ํธ ํ ์คํธ ๋ ธ๋ ฅ์ ํจ๊ณผ๋ฅผ ๊ทน๋ํํ๋ ค๋ฉด ๋ค์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๊ณ ๋ คํ์ญ์์ค:
- ํ ์คํธ๋ฅผ ์ผ์ฐ ๊ทธ๋ฆฌ๊ณ ์์ฃผ ์์ฑํ๊ธฐ: ํ ์คํธ ์ฃผ๋ ๊ฐ๋ฐ(TDD) ์ ๊ทผ ๋ฐฉ์์ ์ฑํํ์ฌ ์ปดํฌ๋ํธ ๋ก์ง์ ๊ตฌํํ๊ธฐ ์ ์ ํ ์คํธ๋ฅผ ์์ฑํฉ๋๋ค.
- ์ฌ์ฉ์ ์ํธ ์์ฉ์ ์ง์คํ๊ธฐ: ์ฌ์ฉ์ ์ํธ ์์ฉ์ ์๋ฎฌ๋ ์ด์ ํ๋ ํ ์คํธ๋ฅผ ์์ฑํ์ฌ ์ปดํฌ๋ํธ๊ฐ ์ฌ์ฉ์ ๊ด์ ์์ ์์๋๋ก ๋์ํ๋์ง ํ์ธํฉ๋๋ค.
- ์ธ๋ถ ์์กด์ฑ ๋ชจ์ํ๊ธฐ: API ํธ์ถ ๋ฐ ์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ฐ์ ์ธ๋ถ ์์กด์ฑ์ ๋ชจ์ํ์ฌ ์ปดํฌ๋ํธ๋ฅผ ๊ฒฉ๋ฆฌํฉ๋๋ค.
- ์ปดํฌ๋ํธ ์ํ ํ ์คํธํ๊ธฐ: ๋ก๋ฉ, ์ค๋ฅ, ์ฑ๊ณต ์ํ๋ฅผ ํฌํจํ ์ปดํฌ๋ํธ์ ๋ชจ๋ ๊ฐ๋ฅํ ์ํ๋ฅผ ํ ์คํธํฉ๋๋ค.
- ์๊ฐ์ ํ ์คํธ ์๋ํํ๊ธฐ: ์๊ฐ์ ํ ์คํธ ๋๊ตฌ๋ฅผ ํตํฉํ์ฌ ์๊ฐ์ ํ๊ท๋ฅผ ์๋์ผ๋ก ๊ฐ์งํฉ๋๋ค.
- ์ ๊ธฐ์ ์ผ๋ก ํ ์คํธ ๊ฒํ ๋ฐ ์ ๋ฐ์ดํธํ๊ธฐ: ์ปดํฌ๋ํธ ๋ก์ง ๋ฐ ๋์ ๋ณ๊ฒฝ์ ๋ฐ๋ผ ํ ์คํธ๋ฅผ ์ต์ ์ํ๋ก ์ ์งํฉ๋๋ค.
- ์ ๊ทผ์ฑ ์ฐ์ ์ํ๊ธฐ: ์ฅ์ ๊ฐ ์๋ ์ฌ๋๋ค๋ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ์ ๊ทผ์ฑ ํ ์คํธ๋ฅผ ์ํฌํ๋ก์ฐ์ ํตํฉํฉ๋๋ค.
๊ณ ๊ธ ํ ์คํธ ๊ธฐ๋ฒ
๊ธฐ๋ณธ์ ์ธ ๋จ์ ๋ฐ ํตํฉ ํ ์คํธ ์ธ์๋, ์น ์ปดํฌ๋ํธ์ ํ์ง๊ณผ ์ ๋ขฐ์ฑ์ ๋์ฑ ํฅ์์ํฌ ์ ์๋ ๋ช ๊ฐ์ง ๊ณ ๊ธ ํ ์คํธ ๊ธฐ๋ฒ์ด ์์ต๋๋ค:
- ์์ฑ ๊ธฐ๋ฐ ํ ์คํธ(Property-Based Testing): ๋ฌด์์๋ก ์์ฑ๋ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์ํ ์กฐ๊ฑด์์ ์ปดํฌ๋ํธ์ ๋์์ ํ ์คํธํฉ๋๋ค. ์ด๋ ์ฃ์ง ์ผ์ด์ค์ ์์์น ๋ชปํ ์ค๋ฅ๋ฅผ ๋ฐ๊ฒฌํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
- ๋ณ์ด ํ ์คํธ(Mutation Testing): ์ปดํฌ๋ํธ ์ฝ๋์ ์์ ๋ณ๊ฒฝ(๋ณ์ด)์ ๋์ ํ๊ณ ํ ์คํธ๊ฐ ์์๋๋ก ์คํจํ๋์ง ํ์ธํฉ๋๋ค. ์ด๋ ํ ์คํธ๊ฐ ์ค๋ฅ๋ฅผ ๊ฐ์งํ๋ ๋ฐ ํจ๊ณผ์ ์ธ์ง ํ์ธํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
- ๊ณ์ฝ ํ ์คํธ(Contract Testing): ์ปดํฌ๋ํธ๊ฐ ์ฌ์ ์ ์๋ ๊ณ์ฝ ๋๋ API๋ฅผ ์ค์ํ๋์ง ํ์ธํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ค๋ฅธ ๋ถ๋ถ๊ณผ์ ํธํ์ฑ์ ๋ณด์ฅํฉ๋๋ค.
- ์ฑ๋ฅ ํ ์คํธ(Performance Testing): ๋ ๋๋ง ์๋ ๋ฐ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋๊ณผ ๊ฐ์ ์ปดํฌ๋ํธ์ ์ฑ๋ฅ์ ์ธก์ ํ์ฌ ์ ์ฌ์ ์ธ ๋ณ๋ชฉ ํ์์ ์๋ณํฉ๋๋ค.
๊ณผ์ ๋ฐ ๊ณ ๋ ค ์ฌํญ
๊ฒฉ๋ฆฌ๋ ์ปดํฌ๋ํธ ํ ์คํธ๋ ์๋ง์ ์ด์ ์ ์ ๊ณตํ์ง๋ง, ์ ์ฌ์ ์ธ ๊ณผ์ ์ ๊ณ ๋ ค ์ฌํญ์ ์ธ์งํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค:
- ์๋ DOM์ ๋ณต์ก์ฑ: ์๋ DOM์ด ์ปดํฌ๋ํธ์ ๋ด๋ถ ๊ตฌ์กฐ๋ฅผ ์บก์ํํ๊ธฐ ๋๋ฌธ์ ์๋ DOM์ ๊ฐ์ง ์ปดํฌ๋ํธ๋ฅผ ํ ์คํธํ๋ ๊ฒ์ ์ด๋ ค์ธ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ Testing Library์ ๊ฐ์ ๋๊ตฌ๋ ์๋ DOM ๋ด์ ์์๋ฅผ ์ฟผ๋ฆฌํ๋ ์ ํธ๋ฆฌํฐ๋ฅผ ์ ๊ณตํฉ๋๋ค.
- ์ด๋ฒคํธ ์ฒ๋ฆฌ: ์น ์ปดํฌ๋ํธ์์ ์ด๋ฒคํธ ์ฒ๋ฆฌ๋ฅผ ํ ์คํธํ๋ ค๋ฉด ์ ์คํ ๊ณ ๋ ค๊ฐ ํ์ํฉ๋๋ค. ์ด๋ฒคํธ๊ฐ ์๋ DOM์ ํตํด ๋ฒ๋ธ๋ง๋ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ํ ์คํธ๊ฐ ์ด๋ฒคํธ ๋์คํจ์น ๋ฐ ์ฒ๋ฆฌ๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์๋ฎฌ๋ ์ด์ ํ๋์ง ํ์ธํ์ญ์์ค.
- ๋น๋๊ธฐ ์์ : API ํธ์ถ๊ณผ ๊ฐ์ ๋น๋๊ธฐ ์์ ์ ์ํํ๋ ์ปดํฌ๋ํธ๋ ํ ์คํธ์์ ํน๋ณํ ์ฒ๋ฆฌ๊ฐ ํ์ํฉ๋๋ค. ๋ชจ์ ๊ธฐ๋ฒ์ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ ํจ์์ ๋์์ ์ ์ดํ์ญ์์ค.
- ํ์ต ๊ณก์ : ๊ฒฉ๋ฆฌ๋ ์ปดํฌ๋ํธ ๊ฒ์ฆ ์์คํ ์ ๊ตฌํํ๋ ค๋ฉด ์๋ก์ด ๋๊ตฌ์ ๊ธฐ์ ์ ๋ฐฐ์์ผ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ํฅ์๋ ํ์ง๊ณผ ์ ์ง๋ณด์์ฑ์ ์ด์ ์ ์ด๊ธฐ ํฌ์๋ฅผ ์์ํฉ๋๋ค.
์น ์ปดํฌ๋ํธ ํ ์คํธ์ ๋ฏธ๋
์น ์ปดํฌ๋ํธ ํ ์คํธ์ ๋ฏธ๋๋ ๋๊ตฌ์ ๋ฐฉ๋ฒ๋ก ์ ์ง์์ ์ธ ๋ฐ์ ์ผ๋ก ์ ๋งํด ๋ณด์ ๋๋ค. ์น ์ปดํฌ๋ํธ ์ํ๊ณ๊ฐ ์ฑ์ํด์ง์ ๋ฐ๋ผ ๋ค์์ ๊ธฐ๋ํ ์ ์์ต๋๋ค:
- ๋ ์ ๊ตํ ํ ์คํธ ํ๋ ์์ํฌ: ์น ์ปดํฌ๋ํธ์ ํนํ๋๊ณ ์์ฑ ๊ธฐ๋ฐ ํ ์คํธ ๋ฐ ๋ณ์ด ํ ์คํธ์ ๊ฐ์ ๊ณ ๊ธ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
- ํฅ์๋ ๋ธ๋ผ์ฐ์ ์ง์: API ๋ฐ ๊ธฐ๋ฅ ํ ์คํธ๋ฅผ ์ํ ์ง์์ด ํฅ์๋์ด ๋ค๋ฅธ ํ๊ฒฝ์์ ์น ์ปดํฌ๋ํธ๋ฅผ ๋ ์ฝ๊ฒ ํ ์คํธํ ์ ์์ต๋๋ค.
- CI/CD ํ์ดํ๋ผ์ธ๊ณผ์ ํตํฉ ๊ฐํ: ํ ์คํธ ํ๋ก์ธ์ค๋ฅผ ์๋ํํ๊ณ ๋ฐฐํฌ ์ ์ ์น ์ปดํฌ๋ํธ๊ฐ ์ฒ ์ ํ ๊ฒ์ฆ๋๋๋ก ํฉ๋๋ค.
- ์๊ฐ์ ํ ์คํธ ์ฑํ ์ฆ๊ฐ: ์๊ฐ์ ํ๊ท๋ฅผ ์๋์ผ๋ก ๊ฐ์งํ๊ณ ๋ค๋ฅธ ๋ธ๋ผ์ฐ์ ๋ฐ ์ฅ์น์์ ์ผ๊ด๋ ์ฌ์ฉ์ ๊ฒฝํ์ ๋ณด์ฅํฉ๋๋ค.
๊ฒฐ๋ก
๊ฒฉ๋ฆฌ๋ ์ปดํฌ๋ํธ ํ ์คํธ๋ ์น ์ปดํฌ๋ํธ ๊ฐ๋ฐ์ ์ค์ํ ์ธก๋ฉด์ผ๋ก, UI ์์์ ํ์ง, ์ ๋ขฐ์ฑ ๋ฐ ์ ์ง๋ณด์์ฑ์ ๋ณด์ฅํฉ๋๋ค. ๊ฒฉ๋ฆฌ๋ ์ปดํฌ๋ํธ ๊ฒ์ฆ ์์คํ ์ ์ฑํํจ์ผ๋ก์จ ํ ์คํธ๋ฅผ ๋จ์ํํ๊ณ , ์ ๋ขฐ์ฑ์ ํฅ์์ํค๋ฉฐ, ๊ฐ๋ฐ์ ๊ฐ์ํํ๊ณ , ์ ์ง๋ณด์์ฑ์ ํฅ์์ํฌ ์ ์์ต๋๋ค. Storybook, Testing Library, Web Test Runner ๋ฐ Open Web Components ๊ถ์ฅ ์ฌํญ๊ณผ ๊ฐ์ ํ๋ ์์ํฌ๋ ํจ๊ณผ์ ์ธ ํ ์คํธ ์ ๋ต์ ๊ตฌํํ๊ธฐ ์ํ ํ๋ฅญํ ๋๊ตฌ์ ์ง์นจ์ ์ ๊ณตํฉ๋๋ค.
ํ๋ก ํธ์๋ ๊ฐ๋ฐ ํ๊ฒฝ์์ ์น ์ปดํฌ๋ํธ๊ฐ ๊ณ์ํด์ ์ฃผ๋ชฉ๋ฐ์์ ๋ฐ๋ผ, ๊ณ ํ์ง์ ํ์ฅ ๊ฐ๋ฅํ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๊ธฐ ์ํด์๋ ๊ฒฌ๊ณ ํ ํ ์คํธ ํ๋ ์์ํฌ์ ํฌ์ํ๋ ๊ฒ์ด ํ์์ ์ ๋๋ค. ๊ฒฉ๋ฆฌ๋ ์ปดํฌ๋ํธ ํ ์คํธ์ ์์น์ ๋ฐ์๋ค์ด๋ฉด ๊ฒฌ๊ณ ํ๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ๋ฉฐ ์ฆ๊ฑฐ์ด ์ฌ์ฉ์ ๊ฒฝํ์ ๋ง๋๋ ๋ฐ ์ ๋๋นํ ์ ์์ ๊ฒ์ ๋๋ค.
์ด ๊ธ์์๋ ์น ์ปดํฌ๋ํธ ํ ์คํธ ํ๋ ์์ํฌ์ ๋ํ ํฌ๊ด์ ์ธ ๊ฐ์๋ฅผ ์ ๊ณตํ์ผ๋ฉฐ, ๊ฒฉ๋ฆฌ๋ ์ปดํฌ๋ํธ ๊ฒ์ฆ ์์คํ ์ ๊ฐ๋ , ๊ทธ ์ด์ , ๊ทธ๋ฆฌ๊ณ ์ด๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ์ค์ ์ ๋์์ต๋๋ค. ์ด ๊ธ์์ ์ค๋ช ํ ์ง์นจ๊ณผ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด๋ฉด ์น ์ปดํฌ๋ํธ์ ํ์ง๊ณผ ์ ๋ขฐ์ฑ์ ํฅ์์ํค๊ณ ๋ ๊ฒฌ๊ณ ํ๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ์ ์์ต๋๋ค.