๐ฅ WebGenie
์น์ฌ์ดํธ๋ฅผ ๋ง๋ค๊ณ ์ถ์ง๋ง ๋ง๋๋ ๊ณผ์ ์ด ๋ณต์กํ๊ณ ์ด๋ ค์ ๊ณ ๋ฏผํ๊ณ ๊ณ์๋์? ์์ฝ๊ฒ ์น์ฌ์ดํธ๋ฅผ ๋ง๋ค ์ ์๋ ์น ์๋ํฐ ์๋น์ค, WebGenie์ ๋๋ค!
WebGenie๋ฅผ ํตํด ๋ช ๋ฒ์ ํด๋ฆญ๊ณผ Drag and Drop์ผ๋ก ๋ฉ์ง ์น์ฌ์ดํธ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. ๋ํ, ์น์ฌ์ดํธ๋ฅผ ๋ง๋ ํ ๋ฐฐํฌํ๊ฒ ๋๋ฉด ๊ณ ์ ํ ์ฃผ์๋ฅผ ๊ฐ๊ฒ ๋์ด ์น๊ตฌ๋ค๊ณผ ์ฃผ๋ณ์ฌ๋๋ค์๊ฒ ๊ณต์ ํ ์ ์์ต๋๋ค.
# No Coding
# Beginner Friendly
๐ Contents
- ๐ฅ WebGenie
- ๐ Link
- ๐ Preview
- ๐ Getting Started
- ๐ก Motivation
- ๐ Features
- ๐ Tech Stacks
- ๐ Planning
- ๐ Technical Log
- ๐ฅ ๊ฐ๋ฐ์ ์๊ฐ
๐ Link
Deploy
Git Repository
๐ Preview
README.demo.mp4
๐ Getting Started
- Frontend(React)
- ํ๋ก์ ํธ๋ฅผ ๋ค์ด ๋ฐ์ ํ ํ๋ก์ ํธ ํด๋ ๋ด์์ ๋ช ๋ น์ด๋ฅผ ์คํํฉ๋๋ค.
npm install
npm start
- ํ๊ฒฝ๋ณ์ ํ์ผ(.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)
- ํ๋ก์ ํธ๋ฅผ ๋ค์ด ๋ฐ์ ํ ํ๋ก์ ํธ ํด๋ ๋ด์์ ๋ช ๋ น์ด๋ฅผ ์คํํฉ๋๋ค.
npm install
npm start
- ํ๊ฒฝ๋ณ์ ํ์ผ(.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
ํ
ํ๋ฆฟ์ ์ฌ๋ ค๋์ font, image, button์ drag and drop์ ์ด์ฉํ์ฌ ์์ ์์ฌ๋ก ์ด๋์ํฌ ์ ์์ต๋๋ค.
Resizing
ํ
ํ๋ฆฟ์ ์ฌ๋ ค๋์ 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}%`;
...