Web-Genie / WebGenie-frontend

Website Editor (frontend repository) ๐ŸŽจ

Home Page:https://www.webgenie.online/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

๐Ÿ–ฅ WebGenie

WebGenie

์›น์‚ฌ์ดํŠธ๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ์ง€๋งŒ ๋งŒ๋“œ๋Š” ๊ณผ์ •์ด ๋ณต์žกํ•˜๊ณ  ์–ด๋ ค์›Œ ๊ณ ๋ฏผํ•˜๊ณ  ๊ณ„์‹œ๋‚˜์š”? ์†์‰ฝ๊ฒŒ ์›น์‚ฌ์ดํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์›น ์—๋””ํ„ฐ ์„œ๋น„์Šค, WebGenie์ž…๋‹ˆ๋‹ค!

WebGenie๋ฅผ ํ†ตํ•ด ๋ช‡ ๋ฒˆ์˜ ํด๋ฆญ๊ณผ Drag and Drop์œผ๋กœ ๋ฉ‹์ง„ ์›น์‚ฌ์ดํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ์›น์‚ฌ์ดํŠธ๋ฅผ ๋งŒ๋“  ํ›„ ๋ฐฐํฌํ•˜๊ฒŒ ๋˜๋ฉด ๊ณ ์œ ํ•œ ์ฃผ์†Œ๋ฅผ ๊ฐ–๊ฒŒ ๋˜์–ด ์นœ๊ตฌ๋“ค๊ณผ ์ฃผ๋ณ€์‚ฌ๋žŒ๋“ค์—๊ฒŒ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

# No Coding # Beginner Friendly

๐Ÿ—‚ Contents

๐Ÿ“Ž Link

Deploy

Git Repository

๐Ÿ” Preview

README.demo.mp4

๐Ÿ”‘ Getting Started

  • Frontend(React)
  1. ํ”„๋กœ์ ํŠธ๋ฅผ ๋‹ค์šด ๋ฐ›์€ ํ›„ ํ”„๋กœ์ ํŠธ ํด๋” ๋‚ด์—์„œ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
npm install
npm start
  1. ํ™˜๊ฒฝ๋ณ€์ˆ˜ ํŒŒ์ผ(.env)์„ ์ƒ์„ฑํ•˜๊ณ  ์•„๋ž˜์™€ ๊ฐ™์ด ์ž…๋ ฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
REACT_APP_API_KEY=<FIREBASE_API_KEY>
REACT_APP_AUTH_DOMAIN=<FIREBASE_AUTH_DOMAIN>
REACT_APP_PROJECT_ID=<FIREBASE_PROJECT_ID>
REACT_APP_FIREBASE_STORAGEBUCKET=<FIREBASE_STORAGE_BUCKET>
REACT_APP_FIREBASE_MESSAGINGSENDERID=<FIREBASE_MESSAGING_SENDER_ID>
REACT_APP_ID=<FIREBASE_APP_ID>
REACT_APP_FIREBASE_MEASUREMENTID=<FIREBASE_MEASUREMENT_ID>
REACT_APP_API_ENDPOINT_URL=<BASE_URL>
  • Backend(Express)
  1. ํ”„๋กœ์ ํŠธ๋ฅผ ๋‹ค์šด ๋ฐ›์€ ํ›„ ํ”„๋กœ์ ํŠธ ํด๋” ๋‚ด์—์„œ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
npm install
npm start
  1. ํ™˜๊ฒฝ๋ณ€์ˆ˜ ํŒŒ์ผ(.env)์„ ์ƒ์„ฑํ•˜๊ณ  ์•„๋ž˜์™€ ๊ฐ™์ด ์ž…๋ ฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
TYPE=<FIREBASE_TYPE>
PROJECT_ID=<FIREBASE_PROJECT_ID>
PRIVATE_KEY_ID=<FIREBASE_KEY_ID>
PRIVATE_KEY=<FIREBASE_PRIVATE_KEY>
CLIENT_EMAIL=<FIREBASE_CLIENT_EMAIL>
CLIENT_ID=<FIREBASE_CLIENT_ID>
AUTH_URI=<FIREBASE_AUTH_URI>
TOKEN_URI=<FIREBASE_TOKEN_URI>
AUTH_PROVIDER_X509_CERT_URL=<FIREBASE_AUTH_PROVIDER_CERT_URL>
CLIENT_X509_CERT_URL=<FIREBASE_CLIENT_CERT_URL>
MONGO_URI=<MONGO_URI>

๐Ÿ’ก Motivation

์‚ฌ์šฉ์ž๋กœ์„œ ๋‹น์—ฐํ•˜๊ฒŒ ์—ฌ๊ธฐ๋ฉฐ ์‚ฌ์šฉํ•ด์™”๋˜ ๊ฒƒ๋“ค์„ ์šฐ๋ฆฌ๊ฐ€ ๊ฐ€์ง„ ๊ธฐ์ˆ ๋กœ ๊ตฌํ˜„ํ•ด๋ณด๋Š” ๊ฒƒ์ด ์–ด๋–จ๊นŒ? ๋ผ๋Š” ์ƒ๊ฐ์—์„œ ์ถœ๋ฐœํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ณผ๊ฑฐ์— ์›น์‚ฌ์ดํŠธ๋ฅผ ๋งŒ๋“ค ์ผ์ด ์ƒ๊ธฐ๋ฉด ์ œ์ผ ๋จผ์ € ์ „๋ฌธ์ง€์‹์ด ๋งŽ์ง€ ์•Š์•„๋„ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ํ”Œ๋žซํผ์„ ์ฐพ์•„๋ณด์•˜๊ณ  ๊ทธ ํ”Œ๋žซํผ์„ ํ†ตํ•ด ์ข‹์€ ๊ฒฝํ—˜์„ ํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์ข‹์€ ๊ฒฝํ—˜์„ ์šฐ๋ฆฌ๊ฐ€ ์„œ๋น„์Šค ํ•ด๋ณธ๋‹ค๋ฉด ์–ด๋–จ์ง€์— ๋Œ€ํ•ด ์˜๋…ผํ•ด ๋ณด์•˜๊ณ , ์ง€๊ธˆ๊นŒ์ง€ ๋ฌด์‹ฌ์ฝ” ์‚ฌ์šฉํ•ด์™”๋˜ Drag and Drop๊ณผ Resizing๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ๋“ค์„ ๊ตฌํ˜„ํ•ด๋ณด๋ฉด ์ข‹๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์–ด ์ด๋ฅผ ๊ตฌ์ฒดํ™”์‹œ์ผœ ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๋Š” ํŽธ๋ฆฌํ•˜๊ฒŒ ์›น ์‚ฌ์ดํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ณ  ์ €ํฌ๋Š” DOM, Javascript, React์— ๋Œ€ํ•ด ๊นŠ๊ฒŒ ๊ณ ๋ฏผํ•˜๊ณ  ๊ณต๋ถ€ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์•„ WebGenie๋ฅผ ๋งŒ๋“ค๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๐ŸŒˆ Features

Drag and Drop

Drag and Drop Demo

ํ…œํ”Œ๋ฆฟ์— ์˜ฌ๋ ค๋†“์€ font, image, button์„ drag and drop์„ ์ด์šฉํ•˜์—ฌ ์ž์œ ์ž์žฌ๋กœ ์ด๋™์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Resizing

Resizing Demo

ํ…œํ”Œ๋ฆฟ์— ์˜ฌ๋ ค๋†“์€ font, image, button์„ ํด๋ฆญํ•˜์—ฌ, Mouse Down ๋œ ์ƒํƒœ์—์„œ ๋งˆ์šฐ์Šค๋ฅผ ์™ผ์ชฝ์œผ๋กœ ์ด๋™์‹œํ‚ค๋ฉด, ํฌ๊ธฐ๋ฅผ ๊ฐ์†Œ์‹œํ‚ค๊ณ  ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ด๋™์‹œํ‚ค๋ฉด ํฌ๊ธฐ๋ฅผ ์ฆ๊ฐ€์‹œํ‚ต๋‹ˆ๋‹ค.

Font, Image, Button, Background change

Feature_Font_Button.mov
Feature_Image_Detail.mov
๊ธ€๊ผด, ๊ธ€์ž ํฌ๊ธฐ, ๊ธ€์ž ์ƒ‰์ƒ, ๊ธ€์ž ์ •๋ ฌ, ๊ธ€์ž ์Šคํƒ€์ผ์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฏธ์ง€๋ฅผ ์ปดํ“จํ„ฐ์—์„œ, URL์„ ํ†ตํ•ด ๋„ฃ์„ ์ˆ˜ ์žˆ๊ณ  ์ด๋ฏธ์ง€ ํˆฌ๋ช…๋„, ๋ฐ๊ธฐ, blur๋ฅผ ์กฐ์ ˆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ…œํ”Œ๋ฆฟ ๋ฐฐ๊ฒฝ์˜ ์ƒ‰์ƒ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Version Log

Feature_VersionLog.mov
saved version log ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ์ €์žฅํ–ˆ๋˜ ์‹œ์ ์˜ ๊ธฐ๋ก์ด ๋‚˜ํƒ€๋‚˜๋ฉฐ ์ตœ๊ทผ ์‹œ์ ๋ถ€ํ„ฐ ๊ณผ๊ฑฐ๋กœ ์ด์–ด์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

ํŠน์ • ์‹œ์ ์„ ํด๋ฆญํ•˜๊ฒŒ ๋˜๋ฉด ๊ทธ๋•Œ ์‚ฌ์šฉ์ž๊ฐ€ ์ €์žฅํ–ˆ๋˜ ํ…œํ”Œ๋ฆฟ์œผ๋กœ ๋Œ์•„๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

KeyDown Event

Feature_Key_Down_Event.mov
๋ฒ„ํŠผ๊ณผ ์ด๋ฏธ์ง€, ๊ธ€์ž๋ฅผ ํด๋ฆญํ•œ ํ›„ Ctrl + X๋ฅผ ํ•˜๋ฉด ์ž˜๋ผ๋‚ด๊ธฐ, Ctrl + C๋ฅผ ํ•˜๋ฉด ๋ณต์‚ฌ, Ctrl + V๋ฅผ ํ•˜๋ฉด ๋ถ™์—ฌ๋„ฃ๊ธฐ, Ctrl + Z๋ฅผ ๋ˆ„๋ฅด๋ฉด ์ด์ „ ์‹œ์ ์œผ๋กœ ๋Œ์•„๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

Deploy

Feature_Deploy.mov
์‚ฌ์šฉ์ž๊ฐ€ publish ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ๊ณ ์œ ํ•œ URL์„ ์ƒ์„ฑํ•ด์ฃผ๋ฉฐ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์ž์‹ ์˜ ์›น์‚ฌ์ดํŠธ ์ฃผ์†Œ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ›  Tech Stacks

Frontend

  • React
  • React-router-dom
  • styled-components
  • Prop-Types

Backend

  • Node.js
  • Express
  • MongoDB
  • Mongoose

Testing

  • Jest
  • React Testing Library
  • Mocha, Chai, Supertest

Deployment

  • Netlify
  • AWS Elastic Beanstalk
  • Amazon Route 53

๐Ÿ—“ Planning

ํ”„๋กœ์ ํŠธ ๊ธฐ๊ฐ„

2022๋…„ 5์›” 30์ผ ~ 6์›” 17์ผ

  • 5์›” 30์ผ ~ 6์›” 2์ผ : ์•„์ด๋””์–ด ๊ธฐํš, ๋ชฉ์—… ์ž‘์„ฑ, ์• ์ž์ผ ์Šคํ”„๋ฆฐํŠธ ํ”Œ๋žœ ์ž‘์„ฑ
  • 6์›” 3์ผ ~ 6์›” 17์ผ : ๊ฐœ๋ฐœ ์ง„ํ–‰, ๋ฐฐํฌ, ํ…Œ์ŠคํŠธ ์ž‘์„ฑ

๐Ÿ“ Technical Log

React + DOM Manipulation

์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์˜ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์ธ Drag and Drop๊ณผ Resizing ๊ธฐ๋Šฅ ๋ชจ๋‘ DOM ์กฐ์ž‘์„ ํ•„์š”๋กœํ–ˆ์Šต๋‹ˆ๋‹ค. ์กฐ์‚ฌ ํ•ด๋ณธ ๊ฒฐ๊ณผ HTML Drag and Drop API๋ฅผ ์•Œ๊ฒŒ ๋˜์—ˆ๊ณ  ์ด๊ฒƒ์„ ์‚ฌ์šฉํ•ด์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์ž์œ ๋กญ๊ฒŒ ๋“œ๋ž˜๊ทธํ•˜์—ฌ ์ˆ˜์ •ํ•  ์š”์†Œ๋“ค์„ ์—๋””ํ„ฐ ํ™”๋ฉด์— ์˜ฌ๋ ค๋‘˜ ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ ๊ตฌํ˜„์„ ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์—๋””ํ„ฐ ํ™”๋ฉด ๋‚ด๋ถ€์— ์˜ฌ๋ ค์ง„ ์š”์†Œ๋“ค์˜ ์œ„์น˜๋ฅผ ๋งˆ์šฐ์Šค ์ด๋ฒคํŠธ์™€ ํด๋ฆญํ•œ ์š”์†Œ์˜ DOMRect๋ฅผ ์ด์šฉํ•˜์—ฌ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ณ€๊ฒฝํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์ถฉ๋Œํ•˜๋Š” DOM Elements

Drag and Drop์„ ํ†ตํ•ด ์กฐ์ž‘๋˜๋Š” ์š”์†Œ ๊ฐ„์˜ ์ถฉ๋Œ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. HTML ์š”์†Œ๋“ค์€ document์˜ ํ๋ฆ„์— ๋”ฐ๋ผ์•ผ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ ์—˜๋ฆฌ๋จผํŠธ๋งŒ์˜ block์ด ์กด์žฌํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ๋ฌธ์ œ๋ฅผ CSS position:absolute ์†์„ฑ์„ ์ ์šฉํ•จ์œผ๋กœ์จ ์—˜๋ฆฌ๋จผํŠธ๋“ค์„ ์ผ๋ฐ˜์ ์ธ document ํ๋ฆ„์—์„œ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ๊ณ , ์ž์œ ๋กœ์šด Drag and Drop์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ดํ›„ ์—˜๋ฆฌ๋จผํŠธ๋“ค์ด ์œ„์•„๋ž˜๋กœ ์ค‘์ฒฉ๋˜์–ด ์žˆ์–ด๋„ ์ถ”๊ฐ€์ ์ธ ๋ฌธ์ œ๋Š” ๋ฐœ์ƒํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

Code Injection ๋ฐฉ์ง€

์‚ฌ์šฉ์ž๊ฐ€ ์ž‘์—…ํ•œ HTML ์ฝ”๋“œ๋ฅผ ์ €์žฅํ•ด์ฃผ๋Š” ๋กœ์ง์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜์˜€๊ธฐ ๋•Œ๋ฌธ์— ์ €์žฅ๋œ ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ณผ์ •์—์„œ Code Injection ์ด ๊ฐ€๋Šฅํ•  ๊ฒƒ์œผ๋กœ ํŒ๋‹จํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž์˜ ์ €์žฅ๋œ ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ DOM์— ๊ทธ๋ ค์ฃผ๋Š” ๊ณผ์ •์—์„œ ์•…์„ฑ์ฝ”๋“œ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด dompurify๋ผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž์˜ ์ฝ”๋“œ๋ฅผ DOM์— ๊ทธ๋ ค์ฃผ๊ธฐ ์ „์— ์•…์„ฑ์ฝ”๋“œ๋ฅผ ํ•„ํ„ฐ๋งํ•ด์ฃผ๊ณ  ๊ทธ๋ ค์ฃผ๋Š” ์ž‘์—…์„ ๊ฑฐ์นจ์œผ๋กœ์จ ์•…์„ฑ์ฝ”๋“œ๊ฐ€ ์—†๋Š” HTML ์ฝ”๋“œ๊ฐ€ ์‚ฌ์šฉ์ž Editor์— ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

Drag and Drop ์ด์šฉํ•œ ์š”์†Œ๋“ค์˜ ์œ„์น˜ ๋ชจ๋“  ํ™”๋ฉด ํฌ๊ธฐ ๋Œ€์‘

์‚ฌ์šฉ์ž๊ฐ€ ๋งˆ์šฐ์Šค๋กœ ์กฐ์ž‘ํ•œ ์š”์†Œ๋“ค์˜ ์œ„์น˜๋ฅผ ์žก์•„์ฃผ๋Š” ๊ฒƒ์€ ๋งˆ์šฐ์Šค ์ด๋ฒคํŠธ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ขŒํ‘œ ๊ธฐ์ค€์œผ๋กœ ๊ณ„์‚ฐํ•˜์—ฌ px ๋‹จ์œ„๋กœ ์ ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ตฌํ˜„ํ•œ Editor ํฌ๊ธฐ์™€ ๋น„์œจ์ด ์ผ๋ฐ˜์ ์ธ ํ™”๋ฉด๊ณผ ๋‹ฌ๋ž๊ธฐ ๋•Œ๋ฌธ์— ํ™”๋ฉด์˜ ํฌ๊ธฐ์— ๋”ฐ๋ผ ์—˜๋ฆฌ๋จผํŠธ๋“ค์˜ ์œ„์น˜๊ฐ€ ์ง€์†์ ์œผ๋กœ ๋ณ€ํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ๊ทน๋ณตํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ™”๋ฉด์˜ ํฌ๊ธฐ์™€ ๋น„์œจ์— ๋”ฐ๋ผ ์œ„์น˜๋ฅผ ์žก์•„์ค„ ํ•„์š”๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์ตœ์ข…์ ์œผ๋กœ ๊ฒฐ์ •ํ•œ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•์€ ํ•ด๋‹น ์—˜๋ฆฌ๋จผํŠธ์˜ ๋ถ€๋ชจ width, height ๊ธฐ์ค€์œผ๋กœ ํผ์„ผํŠธ๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋‹จ์˜ ๋กœ์ง์œผ๋กœ ์—˜๋ฆฌ๋จผํŠธ์˜ left์™€ top์„ ์ด์šฉํ•˜์—ฌ ์ตœ์ข…์œผ๋กœ ์œ„์น˜์‹œ์ผœ์ค„ ๋•Œ percentage๋ฅผ ์ ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๊ฒฐ๊ณผ ์—˜๋ฆฌ๋จผํŠธ๋“ค์€ ๋ถ€๋ชจ์˜ ํฌ๊ธฐ ๊ธฐ๋ฐ˜์œผ๋กœ ์œ„์น˜ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

...
const parentContainerWidth = parentRef.current.getBoundingClientRect().width;
const parentContainerHeight = parentRef.current.getBoundingClientRect().height;

targetRef.current.style.left = `${(coordinates.x / parentContainerWidth) * 100}%`;
targetRef.current.style.top = `${(coordinates.y / parentContainerHeight) * 100}%`;
...

๐Ÿ”ฅ ์ฐธ์—ฌํ•œ ๊ฐœ๋ฐœ์ž ์†Œ๊ฐœ

๊ฐœ๋ฐœ์ž ์†Œ๊ฐœ ์ด๋ฏธ์ง€

About

Website Editor (frontend repository) ๐ŸŽจ

https://www.webgenie.online/


Languages

Language:JavaScript 99.7%Language:HTML 0.3%