"์ฝ”๋“œํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค" ๊ฒฝํ—˜

"์ฝ”๋“œํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค" ๊ฒฝํ—˜

SQL, ์ด๋ณด๋‹ค ๋” ๊ฐ„๋‹จํ•œ ๊ฒƒ์€ ๋ฌด์—‡์ผ๊นŒ์š”? ์šฐ๋ฆฌ ๊ฐ์ž๋Š” ๊ฐ„๋‹จํ•œ ์š”์ฒญ์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ณ ๋ฅด๋‹ค, ํ•„์ˆ˜ ์—ด์„ ๋‚˜์—ดํ•œ ๋‹ค์Œ ์—, ํ…Œ์ด๋ธ” ์ด๋ฆ„, ์ผ๋ถ€ ์กฐ๊ฑด ์–ด๋””์— ๊ทธ๊ฒŒ ์ „๋ถ€์ž…๋‹ˆ๋‹ค. ์œ ์šฉํ•œ ๋ฐ์ดํ„ฐ๋Š” ์šฐ๋ฆฌ ์ฃผ๋จธ๋‹ˆ์— ์žˆ์œผ๋ฉฐ (๊ฑฐ์˜) ๊ทธ ๋‹น์‹œ ์–ด๋–ค DBMS๊ฐ€ ๋‚ด๋ถ€์— ์žˆ๋Š”์ง€์— ๊ด€๊ณ„์—†์ด(๋˜๋Š” ์•„๋งˆ๋„) ์ „ํ˜€ DBMS๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค). ๊ฒฐ๊ณผ์ ์œผ๋กœ, ๊ฑฐ์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐ ์†Œ์Šค(๊ด€๊ณ„ํ˜•์ด๋“  ๊ทธ๋ ‡์ง€ ์•Š๋“ )์— ๋Œ€ํ•œ ์ž‘์—…์€ ์ผ๋ฐ˜ ์ฝ”๋“œ์˜ ๊ด€์ ์—์„œ ๊ณ ๋ ค๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๋ฒ„์ „ ์ œ์–ด, ์ฝ”๋“œ ๊ฒ€ํ† , ์ •์  ๋ถ„์„, ์ž๋™ ํ…Œ์ŠคํŠธ ๋“ฑ์ด ์•”์‹œํ•˜๋Š” ๋ชจ๋“  ๊ฒƒ ํฌํ•จ). ์ด๋Š” ๋ฐ์ดํ„ฐ ์ž์ฒด, ์Šคํ‚ค๋งˆ ๋ฐ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ผ๋ฐ˜์ ์œผ๋กœ ์Šคํ† ๋ฆฌ์ง€์˜ ์ „์ฒด ์ˆ˜๋ช…์— ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด ๊ธฐ์‚ฌ์—์„œ๋Š” "์ฝ”๋“œํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค"๋ผ๋Š” ๊ด€์ ์—์„œ ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…์˜ ์ผ์ƒ์ ์ธ ์ž‘์—…๊ณผ ๋ฌธ์ œ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋ฐ”๋กœ ์‹œ์ž‘ํ•ด๋ณด์ž ORM. "SQL ๋Œ€ ORM" ์œ ํ˜•์˜ ์ฒซ ๋ฒˆ์งธ ์ „ํˆฌ๋Š” XNUMX๋…„์— ๋‚˜ํƒ€๋‚ฌ์Šต๋‹ˆ๋‹ค. ํŽ˜ํŠธ๋ฆฐ ์ด์ „์˜ ๋ฃจ์Šค'.

๊ฐ์ฒด ๊ด€๊ณ„ํ˜• ๋งคํ•‘

ORM ์ง€์ง€์ž๋“ค์€ ์ „ํ†ต์ ์œผ๋กœ ์†๋„์™€ ๊ฐœ๋ฐœ ์šฉ์ด์„ฑ, DBMS๋กœ๋ถ€ํ„ฐ์˜ ๋…๋ฆฝ์„ฑ ๋ฐ ๊น”๋”ํ•œ ์ฝ”๋“œ๋ฅผ ์ค‘์š”ํ•˜๊ฒŒ ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ ์ค‘ ๋Œ€๋ถ€๋ถ„์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(๊ทธ๋ฆฌ๊ณ  ์ข…์ข… ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž์ฒด) ์ž‘์—…์„ ์œ„ํ•œ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋ณดํ†ต ์ด๋Ÿฐ ๋ชจ์Šต์ธ๋ฐ..

@Entity
@Table(name = "stock", catalog = "maindb", uniqueConstraints = {
        @UniqueConstraint(columnNames = "STOCK_NAME"),
        @UniqueConstraint(columnNames = "STOCK_CODE") })
public class Stock implements java.io.Serializable {

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "STOCK_ID", unique = true, nullable = false)
    public Integer getStockId() {
        return this.stockId;
    }
  ...

๋ชจ๋ธ์—๋Š” ๊ธฐ๋ฐœํ•œ ์ฃผ์„์ด ๋‹ฌ๋ ค ์žˆ๊ณ , ๊ทธ ์ด๋ฉด ์–ด๋”˜๊ฐ€์—์„œ ์šฉ๊ฐํ•œ ORM์ด ์ˆ˜๋งŽ์€ SQL ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฑด ๊ทธ๋ ‡๊ณ , ๊ฐœ๋ฐœ์ž๋Š” ์ˆ˜ ํ‚ฌ๋กœ๋ฏธํ„ฐ์˜ ์ถ”์ƒํ™”๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์ž์‹ ์„ ๊ฒฉ๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ตœ์„ ์„ ๋‹คํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. "SQL ์ฆ์˜ค".

๋ฐ”๋ฆฌ์ผ€์ด๋“œ์˜ ๋ฐ˜๋Œ€ํŽธ์—๋Š” ์ˆœ์ˆ˜ํ•œ "์ˆ˜์ œ" SQL ์ง€์ง€์ž๋“ค์ด ์ถ”๊ฐ€ ๊ณ„์ธต์ด๋‚˜ ์ถ”์ƒํ™” ์—†์ด DBMS์—์„œ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์งœ๋‚ผ ์ˆ˜ ์žˆ๋Š” ๋Šฅ๋ ฅ์ด ์žˆ๋‹ค๋Š” ์ ์— ์ฃผ๋ชฉํ•ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ ํŠน๋ณ„ํžˆ ๊ต์œก์„ ๋ฐ›์€ ์‚ฌ๋žŒ๋“ค์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ฐธ์—ฌํ•˜๋Š” "๋ฐ์ดํ„ฐ ์ค‘์‹ฌ" ํ”„๋กœ์ ํŠธ๊ฐ€ ๋‚˜ํƒ€๋‚˜๊ณ (๊ทธ๋“ค์€ "๊ธฐ๋ณธ์ฃผ์˜์ž"์ด๊ธฐ๋„ ํ•˜๊ณ  "๊ธฐ๋ณธ์ฃผ์˜์ž"์ด๊ธฐ๋„ ํ•˜๋ฉฐ "๊ธฐ๋ณธ์ฃผ์˜์ž"์ด๊ธฐ๋„ ํ•จ) ๊ฐœ๋ฐœ์ž๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ๋‹ค๋ฃจ์ง€ ์•Š๊ณ  ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด์ง„ ๋ทฐ์™€ ์ €์žฅ ํ”„๋กœ์‹œ์ €๋งŒ "ํ’€"ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๊ฐ€ ๋‘ ์„ธ๊ณ„์˜ ์žฅ์ ์„ ๋ชจ๋‘ ๊ฐ–๊ณ  ์žˆ๋‹ค๋ฉด ์–ด๋–จ๊นŒ์š”? ์ƒ๋ช…์„ ํ™•์ธํ•˜๋Š” ์ด๋ฆ„์„ ๊ฐ€์ง„ ํ›Œ๋ฅญํ•œ ๋„๊ตฌ์—์„œ ์ด๊ฒƒ์ด ์ˆ˜ํ–‰๋˜๋Š” ๋ฐฉ๋ฒ• ์˜ˆSQL. ๋ฌด๋ฃŒ ๋ฒˆ์—ญ์—์„œ ์ผ๋ฐ˜์ ์ธ ๊ฐœ๋… ์ค‘ ๋ช‡ ์ค„์„ ์†Œ๊ฐœํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—.

Clojure๋Š” DSL์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ๋ฉ‹์ง„ ์–ธ์–ด์ด์ง€๋งŒ SQL ์ž์ฒด๋„ ๋ฉ‹์ง„ DSL์ด๋ฏ€๋กœ ๋‹ค๋ฅธ ์–ธ์–ด๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. S-ํ‘œํ˜„์€ ํ›Œ๋ฅญํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์— ์ƒˆ๋กœ์šด ๊ฒƒ์„ ์ถ”๊ฐ€ํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ ์šฐ๋ฆฌ๋Š” ๋Œ€๊ด„ํ˜ธ๋ฅผ ์œ„ํ•ด ๋Œ€๊ด„ํ˜ธ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค. ๋™์˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ? ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋Œ€ํ•œ ์ถ”์ƒํ™”๊ฐ€ ๋ˆ„์ถœ๋˜๊ธฐ ์‹œ์ž‘ํ•˜๊ณ  ํ•จ์ˆ˜์™€์˜ ์‹ธ์›€์ด ์‹œ์ž‘๋˜๋Š” ์ˆœ๊ฐ„์„ ๊ธฐ๋‹ค๋ฆฌ์‹ญ์‹œ์˜ค. (์›์‹œ SQL)

๊ทธ๋ž˜์„œ ๋‚ด๊ฐ€ ๋ฌด์—‡์„ํ•ด์•ผํ•˜๋‹ˆ? SQL์„ ์ผ๋ฐ˜ SQL(์š”์ฒญ๋‹น ํ•˜๋‚˜์˜ ํŒŒ์ผ)๋กœ ๋‚จ๊ฒจ๋‘ก๋‹ˆ๋‹ค.

-- name: users-by-country
select *
  from users
 where country_code = :country_code

... ๊ทธ๋Ÿฐ ๋‹ค์Œ ์ด ํŒŒ์ผ์„ ์ฝ๊ณ  ์ด๋ฅผ ์ผ๋ฐ˜ Clojure ํ•จ์ˆ˜๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

(defqueries "some/where/users_by_country.sql"
   {:connection db-spec})

;;; A function with the name `users-by-country` has been created.
;;; Let's use it:
(users-by-country {:country_code "GB"})
;=> ({:name "Kris" :country_code "GB" ...} ...)

"SQL ์ž์ฒด, Clojure ์ž์ฒด" ์›์น™์„ ์ค€์ˆ˜ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด์ ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๊ตฌ๋ฌธ๋ก ์  ๋†€๋ผ์›€์€ ์—†์Šต๋‹ˆ๋‹ค. ๊ท€ํ•˜์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” (๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ) SQL ํ‘œ์ค€์„ 100% ์ค€์ˆ˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๋Š” Yesql์—์„œ๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. SQL๊ณผ ๋™๋“ฑํ•œ ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ฐพ๋Š” ๋ฐ ์‹œ๊ฐ„์„ ๋‚ญ๋น„ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•จ์ˆ˜๋กœ ๋Œ์•„๊ฐˆ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. (์›์‹œ SQL "some('funky'::SYNTAX)")).
  • ์ตœ๊ณ ์˜ ํŽธ์ง‘์ž ์ง€์›. ๊ท€ํ•˜์˜ ํŽธ์ง‘์ž๋Š” ์ด๋ฏธ ๋›ฐ์–ด๋‚œ SQL ์ง€์› ๊ธฐ๋Šฅ์„ ๊ฐ–์ถ”๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. SQL์„ SQL๋กœ ์ €์žฅํ•˜๋ฉด ๊ฐ„๋‹จํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํŒ€ ํ˜ธํ™˜์„ฑ. DBA๋Š” Clojure ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” SQL์„ ์ฝ๊ณ  ์“ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์„ฑ๋Šฅ ํŠœ๋‹์ด ๋” ์‰ฌ์›Œ์กŒ์Šต๋‹ˆ๋‹ค. ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ์ฟผ๋ฆฌ์— ๋Œ€ํ•œ ๊ณ„ํš์„ ์„ธ์›Œ์•ผ ํ•ฉ๋‹ˆ๊นŒ? ์ฟผ๋ฆฌ๊ฐ€ ์ผ๋ฐ˜ SQL์ธ ๊ฒฝ์šฐ์—๋Š” ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์ฟผ๋ฆฌ๋ฅผ ์žฌ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋™์ผํ•œ SQL ํŒŒ์ผ์„ ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์— ๋Œ์–ด์„œ ๋†“์œผ์„ธ์š”. ๊ทธ๋ƒฅ ์˜ค๋ž˜๋œ SQL์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ƒฅ ๊ณต์œ ํ•˜์„ธ์š”.

์ œ ์ƒ๊ฐ์—๋Š” ์ด ์•„์ด๋””์–ด๋Š” ๋งค์šฐ ๋ฉ‹์ง€๊ณ  ๋™์‹œ์— ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ๋•๋ถ„์— ์ด ํ”„๋กœ์ ํŠธ๋Š” ๋งŽ์€ ๊ฒƒ์„ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค. ์ถ”์ข…์ž ๋‹ค์–‘ํ•œ ์–ธ์–ด๋กœ. ๊ทธ๋ฆฌ๊ณ  ์šฐ๋ฆฌ๋Š” ๋‹ค์Œ์œผ๋กœ ORM์„ ํ›จ์”ฌ ๋„˜์–ด์„œ๋Š” ๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒƒ์—์„œ SQL ์ฝ”๋“œ๋ฅผ ๋ถ„๋ฆฌํ•˜๋Š” ์œ ์‚ฌํ•œ ์ฒ ํ•™์„ ์ ์šฉํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

IDE ๋ฐ DB ๊ด€๋ฆฌ์ž

๊ฐ„๋‹จํ•œ ์ผ์ƒ ์—…๋ฌด๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์Šคํ‚ค๋งˆ์—์„œ ํ…Œ์ด๋ธ”์„ ์ฐพ๊ณ  ํ•ด๋‹น ๊ตฌ์กฐ(์‚ฌ์šฉ๋˜๋Š” ์—ด, ํ‚ค, ์ธ๋ฑ์Šค, ์ œ์•ฝ ์กฐ๊ฑด ๋“ฑ)๋ฅผ ์—ฐ๊ตฌํ•˜๋Š” ๋“ฑ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์ผ๋ถ€ ๊ฐœ์ฒด๋ฅผ ๊ฒ€์ƒ‰ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ๋ž˜ํ”ฝ IDE๋‚˜ ์ž‘์€ DB ๊ด€๋ฆฌ์ž์—์„œ ๋ฌด์—‡๋ณด๋‹ค๋„ ์šฐ๋ฆฌ๋Š” ๋ฐ”๋กœ ์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ์„ ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ์ •๋ณด๊ฐ€ ํฌํ•จ๋œ ์ฐฝ์ด ๋‚˜ํƒ€๋‚  ๋•Œ๊นŒ์ง€ ์†๋„๊ฐ€ ๋น ๋ฅด๊ณ (ํŠนํžˆ ์›๊ฒฉ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋Œ€ํ•œ ์—ฐ๊ฒฐ์ด ๋Š๋ฆฐ ๊ฒฝ์šฐ) XNUMX๋ถ„์„ ๊ธฐ๋‹ค๋ฆด ํ•„์š”๊ฐ€ ์—†์œผ๋ฉฐ, ๋™์‹œ์— ์ˆ˜์‹ ๋œ ์ •๋ณด๋Š” ์‹ ์„ ํ•˜๊ณ  ๊ด€๋ จ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค. ์บ์‹œ๋œ ์ •ํฌ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ๋”์šฑ์ด, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ๋” ๋ณต์žกํ•˜๊ณ  ํด์ˆ˜๋ก, ๊ทธ ์ˆ˜๊ฐ€ ๋งŽ์„์ˆ˜๋ก ์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ๋” ์–ด๋ ค์›Œ์ง‘๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋ณดํ†ต์€ ๋งˆ์šฐ์Šค๋ฅผ ๋ฒ„๋ฆฌ๊ณ  ์ฝ”๋“œ๋งŒ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. "HR" ์Šคํ‚ค๋งˆ์— ์–ด๋–ค ํ…Œ์ด๋ธ”๊ณผ ์–ด๋–ค ์†์„ฑ์ด ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ์•Œ์•„๋‚ด์•ผ ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ DBMS์—์„œ๋Š” information_schema์˜ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐ„๋‹จํ•œ ์ฟผ๋ฆฌ๋ฅผ ํ†ตํ•ด ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

select table_name
     , ...
  from information_schema.tables
 where schema = 'HR'

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋งˆ๋‹ค ์ด๋Ÿฌํ•œ ์ฐธ์กฐ ํ…Œ์ด๋ธ”์˜ ๋‚ด์šฉ์€ ๊ฐ DBMS์˜ ๊ธฐ๋Šฅ์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด MySQL์˜ ๊ฒฝ์šฐ ๋™์ผํ•œ ์ฐธ์กฐ ์„œ์ ์—์„œ ์ด DBMS์™€ ๊ด€๋ จ๋œ ํ…Œ์ด๋ธ” ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

select table_name
     , storage_engine -- ะ˜ัะฟะพะปัŒะทัƒะตะผั‹ะน "ะดะฒะธะถะพะบ" ("MyISAM", "InnoDB" etc)
     , row_format     -- ะคะพั€ะผะฐั‚ ัั‚ั€ะพะบะธ ("Fixed", "Dynamic" etc)
     , ...
  from information_schema.tables
 where schema = 'HR'

Oracle์€ information_schema๋ฅผ ๋ชจ๋ฅด์ง€๋งŒ ๋‹ค์Œ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ค๋ผํด ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ, ํฐ ๋ฌธ์ œ๋Š” ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

select table_name
     , pct_free       -- ะœะธะฝะธะผัƒะผ ัะฒะพะฑะพะดะฝะพะณะพ ะผะตัั‚ะฐ ะฒ ะฑะปะพะบะต ะดะฐะฝะฝั‹ั… (%)
     , pct_used       -- ะœะธะฝะธะผัƒะผ ะธัะฟะพะปัŒะทัƒะตะผะพะณะพ ะผะตัั‚ะฐ ะฒ ะฑะปะพะบะต ะดะฐะฝะฝั‹ั… (%)
     , last_analyzed  -- ะ”ะฐั‚ะฐ ะฟะพัะปะตะดะฝะตะณะพ ัะฑะพั€ะฐ ัั‚ะฐั‚ะธัั‚ะธะบะธ
     , ...
  from all_tables
 where owner = 'HR'

ClickHouse๋„ ์˜ˆ์™ธ๋Š” ์•„๋‹™๋‹ˆ๋‹ค.

select name
     , engine -- ะ˜ัะฟะพะปัŒะทัƒะตะผั‹ะน "ะดะฒะธะถะพะบ" ("MergeTree", "Dictionary" etc)
     , ...
  from system.tables
 where database = 'HR'

Cassandra์—์„œ๋„ ๋น„์Šทํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(ํ…Œ์ด๋ธ” ๋Œ€์‹  ์ปฌ๋ŸผํŒจ๋ฐ€๋ฆฌ๊ฐ€ ์žˆ๊ณ  ์Šคํ‚ค๋งˆ ๋Œ€์‹  ํ‚ค์ŠคํŽ˜์ด์Šค๊ฐ€ ์žˆ์Œ).

select columnfamily_name
     , compaction_strategy_class  -- ะกั‚ั€ะฐั‚ะตะณะธั ัะฑะพั€ะบะธ ะผัƒัะพั€ะฐ
     , gc_grace_seconds           -- ะ’ั€ะตะผั ะถะธะทะฝะธ ะผัƒัะพั€ะฐ
     , ...
  from system.schema_columnfamilies
 where keyspace_name = 'HR'

๋Œ€๋ถ€๋ถ„์˜ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๊ฒฝ์šฐ์—๋„ ๋น„์Šทํ•œ ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(Mongo๋„ ํŠน๋ณ„ํ•œ ์‹œ์Šคํ…œ ์ปฌ๋ ‰์…˜, ์‹œ์Šคํ…œ์˜ ๋ชจ๋“  ์ปฌ๋ ‰์…˜์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Œ).

๋ฌผ๋ก  ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ํ…Œ์ด๋ธ”๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ผ๋ฐ˜์ ์ธ ๋ชจ๋“  ๊ฐœ์ฒด์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋•Œ๋•Œ๋กœ ์นœ์ ˆํ•œ ์‚ฌ๋žŒ๋“ค์€ Habra ๊ธฐ์‚ฌ ์‹œ๋ฆฌ์ฆˆ "PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฌธ์„œํ™” ๊ธฐ๋Šฅ"(์•„์ด๋ธŒ, ๋ฒค, ํ—ฌ์Šค์žฅ). ๋ฌผ๋ก , ์ด ์‚ฐ๋”๋ฏธ ๊ฐ™์€ ์ฟผ๋ฆฌ๋ฅผ ๋จธ๋ฆฟ์†์— ๊ฐ„์งํ•˜๊ณ  ๊ณ„์†ํ•ด์„œ ์ž…๋ ฅํ•˜๋Š” ๊ฒƒ์€ ์ •๋ง ์ฆ๊ฒ๊ธฐ ๋•Œ๋ฌธ์— ์ œ๊ฐ€ ๊ฐ€์žฅ ์ข‹์•„ํ•˜๋Š” IDE/ํŽธ์ง‘๊ธฐ์—๋Š” ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ์ฟผ๋ฆฌ์— ๋Œ€ํ•ด ๋ฏธ๋ฆฌ ์ค€๋น„๋œ ์Šค๋‹ˆํŽซ ์„ธํŠธ๊ฐ€ ์žˆ๊ณ  ๋‚จ์€ ๊ฒƒ์€ ๋‹ค์Œ์„ ์ž…๋ ฅํ•˜๋Š” ๊ฒƒ๋ฟ์ž…๋‹ˆ๋‹ค. ๊ฐœ์ฒด ์ด๋ฆ„์„ ํ…œํ”Œ๋ฆฟ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ์ ์œผ๋กœ ์ด ๊ฐ์ฒด ํƒ์ƒ‰ ๋ฐ ๊ฒ€์ƒ‰ ๋ฐฉ๋ฒ•์€ ํ›จ์”ฌ ๋” ์œ ์—ฐํ•˜๊ณ  ๋งŽ์€ ์‹œ๊ฐ„์„ ์ ˆ์•ฝํ•˜๋ฉฐ ํ˜„์žฌ ํ•„์š”ํ•œ ํ˜•์‹์œผ๋กœ ์ •๋ณด๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์˜ˆ๋ฅผ ๋“ค์–ด ๊ฒŒ์‹œ๋ฌผ์— ์„ค๋ช…๋œ ๋Œ€๋กœ). "์–ด๋–ค ํ˜•์‹์œผ๋กœ๋“  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๋ฐ์ดํ„ฐ ๋‚ด๋ณด๋‚ด๊ธฐ: IntelliJ ํ”Œ๋žซํผ์—์„œ IDE๊ฐ€ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ž‘์—…").

๊ฐœ์ฒด ์ž‘์—…

ํ•„์š”ํ•œ ๋ฌผ๊ฑด์„ ์ฐพ์•„ ์—ฐ๊ตฌํ•œ ํ›„์—๋Š” ๊ทธ ๋ฌผ๊ฑด์„ ๊ฐ€์ง€๊ณ  ๋ญ”๊ฐ€ ์œ ์šฉํ•œ ์ผ์„ ํ•  ์ฐจ๋ก€์ž…๋‹ˆ๋‹ค. ๋‹น์—ฐํžˆ ํ‚ค๋ณด๋“œ์—์„œ ์†๊ฐ€๋ฝ์„ ๋–ผ์ง€ ์•Š๊ณ ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๋‹จ์ˆœํžˆ ํ…Œ์ด๋ธ”์„ ์‚ญ์ œํ•˜๋ฉด ๊ฑฐ์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๋™์ผํ•˜๊ฒŒ ๋ณด์ธ๋‹ค๋Š” ๊ฒƒ์€ ๋น„๋ฐ€์ด ์•„๋‹™๋‹ˆ๋‹ค.

drop table hr.persons

๊ทธ๋Ÿฌ๋‚˜ ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ค๋ฉด ๋”์šฑ ํฅ๋ฏธ๋กœ์›Œ์ง‘๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ NoSQL์„ ํฌํ•จํ•˜์—ฌ ๊ฑฐ์˜ ๋ชจ๋“  DBMS๋Š” ํ•œ ๊ฐ€์ง€ ํ˜•์‹ ๋˜๋Š” ๋‹ค๋ฅธ ํ˜•์‹์œผ๋กœ "ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑ"ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ฃผ์š” ๋ถ€๋ถ„(์ด๋ฆ„, ์—ด ๋ชฉ๋ก, ๋ฐ์ดํ„ฐ ์œ ํ˜•)์€ ์•ฝ๊ฐ„ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์ง€๋งŒ ๊ธฐํƒ€ ์„ธ๋ถ€ ์‚ฌํ•ญ์€ ๊ทน์ ์œผ๋กœ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค. ํŠน์ • DBMS์˜ ๋‚ด๋ถ€ ์žฅ์น˜ ๋ฐ ๊ธฐ๋Šฅ. ์ œ๊ฐ€ ๊ฐ€์žฅ ์ข‹์•„ํ•˜๋Š” ์˜ˆ๋Š” Oracle ๋ฌธ์„œ์— "create table" ๊ตฌ๋ฌธ์— ๋Œ€ํ•œ "naked" BNF๋งŒ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. 31ํŽ˜์ด์ง€๋ฅผ ์ฐจ์ง€. ๋‹ค๋ฅธ DBMS๋Š” ์ข€ ๋” ์ ๋‹นํ•œ ๊ธฐ๋Šฅ์„ ๊ฐ–๊ณ  ์žˆ์ง€๋งŒ ๊ฐ๊ฐ ํ…Œ์ด๋ธ” ์ƒ์„ฑ์„ ์œ„ํ•œ ํฅ๋ฏธ๋กญ๊ณ  ๋…ํŠนํ•œ ๊ธฐ๋Šฅ๋„ ๋งŽ์ด ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.ํฌ์ŠคํŠธ ๊ทธ๋ ˆ์Šค, MySQL์€, ๋ฐ”ํ€ด๋ฒŒ๋ ˆ, ์นด์‚ฐ๋“œ๋ผ). ๋‹ค๋ฅธ IDE(ํŠนํžˆ ๋ฒ”์šฉ IDE)์˜ ๊ทธ๋ž˜ํ”ฝ "๋งˆ๋ฒ•์‚ฌ"๊ฐ€ ์ด๋Ÿฌํ•œ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์™„์ „ํžˆ ํฌ๊ด„ํ•  ์ˆ˜ ์žˆ์„ ๊ฐ€๋Šฅ์„ฑ์€ ๊ฑฐ์˜ ์—†์œผ๋ฉฐ, ์„ค๋ น ๊ฐ€๋Šฅํ•˜๋”๋ผ๋„ ๋งˆ์Œ์ด ์•ฝํ•œ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ๋Š” ๊ด‘๊ฒฝ์ด ์•„๋‹ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋™์‹œ์— ์ •ํ™•ํ•˜๊ณ  ์‹œ๊ธฐ์ ์ ˆํ•˜๊ฒŒ ์ž‘์„ฑ๋œ ์ง„์ˆ  ํ…Œ์ด๋ธ” ์ƒ์„ฑ ์ด๋ฅผ ํ†ตํ•ด ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์ €์žฅ ๋ฐ ์•ก์„ธ์Šค๋ฅผ ์•ˆ์ •์ ์ด๊ณ  ์ตœ์ ์ด๋ฉฐ ์ตœ๋Œ€ํ•œ ํŽธ์•ˆํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ๋งŽ์€ DBMS์—๋Š” ๋‹ค๋ฅธ DBMS์—์„œ๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๊ณ ์œ ํ•œ ํŠน์ • ์œ ํ˜•์˜ ๊ฐœ์ฒด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐœ์ฒด๋ฟ๋งŒ ์•„๋‹ˆ๋ผ DBMS ์ž์ฒด์—์„œ๋„ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํ”„๋กœ์„ธ์Šค๋ฅผ "์ข…๋ฃŒ"ํ•˜๊ณ , ์ผ๋ถ€ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ ํ™•๋ณดํ•˜๊ณ , ์ถ”์ ์„ ํ™œ์„ฑํ™”ํ•˜๊ณ , "์ฝ๊ธฐ ์ „์šฉ" ๋ชจ๋“œ๋กœ ์ „ํ™˜ํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ์ข€ ๊ทธ๋ ค๋ณด์ž

๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ์ž‘์—… ์ค‘ ํ•˜๋‚˜๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐœ์ฒด๋กœ ๋‹ค์ด์–ด๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜๊ณ  ์•„๋ฆ„๋‹ค์šด ๊ทธ๋ฆผ์—์„œ ๊ฐœ์ฒด์™€ ๊ฐœ์ฒด ๊ฐ„์˜ ์—ฐ๊ฒฐ์„ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ฑฐ์˜ ๋ชจ๋“  ๊ทธ๋ž˜ํ”ฝ IDE, ๋ณ„๋„์˜ "๋ช…๋ น์ค„" ์œ ํ‹ธ๋ฆฌํ‹ฐ, ํŠน์ˆ˜ ๊ทธ๋ž˜ํ”ฝ ๋„๊ตฌ ๋ฐ ๋ชจ๋ธ๋Ÿฌ๊ฐ€ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋“ค์€ "๊ฐ€๋Šฅํ•œ ํ•œ ์ตœ์„ ์„ ๋‹คํ•ด" ๋ฌด์–ธ๊ฐ€๋ฅผ ๊ทธ๋ ค์ค„ ๊ฒƒ์ด๋ฉฐ ๊ตฌ์„ฑ ํŒŒ์ผ์˜ ๋ช‡ ๊ฐ€์ง€ ๋งค๊ฐœ๋ณ€์ˆ˜๋‚˜ ์ธํ„ฐํŽ˜์ด์Šค์˜ ํ™•์ธ๋ž€์„ ํ†ตํ•ด์„œ๋งŒ ์ด ํ”„๋กœ์„ธ์Šค์— ์•ฝ๊ฐ„์˜ ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์ด ๋ฌธ์ œ๋Š” ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ›จ์”ฌ ๋” ๊ฐ„๋‹จํ•˜๊ณ  ์œ ์—ฐํ•˜๋ฉฐ ์šฐ์•„ํ•˜๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณต์žกํ•œ ๋‹ค์ด์–ด๊ทธ๋žจ์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์šฐ๋ฆฌ๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ „๋ฌธ์ ์ธ ๋งˆํฌ์—… ์–ธ์–ด(DOT, GraphML ๋“ฑ)์™€ ์ด๋Ÿฌํ•œ ์ง€์นจ์„ ์ฝ๊ณ  ๋‹ค์–‘ํ•œ ํ˜•์‹์œผ๋กœ ์‹œ๊ฐํ™”ํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค์–‘ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(GraphViz, PlantUML, Mermaid)์„ ๋ณด์œ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. . ๊ธ€์Ž„, ์šฐ๋ฆฌ๋Š” ๊ฐ์ฒด์™€ ๊ฐ์ฒด ๊ฐ„์˜ ์—ฐ๊ฒฐ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์–ป๋Š” ๋ฐฉ๋ฒ•์„ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

PlantUML์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ๋ณด์ผ ์ˆ˜ ์žˆ๋Š”์ง€์— ๋Œ€ํ•œ ์ž‘์€ ์˜ˆ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. PostgreSQL์šฉ ๋ฐ๋ชจ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค (์™ผ์ชฝ์—๋Š” PlantUML์— ํ•„์š”ํ•œ ๋ช…๋ น์„ ์ƒ์„ฑํ•˜๋Š” SQL ์ฟผ๋ฆฌ๊ฐ€ ์žˆ๊ณ  ์˜ค๋ฅธ์ชฝ์—๋Š” ๊ฒฐ๊ณผ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค):

"์ฝ”๋“œํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค" ๊ฒฝํ—˜

select '@startuml'||chr(10)||'hide methods'||chr(10)||'hide stereotypes' union all
select distinct ccu.table_name || ' --|> ' ||
       tc.table_name as val
  from table_constraints as tc
  join key_column_usage as kcu
    on tc.constraint_name = kcu.constraint_name
  join constraint_column_usage as ccu
    on ccu.constraint_name = tc.constraint_name
 where tc.constraint_type = 'FOREIGN KEY'
   and tc.table_name ~ '.*' union all
select '@enduml'

๊ทธ๋ฆฌ๊ณ  ์กฐ๊ธˆ๋งŒ ์‹œ๋„ํ•ด ๋ณด๋ฉด PlantUML์šฉ ER ํ…œํ”Œ๋ฆฟ ์‹ค์ œ ER ๋‹ค์ด์–ด๊ทธ๋žจ๊ณผ ๋งค์šฐ ์œ ์‚ฌํ•œ ๊ฒƒ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

SQL ์ฟผ๋ฆฌ๋Š” ์กฐ๊ธˆ ๋” ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค.

-- ะจะฐะฟะบะฐ
select '@startuml
        !define Table(name,desc) class name as "desc" << (T,#FFAAAA) >>
        !define primary_key(x) <b>x</b>
        !define unique(x) <color:green>x</color>
        !define not_null(x) <u>x</u>
        hide methods
        hide stereotypes'
 union all
-- ะขะฐะฑะปะธั†ั‹
select format('Table(%s, "%s n information about %s") {'||chr(10), table_name, table_name, table_name) ||
       (select string_agg(column_name || ' ' || upper(udt_name), chr(10))
          from information_schema.columns
         where table_schema = 'public'
           and table_name = t.table_name) || chr(10) || '}'
  from information_schema.tables t
 where table_schema = 'public'
 union all
-- ะกะฒัะทะธ ะผะตะถะดัƒ ั‚ะฐะฑะปะธั†ะฐะผะธ
select distinct ccu.table_name || ' "1" --> "0..N" ' || tc.table_name || format(' : "A %s may haven many %s"', ccu.table_name, tc.table_name)
  from information_schema.table_constraints as tc
  join information_schema.key_column_usage as kcu on tc.constraint_name = kcu.constraint_name
  join information_schema.constraint_column_usage as ccu on ccu.constraint_name = tc.constraint_name
 where tc.constraint_type = 'FOREIGN KEY'
   and ccu.constraint_schema = 'public'
   and tc.table_name ~ '.*'
 union all
-- ะŸะพะดะฒะฐะป
select '@enduml'

"์ฝ”๋“œํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค" ๊ฒฝํ—˜

์ž์„ธํžˆ ์‚ดํŽด๋ณด๋ฉด ๋งŽ์€ ์‹œ๊ฐํ™” ๋„๊ตฌ๋„ ์œ ์‚ฌํ•œ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์‹ค, ์ด๋Ÿฌํ•œ ์š”์ฒญ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋งค์šฐ ์‹ฌ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ž์ฒด์˜ ์ฝ”๋“œ์— "ํ•˜๋“œ์™€์ด์–ด"๋˜์–ด ์žˆ์–ด ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค., ์ˆ˜์ •์€ ๋งํ•  ๊ฒƒ๋„ ์—†์Šต๋‹ˆ๋‹ค.

์ธก์ •ํ•ญ๋ชฉ ๋ฐ ๋ชจ๋‹ˆํ„ฐ๋ง

์ „ํ†ต์ ์œผ๋กœ ๋ณต์žกํ•œ ์ฃผ์ œ์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ฑ๋Šฅ ๋ชจ๋‹ˆํ„ฐ๋ง์œผ๋กœ ๋„˜์–ด๊ฐ€๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” "๋‚ด ์นœ๊ตฌ ์ค‘ ํ•œ ๋ช…"์ด ๋‚˜์—๊ฒŒ ๋“ค๋ ค์ค€ ์ž‘์€ ์‹คํ™”๋ฅผ ๊ธฐ์–ตํ•ฉ๋‹ˆ๋‹ค. ๋˜ ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์—๋Š” ๊ฐ•๋ ฅํ•œ DBA๊ฐ€ ์‚ด๊ณ  ์žˆ์—ˆ๋Š”๋ฐ, ๊ทธ๋ฅผ ๊ฐœ์ธ์ ์œผ๋กœ ์•Œ๊ณ  ์žˆ๊ฑฐ๋‚˜ ์ง์ ‘ ๋ณธ ์ ์ด ์žˆ๋Š” ๊ฐœ๋ฐœ์ž๋Š” ๊ฑฐ์˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค(์†Œ๋ฌธ์— ๋”ฐ๋ฅด๋ฉด ๊ทธ๊ฐ€ ๋‹ค์Œ ๊ฑด๋ฌผ ์–ด๋”˜๊ฐ€์—์„œ ์ผํ–ˆ๋‹ค๋Š” ์‚ฌ์‹ค์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ ). X์‹œ๊ฐ„์— ๋Œ€ํ˜• ์†Œ๋งค์—…์ฒด์˜ ์ƒ์‚ฐ ์‹œ์Šคํ…œ์ด ๋‹ค์‹œ "๋ถˆ์พŒ"ํ•ด์ง€๊ธฐ ์‹œ์ž‘ํ•˜์ž ๊ทธ๋Š” ์กฐ์šฉํžˆ Oracle Enterprise Manager์˜ ๊ทธ๋ž˜ํ”„ ์Šคํฌ๋ฆฐ์ƒท์„ ๋ณด๋ƒˆ๊ณ , ๊ฑฐ๊ธฐ์—์„œ ๊ทธ๋Š” "์ดํ•ด์„ฑ"์„ ์˜๋ฏธํ•˜๋Š” ๋นจ๊ฐ„์ƒ‰ ๋งˆ์ปค๋กœ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์„ ์ฃผ์˜ ๊นŠ๊ฒŒ ๊ฐ•์กฐํ–ˆ์Šต๋‹ˆ๋‹ค( ๊ฐ€๋ณ๊ฒŒ ๋งํ•˜๋ฉด ๋ณ„๋กœ ๋„์›€์ด ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.) ๊ทธ๋ฆฌ๊ณ  ์ด 'ํฌํ† ์นด๋“œ'๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์น˜๋ฃŒ๋ฅผ ํ•ด์•ผ ํ–ˆ์–ด์š”. ๋™์‹œ์—, ๋ˆ„๊ตฌ๋„ ๊ท€์ค‘ํ•œ(๋‘ ๊ฐ€์ง€ ์˜๋ฏธ์—์„œ) Enterprise Manager์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ์‹œ์Šคํ…œ์ด ๋ณต์žกํ•˜๊ณ  ๋น„์šฉ์ด ๋งŽ์ด ๋“ค๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ‘์ž๊ธฐ "๊ฐœ๋ฐœ์ž๋“ค์ด ๋ญ”๊ฐ€์— ๊ฑธ๋ ค์„œ ๋ชจ๋“  ๊ฒƒ์„ ๋ง๊ฐ€๋œจ๋ฆฝ๋‹ˆ๋‹ค." ์ด์— ๊ฐœ๋ฐœ์ž๋“ค์€ ๋ธŒ๋ ˆ์ดํฌ์˜ ์œ„์น˜์™€ ์›์ธ์„ '๊ฒฝํ—˜์ ์œผ๋กœ' ์ฐพ์•„๋‚ด๊ณ  ํŒจ์น˜๋ฅผ ๊ณต๊ฐœํ–ˆ๋‹ค. ๊ฐ€๊นŒ์šด ์‹œ์ผ ๋‚ด์— DBA์˜ ์œ„ํ˜‘์ ์ธ ํŽธ์ง€๊ฐ€ ๋‹ค์‹œ ๋„์ฐฉํ•˜์ง€ ์•Š์œผ๋ฉด ๋ชจ๋“  ์‚ฌ๋žŒ์€ ์•ˆ๋„์˜ ํ•œ์ˆจ์„ ์‰ฌ๊ณ  ํ˜„์žฌ ์ž‘์—…์œผ๋กœ ๋Œ์•„๊ฐˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค(์ƒˆ ํŽธ์ง€๊ฐ€ ์˜ฌ ๋•Œ๊นŒ์ง€).

๊ทธ๋Ÿฌ๋‚˜ ๋ชจ๋‹ˆํ„ฐ๋ง ํ”„๋กœ์„ธ์Šค๋Š” ๋”์šฑ ์žฌ๋ฏธ์žˆ๊ณ  ์นœ๊ทผํ•ด ๋ณด์ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ฐ€์žฅ ์ค‘์š”ํ•˜๊ฒŒ๋Š” ๋ชจ๋“  ์‚ฌ๋žŒ์ด ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๊ณ  ํˆฌ๋ช…ํ•˜๊ฒŒ ๋ณด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ตœ์†Œํ•œ ๊ธฐ๋ณธ ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์Šคํ…œ์— ์ถ”๊ฐ€๋˜๋Š” ๊ธฐ๋ณธ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค(ํ™•์‹คํžˆ ์œ ์šฉํ•˜๊ณ  ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ๋Œ€์ฒดํ•  ์ˆ˜ ์—†์Œ). ๋ชจ๋“  DBMS๋Š” ํ˜„์žฌ ์ƒํƒœ์™€ ์„ฑ๋Šฅ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋ฌด๋ฃŒ๋กœ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋™์ผํ•œ "ํ”ผ๋ฌป์€" Oracle DB์—์„œ๋Š” ํ”„๋กœ์„ธ์Šค ๋ฐ ์„ธ์…˜์—์„œ ๋ฒ„ํผ ์บ์‹œ ์ƒํƒœ์— ์ด๋ฅด๊ธฐ๊นŒ์ง€ ์„ฑ๋Šฅ์— ๋Œ€ํ•œ ๊ฑฐ์˜ ๋ชจ๋“  ์ •๋ณด๋ฅผ ์‹œ์Šคํ…œ ๋ทฐ์—์„œ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์˜ˆ: DBA ์Šคํฌ๋ฆฝํŠธ, "๋ชจ๋‹ˆํ„ฐ๋ง" ์„น์…˜). Postgresql์—๋Š” ๋˜ํ•œ ๋‹ค์Œ์„ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ์‹œ์Šคํ…œ ๋ทฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ชจ๋‹ˆํ„ฐ๋ง, ํŠนํžˆ ๋‹ค์Œ๊ณผ ๊ฐ™์ด DBA์˜ ์ผ์ƒ ์ƒํ™œ์— ์—†์–ด์„œ๋Š” ์•ˆ๋  ๊ฒƒ๋“ค์ž…๋‹ˆ๋‹ค. pg_stat_activity, pg_stat_database, pg_stat_bg์ž‘๊ฐ€. MySQL์—๋Š” ์ด๋ฅผ ์œ„ํ•œ ๋ณ„๋„์˜ ์Šคํ‚ค๋งˆ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์„ฑ๋Šฅ_์Šคํ‚ค๋งˆ. A Mongo ๋‚ด์žฅ ํ”„๋กœํŒŒ์ผ๋Ÿฌ ์„ฑ๋Šฅ ๋ฐ์ดํ„ฐ๋ฅผ ์‹œ์Šคํ…œ ๋ชจ์Œ์œผ๋กœ ์ง‘๊ณ„ํ•ฉ๋‹ˆ๋‹ค. ์‹œ์Šคํ…œ.ํ”„๋กœํ•„.

๋”ฐ๋ผ์„œ ์‚ฌ์šฉ์ž ์ •์˜ SQL ์ฟผ๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ผ์ข…์˜ ๋ฉ”ํŠธ๋ฆญ ์ˆ˜์ง‘๊ธฐ(Telegraf, Metricbeat, Collectd), ์ด๋Ÿฌํ•œ ๋ฉ”ํŠธ๋ฆญ์˜ ์ €์žฅ(InfluxDB, Elasticsearch, Timescaledb) ๋ฐ ์‹œ๊ฐํ™” ๋„๊ตฌ(Grafana, Kibana)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ƒ๋‹นํžˆ ์‰ฝ๊ฒŒ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ์‹œ์Šคํ…œ ์ „๋ฐ˜์˜ ์ง€ํ‘œ(์˜ˆ๋ฅผ ๋“ค์–ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„, OS ๋“ฑ์—์„œ ํš๋“)์™€ ๊ธด๋ฐ€ํ•˜๊ฒŒ ํ†ตํ•ฉ๋˜๋Š” ์œ ์—ฐํ•œ ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ด๋Š” InfluxDB + Grafana ์กฐํ•ฉ๊ณผ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋Š” ์‹œ์Šคํ…œ ๋ทฐ์— ๋Œ€ํ•œ ์ฟผ๋ฆฌ ์„ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” pgwatch2์—์„œ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ๋งž์ถค ์ฟผ๋ฆฌ ์ถ”๊ฐ€.

์ „์ฒด๋กœ

์ด๋Š” ์ผ๋ฐ˜ SQL ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋กœ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ž‘์—…์˜ ๋Œ€๋žต์ ์ธ ๋ชฉ๋ก์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ๋” ๋งŽ์€ ์šฉ๋„๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋ผ๊ณ  ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค. ๋Œ“๊ธ€์„ ์ž‘์„ฑํ•ด ์ฃผ์„ธ์š”. ๊ทธ๋ฆฌ๊ณ  ๋‹ค์Œ๋ฒˆ์—๋Š” ์ด ๋ชจ๋“  ๊ฒƒ์„ ์ž๋™ํ™”ํ•˜๊ณ  CI/CD ํŒŒ์ดํ”„๋ผ์ธ์— ํฌํ•จ์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•(๊ทธ๋ฆฌ๊ณ  ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์ด์œ )์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€