자바스크립트 UI를 AI로 뚝딱! 비개발자 위한 바이브 코딩 가이드
웹 UI를 프레임워크 없이 순수 자바스크립트로 구축하는 "Hard Way" 방식은 많은 개발자에게는 도전적인 접근이지만, 성능 최적화와 구조적 명확성을 통해 매우 강력한 대안이 될 수 있습니다.
자바스크립트 뷰를 "Hard Way"로 구축하기란?
이 접근은 React, Vue, Angular 같은 프레임워크 없이 명령형 자바스크립트만으로 UI를 구성하는 방식입니다. 상태 관리, DOM 업데이트, 이벤트 연결 등 모든 과정을 수동으로 처리하며, 다음과 같은 장점이 있습니다.
- 0 dependencies: 외부 라이브러리 없이 동작
- 성능 최적화: 최소한의 연산
- 높은 이식성: 어떤 환경에도 쉽게 포팅 가능
- 명확한 구조: 함수 기반 구성으로 유지보수 용이
구성 요소 설명
1. 템플릿 정의
HTML 구조는 <template>
요소를 사용하여 작성합니다.
const template = document.createElement('template');
template.innerHTML = `<div>Hello <span id="name">world</span>!</div>`;
2. 클론 생성
DOM에 삽입 가능한 복사본을 생성합니다.
function clone() {
return document.importNode(template.content, true);
}
3. 뷰 초기화 함수 (init)
뷰 인스턴스를 생성하고 상태 관리, DOM 참조, 이벤트 핸들러 등을 포함합니다.
function init() {
let frag = clone();
let nameNode = frag.querySelector('#name');
let name;
function setNameNode(value) {
nameNode.textContent = value;
}
function setName(value) {
if (name !== value) {
name = value;
setNameNode(value);
}
}
function update(data = {}) {
if (data.name) setName(data.name);
return frag;
}
return update;
}
역할별 함수 구성
역할 | 설명 |
---|---|
clone() |
템플릿을 복사하여 새로운 DOM 조각을 생성 |
init() |
상태 변수 선언 및 초기화, DOM 요소 참조, 상태 업데이트 함수 정의 |
setXNode(value) |
실제 DOM 요소를 업데이트하는 함수 |
setX(value) |
상태 변경을 감지하고 필요한 경우 DOM을 갱신 |
update(data) |
외부에서 전달받은 데이터를 바탕으로 내부 상태 갱신 |
데이터 흐름
- 부모 → 자식:
update(data)
함수 호출을 통해 상태 전달 - 자식 → 부모: 사용자 인터랙션 발생 시 커스텀 이벤트(
dispatchEvent
)를 사용해 상위 뷰에 전달
실제 사용 예시
const helloUpdate = init();
document.body.appendChild(helloUpdate({ name: 'Jinjong' }));
React 와의 비교
React | JS Hard Way |
---|---|
constructor() |
init() |
render() |
update(data) |
this.setState() |
setX(value) |
props |
update({ ... }) |
JSX / Virtual DOM | <template> + document.importNode |
유지보수 포인트
- XSS 방지: DOM 조작 시
textContent
사용을 원칙으로 - 명명 규칙:
setXNode
,setX
,updateX
와 같이 기능별 함수 분리 - 재사용성 확보: 서브뷰는
init()
을 다시 호출하여 독립적으로 관리 - 디버깅 용이성: 얕은 콜스택으로 디버깅 간소화
실전 활용 예시
- 대시보드 구성: 실시간 데이터 업데이트 뷰 작성에 유리
- IE 호환 필요 시스템: 구형 브라우저 지원 프로젝트에서 유용
- 보안 시스템 UI: 외부 라이브러리 의존을 제거하여 안정성 확보
추천 학습 순서
- DOM API (querySelector, textContent, addEventListener 등)
- 템플릿 사용법 (
<template>
,importNode
) - 상태 분리 패턴 (
setXNode
,setX
) - 이벤트 위임 및 커스텀 이벤트 사용
- 모듈화 및 뷰 조립 방식
추가적으로 WebComponent 방식이나 TypeScript 기반 구조 확장에 대해서도 고려해볼 수 있습니다.
아래는, 실제 웹 UI에 가까운 구조를 프레임워크 없이 순수 자바스크립트로 "탭 UI"를 만드는 예시입니다.
목표: 탭 UI 만들기
탭 버튼을 누르면 각기 다른 콘텐츠가 표시되는 UI를 만들어 봅니다.
[ 탭1 ] [ 탭2 ] [ 탭3 ]
→ "이곳은 탭 1의 내용입니다."
구성 요소
- 탭 버튼들
- 탭에 따라 바뀌는 콘텐츠 영역
- 선택된 탭 표시 및 동작 제어
1️⃣ HTML 구조 (템플릿 정의)
const template = document.createElement('template');
template.innerHTML = `
<style>
.tab-button {
padding: 10px;
border: 1px solid gray;
background: white;
cursor: pointer;
}
.tab-button.active {
background: lightblue;
font-weight: bold;
}
.tab-content {
padding: 15px;
border: 1px solid gray;
margin-top: 10px;
}
</style>
<div>
<div id="tabs">
<button class="tab-button" data-tab="1">탭1</button>
<button class="tab-button" data-tab="2">탭2</button>
<button class="tab-button" data-tab="3">탭3</button>
</div>
<div id="content" class="tab-content">이곳은 탭 1의 내용입니다.</div>
</div>
`;
✔️ HTML 구조와 함께 <style>
로 기본 스타일도 포함되어 있어요.
2️⃣ 클론 함수 작성
템플릿을 실제 DOM 요소로 만들어주는 함수입니다.
function clone() {
return document.importNode(template.content, true);
}
3️⃣ 초기화 함수
상태 관리, 이벤트 연결, 탭 선택 시 UI 업데이트를 담당합니다.
function init() {
const frag = clone();
const buttons = frag.querySelectorAll('.tab-button');
const content = frag.querySelector('#content');
let currentTab = '1'; // 초기값: 탭1
const tabContents = {
'1': '이곳은 탭 1의 내용입니다.',
'2': '여기는 탭 2의 내용입니다!',
'3': '이건 탭 3의 내용이에요.'
};
function setActiveTab(tabId) {
if (tabId === currentTab) return;
// 1. 모든 버튼에서 active 제거
buttons.forEach(btn => btn.classList.remove('active'));
// 2. 선택된 버튼에 active 추가
const selectedBtn = [...buttons].find(btn => btn.dataset.tab === tabId);
if (selectedBtn) selectedBtn.classList.add('active');
// 3. 콘텐츠 변경
content.textContent = tabContents[tabId];
currentTab = tabId;
}
// 초기 탭 상태 설정
setActiveTab(currentTab);
// 이벤트 연결
buttons.forEach(btn => {
btn.addEventListener('click', () => {
setActiveTab(btn.dataset.tab);
});
});
return frag;
}
4️⃣ DOM에 UI 삽입
const view = init();
document.body.appendChild(view);
코드 전체 보기
index.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<title>탭 UI</title>
</head>
<body>
<script src="tab-ui.js"></script>
</body>
</html>
tab-ui.js
const template = document.createElement('template');
template.innerHTML = `
<style>
.tab-button {
padding: 10px;
border: 1px solid gray;
background: white;
cursor: pointer;
}
.tab-button.active {
background: lightblue;
font-weight: bold;
}
.tab-content {
padding: 15px;
border: 1px solid gray;
margin-top: 10px;
}
</style>
<div>
<div id="tabs">
<button class="tab-button" data-tab="1">탭1</button>
<button class="tab-button" data-tab="2">탭2</button>
<button class="tab-button" data-tab="3">탭3</button>
</div>
<div id="content" class="tab-content">이곳은 탭 1의 내용입니다.</div>
</div>
`;
function clone() {
return document.importNode(template.content, true);
}
function init() {
const frag = clone();
const buttons = frag.querySelectorAll('.tab-button');
const content = frag.querySelector('#content');
let currentTab = '1';
const tabContents = {
'1': '이곳은 탭 1의 내용입니다.',
'2': '여기는 탭 2의 내용입니다!',
'3': '이건 탭 3의 내용이에요.'
};
function setActiveTab(tabId) {
if (tabId === currentTab) return;
buttons.forEach(btn => btn.classList.remove('active'));
const selectedBtn = [...buttons].find(btn => btn.dataset.tab === tabId);
if (selectedBtn) selectedBtn.classList.add('active');
content.textContent = tabContents[tabId];
currentTab = tabId;
}
setActiveTab(currentTab);
buttons.forEach(btn => {
btn.addEventListener('click', () => {
setActiveTab(btn.dataset.tab);
});
});
return frag;
}
const view = init();
document.body.appendChild(view);
- textContent 사용: 사용자 입력이 콘텐츠로 들어가는 경우 반드시 XSS 방지
- 명확한 클래스 이름 사용:
.tab-button
,.tab-content
처럼 의미 중심의 네이밍 - 상태값과 DOM 분리:
currentTab
변수와 UI 업데이트 분리하여 유지보수 용이
이 구조를 기반으로 탭 안에 폼 추가, AJAX로 데이터 로딩, 다크모드 토글, 탭 상태 저장 등 고급 확장도 가능합니다.
이번에는 비개발자도 따라할 수 있는 ‘탭 전환 UI’ 웹앱 만들기 여정을 바이브 코딩에 맞춰 코드를 한 줄도 몰라도,
이 과정을 따라가면 “내가 직접 만든 웹앱”을 구현할 수 있습니다.
1단계. 요즘 AI로 이런 것까지 된다고요?
✅ 해보는 것부터 시작입니다.
Gemini, Claude, Lovable 같은 생성형 AI 도구에 "웹 UI를 만들어줘"라고 말해보세요.
예시 프롬프트
“HTML과 JavaScript만으로 탭 UI를 만들어줘. 탭 버튼 3개를 누르면 내용이 바뀌는 구조로 부탁해.”
그러면 코드를 ‘뿅’ 하고 만들어줄 거예요. 이게 바로 바이브 코딩의 시작입니다.
코딩을 몰라도 “프롬프트 한 줄로 웹앱을 만들 수 있는 시대”라는 걸 직접 체험해보세요.
🔍 요즘 어떤 AI들이 있나요?
도구 | 특징 |
---|---|
Gemini (구글) | 무료 사용 가능, Canvas 모드에서 UI 바로 확인 |
Claude (Anthropic) | 긴 문서 처리에 탁월 |
Lovable | PRD 넣으면 바로 앱으로, 수정은 클릭만으로 |
Cursor | 코딩 에이전트지만 초보자는 나중에 접근 추천 |
2단계. 내가 만들고 싶은 걸 정확히 정의하기
🤔 내가 풀고 싶은 문제는?
- 사용자가 버튼을 누르면 다른 내용을 보여주는 UI를 만들고 싶다.
- 고객이 메뉴를 쉽게 전환하면서 정보를 확인할 수 있는 페이지가 필요하다.
✍️ 이렇게 질문해보세요.
- 누가 쓸 건가요? → 홈페이지 사용자
- 어떤 상황에서 필요한가요? → 정보를 메뉴 탭 형태로 나누어 보고 싶을 때
- 기존에는 어떻게 하고 있나요? → 한 페이지에 내용이 모두 있어서 복잡하게 느껴짐
- 더 나은 방법은? → 탭 UI로 구분해서 깔끔하게 정리된 정보를 제공
📄 LLM에게 이렇게 말해보세요. (PRD 작성)
“사용자가 버튼을 눌러서 각기 다른 콘텐츠를 볼 수 있는 간단한 탭 UI를 만들고 싶습니다. HTML, CSS, JavaScript만 사용할 거고, 탭은 3개, 내용은 탭1은 소개, 탭2는 제품, 탭3은 연락처로 보여줘.”
3단계. 눈으로 결과를 직접 확인하며 고치기
👀 프리뷰 가능한 도구에서 실험해봐요.
추천 도구: Gemini Canvas 또는 Lovable
Gemini는 프롬프트 입력 후 바로 결과를 브라우저에서 미리 볼 수 있고,
Lovable은 클릭해서 텍스트나 색상을 직접 수정할 수 있어요.
💬 수정하고 싶은 부분은 이렇게 말해요.
- “버튼을 가운데 정렬해주세요.”
- “버튼 색깔을 초록색으로 바꿔주세요.”
- “탭1의 내용을 '회사 소개'로 수정해주세요.”
✨ 이렇게 말해도 됩니다.
“탭 UI에 간단한 스타일을 추가해서 보기 좋게 만들어줘. 버튼에 간격을 주고, 선택된 탭은 파란색으로 표시되게 해줘.”
4단계. AI에게 정확하게 부탁하는 법 배우기 (프롬프팅 기술)
📦 구조를 설명하면서 요청하면 더 좋아요
“HTML은 탭 버튼 영역과 콘텐츠 영역으로 나눠주세요. 각 탭 버튼은 data-tab 속성으로 구분하고, JavaScript로 해당 콘텐츠를 보여줄 수 있도록 해주세요.”
🗂️ 예시 결과 구조
<div class="tabs">
<button data-tab="1">소개</button>
<button data-tab="2">제품</button>
<button data-tab="3">연락처</button>
</div>
<div class="content">여기에 내용이 나옵니다.</div>
이런 구조를 AI가 만들어주고, 탭을 누르면 내용이 바뀌는 코드를 자동으로 짜줍니다.
5단계. 마무리 다듬기 & 오류 고치기
🐞 혹시 이런 문제가 생겼나요?
- 탭을 눌렀는데 아무 반응이 없음
- 내용이 바뀌지 않음
- 스타일이 적용되지 않음
AI에게 이렇게 피드백 해주세요.
“버튼을 눌렀는데 내용이 바뀌지 않습니다. JavaScript 코드를 점검해주세요.”
“선택된 버튼에만 스타일이 적용되도록 수정해주세요.”
📦 완성 후 저장 & 공유
- Gemini: 코드 복사해서 CodePen에 붙여넣기 → 바로 실행됨
- Lovable: 링크 공유 기능으로 친구에게 앱 보여주기
- Cursor/Replit: 코드를 저장해서 이어서 작업할 수 있음
마무리: 나는 지금 진짜 웹앱을 만든 거예요
여러분이 만든 건 단순한 코드가 아닙니다.
AI를 활용해 직접 아이디어를 구현한 ‘작은 웹앱’이자 프로덕트입니다.
이제부터는 이렇게 만들어볼 수 있어요.
- 💬 “나만의 Q&A 챗봇”
- 🧾 “작업 요청 폼 앱”
- 📅 “일정 관리 미니 캘린더”
- 🎲 “랜덤 추첨기”
팁: 내가 만든 걸 계속 발전시키려면?
- 같은 구조로 다크모드 추가 도전해보기
- 콘텐츠 영역을 카드 형태 UI로 바꾸기
- 버튼 대신 탭 메뉴 아이콘으로 바꿔보기
- 외부 데이터 연동해서 실시간 정보 띄워보기
✨ 다음 스텝이 궁금한가요?
다음에는 이 탭 UI를 확장해서 "상품 리스트 + 상세 보기"로 연결해보거나,
"피드백 폼 제출 후 메시지 보여주기" 같은 기능도 추가해볼 수 있어요.
자신감이 생기셨다면 Lovable, Gemini, Cursor 등 도구별로 따라하는 영상/프롬프트도 시도해볼 수 있습니다.
여러분도 이젠 메이커입니다.
직접 만든 웹앱을 친구들에게 보여주고, 자신만의 도구를 만들어보세요.
AI 시대, 우리는 코드를 몰라도 ‘코딩’할 수 있습니다.