๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๋ฐฑ์—”๋“œ/spring&springboot

[๋‚ด์ผ๋ฐฐ์›€์บ ํ”„_Spring Boot ์ž…๋ฌธ์ฃผ์ฐจ] Database์™€ SQL

by alswlfl 2026. 6. 24.

Database(๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค)

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ๋ฐ์ดํ„ฐ์˜ ์ง‘ํ•ฉ์œผ๋กœ, ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌํ•ด์ฃผ๋Š” ์—ญํ•  ์ˆ˜ํ–‰

DBMS(Database Management System): Database๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ์šด์˜ํ•˜๋Š” ์†Œํ”„ํŠธ์›จ์–ด

RDBMS(Relational DBMS)

๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค

  • ํ…Œ์ด๋ธ”(table)์ด๋ผ๋Š” ์ตœ์†Œ ๋‹จ์œ„๋กœ ๊ตฌ์„ฑ๋˜๋ฉฐ, ์ด ํ…Œ์ด๋ธ”์€ ์—ด(column)๊ณผ ํ–‰(row)์œผ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ์Œ
  • ํ…Œ์ด๋ธ”๊ฐ„ FK(Foreign Key)๋ฅผ ํ†ตํ•ด ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํ•ฉํ•ด์„œ ํ•จ๊ป˜ ๋ณผ ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Œ
  • RDBMS ์ข…๋ฅ˜๋กœ๋Š” Oracle, MySQL, PostgreSQL ๋“ฑ ์กด์žฌ

SQL(Structured Query Language)

SQL์€ RDBMS์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์–ธ์–ด๋กœ, ์ˆ˜ ๋งŽ์€ ์ •๋ณด๋ฅผ Database์—์„œ ์กฐ์ž‘ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” SQL ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•จ

  • ๊ตญ์ œํ‘œ์ค€ํ™”๊ธฐ๊ตฌ์—์„œ SQL์— ๋Œ€ํ•œ ํ‘œ์ค€์„ ์ •ํ•ด์„œ ๋ฐœํ‘œํ•˜๊ณ  ์žˆ์Œ
  • ๊ทธ๋Ÿฌ๋‚˜ DBMS๋ฅผ ๋งŒ๋“œ๋Š” ํšŒ์‚ฌ๊ฐ€ ์—ฌ๋Ÿฌ ๊ณณ์ด๊ธฐ ๋•Œ๋ฌธ์— DBMS ๋งˆ๋‹ค ํ‘œ์ค€ SQL์„ ์ค€์ˆ˜ํ•˜๋˜, ๊ฐ ์ œํ’ˆ์˜ ํŠน์„ฑ์„ ๋ฐ˜์˜ํ•˜๊ธฐ ์œ„ํ•œ ์•ฝ๊ฐ„์˜ ์ฐจ์ด๊ฐ€ ์กด์žฌํ•จ

DDL(Data Definition Language)

ํ…Œ์ด๋ธ”์ด๋‚˜ ๊ด€๊ณ„์˜ ๊ตฌ์กฐ๋ฅผ ์ƒ์„ฑํ•˜๋Š”๋ฐ ์‚ฌ์šฉ

 

CREATE

์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐ ํ…Œ์ด๋ธ” ์ƒ์„ฑ

CREATE DATABASE ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ด๋ฆ„;
CREATE TABLE ํ…Œ์ด๋ธ”์ด๋ฆ„(
    ํ•„๋“œ์ด๋ฆ„1 ํ•„๋“œํƒ€์ž…1,
    ํ•„๋“œ์ด๋ฆ„2 ํ•„๋“œํƒ€์ž…2,
    ...
);

 

[์ œ์•ฝ ์กฐ๊ฑด]

  • AUTO_INCREMENT: ์ปฌ๋Ÿผ์˜ ๊ฐ’์ด ์ค‘๋ณต๋˜์ง€ ์•Š๊ฒŒ 1์”ฉ ์ž๋™์œผ๋กœ ์ฆ๊ฐ€ํ•˜๊ฒŒ ํ•ด์คŒ(๊ณ ์œ ๋ฒˆํ˜ธ ์ƒ์„ฑ)
CREATE TABLE ํ…Œ์ด๋ธ”์ด๋ฆ„(
    ํ•„๋“œ์ด๋ฆ„ ํ•„๋“œํƒ€์ž… AUTO_INCREMENT;
    // id bigint AUTO_INCREMENT;
);
  • NOT NULL: ํ•ด๋‹น ํ•„๋“œ๋Š” NULL ๊ฐ’์„ ์ €์žฅํ•  ์ˆ˜ ์—†์Œ
CREATE TABLE ํ…Œ์ด๋ธ”์ด๋ฆ„(
   ํ•„๋“œ์ด๋ฆ„ ํ•„๋“œํƒ€์ž… NOT NULL,
    ...
);
  • UNIQUE: ํ•ด๋‹น ํ•„๋“œ๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ๊ฐ’์„ ๊ฐ€์ ธ์•ผ๋งŒ ํ•จ
CREATE TABLE ํ…Œ์ด๋ธ”์ด๋ฆ„(
    ํ•„๋“œ์ด๋ฆ„ ํ•„๋“œํƒ€์ž… UNIQUE,
    ...
);
  • PRIMARY KEY: ํ•ด๋‹น ํ•„๋“œ๊ฐ€ NOT NULL๊ณผ UNIQUE ์ œ์•ฝ ์กฐ๊ฑด์˜ ํŠน์ง•์„ ๋ชจ๋‘ ๊ฐ€์ง
CREATE TABLE ํ…Œ์ด๋ธ”์ด๋ฆ„(
    ํ•„๋“œ์ด๋ฆ„ ํ•„๋“œํƒ€์ž… PRIMARY KEY,
    ...
);
PRIMARY KEY(๊ธฐ๋ณธ ํ‚ค)๋Š” ํ…Œ์ด๋ธ” ๋‚ด์—์„œ '์œ ์ผํ•˜๊ฒŒ ์กด์žฌํ•˜๋Š” ๊ฐ’์˜ ์กฐํ•ฉ'์„ ์„ค์ •ํ•ด์„œ ์ค‘๋ณต๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ํ…Œ์ด๋ธ”์— ์‚ฝ์ž…๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๋Š” ์ œ์•ฝ์กฐ๊ฑด์ž„

1. ๋ฐ์ดํ„ฐ์˜ ์ค‘๋ณต ๋ฐฉ์ง€
- ๋งŒ์•ฝ ๊ธฐ๋ณธํ‚ค๋ฅผ ์„ค์ •ํ•˜์ง€ ์•Š๊ณ ์„œ ํšŒ์›์„ ๊ด€๋ฆฌํ•˜๋Š” ํ…Œ์ด๋ธ”์ด ์žˆ์„ ๋•Œ ๊ธฐ์กด์— ์žˆ๋˜ ํšŒ์›์ด ์˜ˆ์ „์— ๊ฐ€์ž…ํ•œ ๊ฒƒ์„ ์žŠ๊ณ  ๋‹ค์‹œ ํšŒ์›๊ฐ€์ž…์„ ํ•˜๋Š” ๊ฒฝ์šฐ ํ˜น์€ ์ตœ๊ทผ์— ๋ฒˆํ˜ธ ๋ฐ ์ฃผ์†Œ๊ฐ€ ๋ณ€๊ฒฝ๋œ ๊ฒฝ์šฐ์—
๋‘˜ ์ค‘์— ์–ด๋А ์ •๋ณด๊ฐ€ ์ •ํ™•ํ•œ ์ •๋ณด์ธ์ง€ ํŒ๋‹จํ•˜๊ธฐ ์–ด๋ ค์›€ โ–บ ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ์ด ๊นจ์ง

2. ๋ฐ์ดํ„ฐ๋ฅผ ๋น ๋ฅด๊ฒŒ ํƒ์ƒ‰ ๊ฐ€๋Šฅ
- ๊ธฐ๋ณธ ํ‚ค๋ฅผ ์„ค์ •ํ•˜๋ฉด DBMS๋Š” ์ธ๋ฑ์Šค๋ฅผ ๋งŒ๋“ฆ
- ์ธ๋ฑ์Šค๋Š” ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ๋นจ๋ฆฌ ์ฐพ์„ ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ฃผ๋Š” ์ผ์ข…์˜ ๋ชฉ์ฐจ์ž„
- ๋งŒ์•ฝ ์ฃผ๋ฏผ๋ฒˆํ˜ธ ์ปฌ๋Ÿผ์— ๊ธฐ๋ณธ ํ‚ค๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ์ง€ ์•Š๋Š”๋‹ค๋ฉด, ์ฃผ๋ฏผ๋ฒˆํ˜ธ๊ฐ€ ์ค‘๋ณต๋  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์€ ์šฐ๋ฆฌ๋Š” ์•Œ์ง€๋งŒ DBMS๋Š” ๋ชจ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์ฃผ๋ฏผ๋ฒˆํ˜ธ๊ฐ€ ์ค‘๋ณต๋  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์„ ๊ฐ€์ •ํ•ด 5000๋งŒ row๋ฅผ ์ „๋ถ€ ํ™•์ธํ•˜๊ฒŒ๋จ
์ด๋•Œ, ์ฃผ๋ฏผ๋ฒˆํ˜ธ์— ๊ธฐ๋ณธ ํ‚ค ์„ค์ •์ด ๋˜์–ด์žˆ์œผ๋ฉด row๋ฅผ ์ „๋ถ€ ํ™•์ธํ•˜์ง€ ์•Š๊ณ  1๊ฐœ๋งŒ ์ฐพ์œผ๋ฉด ๋ฐ”๋กœ ํ•ด๋‹น ๋ฐ์ดํ„ฐ ๋ฐ˜ํ™˜ ๊ฐ€๋Šฅ
  • FOREIGN KEY: ํ•˜๋‚˜์˜ ํ…Œ์ด๋ธ”์„ ๋‹ค๋ฅธ ํ…Œ์ด๋ธ”์— ์˜์กดํ•˜๊ฒŒ ๋งŒ๋“ค๋ฉฐ ๋ฐ์ดํ„ฐ์˜ ๋ฌด๊ฒฐ์„ฑ์„ ๋ณด์žฅํ•ด์คŒ
    ๏นก FK๋ฅผ ๊ฐ€์ง€๋Š” ํ…Œ์ด๋ธ”์ด ์ฐธ์กฐํ•˜๋Š” ๊ธฐ์ค€ ํ…Œ์ด๋ธ”์˜ ์—ด์€ ๋ฐ˜๋“œ์‹œ PK, UNIQUE ์ œ์•ฝ์กฐ๊ฑด์ด ์„ค์ •๋˜์–ด ์žˆ์–ด์•ผํ•จ
CREATE TABLE ํ…Œ์ด๋ธ”์ด๋ฆ„(
    ํ•„๋“œ์ด๋ฆ„, ํ•„๋“œํƒ€์ž…,
    ...
    FOREIGN KEY(ํ•„๋“œ์ด๋ฆ„)
    REFERENCES ํ…Œ์ด๋ธ”์ด๋ฆ„(ํ•„๋“œ์ด๋ฆ„)
);
FOREIGN KEY(์™ธ๋ž˜ ํ‚ค)๋Š” ๋‘ ๊ฐœ์˜ ํ…Œ์ด๋ธ”์„ ์—ฐ๊ฒฐํ•˜๋Š” ๋‹ค๋ฆฌ ์—ญํ• ์„ ํ•ด์ฃผ๋Š” ํ‚ค
- ์™ธ๋ž˜ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ค‘๋ณต๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์—†์• ๊ณ , ์™ธ๋ž˜ํ‚ค๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ฐธ์กฐํ•˜๋Š” ํ…Œ์ด๋ธ”์— ์ ‘๊ทผํ•ด ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Œ
- ๊ธฐ๋ณธ ํ‚ค๊ฐ€ ํ•˜๋‚˜์˜ ํ…Œ์ด๋ธ”์—์„œ ์ค‘๋ณต๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์‚ฝ์ž…๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๋Š” ์—ญํ• ์„ ํ•ด์ฃผ๋Š”๋ฐ ์™ธ๋ž˜ ํ‚ค ์—ญ์‹œ ๋น„์Šทํ•œ ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•˜๋Š” ์—ญํ•  ์ˆ˜ํ–‰ํ•จ! ์™ธ๋ž˜ ํ‚ค๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์ƒˆ๋กญ๊ฒŒ ์ถ”๊ฐ€๋  ๋•Œ ์™ธ๋ž˜ ํ‚ค์— ํ•ด๋‹นํ•˜๋Š” ๊ฐ’์ด ์™ธ๋ž˜ ํ‚ค๊ฐ€ ์ฐธ์กฐํ•˜๋Š” ํ…Œ์ด๋ธ”์— ์กด์žฌํ•˜๋Š”์ง€๋ฅผ ํ™•์ธํ•จ
  • CASCADE: FOREIGN KEY๋กœ ์—ฐ๊ด€๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ญ์ œ, ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Œ
CREATE TABLE ํ…Œ์ด๋ธ”์ด๋ฆ„(
    ํ•„๋“œ์ด๋ฆ„ ํ•„๋“œํƒ€์ž…,
    ...
    FOREIGN KEY(ํ•„๋“œ์ด๋ฆ„)
    REFERENCES ํ…Œ์ด๋ธ”์ด๋ฆ„(ํ•„๋“œ์ด๋ฆ„) ON DELETE CASCADE
    			// ON UPDATE CASCADE
);

 

ALTER

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ํ…Œ์ด๋ธ”์˜ ๋‚ด์šฉ ์ˆ˜์ •

ALTER TABLE ํ…Œ์ด๋ธ”์ด๋ฆ„ ADD ํ•„๋“œ์ด๋ฆ„ ํ•„๋“œํƒ€์ž…;
ALTER TABLE ํ…Œ์ด๋ธ”์ด๋ฆ„ DROP ํ•„๋“œ์ด๋ฆ„;
ALTER TABLE ํ…Œ์ด๋ธ”์ด๋ฆ„ MODIFY COLUMN ํ•„๋“œ์ด๋ฆ„ ํ•„๋“œํƒ€์ž…;

 

DROP

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ํ…Œ์ด๋ธ” ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Œ. ๋ฐ์ดํ„ฐ ๋ฐ ํ…Œ์ด๋ธ” ์ „์ฒด ์‚ญ์ œ

DROP DATABASE ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ด๋ฆ„;
DROP TABLE ํ…Œ์ด๋ธ”์ด๋ฆ„;

 

TRUNCATE

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ํ…Œ์ด๋ธ”์„ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Œ. ์ตœ์ดˆ ํ…Œ์ด๋ธ”์ด ๋งŒ๋“ค์–ด์กŒ๋˜ ์ƒํƒœ์ธ ์ปฌ๋Ÿผ๊ฐ’๋งŒ ๋‚จ๊น€

TRUNCATE DATABASE ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ด๋ฆ„;
TRUNCATE TABLE ํ…Œ์ด๋ธ”์ด๋ฆ„;

DCL(Data Control Language)

๋ฐ์ดํ„ฐ์˜ ์‚ฌ์šฉ ๊ถŒํ•œ์„ ๊ด€๋ฆฌํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•จ

 

GRANT

์‚ฌ์šฉ์ž ๋˜๋Š” ROLE์— ๋Œ€ํ•ด ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ์Œ

GRANT [๊ฐ์ฒด๊ถŒํ•œ๋ช…] (์ปฌ๋Ÿผ)
ON [๊ฐ์ฒด๋ช…]
TO { ์œ ์ €๋ช… | ๋กค๋ช… | PUBLIC } [WITH GRANT OPTION];

// ex
GRANT SELECT, INSERT
ON mp
TO scott WITH GRANT OPTION;

 

REVOKE

์‚ฌ์šฉ์ž ๋˜๋Š” ROLE์— ๋Œ€ํ•ด ๊ถŒํ•œ์„ ํšŒ์ˆ˜ํ•  ์ˆ˜ ์žˆ์Œ

REVOKE { ๊ถŒํ•œ๋ช… [, ๊ถŒํ•œ๋ช…...] ALL }
ON ๊ฐ์ฒด๋ช…
FROM { ์œ ์ €๋ช… [, ์œ ์ €๋ช…...] | ๋กค๋ช…(ROLE) | PUBLIC }
[CASCADE CONSTRAINTS];

// ex
REVOKE SELECT, INSERT
ON emp
FROM scott
[CASCASE CONSTRAINTS];

DML(Data Manipulation Language)

ํ…Œ์ด๋ธ”์— ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ƒ‰, ์‚ฝ์ž…, ์ˆ˜์ •, ์‚ญ์ œํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•จ

 

INSERT

ํ…Œ์ด๋ธ”์— ์ƒˆ๋กœ์šด row ์ถ”๊ฐ€

INSERT INTO ํ…Œ์ด๋ธ”์ด๋ฆ„(ํ•„๋“œ์ด๋ฆ„1, ํ•„๋“œ์ด๋ฆ„2, ํ•„๋“œ์ด๋ฆ„3, ...) VALUES(๋ฐ์ดํ„ฐ๊ฐ’1, ๋ฐ์ดํ„ฐ๊ฐ’2, ๋ฐ์ดํ„ฐ๊ฐ’3, ...);
INSERT INTO ํ…Œ์ด๋ธ”์ด๋ฆ„ VALUES(๋ฐ์ดํ„ฐ๊ฐ’1, ๋ฐ์ดํ„ฐ๊ฐ’2, ๋ฐ์ดํ„ฐ๊ฐ’3, ...);

 

SELECT

ํ…Œ์ด๋ธ”์˜ row ์„ ํƒ

SELECT ํ•„๋“œ์ด๋ฆ„ FROM ํ…Œ์ด๋ธ”์ด๋ฆ„ [WHERE ์กฐ๊ฑด];

 

UPDATE

ํ…Œ์ด๋ธ”์˜ row์˜ ๋‚ด์šฉ ์ˆ˜์ •

UPDATE ํ…Œ์ด๋ธ”์ด๋ฆ„ SET ํ•„๋“œ์ด๋ฆ„1=๋ฐ์ดํ„ฐ๊ฐ’1, ํ•„๋“œ์ด๋ฆ„2=๋ฐ์ดํ„ฐ๊ฐ’2, ... WHERE ํ•„๋“œ์ด๋ฆ„=๋ฐ์ดํ„ฐ๊ฐ’;

 

DELETE

ํ…Œ์ด๋ธ”์˜ row ์‚ญ์ œ

DELETE FROM ํ…Œ์ด๋ธ”์ด๋ฆ„ WHERE ํ•„๋“œ์ด๋ฆ„=๋ฐ์ดํ„ฐ๊ฐ’;

SQL ์—ฐ์Šตํ•˜๊ธฐ

Intellij Database ์—ฐ๋™ํ•˜๊ธฐ

1. ์˜ค๋ฅธ์ชฝ ํƒญ์— Database ํƒญ ํด๋ฆญํ•˜๊ณ  + ๋ฒ„ํŠผ ๋ˆ„๋ฅธ ํ›„, ๋ฐ์ดํ„ฐ ์†Œ์Šค > MySQL ํด๋ฆญ

 

2. ์‚ฌ์šฉ์ž, ๋น„๋ฐ€๋ฒˆํ˜ธ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ •๋ณด ์ถ”๊ฐ€ ํ›„ OK ํด๋ฆญ

 

3. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์„ฑ๊ณต


ํ…Œ์ด๋ธ” ์ƒ์„ฑํ•˜๊ธฐ

CREATE TABLE IF NOT EXISTS MAJOR
(
    major_code varchar(100) primary key comment '์ฃผํŠน๊ธฐ์ฝ”๋“œ',
    major_name varchar(100) not null comment '์ฃผํŠน๊ธฐ๋ช…',
    tutor_name varchar(100) not null comment 'ํŠœํ„ฐ'
);

CREATE TABLE IF NOT EXISTS STUDENT
(
    student_code varchar(100) primary key comment '์ˆ˜๊ฐ•์ƒ์ฝ”๋“œ',
    name varchar(100) not null comment '์ด๋ฆ„',
    birth varchar(8) null comment '์ƒ๋…„์›”์ผ',
    gender varchar(1) not null comment '์„ฑ๋ณ„',
    phone varchar(11) null comment '์ „ํ™”๋ฒˆํ˜ธ',
    major_code varchar(100) not null comment '์ฃผํŠน๊ธฐ์ฝ”๋“œ',
    foreign key(major_code) references major(major_code)
);

CREATE TABLE IF NOT EXISTS EXAM
(
    student_code varchar(100) not null comment '์ˆ˜๊ฐ•์ƒ์ฝ”๋“œ',
    exam_seq int not null comment '์‹œํ—˜์ฃผ์ฐจ',
    score decimal(10,2) not null comment '์‹œํ—˜์ ์ˆ˜',
    result varchar(1) not null comment 'ํ•ฉ๋ถˆ'
);

์„ธ ๊ฐœ์˜ ํ…Œ์ด๋ธ” ๊ด€๊ณ„

ํ…Œ์ด๋ธ” ์ˆ˜์ •ํ•˜๊ธฐ

ALTER TABLE EXAM ADD PRIMARY KEY(student_code, exam_seq);
ALTER TABLE EXAM ADD CONSTRAINT exam_fk_student_code FOREIGN KEY(student_code) REFERENCES STUDENT(student_code);

ํ…Œ์ด๋ธ”์— ๋ฐ์ดํ„ฐ ์‚ฝ์ž…ํ•˜๊ธฐ

INSERT INTO MAJOR VALUES('m1', '์Šคํ”„๋ง', '๋‚จ๋ณ‘๊ด€');
INSERT INTO MAJOR VALUES('m2', '๋…ธ๋“œ', '๊ฐ•์Šนํ˜„');
INSERT INTO MAJOR VALUES('m3', 'ํ”Œ๋ผ์Šคํฌ', '์ด๋ฒ”๊ทœ');
INSERT INTO MAJOR VALUES('m4', '๋ฃจ๋น„์˜จ๋ ˆ์ผ์ฆˆ', '์ฐจ์€์„œ');
...

INSERT INTO STUDENT VALUES('s1', '์ตœ์›๋นˆ', '20220331', 'M', '01000000001', 'm1');
INSERT INTO STUDENT VALUES('s2', '๊ฐ•์ค€๊ทœ', '20220501', 'M', '01000000002', 'm1');
INSERT INTO STUDENT VALUES('s3', '๊น€์˜์ฒ ', '20220711', 'M', '01000000003', 'm1');
...

INSERT INTO EXAM VALUES('s1', 1, 8.5, 'P');
INSERT INTO EXAM VALUES('s1', 2, 9.5, 'P');
INSERT INTO EXAM VALUES('s1', 3, 3.5, 'F');
INSERT INTO EXAM VALUES('s2', 1, 8.2, 'P');
...

ํ…Œ์ด๋ธ” ๋‚ด ๋ฐ์ดํ„ฐ ์ˆ˜์ •ํ•˜๊ธฐ

INSERT INTO STUDENT VALUES('s0', '์ˆ˜๊ฐ•์ƒ', '20220331', 'M', '01000000005', 'm1');
UPDATE STUDENT SET major_code= 'm2' where student_code= 's0';

ํ…Œ์ด๋ธ” ๋‚ด ๋ฐ์ดํ„ฐ ์‚ญ์ œํ•˜๊ธฐ

DELETE FROM STUDENT WHERE student_code = 's0';

ํ…Œ์ด๋ธ” ๋‚ด ํŠน์ • ๋ฐ์ดํ„ฐ ์กฐํšŒํ•˜๊ธฐ

SELECT * FROM STUDENT;
SELECT * FROM STUDENT WHERE STUDENT_CODE = 's1';
SELECT name, major_code FROM STUDENT WHERE student_code = 's1';

2๋ฒˆ์งธ SELECT๋ฌธ ์กฐํšŒ

SELECT s.name, s.major_code, m.major_name FROM STUDENT s JOIN MAJOR m ON s.major_code = m.major_code;
SELECT s.name, s.major_code, m.major_name FROM STUDENT s, MAJOR m WHERE s.major_code = m.major_code;

JOIN SELECT ์ˆ˜ํ–‰

JOIN์€ ๋‚˜๋ˆ„์–ด์ง„ ํ…Œ์ด๋ธ”์„ ํ•˜๋‚˜๋กœ ํ•ฉ์น˜๊ธฐ ์œ„ํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.
- JOIN์€ ON์ด๋ผ๋Š” ํ‚ค์›Œ๋“œ๋ฅผ ํ†ตํ•ด ๊ธฐ์ค€์ด ๋˜๋Š” ์ปฌ๋Ÿผ์„ ์„ ํƒํ•ด 2๊ฐœ์˜ ํ…Œ์ด๋ธ”์„ ํ•ฉ์ณ์คŒ
- JOIN์„ ํ•  ๋•Œ์—๋Š” ์ ์–ด๋„ ํ•˜๋‚˜์˜ ์ปฌ๋Ÿผ์„ ์„œ๋กœ ๊ณต์œ ํ•˜๊ณ  ์žˆ์–ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ…Œ์ด๋ธ”์— ์™ธ๋ž˜ ํ‚ค๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ๋‹ค๋ฉด ํ•ด๋‹น ์ปฌ๋Ÿผ์„ ํ†ตํ•ด JOIN์„ ํ•˜๋ฉด ์กฐ๊ฑด์„ ์ถฉ์กฑํ•  ์ˆ˜ ์žˆ์Œ

โ€ผ๏ธ JOIN์„ ํ•˜๊ธฐ ์œ„ํ•ด ์™ธ๋ž˜ ํ‚ค๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ํ•ญ์ƒ ์ข‹์€ ์„ ํƒ์ด ์•„๋‹ ์ˆ˜ ์žˆ์Œ!
- ์™ธ๋ž˜ ํ‚ค๋ฅผ ์„ค์ •ํ•˜๋ฉด ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ์„ ํ™•์ธํ•˜๋Š” ์ถ”๊ฐ€ ์—ฐ์‚ฐ ๋ฐœ์ƒ
- ๋˜ํ•œ ๋ฌด๊ฒฐ์„ฑ์„ ์ง€์ผœ์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒํ™ฉ์— ๋”ฐ๋ผ ๊ฐœ๋ฐœํ•˜๋Š”๋ฐ ๋ถˆํŽธํ•  ์ˆ˜ ์žˆ์Œ

ํ•ญ์ƒ ํ…Œ์ด๋ธ”์— ๋ชจ๋“  ์ œ์•ฝ์กฐ๊ฑด์„ ๊ฑธ์–ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๊ณ , ํ”„๋กœ์ ํŠธ์˜ ์ƒํ™ฉ์— ๋”ฐ๋ผ ๊ฐ€์žฅ ํšจ์œจ์ ์ธ ์ œ์•ฝ์กฐ๊ฑด์„ ํ…Œ์ด๋ธ”์— ์ ์šฉํ•ด์•ผ ํ•จ

JDBC๋ž€?

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์†Œํ†ต์„ ํ•ด์•ผํ•จ. ์ด๋•Œ, Java ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•˜๋Š” ๊ฒƒ์ด JDBC์ž„!

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ„์˜ ์†Œํ†ต

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ„์˜ ์†Œํ†ต

1. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ์œ„ํ•ด ์ปค๋„ฅ์…˜ ์—ฐ๊ฒฐํ•ด์•ผ ํ•จ

2. SQL ์ž‘์„ฑ ํ›„ ์ปค๋„ฅ์…˜์„ ํ†ตํ•ด SQL ์š”์ฒญ

3. ์š”์ฒญํ•œ SQL์— ๋Œ€ํ•œ ์‘๋‹ต์„ ๋ฐ›์•„์•ผํ•จ

 

์ด๋•Œ MySQL ์„œ๋ฒ„๊ฐ€ ์•„๋‹ˆ๋ผ PostgreSQL ์„œ๋ฒ„๋กœ ๋ณ€๊ฒฝํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ, MySQL๊ณผ PostgreSQL์€ ์ปค๋„ฅ์…˜์„ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•, SQL ์ „๋‹ฌ ๋ฐฉ๋ฒ•, ๊ฒฐ๊ณผ ์‘๋‹ต ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ๋ฒ• ๋ชจ๋‘ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Œ

์ฆ‰, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„ ์ชฝ์— ์ž‘์„ฑํ–ˆ๋˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์ฝ”๋“œ์ธ ๋กœ์ง์„ ์ „๋ถ€ ์ˆ˜์ •ํ•ด์•ผ ํ•จ

 

์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด JDBC ํ‘œ์ค€ ์ธํ„ฐํŽ˜์ด์Šค ๋“ฑ์žฅํ•จ!

JDBC(Java Database Connectivity)

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก Java์—์„œ ์ œ๊ณตํ•˜๋Š” API

  • JDBC์— ์—ฐ๊ฒฐ์„ ํ•ด์•ผํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ JDBC ๋“œ๋ผ์ด๋ฒ„๋ฅผ ์ œ๊ณตํ•˜๋ฉด, ์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์—ฐ๊ฒฐ ๋กœ์ง์„ ๋ณ€๊ฒฝํ•  ํ•„์š” ์—†์ด ์†์‰ฝ๊ฒŒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ
  • JDBC ๋“œ๋ผ์ด๋ฒ„๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํšŒ์‚ฌ๋“ค์ด ์ž์‹ ๋“ค์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋งž๋„๋ก JDBC ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‹ค์ œ๋กœ ๊ตฌํ˜„ํ•œ ํ›„ ์ œ๊ณตํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
    → MySQL ๋“œ๋ผ์ด๋ฒ„๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๊ฐ€ PostgreSQL ์„œ๋ฒ„๋กœ ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•  ๋•Œ, ๋“œ๋ผ์ด๋ฒ„๋งŒ ๊ต์ฒดํ•ด์ฃผ๋ฉด ๋จ

JDBC

JdbcTemplate

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ๊ณผ์ •

 

JDBC๋กœ ์†์‰ฝ๊ฒŒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ต์ฒด๊ฐ€ ๊ฐ€๋Šฅํ•ด์กŒ์ง€๋งŒ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ํ•˜๊ธฐ ์œ„ํ•ด ์œ„์™€ ๊ฐ™์ด ์ˆ˜๋งŽ์€ ์ž‘์—… ํ•„์š”ํ•จ

์ด๋Ÿฐ ์ž‘์—…๋“ค์„ ๋Œ€์‹  ์ฒ˜๋ฆฌํ•ด์ฃผ๋Š” Spring JDBC ๋“ฑ์žฅํ•จ! ๊ทธ ์ค‘ ํ•˜๋‚˜๊ฐ€ JdbcTemplate์ž„

 

JdbcTemplate๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด application.properties์— ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•œ ์ •๋ณด ์ž‘์„ฑํ•ด์•ผํ•จ!

๏นก์‹ค์ œ๋กœ ๊ฐœ๋ฐœํ•  ๋•Œ์—๋Š” JdbcTemplate์„ ์‚ฌ์šฉํ•  ํ™•๋ฅ ์ด ๋‚ฎ์Œ

// build.gradle ๋‚ด dependencies์— ์ถ”๊ฐ€
// MySQL
implementation 'mysql:mysql-connector-java:8.0.28'
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
# memo ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒ์„ฑํ•˜๊ธฐ
create database memo;
// application.properties์— ์ถ”๊ฐ€
spring.datasource.url=jdbc:mysql://localhost:3306/memo
spring.datasource.username=root
spring.datasource.password={๋น„๋ฐ€๋ฒˆํ˜ธ}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

 

Memo ํ…Œ์ด๋ธ” ์ƒ์„ฑ

create table memo
(
    id       bigint       not null auto_increment,
    contents varchar(500) not null,
    username varchar(255) not null,
    primary key (id)
);

 

MemoController์— JdbcTemplate ์ ์šฉ

package com.sparta.memo.controller;

import com.sparta.memo.dto.MemoRequestDto;
import com.sparta.memo.dto.MemoResponseDto;
import com.sparta.memo.entity.Memo;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.web.bind.annotation.*;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

@RestController
@RequestMapping("/api")
public class MemoController {

    private final JdbcTemplate jdbcTemplate; // jdbcTemplate ๋ณ€์ˆ˜ ์„ ์–ธ

    // ์ดˆ๊ธฐํ™”๋ฅผ ์œ„ํ•œ ์ƒ์„ฑ์ž
    // ์™ธ๋ถ€์—์„œ ๋งŒ๋“ค์–ด์ ธ ์žˆ๋Š” JdbcTemplate์„ ์—ฌ๊ธฐ์— ๋„ฃ์–ด์คŒ
    // JdbcTemplate ๊ฐ์ฒด๋Š” Spring์—์„œ ๋”ฐ๋กœ ๊ด€๋ฆฌํ•ด์ฃผ๊ณ  ์žˆ์Œ
    public MemoController(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @PostMapping("/memos")
    public MemoResponseDto createMemo(@RequestBody MemoRequestDto requestDto) {
        // RequestDto -> Entity
        Memo memo = new Memo(requestDto);

        // DB ์ €์žฅ
        KeyHolder keyHolder = new GeneratedKeyHolder(); // ๊ธฐ๋ณธ ํ‚ค๋ฅผ ๋ฐ˜ํ™˜๋ฐ›๊ธฐ ์œ„ํ•œ ๊ฐ์ฒด

        String sql = "INSERT INTO memo (username, contents) VALUES (?, ?)"; // INSERT๋ฌธ
        // INSERT, UPDATE, DELETE ์„ธ ๊ฐ€์ง€ ๋ชจ๋‘ update ๋ฉ”์„œ๋“œ ์ด์šฉ
        jdbcTemplate.update( con -> {
                    PreparedStatement preparedStatement = con.prepareStatement(sql,
                            Statement.RETURN_GENERATED_KEYS);

                    preparedStatement.setString(1, memo.getUsername());
                    preparedStatement.setString(2, memo.getContents());
                    return preparedStatement;
                },
                keyHolder);

        // DB Insert ํ›„ ๋ฐ›์•„์˜จ ๊ธฐ๋ณธํ‚ค ํ™•์ธ
        Long id = keyHolder.getKey().longValue();
        memo.setId(id);

        // Entity -> ResponseDto
        MemoResponseDto memoResponseDto = new MemoResponseDto(memo);

        return memoResponseDto;
    }

    @GetMapping("/memos")
    public List<MemoResponseDto> getMemos() {
        // DB ์กฐํšŒ
        String sql = "SELECT * FROM memo";

        return jdbcTemplate.query(sql, new RowMapper<MemoResponseDto>() {
            @Override
            public MemoResponseDto mapRow(ResultSet rs, int rowNum) throws SQLException {
                // SQL ์˜ ๊ฒฐ๊ณผ๋กœ ๋ฐ›์•„์˜จ Memo ๋ฐ์ดํ„ฐ๋“ค์„ MemoResponseDto ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜ํ•ด์ค„ ๋ฉ”์„œ๋“œ
                Long id = rs.getLong("id");
                String username = rs.getString("username");
                String contents = rs.getString("contents");
                return new MemoResponseDto(id, username, contents);
            }
        });
    }

    @PutMapping("/memos/{id}")
    public Long updateMemo(@PathVariable Long id, @RequestBody MemoRequestDto requestDto) {
        // ํ•ด๋‹น ๋ฉ”๋ชจ๊ฐ€ DB์— ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ
        Memo memo = findById(id);
        if(memo != null) {
            // memo ๋‚ด์šฉ ์ˆ˜์ •
            String sql = "UPDATE memo SET username = ?, contents = ? WHERE id = ?";
            jdbcTemplate.update(sql, requestDto.getUsername(), requestDto.getContents(), id);

            return id;
        } else {
            throw new IllegalArgumentException("์„ ํƒํ•œ ๋ฉ”๋ชจ๋Š” ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
        }
    }

    @DeleteMapping("/memos/{id}")
    public Long deleteMemo(@PathVariable Long id) {
        // ํ•ด๋‹น ๋ฉ”๋ชจ๊ฐ€ DB์— ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ
        Memo memo = findById(id);
        if(memo != null) {
            // memo ์‚ญ์ œ
            String sql = "DELETE FROM memo WHERE id = ?";
            jdbcTemplate.update(sql, id);

            return id;
        } else {
            throw new IllegalArgumentException("์„ ํƒํ•œ ๋ฉ”๋ชจ๋Š” ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
        }
    }

    private Memo findById(Long id) {
        // DB ์กฐํšŒ
        String sql = "SELECT * FROM memo WHERE id = ?";

        return jdbcTemplate.query(sql, resultSet -> {
            if(resultSet.next()) {
                Memo memo = new Memo();
                memo.setUsername(resultSet.getString("username"));
                memo.setContents(resultSet.getString("contents"));
                return memo;
            } else {
                return null;
            }
        }, id);
    }
}

 

JdbcTemplate์„ ์‚ฌ์šฉํ•ด๋„ ์ž‘์„ฑํ•˜๊ธฐ ์–ด๋ ต๊ณ  ๊นŒ๋‹ค๋กœ์šด ๋ฌธ์ œ ์กด์žฌํ•จ. ์ž๋ฐ” ๊ฐœ๋ฐœ์ž๋“ค์„ ์œ„ํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ Java ๊ฐ์ฒด๋ฅผ mappingํ•ด์„œ ์†Œํ†ตํ•  ์ˆ˜ ์žˆ๋Š” ORM์ด๋ผ๋Š” ๊ธฐ์ˆ  ๋“ฑ์žฅํ•จ!