현재 오즈코딩스쿨 강의를 통해 프론트엔드를 학습하고 있습니다.
본 포스트는 해당 강의에 대한 내용 정리를 목적으로 합니다.

데이터베이스는 데이터를 체계적으로 저장하고, 관리하며, 필요할 때 쉽게 꺼내 쓸 수 있게 만든 시스템이다.
쉽게 말해, 정보를 잘 정리해두는 전자 파일함이다.




종이 문서나 엑셀 파일처럼 흩어진 데이터를 하나의 중앙 시스템에서 통일된 구조로 저장하고 관리할 수 있기 때문이다. 덕분에 정보가 일관되며, 오류나 중복을 줄일 수 있기 때문이다.
많은 데이터 속에서 특정 정보를 찾는 데 시간이 오래 걸리지 않기 때문이다.
검색, 필터, 정렬 기능을 통해 필요한 데이터를 효율적으로 조회할 수 있기 때문이다.
여러 명이 동시에 같은 데이터를 사용하거나 수정할 수 있도록 지원하기 때문이다.
예: 쇼핑몰에서 수많은 고객이 동시에 상품 정보를 보는 상황에서도 정확한 데이터 처리가 가능하기 때문이다.
사용자마다 접근 권한을 설정할 수 있어, 중요한 정보를 보호하고 무단 접근을 차단할 수 있기 때문이다.
예: 관리자만 수정 가능, 일반 사용자는 읽기만 가능하도록 설정할 수 있기 때문이다.
실수나 시스템 오류로 데이터가 손상되더라도, 백업된 데이터를 통해 복구할 수 있는 시스템을 갖출 수 있기 때문이다.
웹, 앱, 서버 등 다양한 소프트웨어와 연동되어 실시간으로 데이터를 저장하고 불러오는 기능을 제공하기 때문이다.
예: 게시판에 글을 쓰면 바로 저장되고, 다른 사용자도 즉시 볼 수 있는 이유이기 때문이다.
사람이 감당하기 힘든 수백만 건의 데이터도 정확하고 빠르게 처리할 수 있는 기술적 기반이 되기 때문이다.







데이터 모델링은 업무에서 사용되는 데이터의 구조를 분석하고, 이를 시각적으로 설계하는 과정이다.
데이터 간의 관계, 속성, 제약 조건 등을 정의하여 현실 세계의 정보를 데이터베이스로 구현하기 위한 청사진을 만드는 일이다.

| 요소 | 설명 |
|---|---|
| 개체(Entity) | 독립적으로 존재하는 데이터 단위로, 하나의 테이블이 된다. 예: 회원, 상품, 주문 등이다. |
| 속성(Attribute) | 개체의 성질이나 특징으로, 테이블의 컬럼(Column)이 된다. 예: 이름, 가격, 이메일 등이다. |
| 관계(Relationship) | 개체 간의 연관성을 나타내며, 외래 키 등을 통해 구현된다. 예: 회원은 주문을 한다이다. |
| 제약조건(Constraint) | 데이터의 무결성을 유지하기 위한 규칙이다. 예: NOT NULL, UNIQUE, PRIMARY KEY 등이다. |

| 단계 | 설명 |
|---|---|
| 요구사항 분석 | 어떤 데이터를 다뤄야 하는지를 정의하는 단계이다. |
| 개념적 모델링 | 개체와 관계를 ERD로 표현하는 단계이다. |
| 논리적 모델링 | 정규화 및 테이블 구조를 정의하는 단계이다. |
| 물리적 모델링 | DBMS에 맞춰 실제 구조를 설계하는 단계이다. |
| 모델 검증 및 수정 | 요구사항 반영 여부를 점검하고 개선하는 단계이다. |
| 데이터베이스 구현 | 실제 SQL로 DB를 구축하는 단계이다. |



| 종류 | 설명 |
|---|---|
| 강한 엔터티 | 독립적으로 존재할 수 있는 엔터티이다. 예: 고객, 상품이다. |
| 약한 엔터티 | 다른 엔터티에 의존해야 존재할 수 있는 엔터티이다. 예: 주문 상세, 게시판 댓글이다. |





| 종류 | 설명 |
|---|---|
| 기본 속성 | 일반적인 데이터 값이다. 예: 이름, 나이이다. |
| 식별 속성 | 엔터티를 유일하게 식별할 수 있는 속성이다. 예: 주민등록번호, 회원 ID이다. |
| 복합 속성 | 여러 개의 속성으로 구성된 속성이다. 예: 주소 → (시, 구, 동)이다. |
| 파생 속성 | 다른 속성으로부터 계산되어 도출되는 속성이다. 예: 나이(=현재 연도 - 출생 연도)이다. |
| 다중값 속성 | 하나의 엔터티가 여러 개의 값을 가질 수 있는 속성이다. 예: 이메일이 여러 개일 수 있다. (정규화 필요) |


관계형 데이터베이스는 데이터를 행(Row)과 열(Column)로 구성된 테이블(Table) 형태로 저장하고 관리하는 데이터베이스 시스템이다.
각 테이블은 하나의 엔터티(Entity)를 나타내며, 테이블 간에는 공통된 키(Primary Key, Foreign Key)를 통해 관계(Relationship)를 정의할 수 있다.
데이터를 조작하기 위해 SQL(Structured Query Language)이라는 표준 언어를 사용한다.

| 특징 | 설명 |
|---|---|
| 테이블 기반 구조 | 데이터를 표 형태로 저장하며, 각 행은 레코드, 각 열은 속성이다. |
| 스키마 기반 설계 | 테이블 구조(열 이름, 자료형, 제약조건 등)를 사전에 정의해야 한다. |
| 무결성 제약 조건 | 데이터의 정확성과 일관성을 유지하기 위한 제약 조건이 존재한다. |
| 관계 정의 | 외래 키(Foreign Key)를 통해 테이블 간 관계를 명시할 수 있다. |
| 데이터 정규화 | 중복을 최소화하고 데이터의 일관성을 유지하기 위해 정규화를 적용한다. |
| 트랜잭션 처리 | 원자성, 일관성, 고립성, 지속성을 보장하는 트랜잭션을 지원한다. |




| 구성 요소 | 설명 |
|---|---|
| 테이블(Table) | 데이터를 저장하는 기본 단위로, 엔터티를 표현한다. |
| 레코드(Row) | 한 명의 고객, 한 건의 주문처럼 하나의 개체 정보를 담은 행이다. |
| 속성(Column) | 이름, 가격, 이메일 등 개체의 정보를 담는 열이다. |
| 기본 키(Primary Key) | 테이블 내에서 레코드를 고유하게 식별하는 속성이다. |
| 외래 키(Foreign Key) | 다른 테이블의 기본 키를 참조하여 테이블 간 관계를 형성하는 속성이다. |
| 제품명 | 특징 |
|---|---|
| MySQL | 오픈소스이면서도 안정성이 높고 널리 사용되는 시스템이다. |
| Oracle | 대기업 환경에서 많이 사용되는 고성능, 고가의 상용 RDBMS이다. |
| PostgreSQL | 기능이 풍부하고 확장성이 높은 오픈소스 RDBMS이다. |
| Microsoft SQL Server | 마이크로소프트가 제공하는 관계형 데이터베이스 시스템이다. |
| MariaDB | MySQL의 오픈소스 포크로, MySQL과 호환되며 속도와 기능 개선이 이루어진 시스템이다. |





| 항목 | Supabase | PostgreSQL |
|---|---|---|
| 개념 | 백엔드 플랫폼 | 데이터베이스 엔진 |
| 역할 | 백엔드 통합 서비스 제공 | 데이터 저장 및 관리 |
| 구성 요소 | PostgreSQL, 인증, 스토리지, 실시간 등 포함 | 데이터베이스 기능 중심 |
| 사용 대상 | 프론트엔드 개발자, 스타트업, MVP 개발 | 모든 규모의 애플리케이션 백엔드 |
| 사용 방식 | GUI 기반 + 클라이언트 SDK 제공 | SQL 및 DB 클라이언트로 직접 사용 |



CREATE DATABASE my_database;
CREATE DATABASE = 식별자
my_database = 키워드
잘 생성되면 Success. No rows returned 확인 됨.
SELECT * FROM pg_database; 입력 후 Run

생성된 모든 데이터베이스 나오고 내가 새로 생성한 데이터베이스도 확인할 수 있다.
DROP DATABASE my_database;



Project Settings > General > Delete Project



SQL(Structured Query Language)은 관계형 데이터베이스에서 데이터를 정의하고 조작하는 표준 언어이다. 주로 데이터를 생성(CREATE), 조회(SELECT), 수정(UPDATE), 삭제(DELETE)하는 데 사용되며, 데이터베이스 구조(스키마)를 정의하고, 제약조건, 사용자 권한 등을 관리할 수 있다.






CREATE TABLE Users (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(100) UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE Users ADD COLUMN age INT;

DROP TABLE Users;
INSERT INTO Users (name, email) VALUES ('홍길동', 'hong@example.com');
WHERE, ORDER BY, GROUP BY, LIMIT 등과 함께 사용된다.SELECT id, name FROM Users WHERE age >= 20;
UPDATE Users SET name = '김철수' WHERE id = 1;
DELETE FROM Users WHERE id = 1;
GRANT SELECT, INSERT ON Users TO user1;
REVOKE INSERT ON Users FROM user1;
COMMIT, 실패 시 ROLLBACK하는 방식이다.BEGIN;
UPDATE Users SET name = '최민수' WHERE id = 2;
COMMIT;
SELECT * FROM Users
WHERE age > 20 AND name LIKE '김%';
✅ 주요 SQL 키워드 요약
| 키워드 | 용도 |
|---|---|
SELECT | 데이터 조회이다. |
FROM | 데이터를 가져올 테이블 지정이다. |
WHERE | 조건 지정이다. |
INSERT INTO | 데이터 삽입이다. |
UPDATE | 데이터 수정이다. |
DELETE | 데이터 삭제이다. |
CREATE TABLE | 테이블 생성이다. |
ALTER TABLE | 테이블 수정이다. |
DROP TABLE | 테이블 삭제이다. |
ORDER BY | 정렬이다. |
GROUP BY | 그룹화이다. |
HAVING | 그룹 조건이다. |
| 분류 | 설명 |
|---|---|
| 숫자형(Numeric) | 정수, 실수 등 숫자 데이터를 저장하는 타입이다. |
| 문자형(String) | 문자열 데이터를 저장하는 타입이다. |
| 날짜/시간형(Date/Time) | 날짜 및 시간 정보를 저장하는 타입이다. |
| 논리형(Boolean) | 참 또는 거짓을 저장하는 타입이다. |
| 기타 | JSON, 배열, 바이너리 등 특수 데이터를 위한 타입이다. |


| 데이터 타입 | 설명 |
|---|---|
INT 또는 INTEGER | 일반적인 정수값을 저장하는 타입이다. |
SMALLINT | 작은 범위의 정수값을 저장하는 타입이다. |
BIGINT | 매우 큰 정수값을 저장하는 타입이다. |
DECIMAL(p, s) 또는 NUMERIC(p, s) | 소수점 이하 정밀한 계산이 필요한 숫자를 저장하는 타입이다. |
FLOAT 또는 REAL | 부동소수점 숫자를 저장하는 타입이다. |
SERIAL | 자동 증가하는 정수값(주로 기본 키)에 사용하는 타입이다. (PostgreSQL 전용이다.) |

| 데이터 타입 | 설명 |
|---|---|
CHAR(n) | 고정 길이 문자열이다. (예: CHAR(10) → 항상 10자) |
VARCHAR(n) | 가변 길이 문자열이다. (예: VARCHAR(50) → 최대 50자까지 입력 가능) |
TEXT | 매우 긴 텍스트 데이터를 저장하는 타입이다. |


| 데이터 타입 | 설명 |
|---|---|
DATE | 날짜(연, 월, 일)를 저장하는 타입이다. |
TIME | 시간(시, 분, 초)을 저장하는 타입이다. |
TIMESTAMP | 날짜와 시간을 함께 저장하는 타입이다. |
TIMESTAMPTZ | 타임존 정보를 포함한 날짜와 시간을 저장하는 타입이다. (PostgreSQL 전용이다.) |


| 데이터 타입 | 설명 |
|---|---|
BOOLEAN | 참(TRUE) 또는 거짓(FALSE) 값을 저장하는 타입이다. |

| 데이터 타입 | 설명 |
|---|---|
JSON, JSONB | JSON 형식의 구조화된 데이터를 저장하는 타입이다. (PostgreSQL 전용이다.) |
ARRAY | 배열 형태로 여러 값을 저장하는 타입이다. (PostgreSQL 전용이다.) |
UUID | 고유 식별자를 저장하는 타입이다. |
BYTEA | 이진 데이터를 저장하는 타입이다. (예: 이미지, 파일 등) |






INSERT INTO 테이블명 (열1, 열2, ...)
VALUES (값1, 값2, ...);
- 테이블의 지정된 열(컬럼)에 맞는 값을 하나의 행으로 추가하는 문법이다.
- 각 열의 데이터 타입에 맞는 값을 정확히 입력해야 한다.
INSERT INTO Users (name, email, age)
VALUES ('홍길동', 'hong@example.com', 30);
- Users 테이블에 name, email, age 값을 갖는 새 행을 추가하는 명령어이다.
INSERT INTO Users
VALUES (1, '김철수', 'kim@example.com', 25);
- 테이블에 모든 열 순서대로 값을 넣을 때 열 이름 생략이 가능하다.
- 단, 모든 열의 개수와 순서를 정확히 맞춰야 하므로 추천하지 않는 방식이다.
INSERT INTO Users (name, email, age)
VALUES
('이영희', 'lee@example.com', 27),
('박민준', 'park@example.com', 35);
- 한 번에 여러 개의 행을 삽입할 수 있는 문법이다.
- 대량 데이터 입력 시 성능상 효율적이다.
CREATE TABLE Users (
id SERIAL PRIMARY KEY,
name VARCHAR(50),
age INT DEFAULT 20
);
INSERT INTO Users (name)
VALUES ('최수진');
- age 컬럼은 입력하지 않았지만, DEFAULT 20이 설정되어 자동으로 값이 들어간다.
- SERIAL은 자동 증가이므로 id도 생략 가능하다.
INSERT INTO UsersBackup (id, name, email)
SELECT id, name, email FROM Users;
- SELECT 문을 활용하면 한 테이블에서 다른 테이블로 데이터를 복사할 수 있다.
‼️ 주의사항
- NOT NULL, UNIQUE, PRIMARY KEY, FOREIGN KEY 등의 제약조건을 위반하면 삽입되지 않는다.
- 문자열은 ' 작은 따옴표로 감싸야 하며, 숫자나 날짜 형식은 각 타입에 맞게 지정해야 한다.
- SQL Injection 방지를 위해 값은 반드시 바인딩 또는 필터링이 필요하다.
-- 데이터베이스 생성
CREATE DATABASE my_database;
-- 데이터베이스 삭제
DROP DATABASE my_database;
DROP TABLE accommodation;
CREATE TABLE accommodation (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
address TEXT NOT NULL,
city VARCHAR(100) NOT NULL,
country VARCHAR(100) NOT NULL,
rating DECIMAL(3, 2),
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 레코드가 하나도 없기 때문에 나오지 않는다.
SELECT * FROM accommodation;
INSERT INTO accommodation (name, address, city, country, rating, description)
VALUES
('Nomad House', '123 Beach Rd', 'Canggu', 'Indonesia', 4.5, '멋진 바다'),
('Remote Work Haven', '456 Mountain St', 'Chiang Mai', 'Thailand', 4.7, '아름다운 산'),
('Digital Nomad Loft', '789 City Center', 'Medellin', 'Colombia', 4.8, '도시 중심');
-- 컬럼 이름과 레코드가 나올 것이다.
SELECT * FROM accommodation;
-- 당연히 추가로 더 삽입할 수 있다.
INSERT INTO accommodation (name, address, city, country, rating, description)
VALUES
('Freelancer Hub', '321 Riverbank Ave', 'Lisbon', 'Portugal', 4.6, 'A trendy hub for freelancers with co-working spaces and a great community.'),
('Work & Play Retreat', '654 Historic District', 'Tbilisi', 'Georgia', 4.7, 'Combines workspaces and cultural experiences in a historic city.'),
('Nomad Nest', '987 Coastal Rd', 'Playa del Carmen', 'Mexico', 4.5, 'A beachside accommodation perfect for work and leisure.'),
('Remote R&R', '213 Lakeview Blvd', 'Bansko', 'Bulgaria', 4.6, 'Ideal for remote work with beautiful mountain views and fast internet.'),
('Digital Den', '567 Urban St', 'Budapest', 'Hungary', 4.7, 'Located in a bustling city with great nightlife and work facilities.'),
('Freelance Lodge', '345 Sunset Blvd', 'Barcelona', 'Spain', 4.8, 'Offers a dynamic environment for freelancers with excellent amenities.'),
('Nomad Base', '678 Green Park', 'Ho Chi Minh City', 'Vietnam', 4.5, 'A modern base for digital nomads with all necessary facilities.');
-- 엑셀이나 구글 시트와 다른 점은, 테이블에서 엄격하게 정한 데이터 타입을 넣지 않으면 오류가 난다는 점이다.
INSERT INTO accommodation (name, address, city, country, rating, description)
VALUES
('Nomad Dosi', '123 Teheran-ro', 'Seoul', 'Korea', 'Not a number', '서울에도 멋진 호텔이 있다');
INSERT INTO accommodation (name, address, city, country, rating, description)
VALUES
('Nomad City', '123 Teheran-ro', 'Seoul', '데이터를 삽입해 봅시다. INSERT INTO 명령을 하면 데이터를 삽입할 수 있습니다. INSERT INTO는 문법을 주의하셔야 하는데, INSERT INTO 뒤에는 컬럼 명을 작성하고, VALUES 뒤에는 실제 삽입할 데이터를 넣으면 됩니다. 이제는 우리가 로우를 배웠으니 데이터라고 부르지 않고 로우라고 부르겠습니다.', 4.4, 'description');




SELECT 열1, 열2, ...
FROM 테이블명;
- 지정된 열(column)의 데이터를 테이블에서 조회하는 명령어이다.
- 여러 열을 쉼표로 구분하며, 전체 열을 조회할 경우 *를 사용할 수 있다.
SELECT * FROM Users;
- Users 테이블의 모든 열과 모든 행을 조회하는 명령어이다.
SELECT name, email FROM Users;
- Users 테이블에서 name과 email 열만 조회하는 명령어이다.




SELECT * FROM Users
WHERE age >= 30;
- age가 30 이상인 사용자만 조회하는 조건 검색이다.
- 비교 연산자: =, !=, <, <=, >, >=
- 논리 연산자: AND, OR, NOT


SELECT name, age FROM Users
ORDER BY age DESC;
- age 값을 기준으로 내림차순 정렬하여 데이터를 조회한다.
- ASC는 오름차순, DESC는 내림차순이다.


SELECT DISTINCT age FROM Users;
- age 값의 중복을 제거하고 유일한 값만 조회하는 명령어이다.
SELECT name AS 사용자이름, age AS 나이 FROM Users;
- 조회되는 열에 별칭(alias) 을 붙여 결과를 보기 쉽게 만든다.
- 별칭에는 AS를 쓰거나 생략할 수 있다.
SELECT * FROM Users
WHERE name LIKE '김%';
- name이 ‘김’으로 시작하는 사용자만 조회한다.
- %는 와일드카드이며, 문자열 일부 매칭에 사용된다.

SELECT * FROM Users
LIMIT 10;
- 결과를 최대 10개까지만 출력하는 명령어이다.
- 페이징 처리 시 자주 사용된다.
- 예: LIMIT 10 OFFSET 20 → 21번째부터 10개 출력



SELECT COUNT(*) FROM Users;
SELECT AVG(age), MAX(age), MIN(age) FROM Users;
- COUNT, AVG, SUM, MIN, MAX 등은 통계용 집계 함수이다.
- 테이블의 전체 개수, 평균, 합계, 최댓값, 최솟값 등을 조회할 수 있다.
SELECT age, COUNT(*) FROM Users
GROUP BY age;
- 나이(age)별로 그룹화하여 사용자 수를 집계하는 쿼리이다.
- 그룹화 결과를 필터링할 때는 HAVING을 사용한다.
CREATE TABLE accommodation (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
address TEXT NOT NULL,
city VARCHAR(100) NOT NULL,
country VARCHAR(100) NOT NULL,
zip_code VARCHAR(20),
phone_number VARCHAR(20),
email VARCHAR(100),
website VARCHAR(255),
price_per_night DECIMAL(10, 2),
rating DECIMAL(3, 2),
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO accommodation (
name, address, city, country, zip_code, phone_number, email, website, price_per_night, rating, description
) VALUES
(
'Nomad House',
'123 Freedom St, Suite 5',
'Bali',
'Indonesia',
'80361',
'+62 361 1234567',
'contact@nomadhouse.com',
'https://www.nomadhouse.com',
45.00,
4.75,
'발리 중심부에 위치한 활기찬 공동 거주 공간으로, 고속 인터넷, 코워킹 공간, 같은 생각을 가진 디지털 노마드 커뮤니티를 제공합니다.'
),
(
'Remote Work Paradise',
'456 Innovation Ave',
'Chiang Mai',
'Thailand',
'50200',
'+66 53 123456',
'info@remoteworkparadise.com',
'https://www.remoteworkparadise.com',
35.00,
4.85,
'치앙마이에 위치한 이 숙소는 현대적인 편의 시설, 아늑한 작업 환경, 다른 원격 근무자들과의 네트워킹 기회를 제공합니다.'
),
(
'Digital Nomad Haven',
'789 Tech Lane',
'Medellin',
'Colombia',
'050021',
'+57 4 1234567',
'support@digitalnomadhaven.com',
'https://www.digitalnomadhaven.com',
50.00,
4.90,
'메데인 번화가에 위치한 이 숙소는 뛰어난 인터넷, 개인 작업 공간, 활기찬 디지털 노마드 커뮤니티를 제공합니다.'
),
(
'Nomad Nest',
'101 Explorer Rd',
'Lisbon',
'Portugal',
'1100-001',
'+351 21 1234567',
'hello@nomadnest.com',
'https://www.nomadnest.com',
60.00,
4.80,
'리스본에 위치한 이 숙소는 넓은 작업 공간, 빠른 인터넷, 편안한 숙박 시설을 제공합니다.'
),
(
'Techie Retreat',
'202 Startup St',
'Berlin',
'Germany',
'10115',
'+49 30 123456',
'contact@techieretreat.com',
'https://www.techieretreat.com',
55.00,
4.70,
'베를린에 위치한 이 숙소는 최신 기술을 갖춘 작업 공간과 활발한 디지털 노마드 커뮤니티를 제공합니다.'
),
(
'Work Wander',
'303 Travel Blvd',
'Bangkok',
'Thailand',
'10110',
'+66 2 123456',
'info@workwander.com',
'https://www.workwander.com',
40.00,
4.65,
'방콕에 위치한 이 숙소는 편안한 작업 환경, 고속 인터넷, 다양한 문화 체험 기회를 제공합니다.'
),
(
'Nomad Hub',
'404 Freelancer Ln',
'Ho Chi Minh City',
'Vietnam',
'700000',
'+84 28 1234567',
'support@nomadhub.com',
'https://www.nomadhub.com',
30.00,
4.60,
'호치민시에 위치한 이 숙소는 경제적인 가격, 넓은 작업 공간, 활기찬 커뮤니티를 제공합니다.'
),
(
'Remote Base',
'505 Digital Dr',
'Tbilisi',
'Georgia',
'0105',
'+995 32 123456',
'hello@remotebase.com',
'https://www.remotebase.com',
25.00,
4.55,
'트빌리시에 위치한 이 숙소는 저렴한 가격, 편리한 위치, 쾌적한 작업 환경을 제공합니다.'
),
(
'Wander Work',
'606 Explorer Ave',
'Budapest',
'Hungary',
'1051',
'+36 1 1234567',
'contact@wanderwork.com',
'https://www.wanderwork.com',
45.00,
4.50,
'부다페스트에 위치한 이 숙소는 멋진 도시 경관, 넓은 작업 공간, 편안한 숙박 시설을 제공합니다.'
),
(
'Nomad Life',
'707 Journey St',
'Mexico City',
'Mexico',
'01000',
'+52 55 1234567',
'info@nomadlife.com',
'https://www.nomadlife.com',
35.00,
4.65,
'멕시코 시티에 위치한 이 숙소는 문화적인 체험, 빠른 인터넷, 편안한 작업 환경을 제공합니다.'
);
-- SELECT 실습 영상 샘플 데이터
-- 실습용 코드는 가능하면 직접 손으로 입력해서 연습해 보세요.
-- 전체 조회
SELECT * FROM accommodation;
-- 일부 컬럼 조회
SELECT name, description FROM accommodation;
-- WHERE로 일부 조회
SELECT * FROM accommodation WHERE city = 'Bali';
-- WHERE + OR
SELECT * FROM accommodation WHERE city = 'Chiang Mai' OR city = 'Bali';
-- 평점 4.75점 이상
SELECT * FROM accommodation WHERE rating >= 4.75;
-- 평점 4.5점 이상 4.6 이하
SELECT * FROM accommodation WHERE rating BETWEEN 4.5 AND 4.6;
-- ID가 1, 3
SELECT * FROM accommodation WHERE id IN (1, 3);
-- ID가 1, 3이 아님
SELECT * FROM accommodation WHERE id NOT IN (1, 3);
-- 내림차순 (큰 것 부터)
SELECT * FROM accommodation ORDER BY rating DESC;
-- PostgreSQL은 id 순서롤 보장하지 않기 때문에, 순서가 중요한 경우 꼭 sort를 해준다.
SELECT * FROM accommodation;
SELECT * FROM accommodation ORDER BY id ASC;
SELECT * FROM accommodation ORDER BY created_at ASC;
-- 평점 상위 3개
SELECT * FROM accommodation ORDER BY rating DESC LIMIT 3;
-- 전체 로우 갯수
SELECT COUNT(*) FROM accommodation;
-- 전체 평점 평균, 최솟값, 최댓값
SELECT AVG(rating) as avg_rating FROM accommodation;
SELECT MIN(rating) as min_rating FROM accommodation;
SELECT MAX(rating) as max_rating FROM accommodation;
-- 전체 하루 숙박 가격 평균, 최솟값, 최댓값
SELECT AVG(price_per_night) as avg_price FROM accommodation;
SELECT MIN(price_per_night) as min_price FROM accommodation;
SELECT MAX(price_per_night) as max_price FROM accommodation;
-- 테이블이 가지고 있는 모든 국가
SELECT DISTINCT country FROM accommodation;
SELECT COUNT(DISTINCT country) FROM accommodation;




UPDATE 테이블명
SET 열1 = 값1, 열2 = 값2, ...
WHERE 조건;
- SET 뒤에 수정할 컬럼과 변경할 값을 나열한다.
- WHERE 조건을 반드시 지정하여 수정할 대상 행을 한정하는 것이 매우 중요하다.
- WHERE를 생략하면 테이블 내 모든 행이 수정된다.
UPDATE Users
SET age = 35
WHERE id = 1;
- Users 테이블에서 id가 1인 행의 age 값을 35로 변경하는 명령어이다.

UPDATE Users
SET name = '김민수', email = 'minsu@example.com'
WHERE id = 2;
- 한 행에서 여러 컬럼을 한 번에 수정할 수 있다.
UPDATE Users
SET active = FALSE;
- WHERE 조건이 없으므로 Users 테이블 내 모든 행의 active 컬럼을 FALSE로 변경한다.
- 대규모 변경 작업 시 실수로 전체 데이터가 변경되지 않도록 주의해야 한다.

UPDATE Users
SET status = '휴면'
WHERE last_login < '2023-01-01' AND active = TRUE;
- 마지막 로그인 날짜가 2023년 1월 1일 이전이고, 현재 활성 상태인 사용자들의 상태를 ‘휴면’으로 변경하는 예시이다.
-- 현재 데이터 확인
SELECT * FROM accommodation;
-- UPDATE 쿼리 실행 전 WHERE 조건 확인
SELECT * FROM accommodation
WHERE id = 1;
-- UPDATE 쿼리 실행
UPDATE accommodation
SET name = 'wow'
WHERE id = 1
RETURNING *;
-- 원래대로 변경
UPDATE accommodation
SET name = 'Nomad House'
WHERE id = 1
RETURNING *;
-- UPDATE 쿼리 실행 전 WHERE 조건 확인
SELECT * FROM accommodation
WHERE country = 'Thailand' AND rating < 5.0;
-- WHERE 조건에 해당하는 여러 로우의 값을 변경
-- 기존 rating 값을 활용할 수 있음
UPDATE accommodation
SET rating = rating + 0.1, price_per_night = price_per_night + 1
WHERE country = 'Thailand' AND rating < 5.0
RETURNING *;
-- 원래대로 변경
UPDATE accommodation
SET rating = rating - 0.1, price_per_night = price_per_night - 1
WHERE country = 'Thailand' AND rating < 5.0
RETURNING *;
-- WHERE를 뺴먹으면 로우 전체에 영향을 미칠 수 있다.
UPDATE accommodation
SET price_per_night = price_per_night - 1
RETURNING *;
-- 이전으로 변경
UPDATE accommodation
SET price_per_night = price_per_night + 1
RETURNING *;




DELETE FROM 테이블명
WHERE 조건;
- WHERE 조건에 맞는 행들을 삭제한다.
- WHERE 절을 생략하면 테이블 내 모든 데이터가 삭제된다. (테이블 구조는 유지된다.)
DELETE FROM Users
WHERE id = 1;
- Users 테이블에서 id가 1인 행을 삭제하는 명령어이다.
DELETE FROM Orders
WHERE order_date < '2023-01-01';
- 2023년 1월 1일 이전 주문 데이터를 모두 삭제하는 예시이다.
DELETE FROM Logs;
- WHERE 조건 없이 실행하면 Logs 테이블의 모든 행이 삭제된다.
- 테이블 자체는 삭제되지 않고 빈 상태로 남는다.
‼️ 주의사항
- 삭제 작업은 복구가 어려울 수 있어 신중하게 실행해야 한다.
- 외래키(Foreign Key) 제약조건이 있는 경우, 참조 무결성 때문에 삭제가 제한될 수 있다.
- 트랜잭션을 활용해 안전하게 삭제 작업을 처리할 수 있다.
-- 현재 데이터 확인
SELECT * FROM accommodation;
-- id가 1인 로우 삭제
DELETE FROM accommodation
WHERE id = 1
RETURNING *;
DELETE FROM accommodation
WHERE id = 2 OR id = 3
RETURNING *;