๐จ ๋จ๊ณ๋ณ ์ค์ต ์์ฝ
1. DB ์์ฑ (ERD ๊ธฐ๋ฐ)
sql
๋ณต์ฌํธ์ง
CREATE DATABASE web;
USE web;
CREATE TABLE courses (
course_id INT PRIMARY KEY,
course_name VARCHAR(100)
);
CREATE TABLE sections (
section_id INT PRIMARY KEY,
section_name VARCHAR(100),
course_id INT,
FOREIGN KEY (course_id) REFERENCES courses(course_id)
);
CREATE TABLE lectures (
lecture_id INT PRIMARY KEY AUTO_INCREMENT,
lecture_name VARCHAR(100),
section_id INT,
FOREIGN KEY (section_id) REFERENCES sections(section_id)
);
2. front.html ๋ง๋ค๊ธฐ
html
๋ณต์ฌํธ์ง
<!-- /var/www/web/front.html -->
<h1>์ด๋์
front server</h1>
์ ์ ํ์ธ:
๐ http://XXX.XXX.XXX.XX/front.html
3. back.jsp ๋ง๋ค๊ธฐ (์๋ฒ IP ํ์ธ)
jsp
๋ณต์ฌํธ์ง
<%@ page language="java" %>
<p>Server IP: <%= request.getLocalAddr() %></p>
๐ http://XXX.XXX.XXX.XX/api/back.jsp
→ ์ฌ๋ฌ ๋ฒ ์๋ก๊ณ ์นจํ๋ฉด XX, XX๋ฒ ํฐ์บฃ IP๊ฐ ๋ฒ๊ฐ์ ๋์์ผ ํจ (nginx ๋ผ์ด๋๋ก๋น ํ์ธ)
4. insert.html ๋ง๋ค๊ธฐ
/insert.html์์ course, section, lecture ๊ฐ๊ฐ ์ ์ฅ ๊ฐ๋ฅํ๊ฒ ๊ตฌ์ฑ
→ <form>์ action="/api/insert.jsp"๋ก POST ์์ฒญ
5. insert.jsp (Tomcat XX/XX ๊ณตํต)
DB ์ฐ๊ฒฐ: ๋ง์คํฐ(XX๋ฒ) ์ฌ์ฉ
jsp
๋ณต์ฌํธ์ง
String dbURL = "jdbc:mariadb://XXX.XXX.XXX.XX:3306/web";
์ก์ ๊ฐ(course, section, lecture)์ ๋ฐ๋ผ insert ์ฟผ๋ฆฌ ์คํ
6. select.jsp (Tomcat XX๋ฒ ์ค์ฌ)
DB ์ฐ๊ฒฐ: ์ฌ๋ ์ด๋ธ(XX๋ฒ) ์ฌ์ฉ
jsp
๋ณต์ฌํธ์ง
String dbURL = "jdbc:mariadb://XXX.XXX.XXX.XX:3306/web";
JOIN ์กฐํ SQL
sql
๋ณต์ฌํธ์ง
SELECT
c.course_id, c.course_name,
s.section_id, s.section_name,
l.lecture_name
FROM courses c
LEFT JOIN sections s ON c.course_id = s.course_id
LEFT JOIN lectures l ON s.section_id = l.section_id
ORDER BY c.course_id, s.section_id, l.lecture_id;
7. nginx ์ค์
/etc/nginx/sites-enabled/web
nginx
๋ณต์ฌํธ์ง
upstream tomcat_backend {
server XXX.XXX.XXX.XX:8080;
server XXX.XXX.XXX.XX:8080;
}
server {
listen 80;
root /var/www/web;
location / {
try_files $uri $uri/ =404;
}
location /api {
rewrite ^/api(/.*)$ $1 break;
proxy_pass http://tomcat_backend;
}
}
๐ systemctl restart nginx
8. ๋ง์ง๋ง ์ ๊ฒ
ํญ๋ชฉ ํ์ธ
| insert.jsp๋ก ๊ฐ ์ ๋ ฅ ์ master DB์ ์ ์ฅ๋จ | |
| slave DB์์๋ ์ฆ์ ๋ฐ์๋๋์ง ํ์ธ (select.jsp) | |
| back.jsp ์๋ก๊ณ ์นจํ๋ฉด IP ๋ฒ๊ฐ์ ๋์ค๋์ง ํ์ธ |
๐ ์ ์ฒด ํ๋ฆ ์์ฝ
text
๋ณต์ฌํธ์ง
[์ฌ์ฉ์] -- insert.html
→ [insert.jsp] → [๋ง์คํฐ DB ์ ์ฅ]
[์ฌ์ฉ์] -- select.jsp
→ [์ฌ๋ ์ด๋ธ DB ์กฐํ]
→ ๋ง์คํฐ/์ฌ๋ ์ด๋ธ ๊ฐ ๋ ํ๋ฆฌ์ผ์ด์
์ ์ ๋์ ํ์ธ
→ Nginx ๋ก๋๋ฐธ๋ฐ์ฑ ํ์ธ (back.jsp IP ๋ฒ๊ฐ์ ๋์ด)


โ ์ค์ต ๊ฐ์
- INDEX: ๊ฒ์ ์๋๋ฅผ ๋์ด๊ธฐ ์ํ ๋ฐ์ดํฐ ๊ตฌ์กฐ
- EXPLAIN: SQL ์ฟผ๋ฆฌ๊ฐ ์ค์ ๋ก ์ด๋ป๊ฒ ์คํ๋๋์ง ๋ณด์ฌ์ค
- PROFILE: ์ฟผ๋ฆฌ ์คํ ์๊ฐ ๋ถ์ (๊ฐ ๋จ๊ณ๋ณ ์์ ์๊ฐ)
โ 1. ํ ์ด๋ธ ์์ฑ ๋ฐ ํ ์คํธ ๋ฐ์ดํฐ ์ฝ์
sql
๋ณต์ฌํธ์ง
-- ๊ธฐ์กด post ํ
์ด๋ธ ์ญ์
DROP TABLE IF EXISTS post;
-- post ํ
์ด๋ธ ์์ฑ
CREATE TABLE post (
idx INT AUTO_INCREMENT PRIMARY KEY, -- ๊ฒ์๊ธ ID
writerIdx INT, -- ์์ฑ์ ID (member ํ
์ด๋ธ ์ฐธ์กฐ ๊ฐ์ )
contents VARCHAR(100), -- ๊ฒ์๊ธ ๋ด์ฉ
createdAt DATETIME -- ์์ฑ์ผ
);
-- 1000๊ฐ ๋๋ฏธ ๋ฐ์ดํฐ ์ฝ์
INSERT INTO post (writerIdx, contents, createdAt)
SELECT
FLOOR(1 + RAND() * 1000), -- 1~1000 ์ฌ์ด ์์์ ์์ฑ์ ID
CONCAT('์ด๊ฒ์ ํ
์คํธ ๊ฒ์๊ธ ๋ด์ฉ์
๋๋ค - ', n), -- ๋ด์ฉ ์์
NOW()
FROM (
WITH RECURSIVE seq AS (
SELECT 1 AS n
UNION ALL
SELECT n + 1 FROM seq WHERE n < 1000
)
SELECT * FROM seq
) AS temp;
โ 2. ์ฑ๋ฅ ๋ถ์ ํ์ฑํ (PROFILE)
sql
๋ณต์ฌํธ์ง
-- ์ฟผ๋ฆฌ ํ๋กํ์ผ๋ง ๊ธฐ๋ฅ ํ์ฑํ
SET profiling = 1;
โ 3. ์ธ๋ฑ์ค ์์ด ์ฟผ๋ฆฌ ์คํ + PROFILE ํ์ธ
sql
๋ณต์ฌํธ์ง
-- ์ธ๋ฑ์ค ์๋ ์ํ์์ ํน์ ์์ฑ์์ ๊ฒ์๊ธ ์กฐํ
SELECT * FROM post WHERE writerIdx = 777;
-- ์ต๊ทผ ์คํ๋ ์ฟผ๋ฆฌ ๋ชฉ๋ก ๋ฐ ์คํ ์๊ฐ ํ์ธ
SHOW PROFILES;
-- ์ฒซ ๋ฒ์งธ ์ฟผ๋ฆฌ์ ์์ธ ์คํ ๋จ๊ณ ์๊ฐ ํ์ธ
SHOW PROFILE FOR QUERY 1;
โ 4. EXPLAIN์ผ๋ก ์คํ ๊ณํ ํ์ธ (์ธ๋ฑ์ค ์๋ ์ํ)
sql
๋ณต์ฌํธ์ง
-- EXPLAIN์ผ๋ก ์คํ ๊ณํ ํ์ธ
EXPLAIN SELECT * FROM post WHERE writerIdx = 777;
-- ํ์ธ ํฌ์ธํธ:
-- type: ALL → ํ
์ด๋ธ ์ ์ฒด ๊ฒ์ (๋๋ฆผ)
-- rows: 1000 → ์์ ์ค์บ ํ ์ ๋ง์
-- key: NULL → ์ธ๋ฑ์ค ๋ฏธ์ฌ์ฉ
โ 5. ์ธ๋ฑ์ค ์์ฑ
sql
๋ณต์ฌํธ์ง
-- writerIdx ์ปฌ๋ผ์ ์ธ๋ฑ์ค ์์ฑ
CREATE INDEX idx_writerIdx ON post(writerIdx);
โ 6. ์ธ๋ฑ์ค ์ ์ฉ ํ ์ฟผ๋ฆฌ ์ฌ์คํ + PROFILE ๋น๊ต
sql
๋ณต์ฌํธ์ง
-- ๋์ผํ ์ฟผ๋ฆฌ ์ฌ์คํ
SELECT * FROM post WHERE writerIdx = 777;
-- ์ ์ฟผ๋ฆฌ ์คํ ์๊ฐ ํ์ธ
SHOW PROFILES;
-- ๋ ๋ฒ์งธ ์ฟผ๋ฆฌ์ ์์ธ ์๊ฐ ํ์ธ
SHOW PROFILE FOR QUERY 2;
โ 7. EXPLAIN ์ฌํ์ธ (์ธ๋ฑ์ค ์ ์ฉ ํ)
sql
๋ณต์ฌํธ์ง
EXPLAIN SELECT * FROM post WHERE writerIdx = 777;
-- ํ์ธ ํฌ์ธํธ:
-- type: ref → ์ธ๋ฑ์ค๋ฅผ ํ์ฉํ ๊ฒ์ (๋น ๋ฆ)
-- key: idx_writerIdx → ์ฌ์ฉ๋ ์ธ๋ฑ์ค ์ด๋ฆ
-- rows: ์ ์ → ์ ์ ์์ ํ๋ง ๊ฒ์
โ ์์ฝ ์ ๋ฆฌ
๊ฐ๋ ์ค๋ช
| INDEX | ํน์ ์ปฌ๋ผ์ ๋น ๋ฅธ ๊ฒ์์ ์ํด ๋ฐ์ดํฐ ๊ตฌ์กฐ ์ถ๊ฐ (writerIdx์ ์์ฑ) |
| EXPLAIN | ์ฟผ๋ฆฌ ์คํ ์ ์ MySQL์ด ์ด๋ค ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฐพ๋์ง ๊ณํ์ ๋ณด์ฌ์ค |
| PROFILE | ์ค์ ๋ก ์ฟผ๋ฆฌ๊ฐ ์คํ๋๋ฉด์ ๊ฐ ๋จ๊ณ๋ง๋ค ๊ฑธ๋ฆฐ ์๊ฐ ๋ถ์ ๊ฐ๋ฅ |
- EXPLAIN→ ์ด๋ค ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ง, ๋ช ๊ฐ ํ์ ์ฝ์์ง, ํ ์ด๋ธ์ ์ด๋ป๊ฒ ํ์ํ ์ง ๋ฏธ๋ฆฌ ์ ์ ์์ต๋๋ค.
- → ์ฟผ๋ฆฌ๋ฅผ ์คํํ๊ธฐ ์ ์ MySQL์ด ์ด๋ป๊ฒ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ ์ฒ๋ฆฌํ ๊ณํ์ธ์ง, ์ฆ ์คํ ๊ณํ์ ๋ณด์ฌ์ฃผ๋ ๋ช ๋ น์ด์ ๋๋ค.
- PROFILE→ ์ฟผ๋ฆฌ ์คํ์ ๋ณ๋ชฉ ๊ตฌ๊ฐ์ด๋ ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ๊ตฌ์ฒด์ ์ผ๋ก ๋ถ์ํ ์ ์์ต๋๋ค.
- → ์ฟผ๋ฆฌ๋ฅผ ์ค์ ์คํํ ํ์ ๊ฐ ์คํ ๋จ๊ณ๋ณ๋ก ์ผ๋ง๋ ์๊ฐ์ด ๊ฑธ๋ ธ๋์ง ์์ธํ๊ฒ ๋ณด์ฌ์ฃผ๋ ๋ช ๋ น์ด์ ๋๋ค.
์ฝ๊ฒ ๋งํด,
EXPLAIN์ ๊ณํ์ ๋ณด์ฌ์ฃผ๊ณ , PROFILE์ ์คํ ๊ฒฐ๊ณผ์ ์๊ฐ ๋ถ์์ ๋ณด์ฌ์ค๋๋ค.
INDEX (์ธ๋ฑ์ค)
- ๋ฌด์์ธ๊ฐ?์ฑ ๋ค์ ์๋ ‘์ฐพ์๋ณด๊ธฐ’ ๋ชฉ๋ก๊ณผ ๋น์ทํ ์ญํ ์ ํฉ๋๋ค.
- ํ ์ด๋ธ์์ ๋ฐ์ดํฐ๋ฅผ ๋น ๋ฅด๊ฒ ์ฐพ๋๋ก ๋์์ฃผ๋ ํน๋ณํ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ๋๋ค.
- ์ ํ์ํ๊ฐ?
- ํ ์ด๋ธ์ด ์ปค์ง์๋ก ์ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ฐพ๋ ๋ฐ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋๋ฐ, ์ธ๋ฑ์ค๊ฐ ์์ผ๋ฉด ๊ฒ์ ์๋๊ฐ ํจ์ฌ ๋นจ๋ผ์ง๋๋ค.
- ์ด๋ป๊ฒ ์๋ํ๋?
- ํน์ ์ปฌ๋ผ์ ๋ํด ๋ณ๋์ ์ ๋ ฌ๋ ์๋ฃ๊ตฌ์กฐ(B-ํธ๋ฆฌ ๋ฑ)๋ฅผ ๋ง๋ค์ด์ ๊ฒ์ํ ๋ ์ ์ฒด ํ ์ด๋ธ์ ํ์ง ์๊ณ ๋ ๋ฐ๋ก ์์น๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.
- ์ฃผ์์
- ์ธ๋ฑ์ค๊ฐ ๋ง์ผ๋ฉด ๋ฐ์ดํฐ ์ฝ์ /์์ /์ญ์ ์์ ์ธ๋ฑ์ค๋ ๊ฐ์ด ๊ฐฑ์ ํด์ผ ํ๋ฏ๋ก ์ค๋ฒํค๋๊ฐ ๋ฐ์ํฉ๋๋ค.
- ๋ชจ๋ ์ปฌ๋ผ์ ์ธ๋ฑ์ค๋ฅผ ๋ง๋๋ ๊ฒ์ ์คํ๋ ค ์ฑ๋ฅ ์ ํ๋ฅผ ์ด๋ํ ์ ์์ต๋๋ค.
ํ ์ค ์์ฝ
์ธ๋ฑ์ค๋ ๊ฒ์ ์๋๋ฅผ ๋์ฌ์ฃผ๋ ‘๋น ๋ฅธ ์ฐพ๊ธฐ’์ฉ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ๋๋ค.
'Database' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| Database 8์ผ์ฐจ (1) | 2025.06.18 |
|---|---|
| Database 6์ผ์ฐจ (0) | 2025.06.16 |
| Database 5์ผ์ฐจ (2) | 2025.06.13 |
| Database 4์ผ์ฐจ (0) | 2025.06.12 |
| Database 3์ผ์ฐจ (1) | 2025.06.11 |