생명정보학에서 웹 도구는 오랫동안 접근성의 관문 역할을 해왔다. NCBI BLAST, Ensembl Genome Browser, Galaxy, UCSC Genome Browser — 이 도구들은 명령줄에 익숙하지 않은 실험 생물학자도 시퀀스 검색, 게놈 탐색, 분석 파이프라인 실행을 할 수 있게 만들었다. 웹 도구가 없었다면, 생명정보학은 소수의 전문 프로그래머만 접근할 수 있는 분야로 남았을 것이다.
그러나 이 장에서 웹 도구를 만들기 전에, 한 가지 질문을 던져야 한다. AI 시대에도 웹 도구를 만드는 것이 여전히 의미가 있는가?
웹(World Wide Web)은 30년 넘게 정보 공유의 기본 플랫폼이었다. 그러나 최근 Web 4.0 — AI가 주도하는 지능형 웹 — 에 대한 논의가 활발해지면서, 전통적인 웹 인터페이스의 미래에 의문이 제기되고 있다. 이미 인터넷 트래픽의 상당 부분이 사람이 아닌 봇에 의해 발생하고 있으며, 이 비중은 계속 증가하고 있다. MCP와 같은 프로토콜이 보편화되면, AI 에이전트가 웹 브라우저를 거치지 않고 데이터와 서비스에 직접 접근하는 시대가 올 것이다. 그때 화려한 UI와 반응형 디자인은 더 이상 중요하지 않을 수 있다.
그럼에도 불구하고, 웹 도구를 배우는 것에는 몇 가지 현실적인 이유가 있다:
결론적으로, 웹 인터페이스 자체의 중요성은 점차 줄어들겠지만, 웹 도구를 만드는 과정에서 익히는 기술과 사고방식은 AI 시대에도 유효하다. 이 장에서는 생명정보학 웹 도구의 기반이 되는 프로젝트를 구성한다.
이 책에서는 다음과 같은 기술 스택을 사용하여 생명정보학 웹 도구를 개발한다.
| 기술 | 역할 | 설명 |
|---|---|---|
| SvelteKit | 프론트엔드 프레임워크 | 빠르고 가벼운 웹 앱 개발 프레임워크 |
| Tailwind CSS | CSS 프레임워크 | 유틸리티 클래스 기반의 스타일링 도구 |
| PostgreSQL | 데이터베이스 | 오픈소스 관계형 데이터베이스 |
| Docker | 컨테이너 | 개발 환경 통합 관리 |
이 조합을 선택한 이유는 바이브 코딩에 적합하기 때문이다. SvelteKit은 코드량이 적어 AI가 생성하고 수정하기 쉽고, Tailwind CSS는 스타일 정보가 HTML과 같은 파일에 있어 AI가 맥락을 파악하기 용이하다. PostgreSQL은 안정적이고 널리 사용되는 데이터베이스이므로 AI가 정확한 SQL을 생성할 확률이 높다.
SvelteKit은 Svelte를 기반으로 한 풀스택 웹 프레임워크이다. “풀스택”이란 프론트엔드(사용자가 보는 화면)와 백엔드(서버 로직, 데이터베이스 연동)를 하나의 프레임워크에서 모두 처리할 수 있다는 뜻이다.
React, Vue 등 다른 프레임워크와 비교했을 때 다음과 같은 장점이 있다:
src/routes/tools/blast/+page.svelte 파일을 만들면 자동으로 /tools/blast URL이 생긴다. URL 설정을 위한 별도 파일이 필요 없다.
SvelteKit에서 페이지는 크게 세 가지 파일로 구성된다:
| 파일 | 역할 | 실행 위치 |
|---|---|---|
+page.svelte |
사용자에게 보이는 화면 (HTML + CSS + JS) | 브라우저 |
+page.server.ts |
데이터 로딩, 폼 처리 등 서버 로직 | 서버 |
+server.ts |
REST API 엔드포인트 | 서버 |
예를 들어 BLAST 검색 도구를 만든다면, +page.svelte에는 시퀀스 입력 폼과 결과 테이블을, +page.server.ts에는 BLAST+ 명령 실행과 결과 파싱 로직을 작성한다. 이 구분을 이해하고 있으면, AI에게 “서버 로직에 BLAST 검색 기능 추가해줘”라고 구체적으로 요청할 수 있다.
Tailwind CSS는 유틸리티 클래스 기반의 CSS 프레임워크이다. 전통적인 CSS에서는 별도의 스타일시트 파일을 만들고 클래스 이름을 정의한 후 스타일을 작성한다. Tailwind는 이 과정을 생략하고, 미리 정의된 유틸리티 클래스를 HTML 요소에 직접 적용한다.
<!-- 전통적인 CSS 방식 -->
<div class="card">제목</div>
<!-- Tailwind CSS 방식 -->
<div class="bg-white rounded-lg shadow-md p-6">제목</div>
Tailwind 방식에서 bg-white는 흰색 배경, rounded-lg는 둥근 모서리, shadow-md는 중간 크기 그림자, p-6은 패딩 1.5rem을 의미한다. 클래스 이름만 보면 어떤 스타일이 적용되는지 알 수 있다.
AI 에이전트와 함께 사용하기에 특히 적합한데, 스타일이 HTML과 같은 파일에 있어 컨텍스트를 파악하기 쉽기 때문이다. 전통적인 CSS에서는 AI가 HTML 파일과 CSS 파일을 모두 읽어야 전체 디자인을 이해할 수 있지만, Tailwind에서는 HTML 파일 하나만 읽으면 된다.

PostgreSQL은 세계에서 가장 많이 사용되는 오픈소스 관계형 데이터베이스이다. “관계형”이란 데이터를 표(테이블) 형태로 저장하고, 테이블 간의 관계를 정의할 수 있다는 뜻이다.
이 책에서 PostgreSQL은 다음과 같은 용도로 사용된다:
SQLite 같은 가벼운 데이터베이스도 있지만, PostgreSQL을 선택한 이유는 실무 환경과 동일한 경험을 제공하기 위해서이다. Docker를 통해 실행하므로 설치가 번거롭지도 않다.
SvelteKit은 JavaScript/TypeScript 기반이므로 Node.js가 필요하다. Node.js는 브라우저 밖에서 JavaScript를 실행할 수 있게 해주는 런타임이다. 다음 웹사이트에서 설치한다:
https://nodejs.org/en/download
설치 시 운영체제를 선택하는 화면이 나오는데, Windows 사용자도 WSL 환경에서 개발하므로 Linux를 선택해야 한다. 그다음 nvm(Node Version Manager)과 pnpm(패키지 매니저)을 선택한 후 터미널에 표시되는 명령을 입력한다. nvm은 여러 버전의 Node.js를 설치하고 전환할 수 있게 해주는 도구이다. 프로젝트마다 다른 Node.js 버전이 필요할 수 있으므로, 직접 설치보다 nvm을 통한 설치가 권장된다.
pnpm은 npm의 대안으로, 디스크 공간을 절약하고 설치 속도가 빠르다. 여러 프로젝트에서 같은 패키지를 사용할 때, pnpm은 패키지를 한 번만 다운로드하고 심볼릭 링크로 연결한다.

설치 확인:
node --version
pnpm --version
터미널에서 다음 명령을 실행하여 SvelteKit 프로젝트를 생성한다:
npx sv create my-bioinfo-app
CLI가 대화형으로 옵션을 물어본다. 방향키와 스페이스바로 선택하고 엔터로 진행한다:
| 질문 | 선택 |
|---|---|
| Which template would you like? | SvelteKit minimal |
| Add type checking with TypeScript? | Yes, using TypeScript syntax |
| What would you like to add to your project? | tailwindcss, sveltekit-adapter, paraglide |
| tailwindcss: Which plugins? | typography, forms |
| sveltekit-adapter: Which adapter? | node |
| paraglide: Which languages? | en, ko |
| paraglide: Include a demo? | No |
| Which package manager? | pnpm |
프로젝트 생성이 완료되면, VS Code에서 파일 → 폴더 열기로 my-bioinfo-app 디렉토리를 연다.
각 옵션의 역할을 간단히 정리하면:
참고: 프로젝트 초기 생성은 AI 에이전트에 맡기기보다 직접 수행하는 것이 좋다. AI는 초기화 명령을 사용하기보다 기존 코드를 직접 작성하려는 경향이 있어, 최신 버전이 아닌 코드를 생성할 수 있다. 프로젝트 뼈대를 공식 CLI로 먼저 만들고, 그 위에서 AI에게 기능 추가를 요청하는 것이 안전하다.
Tailwind CSS는 SvelteKit 프로젝트 생성 시 옵션으로 함께 설치할 수 있다. 별도로 수동 설치할 필요 없이, 프로젝트 초기화 과정에서 Tailwind CSS를 선택하면 자동으로 설정된다. Typography 플러그인은 마크다운 렌더링 시 보기 좋은 기본 스타일을 제공하고, Forms 플러그인은 폼 요소(입력 필드, 버튼 등)에 기본 스타일을 적용해 준다.
3장에서 배운 Docker Compose를 실전에 적용한다. Claude Code에게 다음과 같이 요청한다:
“SvelteKit 앱과 PostgreSQL 데이터베이스를 Docker Compose로 구성해줘. compose.yml과 compose.dev.yml을 만들어줘. compose.yml은 배포용이고, compose.dev.yml은 개발용으로 볼륨 마운트와 핫 리로드를 설정해줘. Dockerfile도 함께 만들어줘.”
이때 compose.yml(배포용)과 compose.dev.yml(개발용)을 분리하는 것이 좋다. 개발 환경에서는 코드 변경이 즉시 반영되어야 하지만, 배포 환경에서는 최적화된 빌드 결과만 실행하면 된다. 두 파일을 분리해 두면, 개발할 때는 docker compose -f compose.dev.yml up으로, 배포할 때는 docker compose up으로 실행할 수 있다.
Claude Code가 생성하는 파일의 주요 설정을 이해해 두면, 결과를 검토하고 수정 요청을 내리기 쉽다:
| 설정 | 의미 |
|---|---|
volumes: - .:/app |
로컬 코드를 컨테이너에 연결. 코드 수정 시 즉시 반영 |
/app/node_modules |
컨테이너 자체의 node_modules 사용. 호스트와 충돌 방지 |
depends_on: - db |
db를 먼저 시작한 후 app 시작 |
pgdata:/var/lib/postgresql/data |
컨테이너 삭제해도 데이터베이스 보존 |
DATABASE_URL |
컨테이너 간 네트워크 주소. db는 서비스 이름 |
Dockerfile에서는 3장에서 배운 레이어 캐싱 원리가 적용된다. package.json을 먼저 복사하고 의존성을 설치한 뒤 소스 코드를 복사하면, 소스 코드만 변경되었을 때 의존성 설치 단계를 건너뛸 수 있다. --host 플래그는 Docker 컨테이너 내부 서버에 호스트에서 접속하기 위해 필요하다.
프로젝트에서 데이터베이스 접속 정보, API 키 등 민감한 설정값은 환경 변수로 관리한다. 코드에 비밀번호를 직접 쓰면 Git에 커밋될 위험이 있다. 환경 변수를 사용하면 코드와 설정을 분리할 수 있다.
중요:
.env파일은 반드시 사용자가 직접 작성해야 한다..env에는 데이터베이스 비밀번호, API 키 등 민감한 정보가 포함되므로, Claude Code가 이 파일을 읽거나 생성하게 해서는 안 된다. 글로벌CLAUDE.md(~/.claude/CLAUDE.md)에 다음과 같이 추가하여, AI 에이전트가.env파일에 접근하지 못하도록 설정하는 것을 권장한다:# 보안 규칙 - .env 파일을 절대 읽거나 수정하지 말 것 - .env.example만 참조할 것
프로젝트 루트에 .env 파일을 직접 생성한다:
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/bioinfo
PUBLIC_SITE_NAME=My Bioinfo App
SvelteKit에서 환경 변수는 두 가지로 나뉜다:
| 접두사 | 접근 범위 | 용도 |
|---|---|---|
PUBLIC_ |
서버 + 클라이언트 | 사이트 이름 등 공개 정보 |
| (없음) | 서버만 | 데이터베이스 비밀번호, API 키 등 민감 정보 |
PUBLIC_ 접두사가 없는 환경 변수는 서버 코드(+page.server.ts, +server.ts)에서만 접근할 수 있다. 브라우저에서 실행되는 코드에서는 읽을 수 없으므로, 데이터베이스 비밀번호나 API 키가 사용자에게 노출되지 않는다. 이 구분은 보안상 중요하다.
.env 파일은 .gitignore에 반드시 추가하여 Git에 커밋되지 않도록 한다. 대신 .env.example 파일을 만들어 어떤 환경 변수가 필요한지 안내한다. .env.example에는 실제 값 대신 템플릿을 넣는다. 이 파일은 Claude Code에게 생성을 요청해도 된다.
”
.env.example파일을 만들어줘. DATABASE_URL과 PUBLIC_SITE_NAME이 필요해.”
최종적으로 프로젝트 디렉토리는 다음과 같은 구조를 가진다:
my-bioinfo-app/
├── compose.yml # Docker 서비스 정의
├── Dockerfile # Docker 이미지 정의
├── .env # 환경 변수 (Git에 포함하지 않음)
├── .env.example # 환경 변수 템플릿
├── .gitignore
├── package.json
├── pnpm-lock.yaml
├── svelte.config.js # SvelteKit 설정
├── vite.config.ts # Vite 빌드 도구 설정
├── tailwind.config.ts # Tailwind CSS 설정
├── CLAUDE.md # AI 에이전트 참조용 프로젝트 명세
├── README.md
├── src/
│ ├── app.css # 글로벌 스타일 (Tailwind 임포트)
│ ├── app.html # HTML 템플릿
│ ├── lib/ # 공유 라이브러리
│ │ ├── components/ # 재사용 가능한 컴포넌트
│ │ └── server/ # 서버 전용 코드 (DB 연결 등)
│ └── routes/ # 페이지 라우트
│ ├── +layout.svelte # 공통 레이아웃
│ ├── +page.svelte # 랜딩 페이지
│ └── tools/
│ └── +page.svelte # 도구 페이지
└── static/ # 정적 파일 (이미지, 폰트 등)
이 구조에서 가장 중요한 폴더는 src/routes/이다. SvelteKit의 파일 기반 라우팅에 의해, 이 폴더의 구조가 곧 웹사이트의 URL 구조가 된다. src/routes/tools/blast/+page.svelte를 만들면 /tools/blast라는 URL이 자동으로 생긴다. AI에게 새 페이지를 추가해 달라고 할 때, 이 규칙을 알면 “tools 폴더 아래에 blast 페이지를 만들어줘”라고 구체적으로 지시할 수 있다.
src/lib/ 폴더는 여러 페이지에서 공유하는 코드를 넣는 곳이다. 예를 들어 네비게이션 바 컴포넌트는 모든 페이지에서 사용하므로 src/lib/components/NavBar.svelte에 둔다. src/lib/server/에는 데이터베이스 연결 코드처럼 서버에서만 사용하는 코드를 둔다.
CLAUDE.md는 AI 에이전트가 참조하는 프로젝트 명세 파일이다. Claude Code는 작업을 시작할 때 이 파일을 가장 먼저 읽고, 프로젝트의 구조와 규칙을 파악한다.
핵심 원칙: CLAUDE.md에 정보를 많이 넣을수록 AI는 더 똑똑해진다.
AI 코딩 에이전트는 사람과 달리 프로젝트의 맥락을 스스로 알지 못한다. “Navbar에 로고를 추가해줘”라고 요청했을 때, AI가 올바른 위치에 올바른 방식으로 코드를 작성하려면 다음을 알아야 한다:
이러한 정보가 CLAUDE.md에 없으면 AI는 매번 프로젝트 구조를 탐색하고 추측해야 한다. 반면, 이 정보가 잘 정리되어 있으면 AI는 곧바로 정확한 코드를 작성할 수 있다.
바이브 코딩은 “AI가 다 해주니까 개발을 몰라도 된다”는 뜻이 아니다. 오히려 그 반대이다. CLAUDE.md를 잘 작성하려면 사람이 먼저 프로젝트를 이해하고 있어야 한다.
예를 들어 이런 CLAUDE.md를 작성한다고 하자:
# 프로젝트 개요
생명정보학 웹 도구 모음 사이트
# 기술 스택
- SvelteKit (프론트엔드 + 서버)
- Tailwind CSS (스타일링)
- PostgreSQL (데이터베이스)
# 디렉토리 구조
- src/routes/ : 페이지 라우트 (파일 기반 라우팅)
- src/lib/components/ : 재사용 가능한 UI 컴포넌트
- src/lib/server/ : 서버 전용 코드 (DB 연결 등)
# 코딩 컨벤션
- 컴포넌트 파일명은 PascalCase (예: NavBar.svelte)
- 서버 API는 +server.ts 파일에 작성
- 환경 변수는 $env/static/private 또는 $env/static/public 사용
# 디자인 가이드라인
- 색상: blue-600을 primary color로 사용
- 레이아웃: 최대 너비 max-w-7xl, 중앙 정렬
- 반응형: mobile-first 접근
이 파일을 작성하려면 SvelteKit의 파일 기반 라우팅이 무엇인지, Tailwind의 유틸리티 클래스가 어떻게 동작하는지, 컴포넌트와 레이아웃의 개념이 무엇인지 알아야 한다. 이 책에서 배우는 웹 개발 배경지식이 바로 이를 위한 것이다.
핵심: 바이브 코딩에서 사람의 역할은 코드를 직접 작성하는 것이 아니라, AI가 올바른 코드를 작성할 수 있도록 정확한 지시를 내리는 것이다. 정확한 지시를 내리려면 기본적인 개발 개념을 이해하고 있어야 한다.
| 항목 | 설명 | 예시 |
|---|---|---|
| 프로젝트 개요 | 프로젝트의 목적과 대상 사용자 | “생명정보학 연구자를 위한 웹 기반 시퀀스 분석 도구” |
| 기술 스택 | 사용하는 프레임워크, 라이브러리 | “SvelteKit, Tailwind CSS, PostgreSQL” |
| 디렉토리 구조 | 주요 폴더의 역할 | “src/routes/는 페이지, src/lib/은 공유 코드” |
| 코딩 컨벤션 | 파일명 규칙, 코드 스타일 | “컴포넌트는 PascalCase, 변수는 camelCase” |
| 디자인 가이드라인 | 색상, 폰트, 레이아웃 규칙 | “primary color는 blue-600, 최대 너비 max-w-7xl” |
| 비즈니스 로직 | 도메인 특화 규칙 | “FASTA 형식은 >로 시작하는 헤더 + 시퀀스” |
CLAUDE.md는 한 번 작성하고 끝이 아니다. 프로젝트가 발전할수록 새로운 규칙과 패턴이 생기기 마련이다. 새로운 컴포넌트 규칙이 추가되거나, 디자인 가이드라인이 변경되면 CLAUDE.md도 함께 업데이트해야 한다. AI 에이전트가 항상 최신 상태를 파악할 수 있도록 유지하는 것이 바이브 코딩에서 사람의 중요한 역할이다.
팁: Claude Code에게 “지금까지 작업한 내용을 바탕으로 CLAUDE.md를 업데이트해줘”라고 요청하면, AI가 현재 프로젝트 상태를 분석하여 CLAUDE.md를 자동으로 갱신해 주기도 한다.
docker compose up
브라우저에서 http://localhost:5173으로 접속하면 SvelteKit 앱을 확인할 수 있다. 최초 실행 시 Docker 이미지 빌드와 의존성 설치에 몇 분이 걸릴 수 있지만, 두 번째 실행부터는 캐시 덕분에 수 초 만에 시작된다.
pnpm dev
Docker 없이도 개발 서버를 실행할 수 있지만, 이 경우 PostgreSQL을 별도로 설치하고 실행해야 한다. Docker를 사용하면 docker compose up 한 줄로 웹 서버와 데이터베이스가 모두 시작되므로 더 편리하다.

pnpm create svelte@latest로 뼈대 생성 후 AI와 협업.env를 읽거나 생성하게 하지 않기.env 접근 금지 규칙 추가PUBLIC_ 접두사로 공개/비공개 구분, .gitignore에 반드시 추가