잠자고 있는 스마트폰, 홈서버로 부활시키기 (feat. 바이브코딩)

✔️ 오늘은 여러분의 서랍 속에 잠자고 있던 '옛 스마트폰'을 활용해서 홈페이지, 블로그, n8n 서버 등으로 다양하게 활용가능한, '나만의 홈서버'를 만드는 방법을 준비했습니다 📱 전문가가 아니어도, 코딩을 몰라도 괜찮습니다! '바이브코딩'을 통해, 누구나 쉽게 따라 할 수 있도록 자세히 알려드리겠습니다.

May 14, 2025
Video preview
📲

핵심개념 : 애플리케이션 터널링 배우기

  • 서비스명 : CloudFlare Tunnel (Zero Trust Free)
  • 정의 : 외부에서 직접 접근할수 없는 내부 컴퓨터/서비스에 안전한 전용 통로를 만들어 접속하게 하는 방법을 터널링이라고 합니다.
  • 장점
    • 무료입니다. Zero Trust Free요금제를 사용하면 됩니다. 개인 용도에서는 충분하다고 볼수있습니다.
    • 공인 IP가 없어도 됩니다. 이 말은, 공유기 같은 라우터가 없어도 되기 때문에 장소가 바뀌어도 인터넷만 연결되어 있으면 접속이 가능하다는 말입니다.
    • 보안성이 높습니다. 통로가 암호화되어 해킹으로부터 안전합니다.
    • 설정이 간단합니다. VPN 처럼 설치가 어렵지 않습니다.
notion image
📲

스마트폰 서버 설치 튜토리얼

1. 안드로이드폰 공장 초기화

notion image
📲
안드로이드 초기화 후, 초기 설정을 진행해주세요. 서버용도로 사용되는 만큼 불필요한 기본 앱과 설정 등은 피해주세요.
 

 

2. Mac 또는 윈도우에 scrcpy 설치

Mac 설치방법
  • Homebrew(패키지 관리 프로그램) 설치: 터미널에 다음 명령어 입력
    • /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 파일을 다운로드하고 압축 해제.
      notion image
      notion image
  • C:\scrcpy 폴더로 압축해제된 파일 저장
    • notion image
       
  • 고급시스템설정 → 환경변수 등록
    • 다운로드 받은 scrcpy를 터미널 전역에서 사용할수 있도록 환경변수를 아래 절차대로 등록합니다.
      notion image
      notion image
      C:\scrcpy
      notion image
      이후 모든 열린 창을 [확인] 버튼을 눌러 닫기
      notion image
      notion image
       
  • 터미널을 열어 정상 설치 여부 확인
    • scrcpy -v
      notion image
 

 

3. USB디버깅 와 무선디버깅 활성화

  • 설정 → 휴대전화 정보
    • notion image
notion image
 

 

4. 안드로이드 폰을 PC에 USB로 연결

  • 안드로이드 폰을 집의 공유기에 와이파이로 연결합니다.
  • USB로 내PC에 연결합니다. 연결하면 USB 디버깅 허용 여부를 물으면 허용 버튼을 누릅니다.
    • notion image
       
  • 터미널(파워셀에서 아래 명령실행하면 미러링 창이 뜹니다.
      • 디바이스 연결 확인
      adb devices
      notion image
       
      • 미러링 시작
      scrcpy
      notion image
       
    • 안드로이드 백그라운드 프로세스 자동종료 옵션 OFF
      • adb 명령어는 scrcpy 설치 및 환경변수 등록시 함께 환경변수로 등록됨.
      • # 안드로이드 12 adb shell "device_config put activity_manager max_phantom_processes 2147483647"
        notion image
       

 

5. 리눅스 앱 설치

  1. termux 설치

6. Termux 실행 / 터미널 접속

  • 앱 실행
notion image
  • 패스워드 설정
passwd
notion image
  • Termux 앱 백그라운드 설정
pkg install termux-tools termux-wake-lock
notion image
  • 터미널 자동접속
notion image
  • ssh 실행
sshd
notion image
  • 우분투 수동 설치 명령어
pkg update -y && pkg install wget curl proot tar -y && wget https://raw.githubusercontent.com/AndronixApp/AndronixOrigin/master/Installer/Ubuntu22/ubuntu22.sh -O ubuntu22.sh && chmod +x ubuntu22.sh && bash ubuntu22.sh
notion image
 
  • ssh 설치
pkg install openssh
notion image
  • 사용자 ID 확인
whoami
notion image
 

7. 우분투 실행 / 초기 설정

  • 우분투 실행
./start-ubuntu22.sh
notion image
  • 우분투 업데이트
apt update
notion image
  • 내부망 IP 확인
apt install -y net-tools ifconfig
notion image

8. SSH 원격 접속

  • 노트북에서 SSH 접속
    • 같은 공유기의 WIFI 네트워크로 개인노트북을 이용해 접속합니다. Mac 유저는 ‘터미널’ 윈도우즈 유저는 ‘Powershell’ 창을 열어서 접속을 시도합니다.
      포트번호는 8022 이며, 사용자 ID는 위에서 whoami 로 확인한 ID로 접속합니다.
      ssh [사용자ID]@[프라이빗네트워크주소] ex) ssh u0_a288@192.168.219.117 # 여기서는 u0_a288과 192.168.219.117이니 여러분의 주소에 맞게 수정하세요. # 명령어 입력후 암호 입력합니다.
      notion image
      암호가 아닌 인증키 기반으로 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@[프라이빗네트워크주소]
      notion image
 
  • 우분투 접속
    • 내 PC → ssh → Termux → Ubuntu 순으로 접속되는 것입니다.
      # Termux 쉘에서 ./start-ubuntu22.sh
      notion image
  • tmux 설치
    • tmux는 터미널에서 세션을 유지하고 창/패널을 나눠 여러 작업을 동시에 다루게 해주는 터미널 멀티플렉서 명령어입니다.
      흔히 원격 접속이 끊겨도 작업을 이어가거나, 하나의 터미널에서 여러 창과 분할 화면을 운영할 때 사용합니다.
      우분투에서 여러 서버를 작동하고 서버 프로세스가 스마트폰의 슬립모드 정책에 의해 종료되지 않도록 termux-wave-lock 설정으로 해주고나서, Termux 앱 안의 터미널 세션을 멀티로 유지해줍니다.
      notion image
 

9. VSCode 서버 설치

  • curl 패키지 설치
    • apt install -y curl
  • vscode 다운로드 및 설치
    • 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:8080
  • tmux 세션 나오기
    • 작업 수행하고 나서 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 하세요)
    • notion image
      notion image
      notion image
      notion image
  • 타사 도메인 등록 (Cloudflare 도메인 구입한 경우 Skip 하세요)
      • 도메인 연결 선택
      notion image
      • Free 요금제 선택
      notion image
      • 활성화 진행
        • notion image
       
      • 타사 도메인 입력
      notion image
      • 타사 네임서버 정보 삭제 / cloudflare 네임서버 확인
      notion image
      • 타사로 접속하여 네임서버를 cloudflare로 변경
        • (여기서는 ‘Gabia.com’)
          notion image
 
page icon

포트폴리오 웹사이트 바이브 코딩 및 호스팅하기

이번 바이브 코딩은 안드로이드의 리눅스에 Ubuntu 22 배포판을 Proot-distro 방식으로 설치한 환경에서 root 계정으로 진행하게 됩니다.
완전한 우분투 환경이 아닌 컨테이너 방식으로, 제약사항들이 있습니다.
Docker 는 지원되지 않고, servicectl이나 ps 같은 프로세스 명령어들이 동작하지 않는 점이 있습니다.
claude code에 이런 환경적인 부분을 컨텍스트에 제공하면 서버 설정과 코딩을 더 수월하게 하실수 있습니다.
제가 수차례 테스트한 프롬프트이지만, LLM의 특성상 ‘의외성’과 ‘무작위성’이 있어 결과가 달라질수 있습니다.
만약 바이브코딩으로 설정이 실패한다면,
중고급자 분들은 발생하는 에러를 컨텍스트에 추가하면서 수정하시는 것을 추천드리고,
초급자 분들은 모두 지우고 처음부터 다시 하시는것을 추천드립니다.
  1. VSCode 서버 접속 / 컨텍스트 문서 준비
      • vscode서버를 내부망 IP주소로 접속 (예시 : http://192.168.219.117:8080 여러분은 주소가 다릅니다)
        • 접속한뒤에 컨텍스트 파일을 ref 폴더를 만들어 하나씩 저장합니다.
          notion image
          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 <onboarding@resend.dev>' 형식을 사용한다. * 한글 제목과 내용을 지원해야 한다. ## 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. 연락처 정보 * **이메일**: `datapod.k@gmail.com` * **전화번호**: `+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: 'onboarding@resend.dev', to: 'datapod.k@gmail.com', 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.md
          # 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 ``` ## 주의사항 - 환경 변수의 도메인 주소는 실제 사용 환경에 맞게 변경하세요 - 프로덕션 환경에서는 보안 설정을 강화하세요 - 정기적으로 백업을 수행하세요 - 로그 파일을 모니터링하여 이상 징후를 확인하세요
  1. 바이브코딩 도구 설치
      • claude code 또는 gemini cli 설치
      # Claude Code CLI npm install -g @anthropic-ai/claude-code # 또는 Gemini CLI npm install -g @google/gemini-cli gemini auth login
  1. API 및 링크 준비하기
      • workspace > portfolio-web 폴더 생성
      • Figma 디자인 문서 링크 복사
        • prompt.md 파일에 복사한 링크를 교체주시면 됩니다.
  1. 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
       
  1. 바이브 코딩 시작
      • vscode 플러그인 설치
        • 아래 4개만 설치하도록 하겠습니다.
          Claude Code for VSCode, ESLint, Yaml, Prettier*
          notion image
          notion image
          notion image
          notion image
           
      • Claude 코드 실행
        • 우상단 클로드 버튼을 누르면 편집탭이 열리면서 자동으로 claude code가 실행됩니다.
          notion image
      • n8n 설치 및 호스팅 요청
        • @ref/n8n.md 를 읽고, n8n(5678)을 설치하여 caddy 리버스프록시(5678->5679)로 백그라운드에서 동작하여 호스팅해줘.
      • 포트폴리오 웹사이트 개발 및 호스팅 요청
        • @ref/prompt.md 를 읽고, 지침내용대로 프로젝트를 구현해줘. 개발서버는 3001, node express 운영서버는 5001로 백그라운드 실행해줘.
      • 외부 호스팅 요청
        • @ref/cloudflare.md 를 읽고, n8n과 웹서버를 외부 호스팅해줘.임시 터널링을 먼저 해서 웹주소를 안내해주면 내가 웹사이트를 확인할게. 그다음에 이어서 cloudflared 로그인 및 터널링을 진행해주면되.
          진행 과정에서 로그인은 웹브라우저에서 진행됩니다. 아래 화면 참고하세요.
          cloudflared tunnel login
          notion image
           
          notion image
           
page icon

N8N 설치

  1. tmux 신규 세션 실행 : 백그라운드에서 동작할수 있도록 하기 위함.
    1. tmux new -s n8n # 세션 이름 : n8n
  1. n8n 설치
    1. npm install -g n8n
  1. n8n 실행
    1. 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
  1. 백그라운드 전환 : tmux 세션 빠져나오기
      • 작업 수행하고 나서 ctrl+b 누르고, detach 입력 하면 빠져나오게 됩니다. n8n 서버가 종료되지 않고 백그라운드 작업으로 넘어갑니다.
      tmux ls # 작동중인 세션 목록을 볼수 있음. # tmux attach -t n8n # 다시 세션 접속
page icon

Cloudflare cli 설치 / 터널 수동 등록 가이드

  1. 패키지 관리자 업데이트
    1. apt update && apt upgrade -y
  1. cloudflare 공식 저장소 및 GPG키 추가
    1. 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
  1. 패키지 리스트 갱신 및 cloudflare 설치
    1. apt update && apt install cloudflared
  1. cloudflare 계정 연동 및 인증 (인증 페이지 링크 출력되면 브라우저 새탭에서 열고 진행하세요)
    1. cloudflared tunnel login
      notion image
       
      notion image
  1. cloudflare 터널 생성
    1. cloudflared tunnel create dante-phone-tunnel # 터널이름 변경하세요
  1. cloudflare 터널 설정
    1. 터널을 수동 설정하기 위해서는 tunnel UUID를 알아야 합니다. 아래 화면처럼 콘솔 화면에서 확인하실수 있습니다.
      notion image
      notion image
       
      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
  1. cloudflare 터널 실행
    1. cloudflared tunnel run 2>&1 &
page icon

Cloudflare 서브 도메인 수동 등록 가이드

Cloudflare 도메인을 등록한뒤, 수동으로 서브도메인을 생성된 cloudflare 터널과 연결하는 방법입니다.
등록한 도메인과 생성된 터널이 사전에 준비되어 있어야 합니다.
notion image
 
notion image
notion image
 
notion image
# 형식 : CNAME # 이름 : n8n # 대상 : [터널 uuid].cfargotunnel.com # 프록시 상태 : on