β λμ΄ λ§μΌλ©΄ μ°Ύμ§ λͺ»ν λ²κ·Έλ μλ€. β
- Eric Steven Raymond
μ€ν μμ€μ κ±°μ₯

Athena μ±λ₯ ν₯μ μ λ΅
Athena(μν λ)λ μλ²λ¦¬μ€ μλΉμ€λ‘μ, μ€νν 쿼리μ λν λΉμ©μ μ§λΆνλ©΄ λλ€.
μκΈμ μ€νν μΏΌλ¦¬κ° μ€μΊν λ°μ΄ν°μ μ©λλ§νΌ λΉμ©μ΄ μ²κ΅¬λλ€.
νμ§λ§ μ€νν 쿼리μ λ°μ΄ν° μ©λμ΄ μ΄λ§λ¬΄μνλ©΄ μ무리 μ¨λλ©λ νμμΌ μ§λΌλ μκΈμ΄ λ§μ΄ λ€κ² λλ€.
λ°λΌμ μ μ ν λ°μ΄ν° μμΆκ³Ό νν°μ λμ νμ¬, μ€μΊνλ λ°μ΄ν°μ μμ μ νν΄ λΉμ©μ μ κ°ν μ μλ μ λ΅μΌλ‘ λμκ°μΌ νλ€.
λ°μ΄ν° νν°μ λ
μ©λμ΄ ν° ν μ΄λΈμ΄λ μΈλ±μ€λ₯Ό κ΄λ¦¬νκΈ° μ¬μ΄ νν°μ (partition)μ΄λΌλ μμ λ¨μλ‘ λΆν νλ κ²
μν λλ₯Ό μ¬μ©νκΈ° μν ν μ΄λΈ μμ±(CREATE)μ΄λ νν°μ λμ μν ν μ΄λΈ μμ (ALTER)κ³Ό κ°μ DDLλ¬Έκ³Ό μ€ν¨ν 쿼리문μ λν λΉμ©μ μ²κ΅¬λμ§ μλλ€.
λ°μ΄ν° μμΆ
Athenaμ λΉμ©μ μ€μΊν λ°μ΄ν°μ ν¬κΈ°λ₯Ό κΈ°μ€μΌλ‘ λ°μνλ€.
λ°λΌμ μν λλ₯Ό μ΄μ©ν λλ, S3μ μλ λ‘κ·Έ λ°μ΄ν°λ₯Ό μμΆν΄ λκ³ μ μ₯νλ κ²μ κΆμ₯νλ€.
νμΌ μ©λμ΄ μμΌλ©΄ λ€νΈμν¬ λΉμ© κ°μ, 쿼리μλ ν₯μ, μ€μΊλλ λ°μ΄ν°μ ν¬κΈ° κ°μλμ΄ λΉμ©μ κ° λ± μ»λ κ²μ΄ λ§κΈ° λλ¬Έμ΄λ€.
Athenaκ° μΈμ κ°λ₯ν μμΆ ν¬λ§·μ λ§ν¬ λ° μλ μ¬μ§μ μ°Έκ³ νλ€.
- snappy : Parquet λ°μ΄ν° μ€ν λ¦¬μ§ νμμ νμΌμ λν κΈ°λ³ΈμμΆνμ
- zlip : ORC λ°μ΄ν°μ€ν λ¦¬μ§ νμμ νμΌμ λν κΈ°λ³ΈμμΆνμ
- gzip : λ°μ΄ν°νμΌμ .gzνμ₯νλ‘κ·Έλ¨ μ¬μ©, λν΄νΈ κ°

Athena μμΆ μ§μ - Amazon Athena
Athena μμΆ μ§μ Athenaλ μ¬λ¬ μμΆ νμμ μ¬μ©νλ ν μ΄λΈμμ λ°μ΄ν°λ₯Ό μ½λ κ²μ λΉλ‘―νμ¬, λ°μ΄ν° μ½κΈ° λ° μ°κΈ°λ₯Ό μν λ€μν μμΆ νμμ μ§μν©λλ€. μλ₯Ό λ€μ΄ Athenaλ μΌλΆ Parquet νμΌμ΄
docs.aws.amazon.com
λ°μ΄ν° μμΆ μ€μ νκΈ°
μμΆμ μ§μνλ€κ³ νμΌλ μ€μ μ μ©ν΄λ³΄μ.
μμΆ νμμ TBLPROPERTIES μμ±μΌλ‘ μ§μ ν μ μλ€.
CREATEλ¬Έμ΄λ ALTER λ¬Έμ TBLPROPERTIES μμ±μΌλ‘ orc.compressλ parquet.compression κ°μ μ£Όκ³ μμΆ νμμ μ§μ ν΄μ£Όλ©΄ λλ€.
CREATE EXTERNAL TABLE IF NOT EXISTS test.myjson2 (
`time` STRING,
`user_id` STRING,
`board_name` STRING,
`action` STRING
)
LOCATION 's3://athena-log-test-11/jsonTest'
TBLPROPERTIES("PARQUET.COMPRESS"="GZIP"); -- GZIPμΌλ‘ μ€μ
ALTER TABLE test.myjson SET TBLPROPERTIES("PARQUET.COMPRESS"="GZIP");
ALTER TABLE SET TBLPROPERTIES - Amazon Athena
Thanks for letting us know this page needs work. We're sorry we let you down. If you've got a moment, please tell us how we can make the documentation better.
docs.aws.amazon.com
ν μ΄λΈμ μμ ν΄μ£Όκ³ TBLPROPERTIES μμ±μ μ‘°νν΄λ³΄λ©΄ GZIPμ΄ μ μ©λ κ±Έ νμΈν μ μλ€.
SHOW TBLPROPERTIES test.myjson('parquet.compression');

νΉμ AWS GLUEμμλ νμΈμ΄ κ°λ₯νλ€.
AWS Glue μλΉμ€
AWS Glueλ μμ κ΄λ¦¬ν ETL(μΆμΆ, λ³ν λ° λ‘λ) μλΉμ€λ‘, κ°λ¨νκ² μ¬λ¬ λ°μ΄ν° μ€ν μ΄ λ° μ€νΈλ¦Ό κ°μ μνλ λ°μ΄ν°λ₯Ό λΆλ₯, μ 리, 보κ°, μ΄λνλ€. EC2κ° μΈμ€ν΄μ€(μ»΄ν¨ν )μ λͺ¨μλμ κ²μ΄κ³ , λλ€κ° ν¨μλ€μ λͺ¨μλμ κ²μ΄λΌλ©΄, Glueλ λ°μ΄ν°λ€μ λͺ¨μμ κ΄λ¦¬νλ€κ³ 보면 λλ€.



λ°μ΄ν° νν°μ λ
λ°μ΄ν° νν°μ λ(Data Partitioning)μ΄λ, λ°μ΄ν°λ₯Ό λΆν μ μ₯νμ¬ μ‘°κ±΄μ λ°λΌ μΌλΆ λ°μ΄ν°λ§ κ²μν μ μλλ‘ νλ κΈ°λ²μ΄λ€
κ·Έλμ S3μ μμΈ λ§μ λ‘κ·Έλ₯Ό μ‘°νν λ, νν°μ λμ νμ§ μμΌλ©΄ μν λ 쿼리λ λͺ¨λ λ°μ΄ν°λ₯Ό μ€μΊνκ² λμ§λ§, νν°μ λμ ν΅ν΄ μΏΌλ¦¬λΉ μ€μΊνλ λ°μ΄ν°μ μμ μ€μ¬ μ±λ₯μ ν₯μμν€κ³ , λΉμ©μ μ κ°ν μ μλ€.
νν°μ λμ μ μ ν ν΄μ£Όλ©΄ ν μ΄λΈ μ‘°ν 쿼리 μ€ν μκ°μ΄ 3~5λΆμμ 5μ΄λ‘ μ κ°λλ μΌμ΄μ€κ° μμ μ λμ΄λ€.
κ·Έλμ μν λλ₯Ό μ¬μ©ν λ νν°μ λμ νμλ‘ νλ κ²μ΄ μ’λ€.
λ³΄ν΅ νν°μ λ(partitioning)μ λ μ§κΈ°μ€μΌλ‘ μΏΌλ¦¬κ° μ€μΊνλ λ²μλ₯Ό μ ννλ νΈμ΄λ€.
μλ₯Όλ€μ΄ 2022λ 7μ 1μΌμ λ‘κ·Έ λ°μ΄ν°λ₯Ό μμ§ν λ, 10λ μΉ λ‘κ·Έκ° μμ¬μλ νκ°μ ν΄λμμ μ°Ύμ κ²½μ° 10λ μΉ λ‘κ·Έλ₯Ό λͺ¨λ μ€μΊν΄μΌνμ§λ§, λ‘κ·Έκ° κ° λ ,μ,μΌλ‘ λΆν λμ΄ μλ ν΄λμμ μ°Ύμ κ²½μ°μ bucket/2022/7/1 ν΄λμ μλ λ‘κ·Έλ§ μ€μΊνλ©΄ λλ€.
νν°μ λμ μλμΌλ‘ 맡ννλ λ°©λ²κ³Ό μλμΌλ‘ 맡ννλ λ°©λ²μ΄ μλ€.
λ§μ½ μ΄λ―Έ S3 λ²ν·μ λ‘κ·Έκ° μμ¬μ Έ μμΌλ©΄ λ μ€μ μμ μ S3 ꡬ쑰μ λ§λ λ°©λ²μ μ¬μ©νλ©΄ λκ³ , μμ§ λ‘κ·Έκ° μμ¬μ§ μμ μνλΌλ©΄ μλ 맡ν ꡬ쑰μ λ§κ² λ°μ΄ν°λ₯Ό μ μ¬νλ©΄ νΈλ¦¬νλ€.
μλ 맡ν
λ°μ΄ν°νν°μ λμ μν μλ맀ν κ΅¬μ‘°μΌ κ²½μ°, 곡μλ¬Έμμμ λ²ν·μμ μλμ κ°μ κ΅¬μ‘°λ‘ νμΌμ΄ μμΉν΄μΌ λλ€κ³ λ§νλ€.
S3://your-bucket/pathToTable/<PARTITION_COLUMN_NAME>=<VALUE>/<PARTITION_COLUMN_NAME>=<VALUE>/
μλ₯Όλ€λ©΄ μλμ κ°μ΄ λ²ν·/ν€ κ΅¬μ‘°λ‘ λμ΄ μμ΄μΌ νλ€.
S3://my-bucket/log-data/year=2019/month=3/day=7
μλμ κ°μ κ΅¬μ‘°λ‘ λμ΄ μλ€λ©΄ year, month, dayκ° νν°μ 컬λΌμ΄ λλ€.
μΏΌλ¦¬κ° κ°λ₯νλλ‘ κ΅¬μ‘°λ§ λκ°μ΄ νλ©΄ λκ³ μ»¬λΌλͺ κ³Ό νμμ λ¬λΌλ λλ€.
π€ μ΄κ² λΉμ΅ 무μ¨λ§μΈμ§ λμ ν λͺ¨λ₯΄κ² λ€λ©΄, λ°λ‘ μ€μ μ λμ νλλ‘ νμ.
S3μ λ€μκ³Ό κ°μ΄ csv νμΌμ΄ 3κ°κ° μκ³ , μ΄ λ²ν· κ²½λ‘λ₯Ό Athena(μν λ)λ‘ λ§΅ν μμΌ ν μ΄λΈλ‘ λ§λ€μ΄ λμλ€κ³ κ°μ νμ. κ° csv νμΌλΉ 10κ°μ λ°μ΄ν°κ° μλ€.

λ²ν·μ νμ¬ μ μ₯λμ΄ μλ csv νμΌμ΄ 3κ°μΈλ° count 쿼리λ₯Ό μ€ννλ©΄ 30κ°κ° λμ€λλ°, Data scannedκ³Ό 3κ° csv νμΌ μ¬μ΄μ¦μ ν©μ΄ λμΌν¨μ νμΈν μ μλ€.
λ§μΌ sample3.csvμλ§ μλ λ°μ΄ν°λ₯Ό μ‘°νν νμκ° μμλ, μ μ ν SQLλ¬Έμ 쿼리νλ©΄ μνλ κ²°κ³Όλ μ»μμ§μΈμ μν λλ λ²ν· κ²½λ‘λ₯Ό κΈ°μ€μΌλ‘ 맀ννμ§ λλ¬Έμ 쿼리 μ€νμλ§λ€ λͺ¨λ csv νμΌμ κ²μνκ² λλ€.

μ¦, csv νμΌμ΄ λλμ΄μ Έμμμ λΆκ΅¬νκ³ μν λλ μ΄λ₯Ό νλμ νμΌλ‘ μ³μ λ°μλλ λ¬Έμ μΈ κ²μ΄λ€.
μ΄λ 곧 λΉμ©μ΄λ―λ‘ μ‘°κ±΄μ λ°λΌ μΌλΆ csv νμΌλ§ κ²μνλλ‘ partitioning μ ν΄λ³΄μ.
μ΄λ₯Ό μν΄μλ μλ μμ μ μνν΄μΌ νλ€.
- csv νμΌμ λλ ν 리λ³λ‘ κ·Έλ£Ήν ν΄μ μ μ₯
- λλ ν 리λͺ μ partition 쑰건μΌλ‘ νμ©
λ€μκ³Ό κ°μ΄ λ²ν· λλ ν 리λ₯Ό λ λλ³, μλ³, μΌλ³ λ‘ λλκ³ κ° μΌλ³ ν΄λμ csv νμΌμ μμΉμν¨λ€.




μ΄λ κ² λ²ν· ν΄λ λ³λ‘ ν€(νμΌ)μ΄ μμΉν μνμμ, ν μ΄λΈ μμ± μ νν°μ 컬λΌμ μ€μ ν΄ μ€ μ μλ€.
CREATE EXTERNAL TABLE IF NOT EXISTS test.mycsv_partition (
`time` STRING,
`user_id` STRING,
`board_name` STRING,
`action` STRING
)
PARTITIONED BY (year string, month string, day string) -- νν°μ
μΆκ°
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
ESCAPED BY '\\'
LINES TERMINATED BY '\n'
LOCATION 's3://athena-log-test-11/csvTest/'
TBLPROPERTIES ('skip.header.line.count'='1');

ν μ΄λΈ μμ±νμΌλ©΄, μλμΌλ‘ νν°μ μ μ§μ ν μ μλλ‘ μλμ λͺ λ Ή μννλ€.
MSCK REPAIR TABLE test.mycsv_partition;

ν μ΄λΈ νλλ₯Ό μ 체 μ‘°νν΄λ³΄λ©΄, μ°μΈ‘μ μλ‘μ΄ νλκ° μΆκ°λ¬μμ νμΈ ν μ μλ€.
λ°λ‘ μ΄ μΆκ°λ νν°μ νλλ₯Ό μ΄μ©ν΄μ 쑰건 κ²μμ νλ©΄ λλ κ²μ΄λ€.

λ§μΌ time νλκ° 2022-09-15 21:06 μΈ κ°μ κ²μνκ³ μΆλ€κ³ νμ.
μΌλ°μ μΌλ‘ λ€μκ³Ό κ°μ΄ 쿼리λ₯Ό ν κ²μ΄κ³ μνλ κ²°κ³Όλ₯Ό μ»μ μ μμ κ²μ΄λ€.
νμ§λ§ μ¬κΈ°μ μ€μν건 μ€μΊν λ°μ΄ν° λΆλΆμ΄λ€. μ€μΊν μ©λμ 보λ 1.11KB μ΄λ€.
SELECT * FROM "test"."mycsv_partition" where time='2022-09-15 21:06';

μ΄λ²μ μμμ νν°μ λνμ¬ μΆκ°λ νλλ₯Ό 쑰건 κ²μνμ¬ μΏΌλ¦¬ ν΄λ³΄μ.
SELECT * FROM "test"."mycsv_partition" where time='2022-09-15 21:06' and year=2020 and month=7 and day=3;

쿼리 κ²°κ³Όλ λκ°μ΄ λμμ§λ§, μ€μΊν λ°μ΄ν°λ 0.37KBλ‘ μ€μ΄λ κ±Έ νμΈν μ μλ€.
μ¦, νν°μ λ νλ 쑰건μ μΆκ°νμ§ μμΌλ©΄ λ²ν·μ μλ μ 체 csvλ₯Ό λ€μ Έμ μ§μνμ§λ§, νν°μ λ νλ 쑰건μ μΆκ°νκ² λλ€λ©΄λΌ Athenaκ° μμμ μλ 맡νλ λ²ν· ν΄λ κ²½λ‘λ‘ μ°Ύμλ€μ΄κ° κ·Έ ν΄λ μμμλ csvλ§μ λ€μ§κΈ° λλ¬Έμ μ€μΊν λ°μ΄ν° μ©λμ΄ μ€μ΄λ€κ² λλ κ²μ΄λ€.
λ§μΌ λ‘κ·Έλ₯Ό λ²ν·μ μΆκ°νκ³ Athenaλ‘ κ΄λ¦¬νκ² λ§λ€κ³ μΆμΌλ©΄ μ΄λ»κ² ν κΉ?
λ€μκ³Ό κ°μ΄ λ²ν·μ day=04/ λλ ν 리λ₯Ό λ§λ€κ³ μμ sample4.csv νμΌμ λ£μ΄λ³΄μ.

κ·Έλ¦¬κ³ μλ νν°μ 쿼리λ₯Ό μ€ννλ©΄ μλ‘ μΆκ°λ ν΄λμ λ°μ΄ν°κ° ν μ΄λΈμ μΆκ°λκ² λλ€.

νμ§λ§ λͺ μ² κ° μ΄μμ νν°μ μ΄ μλ κ²½μ°, MSCK REPAIR TABLE λ°©λ²μ DDL 쿼리μ μκ° μ΄κ³Ό λ¬Έμ κ° λ°μν μ μμ΄ λͺ¨λ² μ¬λ‘κ° μλλ€.
μ΄λλ μλ 맡νμ alterλ¬ΈμΌλ‘ νν°μ ν μ΄λΈμ μ λ°μ΄νΈ ν΄μ€μΌ νλ€.
μ΄μ λν΄μ λ°λ‘ λ€μ μλ 맡ν μΉμ μμ λ€λ£¬λ€.
μλ 맡ν
λ λ, μλ³, μΌμ λ³λ‘ μΈμΈν ν΄λλ₯Ό νλνλ λλλ μλ 맡ν νμμ΄ λ§μμ λ€μ§ μλλ€λ©΄, λ΄κ° μνλ λλ‘ λλ ν 리λ₯Ό λ§λ€κ³ μλ 맀νμ ν΄μ£Όλ©΄ λλ€.
λ€μκ³Ό κ°μ΄ μμ λ μ§ μ체λ₯Ό ν΄λλͺ μΌλ‘ νμ¬ μ¬ννκ² λ‘κ·Έλ₯Ό κ΄λ¦¬νκ³ μΆλ€κ³ κ°μ νμ.


λλ ν 리 ꡬ쑰μ λ§κ² νν°μ ν μ΄λΈμ μμ±νλ€.
CREATE EXTERNAL TABLE IF NOT EXISTS test.mycsv_partition2 (
`time` STRING,
`user_id` STRING,
`board_name` STRING,
`action` STRING
)
PARTITIONED BY (date string) -- νν°μ
λ
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
ESCAPED BY '\\'
LINES TERMINATED BY '\n'
LOCATION 's3://athena-log-test-11/csvTest/'
TBLPROPERTIES ('skip.header.line.count'='1');
κ·Έλ¦¬κ³ νν°μ μ λ±λ‘ν΄μ£Όμ΄μΌ νλλ°, μλ 맡νκ³Όλ λ¬λ¦¬ μΌμΌν νν°μ μ μ§μ νμ¬ μΏΌλ¦¬λ₯Ό λ λ €μ£Όμ΄μΌ νλ€.
μλ 맀ν λ°©μλ alterλ¬ΈμΌλ‘ νν°μ μ λ°μ΄νΈκ° κ°λ₯νλ€.
ALTER TABLE test.mycsv_partition2 ADD
PARTITION (date=20220701) LOCATION 's3://athena-log-test-11/csvTest2/20220701/'
PARTITION (date=20220702) LOCATION 's3://athena-log-test-11/csvTest2/20220702/'
PARTITION (date=20220703) LOCATION 's3://athena-log-test-11/csvTest2/20220703/';


κ·Έλ¬λ©΄ S3μ λ‘κ·Έκ° μΆκ°λ λ λ§λ€ μΌμΌν alterλ¬Έμ λ λ €μΌ λλκ³ μλ¬Έμ΄ μκΈΈμ μμν λ°, κ·Έλ΄μ λ°μ μλ€.
μΌμΌλ³λ‘ ν루μ νλ² νν°μ λ‘λλ₯Ό ν΄μ€μΌ νλ€.
κ·Έλμ κ°λ°μλ€μ λ³΄ν΅ λλ€λ μλ²λ¨(aws cli)μμ μ΄λ¬ν κ³Όμ μ μλμΌλ‘ μ²λ¦¬λκ² νλ νΈμ΄λ€.
$ aws athena start-query-execution --query-string "MSCK REPAIR TABLE some_database.some_table" --result-configuration "OutputLocation=s3://SOMEPLACE"
# λλ€
import boto3
def lambda_handler(event, context):
bucket_name = 'some_bucket'
client = boto3.client('athena')
config = {
'OutputLocation': 's3://' + bucket_name + '/',
'EncryptionConfiguration': {'EncryptionOption': 'SSE_S3'}
}
# Query Execution Parameters
sql = 'MSCK REPAIR TABLE some_database.some_table'
context = {'Database': 'some_database'}
client.start_query_execution(QueryString = sql,
QueryExecutionContext = context,
ResultConfiguration = config)
νν°μ μμ
λ§μΌ νν°μ μ μλͺ» μ§μ νμ¬ μμ νκ³ μΆμ κ²½μ° λ€μ 쿼리λ₯Ό λ 리면 λλ€.
ALTER TABLE orders
DROP PARTITION (dt = '2014-05-14', country = 'IN'), PARTITION (dt = '2014-05-15', country = 'IN');
Partition ProjectionμΌλ‘ νν°μ λ μλν
Amazon Athenaμ κ³ λλ‘ λΆν λ ν μ΄λΈμ 쿼리 μ²λ¦¬ μλλ₯Ό λΉ λ₯΄κ² ν΄μ£Όκ³ νν°μ κ΄λ¦¬λ₯Ό μλννλ λ° μΈ μ μλ μλ‘μ΄ κΈ°λ₯μΈ Partition Projection κΈ°λ₯μ΄ μ΅κ·Όμ μΆκ°λμλ€.
μμμ μλ 맡νμ΄λ μλ 맡νμ΄λ λ²ν·μ μλ‘μ΄ λ‘κ·Έ νμΌκ³Ό ν΄λκ° μΆκ°λ κ²½μ° MSCK REPAIR TABLE νΉμ alterλ¬Έ μΌλ‘ νν°μ
λμ μ
λ°μ΄νΈν΄μ€μ μΆκ°λ νμΌμ μΈμμμΌμΌ νλ€.
κ·Έλ¦¬κ³ μ΄λ₯Ό μλν νκΈ°μν΄ λ³΄ν΅ μ μ€ν¬λ¦½νΈλ‘ μ²λ¦¬νκ±°λ λλ€λ‘ μ²λ¦¬νλ€κ³ μμμ νλ² μΈκΈν λ° μλ€.
νμ§λ§ Partition Projectionμ μ¬μ©νλ©΄ νν°μ μ νμ±νλ λ° κ³΅ν΅μ μΌλ‘ μ¬μ©λ ν¨ν΄(μλ₯Ό λ€μ΄ YYYY/MM/DD)κ³Ό κ°μ κ΅¬μ± μ 보λ₯Ό μ§μ ν μ μλ€.
μ¦, Partition Projectionμ μ§μ νλ©΄ μλ‘μ΄ ν΄λμ νμΌμ΄ μΆκ°λλ λ°λ‘ alterλ¬ΈμΌλ‘ νν°μ λμ μΌμΌν μ λ°μ΄νΈ ν΄μ£Όμ§ μμλ μμμ μλμΌλ‘ κ°μ§νμ¬ Athena ν μ΄λΈμ μΆκ°νλ€λ λ§μ΄λ€.
μ΄μ λν μ¬μ©λ²μ λ€μ ν¬μ€ν μ μ°Έκ³ νκΈΈ λ°λλ€.
[AWS] π Athena - Partition Projection νν°μ λ μλν νκΈ°
νν°μ νλ‘μ μ (Partition Projection) Athena partitioned table κ΄λ ¨ 곡μ λ¬Έμμμ MSCK REPAIR TABLE queryλ‘ partitionμ μΈμνλ λ°©λ²μ μκ°νλλ°, μ΄λ μ²μμλ§ μλμΌλ‘ 맡νν΄μ£Όμ§, κ·Έ μ΄νμ μΆ..
inpa.tistory.com
# μ°Έκ³ μλ£
μ΄ κΈμ΄ μ’μΌμ ¨λ€λ©΄ ꡬλ & μ’μμ
μ¬λ¬λΆμ ꡬλ
κ³Ό μ’μμλ
μ μμκ² ν° νμ΄ λ©λλ€.