BioPlayground

🧬
목록으로

데이터베이스로 실험 데이터 영구 저장하기

데이터베이스와 SQL의 핵심을 바이오 예제로 배웁니다. 시료 관리 테이블을 만들고 CRUD 쿼리를 작성합니다.

입문
|
60
|
검증 완료 (2026-06)
데이터베이스SQL테이블CRUD관계형 데이터베이스MySQL
트랙 진행률0/11 (0%)

데이터베이스로 실험 데이터 영구 저장하기

지금까지 Express 서버에서 시료 데이터를 배열로 관리했습니다. 문제는 — 서버를 껐다 켜면 데이터가 전부 사라진다는 것입니다. 배열은 메모리에만 존재하기 때문입니다.

실험실에서 결과를 포스트잇에 적어놓으면 바람에 날아가지만, 실험 노트에 적으면 영구히 남습니다. 데이터베이스는 웹 개발의 실험 노트입니다 — 서버가 꺼져도, 컴퓨터를 재시작해도, 데이터는 안전하게 남아 있습니다.

파일 vs 데이터베이스

앞에서 Node.js로 CSV 파일을 읽고 쓰는 법을 배웠습니다. 파일도 데이터를 저장할 수 있는데, 왜 데이터베이스가 필요할까요?

파일 (CSV, JSON)데이터베이스
검색전체 파일을 읽고 직접 필터링조건만 말하면 즉시 검색
동시 접근여러 프로그램이 동시에 쓰면 충돌안전하게 동시 접근 처리
데이터량수만 건이면 느려짐수백만 건도 빠르게 처리
구조 강제아무 형식이나 저장 가능 (실수 위험)컬럼 타입을 강제 (INT, VARCHAR 등)

실험 시료가 10개면 엑셀이면 충분합니다. 하지만 10만 건의 시료 데이터에서 "OD 1.0 이상이면서 2024년 3월에 등록된 혈액 시료만" 찾으려면 — 파일로는 고통스럽고, 데이터베이스에서는 한 줄이면 됩니다.

SQL: 데이터베이스와 대화하는 언어

데이터베이스에게 "이 데이터 줘", "이것 저장해", "이것 삭제해"라고 말하는 언어가 SQL(Structured Query Language)입니다.

SQL은 프로그래밍 언어 중 가장 쉬운 축에 속합니다. 영어 문장처럼 읽힙니다:

sql
SELECT name, od FROM samples WHERE status = 'fail';

이 한 줄은 "samples 테이블에서 status가 fail인 행의 name과 od를 가져와"라는 뜻입니다. PubMed에서 키워드 조합으로 논문을 검색하듯, SQL은 조건 조합으로 데이터를 검색합니다.

테이블: 데이터의 구조

데이터베이스에서 데이터는 테이블(table) 안에 저장됩니다. 엑셀 시트와 거의 같은 구조입니다:

text
samples 테이블
┌────┬──────────────┬──────┬────────┬────────────┐
│ id │ name         │ od   │ status │ created_at │
├────┼──────────────┼──────┼────────┼────────────┤
│  1 │ Blood-A      │ 1.85 │ pass   │ 2026-03-01 │
│  2 │ Tissue-B     │ 0.42 │ fail   │ 2026-03-02 │
│  3 │ Serum-C      │ 2.10 │ pass   │ 2026-03-03 │
│  4 │ Plasma-D     │ 0.15 │ fail   │ 2026-03-03 │
└────┴──────────────┴──────┴────────┴────────────┘

용어 정리:

  • 행(Row) = 레코드 하나. 시료 한 건의 전체 정보
  • 열(Column) = 항목 하나. 이름, OD 값, 상태 같은 데이터 종류
  • 스키마(Schema) = 테이블의 설계도. 어떤 컬럼이 있고, 각 컬럼의 데이터 타입이 무엇인지

CRUD: 데이터의 4가지 기본 동작

모든 정보 시스템의 핵심은 CRUD — 생성, 읽기, 수정, 삭제입니다. 실험실 LIMS도 결국 이 네 가지 동작의 조합입니다.

CREATE — 테이블 만들기

sql
CREATE TABLE samples (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  od DECIMAL(5, 2),
  status VARCHAR(10) DEFAULT 'pending',
  created_at DATE
);
  • INT — 정수 (id, 시료 번호)
  • VARCHAR(100) — 최대 100자 문자열 (시료 이름)
  • DECIMAL(5, 2) — 소수점 포함 숫자 (OD 값: 소수점 아래 2자리)
  • AUTO_INCREMENT — 새 행이 추가될 때 자동으로 번호가 올라감
  • PRIMARY KEY — 이 컬럼이 각 행의 고유 식별자
  • NOT NULL — 빈 값을 허용하지 않음

프로토콜에 "반응 온도: ___°C, 시간: ___분"이라고 칸을 만들어 놓는 것과 같습니다. 구조를 먼저 정의하면, 나중에 엉뚱한 데이터가 들어오는 것을 방지합니다.

INSERT — 데이터 넣기

sql
INSERT INTO samples (name, od, status, created_at) VALUES
  ('Blood-A', 1.85, 'pass', '2026-03-01'),
  ('Tissue-B', 0.42, 'fail', '2026-03-02'),
  ('Serum-C', 2.10, 'pass', '2026-03-03');

idAUTO_INCREMENT이므로 직접 넣지 않아도 자동으로 1, 2, 3이 배정됩니다.

SELECT — 데이터 꺼내기 (가장 많이 쓰는 명령)

sql
-- 전체 조회
SELECT * FROM samples;

-- 특정 컬럼만
SELECT name, od FROM samples;

-- 조건 검색
SELECT * FROM samples WHERE status = 'fail';

-- OD 1.0 이상만, OD 높은 순으로 정렬
SELECT name, od FROM samples WHERE od >= 1.0 ORDER BY od DESC;

-- 몇 건인지 세기
SELECT COUNT(*) FROM samples WHERE status = 'pass';

SQL의 힘은 이 조건 조합에 있습니다. 파일을 열어서 for문으로 하나하나 비교할 필요 없이, 조건만 말하면 데이터베이스가 최적의 방법으로 찾아줍니다.

UPDATE — 데이터 수정

sql
-- id가 2인 시료의 OD를 재측정 값으로 업데이트
UPDATE samples SET od = 0.98, status = 'pass' WHERE id = 2;

WHERE 조건을 빠뜨리면 모든 행이 수정됩니다. 실험 노트에서 한 시료의 결과만 수정하려다 전체를 덮어쓰는 사고와 같습니다. UPDATEDELETE에는 반드시 WHERE를 확인하세요.

DELETE — 데이터 삭제

sql
-- 특정 시료 삭제
DELETE FROM samples WHERE id = 4;

-- 모든 fail 시료 삭제 (주의!)
DELETE FROM samples WHERE status = 'fail';

관계형 데이터베이스: 테이블 간의 연결

"관계형"이라는 이름은 테이블끼리 관계를 맺을 수 있다는 뜻입니다. 시료 테이블과 연구자 테이블을 연결하면:

text
researchers 테이블          samples 테이블
┌────┬──────────┐          ┌────┬──────────┬───────────────┐
│ id │ name     │          │ id │ name     │ researcher_id │
├────┼──────────┤          ├────┼──────────┼───────────────┤
│  1 │ 김연구   │◄─────────│  1 │ Blood-A  │             1 │
│  2 │ 박분석   │◄─────────│  2 │ Tissue-B │             2 │
└────┴──────────┘          │  3 │ Serum-C  │             1 │
                           └────┴──────────┴───────────────┘

researcher_id가 두 테이블을 연결하는 열쇠입니다. 이 구조가 있으면:

sql
SELECT samples.name, researchers.name
FROM samples
JOIN researchers ON samples.researcher_id = researchers.id
WHERE researchers.name = '김연구';

"김연구 연구원이 등록한 시료만 보여줘" — 엑셀에서 VLOOKUP을 쓰는 것과 비슷하지만, 수백만 건에서도 순식간에 동작합니다.

어떤 데이터베이스를 쓸까

제품특징적합한 상황
MySQL가장 널리 쓰이는 오픈소스 DB웹 서비스 (WordPress, 대부분의 웹사이트)
PostgreSQL고급 기능, 복잡한 쿼리에 강함분석 중심 서비스, Supabase
SQLite설치 불필요, 파일 하나가 DB 전체로컬 앱, 프로토타입, 개인 프로젝트

BioPlayground 같은 프로젝트는 Supabase(PostgreSQL 기반)를 사용합니다. SQL 문법은 MySQL이든 PostgreSQL이든 90% 이상 동일하므로, 하나만 배우면 나머지는 쉽게 적응할 수 있습니다.

직접 해보기 (Faded Example)

아래 빈칸을 채워 QC 실패 시료를 검색하는 SQL 쿼리를 완성하세요.

빈칸 채우기sql
name, od
FROM
status = 'fail'
ORDER BY od ;

흔한 에러 & 해결법

Q: Table 'database.samples' doesn't exist 에러가 납니다

CREATE TABLE을 아직 실행하지 않았거나, 다른 데이터베이스에 접속한 상태입니다. SHOW TABLES;로 현재 데이터베이스의 테이블 목록을 확인하세요.

Q: UPDATE로 한 행만 수정하려 했는데 전부 바뀌었습니다

WHERE 조건을 빠뜨렸습니다. UPDATE samples SET status = 'pass'모든 행의 status를 pass로 바꿉니다. 반드시 WHERE id = 2 같은 조건을 추가하세요. 중요한 작업 전에는 같은 WHERE 조건으로 SELECT를 먼저 실행해서 어떤 행이 영향받는지 확인하는 습관을 기르세요.

Q: VARCHARTEXT의 차이가 뭔가요?

VARCHAR(100)은 최대 100자까지 저장하며 길이를 지정합니다. TEXT는 길이 제한이 거의 없습니다. 시료 이름이나 상태 같은 짧은 데이터는 VARCHAR, 실험 메모나 긴 설명은 TEXT가 적합합니다.

Q: SQL 명령어가 대문자여야 하나요?

아닙니다. SELECTselect는 같습니다. 대문자는 관례일 뿐입니다. SQL 키워드를 대문자로, 테이블/컬럼 이름을 소문자로 쓰면 코드를 읽기 쉽습니다.

Q: 터미널 말고 GUI로 MySQL을 볼 수 있는 도구가 있나요?

MySQL을 터미널에서 mysql -u root -p로 접속하는 것이 기본이지만, GUI 클라이언트를 쓰면 테이블 구조와 데이터를 시각적으로 확인할 수 있습니다.

도구특징가격
Sequel Ace가볍고 빠름. 기본 쿼리/테이블 관리에 최적 (Mac 전용)무료
TablePlus세련된 UI. MySQL, PostgreSQL, SQLite 등 여러 DB 지원일부 무료
MySQL WorkbenchMySQL 공식 도구. 기능이 많지만 무거움무료

처음에는 Sequel Ace(Mac) 또는 MySQL Workbench(전 플랫폼)로 시작하는 것을 추천합니다. SQL 명령어를 직접 치는 것에 익숙해진 후 GUI를 보조로 쓰면, 데이터를 한눈에 확인하면서 작업할 수 있습니다.