안녕하세요, GPTers 여러분! 단테입니다.
오늘은 안드로이드폰을 나만의 홈서버로 탈바꿈시키는 과정을 단계별로 공유해 드리려고 합니다. 복잡하게만 느껴졌던 서버 구축, 이제 여러분의 손안에 있는 스마트폰으로 직접 해볼 수 있습니다! 이 가이 드만 따라오시면 누구나 쉽게 전문가처럼 나만의 웹사이트, 블로그, n8n 서버를 호스팅할 수 있게됩니다.💪
가이드 활용법
본 가이드 문서만으로도 서버 설치 진행이 가능합니다.
아래의 유튜브 채널 영상을 함께 보시면 보다 이해가 쉽습니다.
(영상 바로가기) 유튜브 영상 링크
https://youtu.be/trjUbvSXfmc?si=4PGxJZn9xuSLd2L5
진행 방법
🎯 프로젝트 개요
목표: 안드로이드폰을 활용해 나만의 포트폴리오 웹사이트를 구축하고, Cloudflare 터널링을 통해 외부에서 접속 가능한 상태로 만들기.
핵심 기술: 클로드 코드, Cloudflare Tunnel, VSCode 서버, Termux
예상 시간: 2~3시간
준비물: 안드로이드 스마트폰, PC (Mac 또는 Windows), USB 케이블, 그리고 약간의 도전 정신 😊
핵심개념 : 애플리케이션 터널링 배우기
서비스명 : CloudFlare Tunnel (Zero Trust Free)
정의 : 외부에서 직접 접근할수 없는 내부 컴퓨터/서비스에 안전한 전용 통로를 만들어 접속 하게 하는 방법을 터널링이라고 합니다.
장점
무료입니다. Zero Trust Free요금제를 사용하면 됩니다. 개인 용도에서는 충분하다고 볼수있습니다.
공인 IP가 없어도 됩니다. 이 말은, 공유기 같은 라우터가 없어도 되기 때문에 장소가 바뀌어도 인터넷만 연결되어 있으면 접속이 가능하다는 말입니다.
보안성이 높습니다. 통로가 암호화되어 해킹으로부터 안전합니다.
설정이 간단합니다. VPN 처럼 설치가 어렵지 않습니다.
스마트폰 서버 설치 튜토리얼
1. 안드로이드폰 공장 초기화
안드로이드 초기화 후, 초기 설정을 진행해주세요. 서버용도로 사용되는 만큼 불필요한 기본 앱과 설정 등은 피해주세요.
2. Mac 또는 윈도우에 scrcpy 설치
Mac 설치방법
Homebrew(패키지 관리 프로그램) 설치: 터미널에 다음 명령어 입력
/bin/bash -c "$(curl -fsSL <https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh>)"/bin/bash -c "$(curl -fsSL <https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh>)"scrcpy 및 android-platform-tools 설치:
brew install scrcpy brew install android-platform-tools` # 또는 (Homebrew 버전에 따라 다릅니다) brew install --cask android-platform-tools터미널을 재시작하고 설치 여부 확인
scrcpy -v
Windows 설치 방법
공식 배포 사이트에서 scrcpy 다운로드 (다운로드 링크)
Windows용 zip 파일을 다운로드하고 압축 해제.
C:\scrcpy 폴더로 압축해제된 파일 저장
고급시스템설정 → 환경변수 등록
다운로드 받은 scrcpy를 터미널 전역에서 사용할수 있도록 환경변수를 아래 절차대로 등록합니다.
C:\\scrcpy
이후 모든 열린 창을 [확인] 버튼을 눌러 닫기
터미널을 열어 정상 설치 여부 확인
scrcpy -v
3. USB디버깅 와 무선디버깅 활성화
설정 → 휴대전화 정보
4. 안드로이드 폰을 PC에 USB로 연결
안드로이드 폰을 집의 공유기에 와이파이로 연결합니다.
USB로 내PC에 연결합니다. 연결하면 USB 디버깅 허용 여부를 물으면 허용 버튼을 누릅니다.
터미널(파워셀에서 아래 명 령실행하면 미러링 창이 뜹니다.
5. 리눅스 앱 설치
termux 설치
플레이스토어에서 설치 : https://play.google.com/store/apps/details?id=com.termux
Github에서 다운 및 설치 : https://github.com/termux/termux-app/releases
6. Termux 실행 / 터미널 접속
7. 우분투 실행 / 초기 설정
8. SSH 원격 접속
노트북에서 SSH 접속
같은 공유기의 WIFI 네트워크로 개인노트북을 이용해 접속합니다. Mac 유저는 ‘터미널’ 윈도우즈 유저는 ‘Powershell’ 창을 열어서 접속을 시도합니다.
포트번호는 8022 이며, 사용자 ID는 위에서
whoami로 확인한 ID로 접속합니다.ssh [사용자ID]@[프라이빗네트워크주소] ex) ssh [email protected] # 여기서는 u0_a288과 192.168.219.117이니 여러분의 주소에 맞게 수정하세요. # 명령어 입력후 암호 입력합니다.
암호가 아닌 인증키 기반으로 ssh 접속을 하기 위해, ssh 인증키를 생성해서 설정해야합니다.
# 공개키와 비밀키 쌍 생성
ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_phone
(엔터 2번)
# 출력된 공개키 내용을 미니PC 서버에 저장
ssh-copy-id -i ~/.ssh/id_phone.pub -p 8022 [사용자ID]@[프라이빗네트워크주소]
(엔터, 압호입력)
# 다시 서버 접속
ssh -i ~/.ssh/id_phone root@[프라이빗네트워크주소]
우분투 접속
내 PC → ssh → Termux → Ubuntu 순으로 접속되는 것입니다.
# Termux 쉘에서
./start-ubuntu22.sh
tmux 설치
tmux는 터미널에서 세션을 유지하고 창/패널을 나눠 여러 작업을 동시에 다루게 해주는 터미널 멀티플렉서 명령어입니다.
흔히 원격 접속이 끊겨도 작업을 이어가거나, 하나의 터미널에서 여러 창과 분할 화면을 운영할 때 사용합니다.
우분투에서 여러 서버를 작동하고 서버 프로세스가 스마트폰의 슬립모드 정책에 의해 종료되지 않도록 termux-wave-lock 설정으로 해주고나서, Termux 앱 안의 터미널 세션을 멀티로 유지해줍니다.
9. VSCode 서버 설치
curl 패키지 설치
apt install -y curlvscode 다운로드 및 설치
curl -fsSL <https://code-server.dev/install.sh> | sh비밀번호 및 포트번호 설정
cat > /root/.config/code-server/config.yaml# 엔터 후 아래 내용 입력
bind-addr: 127.0.0.1:8080
auth: password
password: 12345678 # <<< 비밀번호 변경하세요.
cert: false
(Ctrl + C) 입력하여 빠져나오기
tmux 세션 실행 (이름은 : code)
tmux new -s code# 세션명 : code서버 실행
code-server --bind-addr 0.0.0.0:8080tmux 세션 나오기
작업 수행하고 나서 ctrl+b 누르고, detach 입력 하면 세션을 빠져나옵니다. 세션은 백그라운드로 전환되어 작업이 종료되지 않습니다.
웹브라우저에서 접속하기
192.168.x.x:8080으로 접속할수 있습니다. 내부망 IP는 위에 확인 방법을 기재해두었습니다.
10. Node.js 설치
node 22 버전 설치
apt install curl ca-certificates gnupg -y
curl -fsSL <https://deb.nodesource.com/setup_22.x> -o nodesource_setup.sh
bash nodesource_setup.sh
apt install nodejs -y
node -v
npm -v
11. Cloudflare 도메인 등록
도메인 검색 및 구매 (cloudflare에서 도메인을 구매하지 않고 타사에서 구매한 경우는 Skip 하세요)
타사 도메인 등록 (Cloudflare 도메인 구입한 경우 Skip 하세요)
포트폴리오 웹사이트 바이브 코딩 및 호스팅하기
이번 바이브 코딩은 안드로이드의 리눅스에 Ubuntu 22 배포판을 Proot-distro 방식으로 설치한 환경에서 root 계정으로 진행하게 됩니다.
완전한 우분투 환경이 아닌 컨테이너 방식으로, 제약사항들이 있습니다.Docker 는 지원되지 않고, servicectl이나 ps 같은 프로세스 명령어들이 동작하지 않는 점이 있습니다.
claude code에 이런 환경적인 부분을 컨텍스트에 제공하면 서버 설정과 코딩을 더 수월하게 하실수 있습니다.제가 수차례 테스트한 프롬프트이지만, LLM의 특성상 ‘의외성’과 ‘무작위성’이 있어 결과가 달라질수 있습니다.
만약 바이브코딩으로 설정이 실패한다면, 중고급자 분들은 발생하는 에러를 컨텍스트에 추가하면서 수정하시는 것을 추천드리고, 초급자 분들은 모두 지우고 처음부터 다시 하시는것을 추천드립니다.
VSCode 서버 접속 / 컨텍스트 문서 준비
vscode서버를 내부망 IP주소로 접속 (예시 : http://192.168.219.117:8080 여러분은 주소가 다릅니다)
접속한뒤에 컨텍스트 파일을 ref 폴더를 만들어 하나씩 저장합니다.
prompt.md (각자에 맞게 내용을 수정하세요, Figma 템플릿 주소를 수정하셔야 합니다.)
# 생성 요청 프롬프트 (강화버전)
## 1) 역할 / 페르소나
당신은 개인 포트폴리오 웹사이트 제작 전문 개발자이다. 다음 MCP 도구를 활용해서 맥락을 파악하여 포트폴리오 웹사이트를 완성해야한다.
## 2) 목표 / 의도
* Figma 참고 포트폴리오 웹사이트 디자인 템플릿을 기반으로 개인 포트폴리오 웹사이트를 구축한다.
* 디자인 → 구조 → 콘텐츠 삽입 → 테스트 → 배포의 일관된 워크플로우를 따른다.
* 사용자가 제공하는 1)포트폴리오 웹사이트 템플릿 컨텍스트와 2)개인 스펙 문서를 기반으로 개별 맞춤 콘텐츠를 반영한다.
## 3) 배경정보
* 템플릿 프로젝트 : https://www.figma.com/design/fzR2M4whnQv4KdKIiE6Bdx/Picto---Personal-Portfolio-Free-Template--Community---Community-
* 개인 스펙 문서 : /root/vibe-portfolio/ref/my-info.md 파일에 저장되어 있다.
* 이메일 전송 코드 스니펫 : /root/vibe-portfolio/ref/resend-example.md
## 4) 사용해야할 MCP도구
* Context7: Vite + React.js, Node.js의 최신 문법과 사용 예제 들을 확인한다.
* SequentialThinking: 전체 절차를 단계별로 계획하고, 각 단계가 다음 단계로 이어지도록 한다.
* Pexels: 필요한 이미지를 조회하고 다운로드하고 ./public/images에 저장하고 웹페이지에 연결한다.
* Playwright: 생성된 웹사이트를 브라우저 테스트하고 브라우저 동작을 시뮬레이션한다.
* FigmaDev: 피그마 디자인 문서를 조회하여 웹사이트의 기본 구조와 스타일 가이드를 제공한다. 단, 피그마 디자인 문서의 크기가 허용치 초과시, 하위 노드들을 조회하고 하위 노드를 하나씩 조회하여 전체 구조와 디자인, 색상 및 폰트 테마를 파악한다.
* ssh / scp : 원격 서버로 코드를 배포 및 스크립트 실행 등의 작업을 한다.
## 5) 기술 스택 및 아키텍처 (중요)
### 프로젝트 구조
```
├── public/
│ └── images/ # 이미지 파일 (Pexels에서 다운로드)
├── src/
│ ├── components/ # React 컴포넌트
│ ├── content.json # 한글 콘텐츠 관리
│ ├── App.jsx
│ ├── main.jsx
│ └── index.css
├── server.js # Express 서버 (ES6 모듈 사용)
├── vite.config.js # Vite 설정
├── package.json
└── .env # 환경 변수 (RESEND_API_KEY, PORT)
```
### 핵심 기술 선택
* **프론트엔드**: React 19 + Vite
* **백엔드**: Node.js Express (ES6 모듈 - `"type": "module"` 필수)
* **빌드 도구**: Vite
* **이메일 서비스**: Resend.com API
### package.json 필수 설정
```json
{
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"server": "node server.js",
"start": "npm run server"
}
}
```
## 6) 중요 구현 지침 (시행착오 방지)
### 6.1) Express 서버 구현 시 주의사항
#### ✅ 올바른 라우트 순서 (매우 중요!)
```javascript
import express from 'express';
import cors from 'cors';
import dotenv from 'dotenv';
import { Resend } from 'resend';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
dotenv.config();
const app = express();
const resend = new Resend(process.env.RESEND_API_KEY);
app.use(cors());
app.use(express.json());
// 1. API 라우트를 먼저 정의 (중요!)
app.post('/api/send-email', async (req, res) => {
// 이메일 전송 로직
});
// 2. 정적 파일 서빙은 API 라우트 다음에 (순서 중요!)
app.use(express.static(path.join(__dirname, 'dist')));
// 3. Express 5에서는 와일드카드 라우트 사용 안함
// app.get('*', ...) 또는 app.get('/*', ...) 사용하지 말 것
const PORT = process.env.PORT || 5001; // 5000번 포트는 macOS에서 충돌 가능
```
### 6.2) Vite 프록시 설정
```javascript
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
server: {
port: 3001, // 3000번 대신 3001 사용
proxy: {
'/api': {
target: 'http://localhost:5001', // Express 서버 포트와 일치
changeOrigin: true,
},
},
},
});
```
### 6.3) 환경 변수 설정
```env
RESEND_API_KEY=your_actual_api_key_here
PORT=5001
```
### 6.4) 이미지 경로 설정
* Pexels 이미지는 `/public/images/` 디렉토리에 저장
* React 컴포넌트에서 참조 시: `<img src="/images/filename.jpg" />`
* CSS에서 참조 시: `url('/images/filename.jpg')`
### 6.5) API 호출 시 주의사항
```javascript
// Contact.jsx에서 이메일 전송
const handleSubmit = async (e) => {
e.preventDefault();
try {
const response = await fetch('/api/send-email', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formData),
});
const data = await response.json();
if (data.success) {
// 성공 처리
} else {
// 실패 처리
}
} catch (error) {
console.error('Email send error:', error);
}
};
```
## 7) 출력형식 및 제약조건
* 단계적 접근: SequentialThinking 도구로 각 단계별 액션을 계획하고 실행한다.
* 1단계) 피그마 웹페이지디자인의 구조, 스타일, 테마, 폰트, 색상 등을 먼저 정리해서 design.md 에 저장한다.
* 2단계) Vite + React 프로젝트를 생성하고 Express 서버를 설정한다.
* 3단계) 컴포넌트별로 하나씩 구현하며 content.json에서 한글 콘텐츠를 관리한다.
* 4단계) 정적파일과 이미지를 생성하고, 컴포넌트에 내용을 연결한다.
* 5단계) 기능과 디자인을 점검 테스트한다 (특히 이메일 전송 기능).
* 6단계) 프로젝트를 빌드한다 (`npm run build`).
* 7단계) README.md 파일을 만들어서 프로젝트 명세를 작성한다.
* 8단계) 원격서버에 프로젝트를 복사(배포) 하고, 프로덕션을 위해 서버(3001번 포트)를 가동한다.
* 9단계) cloudflare 터널링을 사용해서 정해진 주소로 웹사이트 페이지를 외부로 노출한다.
* 사용 기술:
- Frontend: React + Vite
- Backend: Node.js Express (ES6 모듈)
- Email: Resend.com API
* 페이지 구성 지침: 1페이지를 여러 섹션으로 나누고 Nav바에서 선택된 항목에 해당하는 섹션으로 자동 스크롤로 구성한다.
* 정적 내용 관리지침: 정적 내용 (카피, 제목, 아티클)은 모두 한글로 작성되어야 하며, content.json 파일 하나에서 관리한다.
* 템플릿 일관성: 템플릿 코드의 수정하여 개발함으로서 디자인과 구조의 일관성을 유지한다. 개인스펙문서에 없는 정보의 템플릿 섹션은 제거한다. 템플릿에 있는 예시 이미지(인물사진 등)은 모두 Pexels에서 가져온 이미지로 교체한다.
* 폰트 및 테마:
- 테마는 템플릿의 정보를 유지
- 한글 폰트는 '나눔스퀘어' 사용
- CSS에서: `@import url('https://hangeul.pstatic.net/hangeul_static/css/nanum-square.css');`
- font-family: `'Nanum Square', sans-serif;`
* 정확성: 개인스펙문서의 정보는 그대로 반영해야 한다.
* 검증 완료: Playwright 도구 테스트에서 오류가 없는 상태로 마무리한다. Playwright로 인터랙티브 동작으로 기능 구현을 확인하고, 스크린샷을 찍어서 화면 상태와 UI을 확인한다.
## 8) 세부기능
### 이메일 전송 기능
* Resend.com 라이브러리를 활용해서 서버사이드에 구축한다.
* 수신 이메일 주소는 개인스펙문서의 이메일 또는 사용자가 지정한 주소를 사용한다.
* 발신자는 'Portfolio Contact <[email protected]>' 형식을 사용한다.
* 한글 제목과 내용을 지원해야 한다.
## 9) 테스트 체크리스트
개발 완료 전 다음 사항을 반드시 확인:
- [ ] React 개발 서버가 3001 포트에서 정상 작동
- [ ] Express 서버가 5001 포트에서 정상 작동
- [ ] 이메일 전송 API가 정상 작동 (`/api/send-email`)
- [ ] 모든 이미지가 정상적으로 로드됨
- [ ] 네비게이션 스크롤이 부드럽게 작동
- [ ] 반응형 디자인이 모바일/태블릿/데스크톱에서 정상 작동
- [ ] 빌드된 프로덕션 버전이 정상 작동
## 10) Cloudflare
## 11) 자주 발생하는 문제와 해결책
### 문제 1: API 엔드포인트가 HTML을 반환
**원인**: Express에서 정적 파일 서빙이 API 라우트보다 먼저 처리됨
**해결**: API 라우트를 정적 파일 서빙보다 먼저 정의
### 문제 2: Express 5 와일드카드 라우트 에러
**원인**: Express 5에서 `app.get('*')` 구문 변경
**해결**: 와일드카드 라우트 제거, 정적 파일 서빙만 사용
### 문제 3: ES6 모듈 import 에러
**원인**: package.json에 `"type": "module"` 누락
**해결**: package.json에 `"type": "module"` 추가
### 문제 4: __dirname is not defined 에러
**원인**: ES6 모듈에서 __dirname 사용 불가
**해결**: `import.meta.url`과 `fileURLToPath` 사용my-info.md (각자에 맞게 내용을 수정하세요, 개인 스펙 문서 정보를 수정해주셔야합니다.)
## 1. 기본 정보
* **이름**: 김준서 (Junseo Kim)
* **닉네임 / 작명**: digitmarketer
* **프로필 사진 URL**: `pexels에서 샘플이미지로 대체`
* **간단한 소개**:
데이터 기반 마케팅 전략과 디지털 캠페인 자동화에 특화된 디지털마케터. 최신 AI·데이터 분석 기술을 활용해 브랜드 성장과 고객 경험 혁신을 이끌어냅니다. 다양한 산업군에서 실전 마케팅 프로젝트를 리딩하며, 성과 중심의 데이터 마케팅 솔루션을 제공합니다.
---
## 2. 연락처 정보
* **이메일**: `[email protected]`
* **전화번호**: `+82-10-9876-5432`
* **Youtube** : [https://www.youtube.com/@junseo-marketing](https://www.youtube.com/@junseo-marketing)
* **Homepage** : [https://junseo-marketing.com](https://junseo-marketing.com)
* **LinkedIn**: [www.linkedin.com/in/junseo-kim-marketing](www.linkedin.com/in/junseo-kim-marketing)
* **개인 블로그**: [junseo-marketing.dev](https://junseo-marketing.dev)
---
## 3. 경력 / 경험
* **현재 직무**: 디지털마케팅 컨설턴트 / 데이터 기반 마케팅 자동화 전문가
* **경력 요약**:
10년 이상 디지털 마케팅, 데이터 분석, AI 기반 마케팅 자동화 프로젝트를 리딩. 이커머스, 플랫폼, B2B/B2C 등 다양한 산업에서 마케팅 전략 수립과 실행 경험 보유. 데이터 기반 퍼포먼스 마케팅, 고객 여정 분석, 마케팅 자동화 시스템 구축에 강점.
* **주요 경력**:
* **2024–현재**: 데이터마케팅랩 – 디지털마케팅 컨설팅 및 자동화 솔루션 개발
* **2022–2023**: 넥스트커머스 – 데이터 기반 마케팅 전략 및 캠페인 운영
* **2021–2022**: 테크솔루션즈 – AI 기반 고객 데이터 분석 및 마케팅 솔루션 개발
* **2019–2021**: 그린라이프 그룹 – 이커머스 마케팅 데이터 분석 및 최적화
* **2017–2019**: 푸드테크 그룹 – 브랜드 마케팅 데이터 분석 및 캠페인 기획
---
## 4. 학력
* **대학교**: 서울디지털대학교 디지털마케팅학과 (B.S. in Digital Marketing, 2017 졸업)
---
## 5. 기술 스택
* **마케팅 툴**: Google Analytics, Tableau, Power BI, Salesforce Marketing Cloud, HubSpot, Braze, Google Ads, Facebook Ads Manager
* **데이터 분석/엔지니어링**: Python, SQL, BigQuery, AWS Redshift, PySpark, ElasticSearch
* **마케팅 자동화/AI**: MCP 기반 마케팅 자동화, AI 추천 시스템, 퍼널 분석, 텍스트 마이닝, AARRR 프레임워크
* **기타**: Docker, GitHub Actions, Figma
---
## 6. 프로젝트
* **프로젝트명**: 스마트 마케팅 자동화 플랫폼
* **설명**: 고객 행동 데이터 분석을 통한 맞춤형 마케팅 자동화 플랫폼 구축
* **역할**: 프로젝트 리딩, 데이터 분석, 마케팅 자동화 설계 및 실행
* **기술**: Python, BigQuery, Salesforce Marketing Cloud, MCP
* **프로젝트명**: 실시간 캠페인 성과 분석 시스템
* **설명**: 실시간 광고 성과 및 고객 여정 시각화 대시보드 개발
* **역할**: 데이터 파이프라인 설계, 대시보드 구축, 마케팅 인사이트 도출
* **기술**: SQL, Tableau, Google Analytics, Python
---
## 7. 수상 및 자격증
* **2021**: 디지털 마케팅 혁신 컨퍼런스 – 최우수상 (AI 기반 마케팅 자동화 솔루션 개발)
* **2018**: Google Analytics Individual Qualification (GAIQ)
* **2017**: ADsP 데이터분석준전문가
---
## 8. 기타 개인화 요소
* **취미 / 관심사**: 디지털 아트, 마케팅 트렌드 연구, 여행, AI 기반 마케팅 실험
* **개인 모토**: "데이터는 최고의 마케터다."
---
> 참고: 김준서의 경력 및 전문성은 [공식 프로필](https://junseo-marketing.com/profile/)을 참고하세요.
[출처: https://junseo-marketing.com/profile/]
resend-example.md (각자에 맞게 내용을 수정하세요. API키를 수정하셔야 합니다.)
```javascript
import { Resend } from 'resend';
const resend = new Resend('re_4iHAn8qM_LUkjctQjoQmcGLsvEKkkRFqQ');
resend.emails.send({
from: '[email protected]',
to: '[email protected]',
subject: 'Hello World',
html: '<p>Congrats on sending your <strong>first email</strong>!</p>'
});
```cloudflare.md (각자에 맞게 내용을 수정하세요. 도메인 주소와 터널명을 수정하셔야 합니다.)
# Cloudflare 터널링 가이드
## 1. 패키지 관리자 업데이트
`apt update && apt upgrade -y`
## 2. cloudflare 공식 저장소 및 GPG키 추가
```bash
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflared.list
```
## 3. 패키지 리스트 갱신 및 cloudflare 설치
`apt update && apt install cloudflared`
## 4. cloudflare 임시 터널링
`cloudflared tunnel --url http://localhost:5001 2>&1 &`
## 5. cloudflare 계정 연동 및 인증 (인증 페이지 링크 제시 후 cloudflare 계정 로그인 유도)
`cloudflared tunnel login`
## 6. cloudflare 터널 생성
`cloudflared tunnel create dante-phone-tunnel` # <<< 터널이름 변경하세요
## 7. cloudflare 터널 설정
`cat > /root/.cloudflared/config.yml`
```yaml
############ 아래 내용을 복사해서 붙여넣으세요 ###########
tunnel: xxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxx # 터널ID
credentials-file: /root/.cloudflared/xxxxxx-xxxxx-xxxxx-xxxx-xxxxxxx.json # 터널ID.json
ingress:
- hostname: n8n.dante-labs.com # <<< 주소 변경하세요
service http://localhost:5679
- hostname: portfolio.dante-labs.com # <<< 주소 변경하세요
service http://localhost:5001
- service http_status:404
############ 위 내용을 복사해서 붙여넣으세요 ###########
(Ctrl+C를 눌러 편집 종료)
```
## 8. DNS 연결
```bash
cloudflared tunnel route dns dante-phone-tunnel n8n.dante-labs.com # <<< 서브 도메인 주소 및 터널명을 변경하세요
cloudflared tunnel route dns dante-phone-tunnel portfolio.dante-labs.com # 서브 도메인 주소 및 터널명을 변경하세요
## 9. cloudflare 터널 실행
`cloudflared tunnel run`
# n8n + Caddy 리버스 프록시 설정 가이드
이 가이드는 proot-distro Ubuntu 22.04 환경에서 n8n을 설치하고 Caddy를 사용하여 포트 5678에서 실행되는 n8n을 포트 5679로 리버스프록시하는 방법을 설명합니다.
## 전제조건
- proot-distro Ubuntu 22.04 환경
- Node.js 및 npm 설치
- 기본적인 Linux 명령어 사용 능력
## 1. 시스템 업데이트 및 필수 패키지 설치
```bash
# 시스템 업데이트
sudo apt update && sudo apt upgrade -y
# curl 설치 (Caddy 설치에 필요)
sudo apt install -y curl
# Node.js 및 npm 설치 (n8n용)
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
```
## 2. n8n 설치
```bash
# n8n 전역 설치
npm install -g n8n
# 설치 확인
n8n --version
```
## 3. Caddy 설치
```bash
# Caddy GPG 키 추가
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
# Caddy 리포지토리 추가
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
# 패키지 리스트 업데이트 및 Caddy 설치
sudo apt update
sudo apt install caddy -y
# Caddy 서비스 상태 확인
sudo systemctl status caddy
```
## 4. Caddy 설정 (리버스 프록시)
Caddy 설정 파일을 생성하여 n8n의 포트 5678을 5679로 리버스프록시합니다.
```bash
# Caddy 설정 파일 생성
sudo tee /etc/caddy/Caddyfile > /dev/null <<EOF
# n8n 리버스 프록시 설정
:5679 {
# localhost:5678로 리버스 프록시
reverse_proxy localhost:5678 {
# WebSocket 지원 (n8n에서 필요)
header_up Upgrade {>Upgrade}
header_up Connection {>Connection}
}
# 보안 헤더 추가
header {
# XSS 보호
X-Frame-Options "SAMEORIGIN"
# MIME 타입 스니핑 방지
X-Content-Type-Options "nosniff"
# Clickjacking 방지
X-Frame-Options "DENY"
}
# 로그 설정
log {
output file /var/log/caddy/n8n.log
format json
}
}
EOF
```
## 5. Caddy 서비스 재시작
```bash
# 설정 검증
sudo caddy validate --config /etc/caddy/Caddyfile
# Caddy 서비스 재시작
sudo systemctl restart caddy
# 서비스 상태 확인
sudo systemctl status caddy
```
## 6. n8n 실행 스크립트
n8n을 백그라운드에서 실행하는 스크립트를 생성합니다.
```bash
# n8n 실행 스크립트 생성
cat > ~/start-n8n.sh << 'EOF'
#!/bin/bash
# 환경 변수 설정
export WEBHOOK_URL=https://n8n.dante-labs.com
export N8N_HOST=n8n.dante-labs.com
export N8N_PROTOCOL=https
export N8N_PORT=5678
# n8n 백그라운드 실행
echo "Starting n8n on port 5678..."
n8n start &
N8N_PID=$!
echo "n8n started with PID: $N8N_PID"
echo "n8n is accessible at: http://localhost:5678"
echo "Via Caddy reverse proxy: http://localhost:5679"
# 프로세스 종료 대기
wait $N8N_PID
EOF
# 실행 권한 부여
chmod +x ~/start-n8n.sh
```
## 7. 전체 설치 및 실행
### 자동 설치 스크립트
```bash
# 전체 설치 및 설정 자동화 스크립트
cat > ~/setup-n8n-complete.sh << 'EOF'
#!/bin/bash
echo "=== n8n + Caddy Setup Script ==="
# 1. 시스템 업데이트
echo "Step 1: Updating system..."
sudo apt update && sudo apt upgrade -y
# 2. 필수 패키지 설치
echo "Step 2: Installing required packages..."
sudo apt install -y curl
# Node.js 설치
echo "Step 3: Installing Node.js..."
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
# 3. n8n 설치
echo "Step 4: Installing n8n..."
npm install -g n8n
# 4. Caddy 설치
echo "Step 5: Installing Caddy..."
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy -y
# 5. Caddy 설정
echo "Step 6: Configuring Caddy..."
sudo tee /etc/caddy/Caddyfile > /dev/null <<'CADDYEOF'
:5679 {
reverse_proxy localhost:5678 {
header_up Upgrade {>Upgrade}
header_up Connection {>Connection}
}
header {
X-Frame-Options "SAMEORIGIN"
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
}
log {
output file /var/log/caddy/n8n.log
format json
}
}
CADDYEOF
# 6. Caddy 재시작
echo "Step 7: Restarting Caddy..."
sudo systemctl restart caddy
# 7. n8n 실행 스크립트 생성
echo "Step 8: Creating n8n startup script..."
cat > ~/start-n8n.sh << 'N8NEOF'
#!/bin/bash
export WEBHOOK_URL=https://n8n.dante-labs.com
export N8N_HOST=n8n.dante-labs.com
export N8N_PROTOCOL=https
export N8N_PORT=5678
echo "Starting n8n on port 5678..."
n8n start &
N8N_PID=$!
echo "n8n started with PID: $N8N_PID"
echo "n8n is accessible at: http://localhost:5678"
echo "Via Caddy reverse proxy: http://localhost:5679"
wait $N8N_PID
N8NEOF
chmod +x ~/start-n8n.sh
echo "=== Setup Complete! ==="
echo "To start n8n, run: ~/start-n8n.sh"
echo "Access n8n via: http://localhost:5679"
echo "Direct access: http://localhost:5678"
EOF
# 자동 설치 스크립트 실행 권한 부여
chmod +x ~/setup-n8n-complete.sh
echo "Run the complete setup with: ~/setup-n8n-complete.sh"
```
### 수동 실행
```bash
# n8n 실행 (백그라운드)
~/start-n8n.sh &
# 또는 직접 실행
export WEBHOOK_URL=https://n8n.dante-labs.com
export N8N_HOST=n8n.dante-labs.com
export N8N_PROTOCOL=https
export N8N_PORT=5678
n8n start
```
## 8. 접속 방법
설정이 완료되면 다음 주소로 n8n에 접속할 수 있습니다:
- **Caddy 리버스 프록시**: `http://localhost:5679`
- **직접 접속**: `http://localhost:5678`
## 9. 문제해결
### Caddy 설정 확인
```bash
# Caddy 설정 검증
sudo caddy validate --config /etc/caddy/Caddyfile
# Caddy 로그 확인
sudo tail -f /var/log/caddy/n8n.log
```
### n8n 프로세스 확인
```bash
# n8n 프로세스 확인
ps aux | grep n8n
# 포트 사용 확인
netstat -tlnp | grep :5678
netstat -tlnp | grep :5679
```
### 서비스 재시작
```bash
# Caddy 재시작
sudo systemctl restart caddy
# n8n 재시작 (프로세스 ID 확인 후)
kill -9 <N8N_PID>
~/start-n8n.sh &
```
### 방화벽 설정 (필요시)
```bash
# 포트 5679 허용
sudo ufw allow 5679
# 방화벽 상태 확인
sudo ufw status
```
## 10. 추가 설정 (선택사항)
### HTTPS 활성화
```bash
# Caddyfile에 HTTPS 설정 추가
sudo tee -a /etc/caddy/Caddyfile > /dev/null <<EOF
# HTTPS 설정 (자동 SSL 인증서)
https://n8n.dante-labs.com {
reverse_proxy localhost:5678 {
header_up Upgrade {>Upgrade}
header_up Connection {>Connection}
}
}
EOF
sudo systemctl restart caddy
```
### n8n 추가 설정
```bash
# n8n 설정 파일 생성
mkdir -p ~/.n8n
cat > ~/.n8n/config <<EOF
{
"executions": {
"process": "main",
"timeout": 3600
},
"security": {
"basicAuth": {
"active": true,
"user": "admin",
"password": "your_secure_password"
}
}
}
EOF
```
## 주의사항
- 환경 변수의 도메인 주소는 실제 사용 환경에 맞게 변경하세요
- 프로덕션 환경에서는 보안 설정을 강화하세요
- 정기적으로 백업을 수행하세요
- 로그 파일을 모니터링하여 이상 징후를 확인하세요
바이브코딩 도구 설치
claude code 또는 gemini cli 설치
# Claude Code CLI
npm install -g @anthropic-ai/claude-code
# 또는 Gemini CLI
npm install -g @google/gemini-cli
gemini auth loginAPI 및 링크 준비하기
workspace > portfolio-web 폴더 생성
템플릿 가져오기
Figma 템플릿 마켓플레이스
https://www.figma.com/ko-kr/community/portfolio-templates?editor_type=figma
Figma 디자인 문서 링크 복사
prompt.md 파일에 복사한 링크를 교체주시면 됩니다.
Resend 가입 및 API 준비
resend-example.md 파일에 복사한 API를 교체해주시면 됩니다.
MCP 설치
context7 mcp 준비
pexels mcp 준비
가입하기
api키 발급
smithery.ai 에서 mcp 가져오기
claude code
claude mcp add --transport http Context7 <https://mcp.context7.com/mcp> --header "CONTEXT7_API_KEY: ctx7sk-c8830a7b-db4b-462c-9e1f-bc93765fc108"
claude mcp add SequentialThinking -- npx -y @modelcontextprotocol/server-sequential-thinking
claude mcp add Playwright -- npx @playwright/mcp@latest
claude mcp add --transport http Pexels "<https://server.smithery.ai/@CaullenOmdahl/pexels-mcp-server/mcp?api_key=477bdb37-fb28-4d06-a0e9-e61855e52142&profile=crowded-mosquito-ykHWfz>"
claude mcp add FigmaDev -- npx -y figma-developer-mcp --stdio --figma-api-key=figd_9Ql6wYX03lf3BnITnw-hBmeuRMm7WSmwKKrFpE3S
gemini-cli
gemini mcp add --transport http Context7 <https://mcp.context7.com/mcp> --header "CONTEXT7_API_KEY: ctx7sk-c8830a7b-db4b-462c-9e1f-bc93765fc108"
gemini mcp add SequentialThinking npx -- -y @modelcontextprotocol/server-sequential-thinking
gemini mcp add Playwright npx -- @playwright/mcp@latest
gemini mcp add FigmaDev npx -- mcp-remote <http://127.0.0.1:3845/mcp>
gemini mcp add --transport http Pexels "<https://server.smithery.ai/@CaullenOmdahl/pexels-mcp-server/mcp?api_key=477bdb37-fb28-4d06-a0e9-e61855e52142&profile=crowded-mosquito-ykHWfz>"
프로젝트 폴더 생성
# 폴더 생성 mkdir ~/vibe-portfolio
바이브 코딩 시작
vscode 플러그인 설치
아래 4개만 설치하도록 하겠습니다.
Claude Code for VSCode, ESLint, Yaml, Prettier*
Claude 코드 실행
우상단 클로드 버튼을 누르면 편집탭이 열리면서 자동으로 claude code가 실행됩니다.
n8n 설치 및 호스팅 요청
@ref/n8n.md 를 읽고, n8n(5678)을 설치하여 caddy 리버스프록시(5678->5679)로 백그라운드에서 동작하여 호스팅해줘.포트폴리오 웹사이트 개발 및 호스팅 요청
@ref/prompt.md 를 읽고, 지침내용대로 프로젝트를 구현해줘. 개발서버는 3001, node express 운영서버는 5001 로 백그라운드 실행해줘.외부 호스팅 요청
@ref/cloudflare.md 를 읽고, n8n과 웹서버를 외부 호스팅해줘.임시 터널링을 먼저 해서 웹주소를 안내해주면 내가 웹사이트를 확인할게. 그다음에 이어서 cloudflared 로그인 및 터널링을 진행해주면되.진행 과정에서 로그인은 웹브라우저에서 진행됩니다. 아래 화면 참고하세요.
cloudflared tunnel login
[N8N 설치]
tmux 신규 세션 실행 : 백그라운드에서 동작할수 있도록 하기 위함.
tmux new -s n8n# 세션 이름 : n8nn8n 설치
npm install -g n8nn8n 실행
export WEBHOOK_URL=https://n8n.dante-labs.com ## 주소 변경하세요 export N8N_HOST=n8n.dante-labs.com ## 주소 변경하세요 export N8N_PROTOCOL=https export N8N_SECURE_COOKIE=false n8n start백그라운드 전환 : tmux 세션 빠져나오기
작업 수행하고 나서 ctrl+b 누르고, detach 입력 하면 빠져나오게 됩니다. n8n 서버가 종료되지 않고 백그라운드 작업으로 넘어갑니다.
tmux ls # 작동중인 세션 목록을 볼수 있음.
# tmux attach -t n8n # 다시 세션 접속
[Cloudflare cli 설치 / 터널 수동 등록 가이드]
패키지 관리자 업데이트
apt update && apt upgrade -ycloudflare 공식 저장소 및 GPG키 추가
sudo mkdir -p --mode=0755 /usr/share/keyrings curl -fsSL <https://pkg.cloudflare.com/cloudflare-main.gpg> | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] <https://pkg.cloudflare.com/cloudflared> $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflared.list
패키지 리스트 갱신 및 cloudflare 설치
apt update && apt install cloudflaredcloudflare 계정 연동 및 인증 (인증 페이지 링크 출력되면 브라우저 새탭에서 열고 진행하세요)
cloudflared tunnel login
cloudflare 터널 생성
cloudflared tunnel create dante-phone-tunnel# 터널이름 변경하세요cloudflare 터널 설정
터널을 수동 설정하기 위해서는 tunnel UUID를 알아야 합니다. 아래 화면처럼 콘솔 화면에서 확인하실수 있습니다.
cat > /root/.cloudflared/config.yml
tunnel: xxxxxx-xxxxx-xxxxx-xxxx-xxxxxxx # 터널 UUID
credentials-file: /root/.cloudflared/xxxxxx-xxxxx-xxxxx-xxxx-xxxxxxx.json # 터널ID.json
ingress:
- hostname: dante-labs.com # <<< 주소 변경하세요
service <http://localhost:3001>
- service http_status:404
cloudflare 터널 실행
cloudflared tunnel run 2>&1 &
[Cloudflare 서브 도메인 수동 등록 가이드]
Cloudflare 도메인을 등록한뒤, 수동으로 서브도메인을 생성된 cloudflare 터널과 연결하는 방법입니다.
등록한 도메인과 생성된 터널이 사전에 준비되어 있어야 합니다.
# 형식 : CNAME
# 이름 : n8n
# 대상 : [터널 uuid].cfargotunnel.com
# 프록시 상태 : on
이제 여러분만의 강력한 모바일 서버가 완성되었습니다. 프로젝트를 계속 발전시키고, 더 많은 기능을 추가하며 나만의 자동화 서버를 만들어 보세요! 😊
단테랩스