๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿš€ Development/AWS(Amazon Web Services)

PySpark(ํŒŒ์ด์ŠคํŒŒํฌ)์˜ AWS Glue(๊ธ€๋ฃจ) ETL ๋ž€?

by Jay Din 2024. 2. 19.
728x90
๋ฐ˜์‘ํ˜•

AWS Glue(๊ธ€๋ฃจ) ๋ž€?

https://d2908q01vomqb2.cloudfront.net/b6692ea5df920cad691c20319a6fffd7a4a766b8/2022/05/24/Blogimage-1024x896.png

 

AWS Glue๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœ, ๋ณ€ํ™˜, ๋กœ๋“œ(ETL)ํ•˜๊ธฐ ์œ„ํ•œ ์™„์ „ ๊ด€๋ฆฌํ˜• ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค.

Glue๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ ์›จ์–ดํ•˜์šฐ์Šค, ๋ฐ์ดํ„ฐ ๋ ˆ์ดํฌ, ๋ถ„์„์šฉ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋“ฑ ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ ๊ฐ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ด๋™ํ•˜๊ณ  ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

PySpark ๋ž€?

Glue์˜ PySpark๋Š” Python API์ธ PySpark๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

PySpark๋Š” Apache Spark์˜ Python API๋กœ, ๋ถ„์‚ฐํ˜• ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋ฐ ๋ถ„์„์„ ์œ„ํ•œ ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

Glue์˜ PySpark๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Python์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์ž‘์—…์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

Glue์˜ PySpark ์ฃผ์š” ๊ธฐ๋Šฅ

  1. ๋ฐ์ดํ„ฐ ์ถ”์ถœ(Extract):
    • Glue์˜ PySpark๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ์†Œ์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด, Amazon S3, RDS, Redshift, DynamoDB ๋“ฑ์˜ AWS ์„œ๋น„์Šค ๋ฐ JDBC ํ˜ธํ™˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋“ฑ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜(Transform):
    • PySpark๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. PySpark๋Š” ๊ฐ•๋ ฅํ•œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋ฐ ๋ถ„์„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, ๋ฐ์ดํ„ฐ๋ฅผ ํ•„ํ„ฐ๋งํ•˜๊ณ  ๋ณ€ํ™˜ํ•˜๋ฉฐ, ์ง‘๊ณ„ ๋ฐ ๋ถ„์„ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  3. ๋ฐ์ดํ„ฐ ๋กœ๋“œ(Load):
    • Glue์˜ PySpark๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณ€ํ™˜๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์–‘ํ•œ ํ˜•์‹์œผ๋กœ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด, Amazon S3์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ฑฐ๋‚˜, Redshift, RDS ๋“ฑ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  4. ์Šค์ผ€์ค„๋ง ๋ฐ ์ž๋™ํ™”:
    • Glue์˜ PySpark๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ETL ์ž‘์—…์„ ์Šค์ผ€์ค„๋งํ•˜๊ณ  ์ž๋™ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ฃผ๊ธฐ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœ, ๋ณ€ํ™˜, ๋กœ๋“œํ•˜์—ฌ ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ์ž๋™ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋ฐ์ดํ„ฐ ๋ถ„์„ ์ž‘์—… ์ข…๋ฅ˜

  • ์ง‘๊ณ„ ๋ฐ ๊ทธ๋ฃนํ™”:
    • ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋ฃนํ™”ํ•˜๊ณ  ์ง‘๊ณ„ํ•˜์—ฌ ์š”์•ฝ ํ†ต๊ณ„๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด, ํŠน์ • ๊ธฐ๊ฐ„ ๋™์•ˆ์˜ ๋งค์ถœ์„ ํ•ฉ์‚ฐํ•˜๊ฑฐ๋‚˜, ์ง€์—ญ๋ณ„ ๊ณ ๊ฐ ์ˆ˜๋ฅผ ์ง‘๊ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ •๋ ฌ ๋ฐ ํ•„ํ„ฐ๋ง:
    • ๋ฐ์ดํ„ฐ๋ฅผ ์ •๋ ฌํ•˜๊ฑฐ๋‚˜ ํŠน์ • ์กฐ๊ฑด์— ๋”ฐ๋ผ ํ•„ํ„ฐ๋งํ•˜์—ฌ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด, ํŠน์ • ๊ฐ€๊ฒฉ ๋ฒ”์œ„ ๋‚ด์˜ ์ œํ’ˆ์„ ์ฐพ๊ฑฐ๋‚˜, ํŠน์ • ๋‚ ์งœ ์ดํ›„์˜ ์ฃผ๋ฌธ์„ ํ•„ํ„ฐ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฐ์ดํ„ฐ ๊ฒฐํ•ฉ:
    • ์—ฌ๋Ÿฌ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ฅผ ๊ฒฐํ•ฉํ•˜๊ณ  ์กฐ์ธํ•˜์—ฌ ๋” ๋ณต์žกํ•œ ๋ถ„์„์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ณ ๊ฐ ์ •๋ณด์™€ ์ฃผ๋ฌธ ์ •๋ณด๋ฅผ ๊ฒฐํ•ฉํ•˜์—ฌ ๊ณ ๊ฐ๋ณ„ ๋งค์ถœ์„ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์‹œ๊ณ„์—ด ๋ถ„์„:
    • ์—ฌ๋Ÿฌ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ฅผ ๊ฒฐํ•ฉํ•˜๊ณ  ์กฐ์ธํ•˜์—ฌ ๋” ๋ณต์žกํ•œ ๋ถ„์„์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ณ ๊ฐ ์ •๋ณด์™€ ์ฃผ๋ฌธ ์ •๋ณด๋ฅผ ๊ฒฐํ•ฉํ•˜์—ฌ ๊ณ ๊ฐ๋ณ„ ๋งค์ถœ์„ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋จธ์‹  ๋Ÿฌ๋‹ ๋ฐ ์˜ˆ์ธก:
    • PySpark๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋จธ์‹  ๋Ÿฌ๋‹ ๋ชจ๋ธ์„ ๊ตฌ์ถ•ํ•˜๊ณ  ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์˜ˆ์ธก์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ณ ๊ฐ์˜ ๊ตฌ๋งค ์ด๋ ฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋‹ค์Œ์— ์ œํ’ˆ์„ ์˜ˆ์ธกํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํ…์ŠคํŠธ ๋ถ„์„:
    • ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„์„ํ•˜์—ฌ ์ฃผ์š” ๋‹จ์–ด ๋นˆ๋„, ๊ฐ์„ฑ ๋ถ„์„, ์ฃผ์ œ ๋ชจ๋ธ๋ง ๋“ฑ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ณ ๊ฐ ๋ฆฌ๋ทฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„์„ํ•˜์—ฌ ์ œํ’ˆ์— ๋Œ€ํ•œ ๊ธ์ •์  ๋˜๋Š” ๋ถ€์ •์ ์ธ ํ”ผ๋“œ๋ฐฑ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ทธ๋ž˜ํ”„ ๋ถ„์„:
    • ๊ทธ๋ž˜ํ”„ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„์„ํ•˜์—ฌ ๋„คํŠธ์›Œํฌ ๊ตฌ์กฐ, ์ค‘์‹ฌ์„ฑ ์ง€ํ‘œ, ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ฐ์ง€ ๋“ฑ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด, ์†Œ์…œ ๋„คํŠธ์›Œํฌ์—์„œ ์‚ฌ์šฉ์ž ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ๋ถ„์„ํ•˜๊ณ  ์ค‘์š”ํ•œ ์˜ํ–ฅ๋ ฅ ์žˆ๋Š” ์‚ฌ์šฉ์ž๋ฅผ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

728x90

 

Glue์˜ PySpark ์‚ฌ์šฉ ์˜ˆ์‹œ

  • ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜:
    • PySpark๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JSON ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด๋“ค์—ฌ์„œ ํ•„์š”ํ•œ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฐ์ดํ„ฐ๋ฅผ ํ•„ํ„ฐ๋งํ•˜๊ฑฐ๋‚˜ ์ง‘๊ณ„ํ•˜์—ฌ ๋ถ„์„์— ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋‹ค์ค‘ ๋ฐ์ดํ„ฐ ์†Œ์Šค ๊ฐ„์˜ ๋ฐ์ดํ„ฐ ์ด๋™:
    • Glue์˜ PySpark๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ์†Œ์Šค ๊ฐ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ด๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด, RDS์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•˜์—ฌ ๋ณ€ํ™˜ํ•œ ํ›„์— Amazon S3์— ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฐ์ดํ„ฐ ์ง‘๊ณ„ ๋ฐ ๋ถ„์„:
    • PySpark๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ง‘๊ณ„ํ•˜๊ณ  ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด, ๋กœ๊ทธ ๋ฐ์ดํ„ฐ์—์„œ ์‚ฌ์šฉ์ž์˜ ํ–‰๋™ ํŒจํ„ด์„ ๋ถ„์„ํ•˜๊ฑฐ๋‚˜, ํŒ๋งค ๋ฐ์ดํ„ฐ์—์„œ ๋งค์ถœ์„ ์ง‘๊ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

Glue์˜ PySpark ์ฝ”๋“œ ์‚ฌ์šฉ ์˜ˆ์‹œ

๊ฐ€์ •:

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

 

1. ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ:

  • ๋จผ์ €, PySpark๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Amazon S3์— ์ €์žฅ๋œ CSV ํŒŒ์ผ์„ ์ฝ์–ด ๋“ค์ž…๋‹ˆ๋‹ค.
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from pyspark.sql import SparkSession

sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session

# S3์— ์ €์žฅ๋œ CSV ํŒŒ์ผ์„ ์ฝ์–ด ๋“ค์ž…๋‹ˆ๋‹ค.
sales_data = spark.read.format("csv") \
    .option("header", "true") \
    .load("s3://bucket_name/path/to/sales_data.csv")

 

2. ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜:

  • ๋‹ค์Œ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ํ•„ํ„ฐ๋งํ•˜๊ณ  ํ•„์š”ํ•œ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ๋‚ ์งœ ๋ฒ”์œ„ ๋‚ด์˜ ๋ฐ์ดํ„ฐ๋งŒ ์„ ํƒํ•˜๊ณ , ๋งค์ถœ์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.
from pyspark.sql.functions import col, sum

# ๋‚ ์งœ ๋ฒ”์œ„ ๋‚ด์˜ ๋ฐ์ดํ„ฐ ํ•„ํ„ฐ๋ง
filtered_data = sales_data.filter((col("date") >= "2023-01-01") & (col("date") <= "2023-12-31"))

# ๋งค์ถœ ๊ณ„์‚ฐ
total_sales = filtered_data.select(sum(col("sales_amount")).alias("total_sales"))

 

3. ๊ฒฐ๊ณผ ์ €์žฅ:

  • ๋งˆ์ง€๋ง‰์œผ๋กœ, ๊ณ„์‚ฐ๋œ ๊ฒฐ๊ณผ๋ฅผ ์›ํ•˜๋Š” ํ˜•์‹์œผ๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ์ƒˆ๋กœ์šด CSV ํŒŒ์ผ์„๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
# ๊ณ„์‚ฐ๋œ ๊ฒฐ๊ณผ๋ฅผ CSV ํŒŒ์ผ๋กœ ์ €์žฅ
total_sales.write.format("csv").mode("overwrite").save("s3://bucket_name/path/to/total_sales_result")

 

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Glue์˜ PySpark๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ณ  ๋ณ€ํ™˜ํ•˜๊ณ  ์ €์žฅํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์˜ˆ์‹œ๋ฅผ ์‚ดํŽด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ž‘์—…์€ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋ฐ ๋ถ„์„์„ ์ž๋™ํ™”ํ•˜๊ณ  ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

 

 

728x90
๋ฐ˜์‘ํ˜•