๐Ÿช Perl์˜ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋Šฅ๋ ฅ: ETL ํ”„๋กœ์„ธ์Šค ๊ตฌํ˜„ ๐Ÿš€

์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿช Perl์˜ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋Šฅ๋ ฅ: ETL ํ”„๋กœ์„ธ์Šค ๊ตฌํ˜„ ๐Ÿš€

 

 

์•ˆ๋…•ํ•˜์„ธ์š”, ๋ฐ์ดํ„ฐ ๋งˆ๋ฒ•์‚ฌ๋“ค! ์˜ค๋Š˜์€ Perl์ด๋ผ๋Š” ๊ฐ•๋ ฅํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•ด ETL(Extract, Transform, Load) ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ํฅ๋ฏธ์ง„์ง„ํ•œ ์—ฌ์ •์„ ๋– ๋‚˜๋ณผ ๊ฑฐ์˜ˆ์š”. ๐Ÿง™โ€โ™‚๏ธโœจ Perl์€ ๋งˆ์น˜ ์Šค์œ„์Šค ๊ตฐ์šฉ ์นผ์ฒ˜๋Ÿผ ๋‹ค์žฌ๋‹ค๋Šฅํ•˜๊ณ , ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์— ์žˆ์–ด์„œ๋Š” ์ง„์ •ํ•œ ์ฑ”ํ”ผ์–ธ์ด๋ž๋‹ˆ๋‹ค!

์—ฌ๋Ÿฌ๋ถ„, ํ˜น์‹œ ์žฌ๋Šฅ๋„ท์ด๋ผ๋Š” ๋ฉ‹์ง„ ์žฌ๋Šฅ ๊ณต์œ  ํ”Œ๋žซํผ์„ ๋“ค์–ด๋ณด์…จ๋‚˜์š”? ์ด ํ”Œ๋žซํผ์—์„œ๋Š” ๋‹ค์–‘ํ•œ ์žฌ๋Šฅ์„ ๊ฐ€์ง„ ์‚ฌ๋žŒ๋“ค์ด ๋ชจ์—ฌ ์„œ๋กœ์˜ ์ง€์‹๊ณผ ๊ธฐ์ˆ ์„ ๋‚˜๋ˆ„๊ณ  ์žˆ์–ด์š”. ์˜ค๋Š˜ ์šฐ๋ฆฌ๊ฐ€ ๋ฐฐ์šธ Perl๊ณผ ETL ํ”„๋กœ์„ธ์Šค ๊ตฌํ˜„ ๋Šฅ๋ ฅ๋„ ์žฌ๋Šฅ๋„ท์—์„œ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ‹์ง„ ์žฌ๋Šฅ์ด ๋  ์ˆ˜ ์žˆ๊ฒ ์ฃ ? ๐Ÿ˜‰

๐ŸŽญ ์ƒ์ƒํ•ด๋ณด์„ธ์š”: ์—ฌ๋Ÿฌ๋ถ„์ด ๊ฑฐ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ ์ฐฝ๊ณ ์˜ ๊ด€๋ฆฌ์ž๋ผ๊ณ  ๋ง์ด์—์š”. ๋งค์ผ ์ˆ˜๋งŽ์€ ํŠธ๋Ÿญ์ด ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฅผ ์‹ฃ๊ณ  ๋“ค์–ด์˜ค๊ณ , ์—ฌ๋Ÿฌ๋ถ„์€ ์ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„๋ฅ˜ํ•˜๊ณ , ์ •๋ฆฌํ•˜๊ณ , ํ•„์š”ํ•œ ๊ณณ์— ๋ฐฐ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋ฐ”๋กœ ETL ํ”„๋กœ์„ธ์Šค์˜ ๋ณธ์งˆ์ด์—์š”!

์ž, ์ด์ œ Perl์„ ์‚ฌ์šฉํ•ด ์ด ๋ณต์žกํ•œ ์ž‘์—…์„ ์–ด๋–ป๊ฒŒ ์‰ฝ๊ณ  ์žฌ๋ฏธ์žˆ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ์•„๋ณผ๊นŒ์š”? ์ค€๋น„๋˜์…จ๋‚˜์š”? ๊ทธ๋Ÿผ ์‹œ์ž‘ํ•ด๋ณผ๊นŒ์š”! ๐Ÿš€

๐Ÿซ Perl: ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์˜ ์Šˆํผํžˆ์–ด๋กœ

Perl์€ 1987๋…„์— ๋ž˜๋ฆฌ ์›”์ด ๋งŒ๋“  ๊ณ ๊ธ‰ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์ž…๋‹ˆ๋‹ค. ๊ทธ ์ด๋ฆ„์€ "Practical Extraction and Reporting Language"์˜ ์•ฝ์ž๋กœ, ์‹ค์šฉ์ ์ธ ์ถ”์ถœ๊ณผ ๋ณด๊ณ  ์–ธ์–ด๋ผ๋Š” ๋œป์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์š”. ์ด๋ฆ„๋งŒ ๋ด๋„ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์— ์–ผ๋งˆ๋‚˜ ํŠนํ™”๋˜์–ด ์žˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์ฃ ? ๐Ÿ˜Ž

Perl์˜ ํŠน์ง•์„ ๊ฐ„๋‹จํžˆ ์‚ดํŽด๋ณผ๊นŒ์š”?

  • ๐Ÿ” ๊ฐ•๋ ฅํ•œ ์ •๊ทœ ํ‘œํ˜„์‹ ์ง€์›: ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ์˜ ๋‹ฌ์ธ!
  • ๐Ÿ”ง ์œ ์—ฐํ•œ ๋ฌธ๋ฒ•: "There's more than one way to do it" (TMTOWTDI) ์ฒ ํ•™
  • ๐Ÿš€ ๋น ๋ฅธ ํ”„๋กœํ† ํƒ€์ดํ•‘: ์•„์ด๋””์–ด๋ฅผ ๋น ๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์š”
  • ๐ŸŒ ํฌ๋กœ์Šค ํ”Œ๋žซํผ ์ง€์›: ์–ด๋””์„œ๋“  ์‹คํ–‰ ๊ฐ€๋Šฅ!
  • ๐Ÿ“š ๋ฐฉ๋Œ€ํ•œ ๋ชจ๋“ˆ ์ƒํƒœ๊ณ„: CPAN(Comprehensive Perl Archive Network)์„ ํ†ตํ•ด ์ˆ˜๋งŽ์€ ๋ชจ๋“ˆ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

์ด๋Ÿฐ ํŠน์ง•๋“ค ๋•๋ถ„์— Perl์€ ETL ํ”„๋กœ์„ธ์Šค ๊ตฌํ˜„์— ์žˆ์–ด ์ตœ๊ณ ์˜ ์„ ํƒ์ง€ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋˜์—ˆ๋‹ต๋‹ˆ๋‹ค. ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ๋‹ค์–‘ํ•œ ์žฌ๋Šฅ์„ ๊ฐ€์ง„ ์‚ฌ๋žŒ๋“ค์„ ๋งŒ๋‚  ์ˆ˜ ์žˆ๋“ฏ์ด, Perl์„ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๊ธฐ์ˆ ์„ ๋งŒ๋‚˜๋ณผ ์ˆ˜ ์žˆ์–ด์š”!

๐Ÿ’ก ์žฌ๋ฏธ์žˆ๋Š” ์‚ฌ์‹ค: Perl์˜ ๋งˆ์Šค์ฝ”ํŠธ๋Š” ๋‚™ํƒ€(Camel)์˜ˆ์š”. ์™œ ๋‚™ํƒ€์ผ๊นŒ์š”? ๋‚™ํƒ€๊ฐ€ ์˜ค์•„์‹œ์Šค์—์„œ ์˜ค์•„์‹œ์Šค๋กœ ์ด๋™ํ•˜๋ฉฐ ์‚ฌ๋ง‰์„ ํšก๋‹จํ•˜๋“ฏ, Perl๋„ ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ฅผ ๋„˜๋‚˜๋“ค๋ฉฐ ์ •๋ณด๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋ž๋‹ˆ๋‹ค!

์ž, ์ด์ œ Perl์ด ์–ผ๋งˆ๋‚˜ ๋ฉ‹์ง„ ์–ธ์–ด์ธ์ง€ ์•Œ๊ฒŒ ๋˜์…จ์ฃ ? ๊ทธ๋Ÿผ ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ ETL ํ”„๋กœ์„ธ์Šค์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ณ , Perl๋กœ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์‚ดํŽด๋ณผ๊นŒ์š”? ๐Ÿ•ต๏ธโ€โ™‚๏ธ

๐Ÿ”„ ETL ํ”„๋กœ์„ธ์Šค: ๋ฐ์ดํ„ฐ์˜ ์—ฌํ–‰

ETL์€ Extract(์ถ”์ถœ), Transform(๋ณ€ํ™˜), Load(์ ์žฌ)์˜ ์•ฝ์ž๋กœ, ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ ์‹œ์Šคํ…œ์—์„œ ๋‹ค๋ฅธ ์‹œ์Šคํ…œ์œผ๋กœ ์ด๋™์‹œํ‚ค๋Š” ๊ณผ์ •์„ ๋งํ•ด์š”. ๋งˆ์น˜ ์š”๋ฆฌ์‚ฌ๊ฐ€ ์žฌ๋ฃŒ๋ฅผ ๊ณ ๋ฅด๊ณ (Extract), ์†์งˆํ•˜๊ณ (Transform), ์š”๋ฆฌํ•ด์„œ ์ ‘์‹œ์— ๋‹ด๋Š”(Load) ๊ณผ์ •๊ณผ ๋น„์Šทํ•˜๋‹ต๋‹ˆ๋‹ค! ๐Ÿณ

๊ฐ ๋‹จ๊ณ„๋ฅผ ์ž์„ธํžˆ ์‚ดํŽด๋ณผ๊นŒ์š”?

  1. Extract (์ถ”์ถœ) ๐Ÿ“ค: ๋‹ค์–‘ํ•œ ์†Œ์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋‹จ๊ณ„
  2. Transform (๋ณ€ํ™˜) ๐Ÿ”„: ์ถ”์ถœํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํ•„์š”ํ•œ ํ˜•ํƒœ๋กœ ๊ฐ€๊ณตํ•˜๋Š” ๋‹จ๊ณ„
  3. Load (์ ์žฌ) ๐Ÿ“ฅ: ๋ณ€ํ™˜๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชฉํ‘œ ์‹œ์Šคํ…œ์— ์ €์žฅํ•˜๋Š” ๋‹จ๊ณ„

์ด ๊ณผ์ •์€ ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ๋‹ค์–‘ํ•œ ์žฌ๋Šฅ์„ ๊ฐ€์ง„ ์‚ฌ๋žŒ๋“ค์˜ ์ •๋ณด๋ฅผ ์ˆ˜์ง‘ํ•˜๊ณ (Extract), ํ”Œ๋žซํผ์— ๋งž๊ฒŒ ์ •๋ฆฌํ•˜๊ณ (Transform), ์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ ๋ณด์—ฌ์ฃผ๋Š”(Load) ๊ณผ์ •๊ณผ ๋น„์Šทํ•˜๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ์–ด์š”!

ETL ํ”„๋กœ์„ธ์Šค ๋‹ค์ด์–ด๊ทธ๋žจ Extract Transform Load

ETL ํ”„๋กœ์„ธ์Šค๋Š” ๋ฐ์ดํ„ฐ ์›จ์–ดํ•˜์šฐ์Šค ๊ตฌ์ถ•, ๋ฐ์ดํ„ฐ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜, ์‹œ์Šคํ…œ ํ†ตํ•ฉ ๋“ฑ ๋‹ค์–‘ํ•œ ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉ๋ผ์š”. ๊ทธ๋ฆฌ๊ณ  ์ด ๋ชจ๋“  ๊ณผ์ •์„ Perl๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค! ๐Ÿ˜ƒ

๐ŸŽญ ์ƒ์ƒํ•ด๋ณด์„ธ์š”: ์—ฌ๋Ÿฌ๋ถ„์ด ๊ฑฐ๋Œ€ํ•œ ๋„์„œ๊ด€์˜ ์‚ฌ์„œ๋ผ๊ณ  ํ•ด๋ณผ๊นŒ์š”? ๋งค์ผ ์ƒˆ๋กœ์šด ์ฑ…๋“ค์ด ๋“ค์–ด์˜ค๊ณ (Extract), ์ด ์ฑ…๋“ค์„ ๋ถ„๋ฅ˜ํ•˜๊ณ  ์นดํƒˆ๋กœ๊ทธ๋ฅผ ๋งŒ๋“ค๊ณ (Transform), ์ ์ ˆํ•œ ์„œ๊ฐ€์— ๊ฝ‚์•„๋‘๋Š”(Load) ์ผ์„ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์„ธ์š”. ์ด๊ฒƒ์ด ๋ฐ”๋กœ ETL ํ”„๋กœ์„ธ์Šค์˜ ์‹ค์ œ ๋ชจ์Šต์ด์—์š”!

์ž, ์ด์ œ ETL ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์ดํ•ดํ•˜์…จ์ฃ ? ๊ทธ๋Ÿผ ์ด์ œ Perl์„ ์‚ฌ์šฉํ•ด ์ด ๊ณผ์ •์„ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์ž์„ธํžˆ ์•Œ์•„๋ณผ๊นŒ์š”? ์ค€๋น„๋˜์…จ๋‚˜์š”? Let's dive in! ๐ŸŠโ€โ™‚๏ธ

๐Ÿ“ค Extract: ๋ฐ์ดํ„ฐ ์ถ”์ถœ์˜ ๋งˆ๋ฒ•

ETL ํ”„๋กœ์„ธ์Šค์˜ ์ฒซ ๋‹จ๊ณ„์ธ Extract(์ถ”์ถœ)๋Š” ๋‹ค์–‘ํ•œ ์†Œ์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ณผ์ •์ด์—์š”. ์ด๋Š” ๋งˆ์น˜ ๋ณด๋ฌผ ์‚ฌ๋ƒฅ๊พผ์ด ์—ฌ๋Ÿฌ ์žฅ์†Œ์—์„œ ๋ณด๋ฌผ์„ ์ฐพ์•„๋‚ด๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•˜๋‹ต๋‹ˆ๋‹ค! ๐Ÿดโ€โ˜ ๏ธ๐Ÿ’Ž

Perl์€ ์ด ๋‹จ๊ณ„์—์„œ ์ •๋ง ๋น›์„ ๋ฐœํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ์†Œ์Šค์—์„œ ์ •๋ณด๋ฅผ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ๋“ค์„ ์ œ๊ณตํ•˜๊ฑฐ๋“ ์š”. ์–ด๋–ค ๊ธฐ๋Šฅ๋“ค์ด ์žˆ๋Š”์ง€ ์‚ดํŽด๋ณผ๊นŒ์š”?

1. ํŒŒ์ผ ์ฝ๊ธฐ ๐Ÿ“‚

Perl์€ ํŒŒ์ผ์„ ์ฝ๋Š” ๋ฐ ํƒ์›”ํ•œ ๋Šฅ๋ ฅ์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์š”. ํ…์ŠคํŠธ ํŒŒ์ผ, CSV, JSON, XML ๋“ฑ ๋‹ค์–‘ํ•œ ํ˜•์‹์˜ ํŒŒ์ผ์„ ์‰ฝ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ํ…์ŠคํŠธ ํŒŒ์ผ์„ ์ฝ๋Š” ๊ฐ„๋‹จํ•œ Perl ์ฝ”๋“œ๋ฅผ ๋ณผ๊นŒ์š”?


open(my $fh, '<', 'data.txt') or die "ํŒŒ์ผ์„ ์—ด ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค: $!";
while (my $line = <$fh>) {
    chomp $line;
    print "$line\n";
}
close($fh);
  

์ด ์ฝ”๋“œ๋Š” 'data.txt' ํŒŒ์ผ์„ ์—ด๊ณ , ๊ฐ ์ค„์„ ์ฝ์–ด ์ถœ๋ ฅํ•œ ๋’ค ํŒŒ์ผ์„ ๋‹ซ์•„์š”. ์ •๋ง ๊ฐ„๋‹จํ•˜์ฃ ? ๐Ÿ˜Š

2. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ๐Ÿ—„๏ธ

Perl์˜ DBI(Database Interface) ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์‰ฝ๊ฒŒ ์—ฐ๊ฒฐํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ์–ด์š”.

MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•˜๋Š” ์˜ˆ์ œ๋ฅผ ๋ณผ๊นŒ์š”?


use DBI;

my $dbh = DBI->connect("DBI:mysql:database=mydb;host=localhost", "user", "password")
    or die "๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์‹คํŒจ: " . DBI->errstr;

my $sth = $dbh->prepare("SELECT * FROM users");
$sth->execute();

while (my $row = $sth->fetchrow_hashref) {
    print "์ด๋ฆ„: $row->{name}, ์ด๋ฉ”์ผ: $row->{email}\n";
}

$sth->finish();
$dbh->disconnect();
  

์ด ์ฝ”๋“œ๋Š” MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์—ฐ๊ฒฐํ•˜์—ฌ 'users' ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ์ถœ๋ ฅํ•ด์š”. Perl์˜ DBI ๋ชจ๋“ˆ ๋•๋ถ„์— ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…์ด ์ •๋ง ์‰ฌ์›Œ์กŒ์ฃ ? ๐Ÿ‘จโ€๐Ÿ’ป

3. ์›น ์Šคํฌ๋ž˜ํ•‘ ๐Ÿ•ธ๏ธ

Perl์€ ์›น ์Šคํฌ๋ž˜ํ•‘์—๋„ ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด์š”. LWP::UserAgent์™€ HTML::TreeBuilder ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๋ฉด ์›น ํŽ˜์ด์ง€์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์‰ฝ๊ฒŒ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค.

๊ฐ„๋‹จํ•œ ์›น ์Šคํฌ๋ž˜ํ•‘ ์˜ˆ์ œ๋ฅผ ๋ณผ๊นŒ์š”?


use LWP::UserAgent;
use HTML::TreeBuilder;

my $ua = LWP::UserAgent->new;
my $response = $ua->get('https://www.example.com');

if ($response->is_success) {
    my $tree = HTML::TreeBuilder->new_from_content($response->decoded_content);
    my @links = $tree->look_down(_tag => 'a');
    
    foreach my $link (@links) {
        print $link->attr('href'), "\n";
    }
    
    $tree->delete;
} else {
    die "์›น ํŽ˜์ด์ง€๋ฅผ ๊ฐ€์ ธ์˜ค๋Š”๋ฐ ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค: " . $response->status_line;
}
  

์ด ์ฝ”๋“œ๋Š” ์›น ํŽ˜์ด์ง€๋ฅผ ๊ฐ€์ ธ์™€์„œ ๋ชจ๋“  ๋งํฌ(a ํƒœ๊ทธ)์˜ href ์†์„ฑ์„ ์ถœ๋ ฅํ•ด์š”. ์›น ํŽ˜์ด์ง€์—์„œ ์›ํ•˜๋Š” ์ •๋ณด๋ฅผ ์ถ”์ถœํ•˜๋Š” ๋ฐ ์•„์ฃผ ์œ ์šฉํ•˜๋‹ต๋‹ˆ๋‹ค! ๐Ÿ•ต๏ธโ€โ™‚๏ธ

๐Ÿ’ก Pro Tip: ์›น ์Šคํฌ๋ž˜ํ•‘์„ ํ•  ๋•Œ๋Š” ํ•ญ์ƒ ํ•ด๋‹น ์›น์‚ฌ์ดํŠธ์˜ robots.txt ํŒŒ์ผ์„ ํ™•์ธํ•˜๊ณ , ์›น์‚ฌ์ดํŠธ์˜ ์ด์šฉ ์•ฝ๊ด€์„ ์ค€์ˆ˜ํ•ด์•ผ ํ•ด์š”. ๊ทธ๋ฆฌ๊ณ  ๋„ˆ๋ฌด ๋นˆ๋ฒˆํ•œ ์š”์ฒญ์œผ๋กœ ์„œ๋ฒ„์— ๋ถ€๋‹ด์„ ์ฃผ์ง€ ์•Š๋„๋ก ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค!

์ด๋ ‡๊ฒŒ Perl์„ ์‚ฌ์šฉํ•˜๋ฉด ํŒŒ์ผ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, ์›น ๋“ฑ ๋‹ค์–‘ํ•œ ์†Œ์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์‰ฝ๊ฒŒ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ์–ด์š”. ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ๋‹ค์–‘ํ•œ ๋ถ„์•ผ์˜ ์ „๋ฌธ๊ฐ€๋“ค์„ ๋งŒ๋‚  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, Perl์„ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ฅผ ๋งŒ๋‚  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค! ๐Ÿ˜„

Extract ๋‹จ๊ณ„์—์„œ Perl์˜ ๊ฐ•๋ ฅํ•จ์„ ๋Š๋ผ์…จ๋‚˜์š”? ์ด์ œ ์šฐ๋ฆฌ๋Š” ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ์ถ”์ถœํ–ˆ์–ด์š”. ๋‹ค์Œ์€ ์ด ๋ฐ์ดํ„ฐ๋ฅผ ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” Transform ๋‹จ๊ณ„๋กœ ๋„˜์–ด๊ฐ€๋ณผ๊นŒ์š”? ์ค€๋น„๋˜์…จ๋‚˜์š”? Let's go! ๐Ÿš€

๐Ÿ”„ Transform: ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜์˜ ์—ฐ๊ธˆ์ˆ 

ETL ํ”„๋กœ์„ธ์Šค์˜ ๋‘ ๋ฒˆ์งธ ๋‹จ๊ณ„์ธ Transform(๋ณ€ํ™˜)์€ ์ถ”์ถœํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํ•„์š”ํ•œ ํ˜•ํƒœ๋กœ ๊ฐ€๊ณตํ•˜๋Š” ๊ณผ์ •์ด์—์š”. ์ด๋Š” ๋งˆ์น˜ ์š”๋ฆฌ์‚ฌ๊ฐ€ ์žฌ๋ฃŒ๋ฅผ ์†์งˆํ•˜๊ณ  ์กฐ๋ฆฌํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•˜๋‹ต๋‹ˆ๋‹ค! ๐Ÿ‘จโ€๐Ÿณโœจ

Perl์€ ์ด ๋‹จ๊ณ„์—์„œ๋„ ๋†€๋ผ์šด ๋Šฅ๋ ฅ์„ ๋ฐœํœ˜ํ•ด์š”. ๊ฐ•๋ ฅํ•œ ๋ฌธ์ž์—ด ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ๊ณผ ์ •๊ทœ ํ‘œํ˜„์‹ ์ง€์›, ๊ทธ๋ฆฌ๊ณ  ๋‹ค์–‘ํ•œ ๋‚ด์žฅ ํ•จ์ˆ˜๋“ค ๋•๋ถ„์— ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ ์ž‘์—…์„ ํšจ์œจ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค. ์–ด๋–ค ๊ธฐ๋Šฅ๋“ค์ด ์žˆ๋Š”์ง€ ์ž์„ธํžˆ ์‚ดํŽด๋ณผ๊นŒ์š”?

1. ๋ฌธ์ž์—ด ์ฒ˜๋ฆฌ ๐Ÿงต

Perl์€ ๋ฌธ์ž์—ด ์ฒ˜๋ฆฌ์— ์žˆ์–ด ํƒ€์˜ ์ถ”์ข…์„ ๋ถˆํ—ˆํ•˜๋Š” ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด์š”. ๋ฌธ์ž์—ด์„ ์ž๋ฅด๊ณ , ๋ถ™์ด๊ณ , ๋ฐ”๊พธ๋Š” ๋“ฑ์˜ ์ž‘์—…์„ ์•„์ฃผ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค.

๊ฐ„๋‹จํ•œ ๋ฌธ์ž์—ด ์ฒ˜๋ฆฌ ์˜ˆ์ œ๋ฅผ ๋ณผ๊นŒ์š”?


my $string = "Hello, World!";
print uc($string);  # ๋Œ€๋ฌธ์ž๋กœ ๋ณ€ํ™˜: HELLO, WORLD!
print lc($string);  # ์†Œ๋ฌธ์ž๋กœ ๋ณ€ํ™˜: hello, world!
print substr($string, 0, 5);  # ๋ถ€๋ถ„ ๋ฌธ์ž์—ด ์ถ”์ถœ: Hello
$string =~ s/World/Perl/;  # ๋ฌธ์ž์—ด ์น˜ํ™˜
print $string;  # ๊ฒฐ๊ณผ: Hello, Perl!
  

์ด๋ ‡๊ฒŒ Perl์€ ๋ฌธ์ž์—ด์„ ๋‹ค๋ฃจ๋Š” ๋‹ค์–‘ํ•œ ํ•จ์ˆ˜์™€ ์—ฐ์‚ฐ์ž๋ฅผ ์ œ๊ณตํ•ด์š”. ๋งˆ์น˜ ๋งˆ๋ฒ•์‚ฌ๊ฐ€ ์ฃผ๋ฌธ์„ ์™ธ์šฐ๋“ฏ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋ฌธ์ž์—ด์„ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค! ๐Ÿง™โ€โ™‚๏ธ

2. ์ •๊ทœ ํ‘œํ˜„์‹ ๐ŸŽญ

Perl์˜ ์ •๊ทœ ํ‘œํ˜„์‹(Regular Expression) ์ง€์›์€ ์ •๋ง ๊ฐ•๋ ฅํ•ด์š”. ๋ณต์žกํ•œ ํŒจํ„ด์˜ ๋ฌธ์ž์—ด์„ ์ฐพ๊ณ  ๋ณ€๊ฒฝํ•˜๋Š” ๋ฐ ์•„์ฃผ ์œ ์šฉํ•˜๋‹ต๋‹ˆ๋‹ค.

์ด๋ฉ”์ผ ์ฃผ์†Œ๋ฅผ ์ถ”์ถœํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์ •๊ทœ ํ‘œํ˜„์‹ ์˜ˆ์ œ๋ฅผ ๋ณผ๊นŒ์š”?


my $text = "์—ฐ๋ฝ์ฒ˜: john@example.com, mary@example.com";
while ($text =~ /(\S+@\S+)/g) {
    print "๋ฐœ๊ฒฌ๋œ ์ด๋ฉ”์ผ: $1\n";
}
  

์ด ์ฝ”๋“œ๋Š” ๋ฌธ์ž์—ด์—์„œ ์ด๋ฉ”์ผ ์ฃผ์†Œ ํŒจํ„ด์„ ์ฐพ์•„ ์ถœ๋ ฅํ•ด์š”. Perl์˜ ์ •๊ทœ ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ณต์žกํ•œ ํŒจํ„ด๋„ ์‰ฝ๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค! ๐Ÿ‘€

3. ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ๋ณ€ํ™˜ ๐Ÿ”€

Perl์€ ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์ง€์›ํ•˜๋ฉฐ, ์ด๋“ค ์‚ฌ์ด์˜ ๋ณ€ํ™˜๋„ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ์–ด์š”. ๋ฐฐ์—ด, ํ•ด์‹œ, ์ฐธ์กฐ ๋“ฑ์„ ์ž์œ ์ž์žฌ๋กœ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค.

JSON ๋ฐ์ดํ„ฐ๋ฅผ Perl์˜ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์˜ˆ์ œ๋ฅผ ๋ณผ๊นŒ์š”?


use JSON;

my $json_text = '{"name": "John", "age": 30, "city": "New York"}';
my $perl_data = decode_json($json_text);

print "์ด๋ฆ„: $perl_data->{name}\n";
print "๋‚˜์ด: $perl_data->{age}\n";
print "๋„์‹œ: $perl_data->{city}\n";

# ๋ฐ์ดํ„ฐ ์ˆ˜์ •
$perl_data->{country} = "USA";

# ๋‹ค์‹œ JSON์œผ๋กœ ๋ณ€ํ™˜
my $new_json = encode_json($perl_data);
print "์ƒˆ๋กœ์šด JSON: $new_json\n";
  

์ด ์ฝ”๋“œ๋Š” JSON ๋ฌธ์ž์—ด์„ Perl์˜ ํ•ด์‹œ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , ๋‹ค์‹œ JSON์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •์„ ๋ณด์—ฌ์ค˜์š”. Perl์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ํ˜•์‹ ์‚ฌ์ด์˜ ๋ณ€ํ™˜์ด ์ •๋ง ์‰ฌ์›Œ์ง„๋‹ต๋‹ˆ๋‹ค! ๐Ÿ”„

4. ๋ฐ์ดํ„ฐ ์ •์ œ ๋ฐ ํ‘œ์ค€ํ™” ๐Ÿงผ

๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ ๊ณผ์ •์—์„œ ์ค‘์š”ํ•œ ์ž‘์—… ์ค‘ ํ•˜๋‚˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ •์ œํ•˜๊ณ  ํ‘œ์ค€ํ™”ํ•˜๋Š” ๊ฒƒ์ด์—์š”. Perl์€ ์ด๋Ÿฐ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋‹ค์–‘ํ•œ ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์ „ํ™”๋ฒˆํ˜ธ๋ฅผ ํ‘œ์ค€ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์˜ˆ์ œ๋ฅผ ๋ณผ๊นŒ์š”?


sub standardize_phone {
    my $phone = shift;
    $phone =~ s/\D//g;  # ์ˆซ์ž๊ฐ€ ์•„๋‹Œ ๋ชจ๋“  ๋ฌธ์ž ์ œ๊ฑฐ
    if (length($phone) == 10) {
        return substr($phone, 0, 3) . "-" . substr($phone, 3, 3) . "-" . substr($phone, 6);
    }
    return $phone;  # 10์ž๋ฆฌ๊ฐ€ ์•„๋‹ˆ๋ฉด ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜
}

my @phones = ("123-456-7890", "(987) 654-3210", "0");
foreach my $phone (@phones) {
    print standardize_phone($phone), "\n";
}
  

์ด ์ฝ”๋“œ๋Š” ๋‹ค์–‘ํ•œ ํ˜•์‹์˜ ์ „ํ™”๋ฒˆํ˜ธ๋ฅผ ํ‘œ์ค€ ํ˜•์‹(XXX-XXX-XXXX)์œผ๋กœ ๋ณ€ํ™˜ํ•ด์š”. ์ด๋ ‡๊ฒŒ Perl์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค! โœจ

๐Ÿ’ก Pro Tip: ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ ์ž‘์—…์„ ํ•  ๋•Œ๋Š” ํ•ญ์ƒ ์›๋ณธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์กดํ•˜๊ณ , ๋ณ€ํ™˜๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ„๋„๋กœ ์ €์žฅํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋‚˜์ค‘์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์„ ๋•Œ ์›๋ณธ์œผ๋กœ ๋Œ์•„๊ฐˆ ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค!

์ด๋ ‡๊ฒŒ Perl์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•˜๊ณ  ๊ฐ€๊ณตํ•  ์ˆ˜ ์žˆ์–ด์š”. ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ๋‹ค์–‘ํ•œ ์žฌ๋Šฅ์„ ๊ฐ€์ง„ ์‚ฌ๋žŒ๋“ค์ด ์ž์‹ ์˜ ๊ธฐ์ˆ ์„ ๋‹ค๋“ฌ๊ณ  ๋ฐœ์ „์‹œํ‚ค๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, Perl์„ ํ†ตํ•ด ์šฐ๋ฆฌ์˜ ๋ฐ์ดํ„ฐ๋„ ๋”์šฑ ๊ฐ€์น˜ ์žˆ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค! ๐Ÿ˜„

Transform ๋‹จ๊ณ„์—์„œ Perl์˜ ๊ฐ•๋ ฅํ•จ์„ ๋Š๋ผ์…จ๋‚˜์š”? ์ด์ œ ์šฐ๋ฆฌ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์›ํ•˜๋Š” ํ˜•ํƒœ๋กœ ์„ฑ๊ณต์ ์œผ๋กœ ๋ณ€ํ™˜ํ–ˆ์–ด์š”. ๋‹ค์Œ์€ ์ด ๋ณ€ํ™˜๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชฉํ‘œ ์‹œ์Šคํ…œ์— ์ €์žฅํ•˜๋Š” Load ๋‹จ๊ณ„๋กœ ๋„˜์–ด๊ฐ€๋ณผ๊นŒ์š”? ์ค€๋น„๋˜์…จ๋‚˜์š”? Let's move on! ๐Ÿš€

๐Ÿ“ฅ Load: ๋ฐ์ดํ„ฐ์˜ ์ƒˆ๋กœ์šด ๋ณด๊ธˆ์ž๋ฆฌ

ETL ํ”„๋กœ์„ธ์Šค์˜ ๋งˆ์ง€๋ง‰ ๋‹จ๊ณ„์ธ Load(์ ์žฌ)๋Š” ๋ณ€ํ™˜๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชฉํ‘œ ์‹œ์Šคํ…œ์— ์ €์žฅํ•˜๋Š” ๊ณผ์ •์ด์—์š”. ์ด๋Š” ๋งˆ์น˜ ์šฐ๋ฆฌ๊ฐ€ ์ •์„ฑ์Šค๋Ÿฝ๊ฒŒ ์ค€๋น„ํ•œ ์š”๋ฆฌ๋ฅผ ์†๋‹˜๋“ค์˜ ์‹ํƒ์— ๋‚ด๋†“๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ต๋‹ˆ๋‹ค! ๐Ÿฝ๏ธ

Perl์€ ์ด ๋‹จ๊ณ„์—์„œ๋„ ๋›ฐ์–ด๋‚œ ์„ฑ๋Šฅ์„ ๋ณด์—ฌ์ค˜์š”. ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‹œ์Šคํ…œ๊ณผ์˜ ์—ฐ๋™, ํŒŒ์ผ ์‹œ์Šคํ…œ ์กฐ์ž‘, ๋„คํŠธ์›Œํฌ ํ†ต์‹  ๋“ฑ์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ ์žฌํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค. ์–ด๋–ค ๋ฐฉ๋ฒ•๋“ค์ด ์žˆ๋Š”์ง€ ์ž์„ธํžˆ ์‚ดํŽด๋ณผ๊นŒ์š”?

1. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ์žฌ ๐Ÿ’พ

Perl์˜ DBI ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‹œ์Šคํ…œ์— ๋ฐ์ดํ„ฐ๋ฅผ ์‰ฝ๊ฒŒ ์ ์žฌํ•  ์ˆ˜ ์žˆ์–ด์š”.

MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ์ดํ„ฐ๋ฅผ ์ ์žฌํ•˜๋Š” ์˜ˆ์ œ๋ฅผ ๋ณผ๊นŒ์š”?


use DBI;

my $dbh = DBI->connect("DBI:mysql:database=mydb;host=localhost", "user", "password")
    or die "๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์‹คํŒจ: " . DBI->errstr;

my $sth = $dbh->prepare("INSERT INTO users (name, email, age) VALUES (?, ?, ?)");

my @users = (
    ["John Doe", "john@example.com", 30],
    ["Jane Smith",