Avatar
๐Ÿ˜‰

Organizations

  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ค๊ณ„์—์„œ **์ •๊ทœํ™”(Normalization)**์™€ **๋ฐ˜์ •๊ทœํ™”(Denormalization)**๋Š” ๋ฐ์ดํ„ฐ์˜ **๋ฌด๊ฒฐ์„ฑ(Integrity)**๊ณผ ์„ฑ๋Šฅ(Performance) ์‚ฌ์ด์˜ ๊ท ํ˜•์„ ๋งž์ถ”๋Š” ํ•ต์‹ฌ์ ์ธ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค.

    ์ด ๋‘˜์˜ ๊ด€๊ณ„๋Š” ํ”ํžˆ **“๋ฐ์ดํ„ฐ ์ •ํ•ฉ์„ฑ vs. ์ฝ๊ธฐ ์„ฑ๋Šฅ”**์˜ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„(Trade-off)๋กœ ์š”์•ฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ๊ฐœ๋…์˜ ํŠน์ง•๊ณผ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„ ์š”์†Œ๋ฅผ ์ƒ์„ธํžˆ ๋ถ„์„ํ•ด ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.


    1. ํ•ต์‹ฌ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„ ์š”์•ฝ

    ๊ฐ€์žฅ ๋จผ์ € ์ดํ•ดํ•ด์•ผ ํ•  ํฐ ๊ทธ๋ฆผ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    • ์ •๊ทœํ™”: ๋ฐ์ดํ„ฐ๋ฅผ ์ชผ๊ฐœ์„œ ์ค‘๋ณต์„ ์ œ๊ฑฐํ•˜๊ณ  ๋ฌด๊ฒฐ์„ฑ์„ ์ง€ํ‚ต๋‹ˆ๋‹ค. (์“ฐ๊ธฐ ์„ฑ๋Šฅ ํ–ฅ์ƒ, ์ฝ๊ธฐ ์‹œ JOIN ๋น„์šฉ ๋ฐœ์ƒ)
    • ๋ฐ˜์ •๊ทœํ™”: ์„ฑ๋Šฅ์„ ์œ„ํ•ด ์˜๋„์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ค‘๋ณต์‹œํ‚ต๋‹ˆ๋‹ค. (์ฝ๊ธฐ ์„ฑ๋Šฅ ํ–ฅ์ƒ, ์“ฐ๊ธฐ ์‹œ ๋™๊ธฐํ™” ๋น„์šฉ ๋ฐœ์ƒ)

    2. ์ •๊ทœํ™” (Normalization)

    ๋ฐ์ดํ„ฐ์˜ ์ค‘๋ณต์„ ์ตœ์†Œํ™”ํ•˜๊ณ , ์ด์ƒ ํ˜„์ƒ(Anomaly)์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ํ…Œ์ด๋ธ”์„ ๋ถ„๋ฆฌํ•˜๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค.

    Created Wed, 21 Jan 2026 21:20:45 +0900
  • ์žฅ๋‹จ์ 

    ์Šคํ”„๋ง๋ถ€ํŠธ(Spring Boot)์™€ JPA(Hibernate) ํ™˜๊ฒฝ์—์„œ **์ŠคํŠธ๋ฆฌ๋ฐ ์ฟผ๋ฆฌ(Streaming Query)**๋Š” ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ ๋ฉ”๋ชจ๋ฆฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๋งค์šฐ ์ค‘์š”ํ•œ ๊ธฐ์ˆ ์ž…๋‹ˆ๋‹ค.

    ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ List<T> ํ˜•ํƒœ๋กœ ์กฐํšŒํ•˜๋ฉด ๋ชจ๋“  ๊ฒฐ๊ณผ๊ฐ€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฉ”๋ชจ๋ฆฌ(RAM)์— ์ ์žฌ๋˜์ง€๋งŒ, ์ŠคํŠธ๋ฆฌ๋ฐ ์ฟผ๋ฆฌ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค์„œ(Cursor)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•„์š”ํ•œ ๋งŒํผ๋งŒ ์กฐ๊ธˆ์”ฉ ๊ฐ€์ ธ์™€ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

    ์š”์ฒญํ•˜์‹  ์ŠคํŠธ๋ฆฌ๋ฐ ์ฟผ๋ฆฌ์˜ ํŠน์ง•๊ณผ ์žฅ๋‹จ์ ์„ ์ •๋ฆฌํ•ด ๋“œ๋ฆฝ๋‹ˆ๋‹ค.


    1. ์ŠคํŠธ๋ฆฌ๋ฐ ์ฟผ๋ฆฌ์˜ ์ฃผ์š” ํŠน์ง•

    ์ŠคํŠธ๋ฆฌ๋ฐ ์ฟผ๋ฆฌ๋Š” Java 8์˜ Stream<T> API๋ฅผ ํ™œ์šฉํ•˜์—ฌ DB ๊ฒฐ๊ณผ๋ฅผ ๋ฌผ ํ๋ฅด๋“ฏ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

    • ์ปค์„œ(Cursor) ๊ธฐ๋ฐ˜ ๋™์ž‘: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋‚ด๋ถ€์˜ ์ปค์„œ๋ฅผ ์ด๋™์‹œํ‚ค๋ฉฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ์ฝ์–ด์˜ต๋‹ˆ๋‹ค.
    • ์ง€์—ฐ ๋กœ๋”ฉ(Lazy Loading)๊ณผ ์œ ์‚ฌ: Stream ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ ์‹œ์ ์—๋Š” ์ฟผ๋ฆฌ๋งŒ ์‹คํ–‰๋˜๊ณ , ์‹ค์ œ ๋ฐ์ดํ„ฐ๋Š” stream.forEach()๋‚˜ next() ๋“ฑ์„ ํ˜ธ์ถœํ•  ๋•Œ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
    • ํŠธ๋žœ์žญ์…˜ ์˜์กด์„ฑ: ์ŠคํŠธ๋ฆผ ์ฒ˜๋ฆฌ๊ฐ€ ๋๋‚  ๋•Œ๊นŒ์ง€ DB ์—ฐ๊ฒฐ(Connection)์„ ์œ ์ง€ํ•ด์•ผ ํ•˜๋ฏ€๋กœ, ๋ฐ˜๋“œ์‹œ ํ™œ์„ฑํ™”๋œ ํŠธ๋žœ์žญ์…˜ ์•ˆ์—์„œ ์ˆ˜ํ–‰๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    2. ์žฅ์  (Pros)

    ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ(Batch ์ž‘์—…, ์—‘์…€ ๋‹ค์šด๋กœ๋“œ ๋“ฑ)์—์„œ ๊ฐ•๋ ฅํ•œ ์ด์ ์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

    Created Tue, 20 Jan 2026 21:20:45 +0900
  • Memcached์™€ Redis๋Š” ๋‘˜ ๋‹ค ๊ณ ์„ฑ๋Šฅ ์ธ๋ฉ”๋ชจ๋ฆฌ(In-memory) ํ‚ค-๊ฐ’(Key-Value) ์ €์žฅ์†Œ๋กœ, ์ฃผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ถ€ํ•˜๋ฅผ ์ค„์ด๊ณ  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์†๋„๋ฅผ ๋†’์ด๋Š” ์บ์‹œ(Cache) ์šฉ๋„๋กœ ์‚ฌ์šฉ๋œ๋‹ค๋Š” ๊ณตํ†ต์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

    ํ•˜์ง€๋งŒ “๋‹จ์ˆœํ•จ๊ณผ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ(Memcached)” ๋Œ€ **“๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ๊ณผ ์œ ์—ฐ์„ฑ(Redis)”**์ด๋ผ๋Š” ๋ช…ํ™•ํ•œ ์ฐจ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

    ๋‘ ๊ธฐ์ˆ ์˜ ํ•ต์‹ฌ์ ์ธ ์ฐจ์ด๋ฅผ 4๊ฐ€์ง€ ๊ด€์ (๋ฐ์ดํ„ฐ ๊ตฌ์กฐ, ์•„ํ‚คํ…์ฒ˜, ์˜์†์„ฑ, ํ™•์žฅ์„ฑ)์—์„œ ์ •๋ฆฌํ•ด ๋“œ๋ฆฝ๋‹ˆ๋‹ค.


    1. ํ•œ๋ˆˆ์— ๋ณด๋Š” ๋น„๊ต (Executive Summary)

    ํŠน์ง• Memcached Redis
    ์ฃผ์š” ์ปจ์…‰ ๊ณ ์„ฑ๋Šฅ, ๋‹จ์ˆœํ•จ, ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ๋‹ค์–‘ํ•œ ์ž๋ฃŒ๊ตฌ์กฐ, ์˜์†์„ฑ, ๊ธฐ๋Šฅ ํ’๋ถ€
    ์ž๋ฃŒ ๊ตฌ์กฐ String (๋‹จ์ˆœ ๋ฌธ์ž์—ด/๋ฐ”์ด๋„ˆ๋ฆฌ) String, List, Set, Hash, Sorted Set, Geo ๋“ฑ
    ์Šค๋ ˆ๋“œ ๋ชจ๋ธ ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ (Multi-threaded) ์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ (Single-threaded) (I/O๋Š” ๋ฉ€ํ‹ฐ ๊ฐ€๋Šฅ)
    ๋ฐ์ดํ„ฐ ์˜์†์„ฑ ์ง€์› ์•ˆ ํ•จ (์žฌ๋ถ€ํŒ… ์‹œ ๋ฐ์ดํ„ฐ ์†Œ๋ฉธ) ์ง€์› (RDB, AOF)
    ํ™•์žฅ์„ฑ(Clustering) ํด๋ผ์ด์–ธํŠธ ์ธก ๋ถ„์‚ฐ (Consistent Hashing) ์„œ๋ฒ„ ์ธก ๋ถ„์‚ฐ (Redis Cluster)
    ๋ณต์ œ(Replication) ์ง€์› ์•ˆ ํ•จ Master-Slave ๋ณต์ œ ์ง€์›
    ์ฃผ์š” ์šฉ๋„ ๋‹จ์ˆœ ์บ์‹ฑ (์„ธ์…˜, HTML ์กฐ๊ฐ) ๋ณต์žกํ•œ ์บ์‹ฑ, ๋ฆฌ๋”๋ณด๋“œ, ๋Œ€๊ธฐ์—ด, ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค

    2. ์ƒ์„ธ ์ฐจ์ด์  ๋ถ„์„

    โ‘  ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ (Data Structures)

    • Memcached: ์˜ค์ง **๋ฌธ์ž์—ด(String)**๋งŒ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ๋ฆฌ์ŠคํŠธ๋‚˜ ํ•ด์‹œ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ์ €์žฅํ•˜๋ ค๋ฉด JSON ๋“ฑ์œผ๋กœ ์ง๋ ฌํ™”(Serialize)ํ•ด์„œ ๋ฌธ์ž์—ด๋กœ ๋งŒ๋“  ๋’ค ์ €์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•˜๋ ค๋ฉด ์ „์ฒด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์„œ ์ˆ˜์ •ํ•œ ๋’ค ๋‹ค์‹œ ๋ฎ์–ด์จ์•ผ ํ•˜๋Š” ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
    • Redis: ๋‹ค์–‘ํ•œ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ๋ฆฌ์ŠคํŠธ(List)์— ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜, ํ•ด์‹œ(Hash)์˜ ํŠน์ • ํ•„๋“œ๋งŒ ์ˆ˜์ •ํ•˜๋Š” ๋“ฑ ํšจ์œจ์ ์ธ ๋ฐ์ดํ„ฐ ์กฐ์ž‘์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
    • ํ™œ์šฉ ์˜ˆ: ‘์‹ค์‹œ๊ฐ„ ๋žญํ‚น’ ๊ตฌํ˜„ ์‹œ Redis์˜ Sorted Set์„ ์“ฐ๋ฉด ๋งค์šฐ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

    โ‘ก ์Šค๋ ˆ๋“œ ๋ชจ๋ธ (Architecture)

    ๊ฐ€์žฅ ํฐ ์•„ํ‚คํ…์ฒ˜ ์ฐจ์ด์ž…๋‹ˆ๋‹ค.

    Created Tue, 20 Jan 2026 09:41:22 +0900
  • Kubernetes(์ฟ ๋ฒ„๋„คํ‹ฐ์Šค)์™€ Docker(๋„์ปค)์˜ ๊ด€๊ณ„๋Š” **“๊ฒฝ์Ÿ ๊ด€๊ณ„"๊ฐ€ ์•„๋‹ˆ๋ผ “์ƒํ˜ธ ๋ณด์™„์ ์ธ ๊ด€๊ณ„”**์ž…๋‹ˆ๋‹ค. ์ด ๋‘˜์˜ ์ฐจ์ด๋ฅผ ๋ช…ํ™•ํžˆ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ€์žฅ ์‰ฌ์šด ๋น„์œ ๋ฅผ ๋“ค์–ด ์„ค๋ช…ํ•ด ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.


    1. ํ•ต์‹ฌ ๋น„์œ : ํ™”๋ฌผ์„ ๊ณผ ํ•ญ๋งŒ ์‹œ์Šคํ…œ

    ์ด ๋‘ ๊ธฐ์ˆ ์˜ ๊ด€๊ณ„๋ฅผ ๋ฌผ๋ฅ˜ ์‹œ์Šคํ…œ์— ๋น„์œ ํ•˜๋ฉด ์•„์ฃผ ๋ช…ํ™•ํ•ด์ง‘๋‹ˆ๋‹ค.

    • Docker (์ปจํ…Œ์ด๋„ˆ): **‘๊ทœ๊ฒฉํ™”๋œ ํ™”๋ฌผ ์ปจํ…Œ์ด๋„ˆ ๋ฐ•์Šค’**์ž…๋‹ˆ๋‹ค.

    • ๋ฌผ๊ฑด(์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ, ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋“ฑ)์„ ๋ฐ•์Šค์— ๋‹ด์•„ ํฌ์žฅํ•˜๋Š” ๊ธฐ์ˆ ์ž…๋‹ˆ๋‹ค.

    • ์ด ๋ฐ•์Šค๋งŒ ์žˆ์œผ๋ฉด ์–ด๋–ค ๋ฐฐ(์„œ๋ฒ„)๋‚˜ ํŠธ๋Ÿญ(๋…ธํŠธ๋ถ)์— ์‹ค์–ด๋„ ๋‚ด์šฉ๋ฌผ์ด ์•ˆ์ „ํ•˜๊ฒŒ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.

    • Kubernetes (์กฐํƒ€์ˆ˜/ํ•ญ๋งŒ ๊ด€๋ฆฌ์ž): **‘์ˆ˜์ฒœ ๊ฐœ์˜ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์‹œ์Šคํ…œ’**์ž…๋‹ˆ๋‹ค.

    • ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๋ฐฐ์— ์ž˜ ์‹ค๋ ธ๋Š”์ง€, ๋ฐฐ๊ฐ€ ํ”๋“ค๋ ค ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๋–จ์–ด์ง€๋ฉด(์—๋Ÿฌ ๋ฐœ์ƒ) ๋‹ค์‹œ ์‹ค์–ด์ฃผ๋Š”์ง€, ํ™”๋ฌผ์ด ๋งŽ์•„์ง€๋ฉด ๋ฐฐ๋ฅผ ๋” ๋ถ€๋ฅผ์ง€(์Šค์ผ€์ผ๋ง)๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

    Created Tue, 06 Jan 2026 10:30:03 +0900
  • ๋‹ต

    import java.util.ArrayList;
    
    // 30. ๊ฐ„๋‹จํ•œ ์œ ๋‹ˆ์˜จ ํŒŒ์ธ๋“œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ตฌํ˜„ํ•˜๊ธฐ
    public class Solution30 {
    
        private static int[] parent;
    
        private static int findRootNode(int x) {
            if (parent[x] == x) {
                return x;
            }
            parent[x] = findRootNode(parent[x]);
            return parent[x];
        }
    
        private static void union(int x, int y) {
            int root1 = findRootNode(x);
            int root2 = findRootNode(y);
            parent[root2] = root1;
        }
    
        public static Boolean[] solution(int k, int[][] operations) {
    
            parent = new int[k];
    
            for (int i = 0; i < k; i++) {
                parent[i] = i;
            }
    
            ArrayList<Boolean> answer = new ArrayList<>();
    
            for (int[] op : operations) {
                if (op[0] == 0) {
                    union(op[1], op[2]);
                }
                else {
                    answer.add(findRootNode(op[1]) == findRootNode(op[2]));
                }
            }
    
            return answer.toArray(new Boolean[0]);
        }
    }
    

    ์ฝ”๋“œ์—์„œ return answer.toArray(new Boolean[0]); ๊ตฌ๋ฌธ์€ ArrayList<Boolean> ํƒ€์ž…์ธ answer๋ฅผ Boolean[] ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

    Created Mon, 29 Dec 2025 09:37:03 +0900
  • ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ํ™•์ธํ•˜๊ธฐ.

    ๋ฐฉ๋ฒ• 1: ์ง์ ‘ ๋งŒ๋“  ์Šคํฌ๋ฆฝํŠธ (์˜์กด์„ฑ ์—†์Œ)

    chmod +x scan-secrets.sh
    ./scan-secrets.sh
    

    ๋ฐฉ๋ฒ• 2: gitleaks ์‚ฌ์šฉ (๋” ์ •ํ™•ํ•จ, ๊ถŒ์žฅ)

    # gitleaks ์„ค์น˜
    brew install gitleaks  # ๋˜๋Š” apt install gitleaks
    
    # ๊ฐ ๋ ˆํฌ์—์„œ ์‹คํ–‰
    git clone git@github.com:dev-minimalism/kr-canslim-notifier.git
    cd kr-canslim-notifier
    gitleaks detect --source . --verbose
    
    # ์ „์ฒด ํžˆ์Šคํ† ๋ฆฌ ํฌํ•จ
    gitleaks detect --source . --verbose --log-opts="--all"
    

    ๋ฐฉ๋ฒ• 3: truffleHog (์—”ํŠธ๋กœํ”ผ ๊ธฐ๋ฐ˜ ํƒ์ง€)

    pip install truffleHog
    truffleHog git git@github.com:dev-minimalism/kr-canslim-notifier.git --since_commit HEAD~100
    

    ํ˜น์€ ํžˆ์Šคํ† ๋ฆฌ ๋‹ค ๋‚ ๋ ค๋ฒ„๋ฆฌ๊ณ  ์ดˆ๊ธฐํ™” ํ•˜๊ธฐ

    git checkout --orphan latest_branch
    git add .
    git commit -m "initial commit after reset"
    git branch -D main
    git branch -m main
    git push -f origin main
    

    ํŠน์ • ํŒŒ์ผ๋งŒ ํžˆ์Šคํ† ๋ฆฌ์—์„œ ์™„์ „ํžˆ ์—†์• ๊ธฐ (.env์˜ ์˜ˆ)

    git filter-branch --force --index-filter "git rm --cached --ignore-unmatch .env" --prune-empty --tag-name-filter cat -- --all
    
    Created Wed, 17 Dec 2025 11:16:03 +0900