Indexes
์ด ํ์ด์ง์ ๋ด์ฉ
๊ฐ์
์ด ๊ฐ์ด๋์์๋ MongoDB Go ๋๋ผ์ด๋ฒ์์ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์ธ ์ ์์ต๋๋ค.
์ธ๋ฑ์ค๋ MongoDB์์ ์ฟผ๋ฆฌ๋ฅผ ํจ์จ์ ์ผ๋ก ์คํํ ์ ์๋๋ก ์ง์ํฉ๋๋ค. ์ธ๋ฑ์ค๊ฐ ์๋ MongoDB๋ collection์ ๋ชจ๋ ๋ฌธ์๋ฅผ ์ค์บํด (์ปฌ๋ ์ ์ค์บ) ์ฟผ๋ฆฌ์ ์ผ์นํ๋ ๋ฌธ์๋ฅผ ์ฐพ์ต๋๋ค. ์ปฌ๋ ์ ์ค์บ์ ์๋๊ฐ ๋๋ ค ์ ํ๋ฆฌ์ผ์ด์ ์ฑ๋ฅ์ ๋ถ์ ์ ์ธ ์ํฅ์ ๋ฏธ์น ์ ์์ต๋๋ค. ์ ์ ํ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ๋ฉด MongoDB๊ฐ ๊ฒ์ฌํ๋ ๋ฌธ์ ์๋ฅผ ์ ํํ ์ ์์ต๋๋ค.
ํ
์ ๋ฐ์ดํธ ์์ , ์ญ์ ์์ ๋ฐ ํน์ ์ง๊ณ ํ์ดํ๋ผ์ธ ๋จ๊ณ์์ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์๋ ์์ต๋๋ค.
์ฟผ๋ฆฌ ์ปค๋ฒ๋ฆฌ์ง ๋ฐ ์ฑ๋ฅ
MongoDB์ ์ฟผ๋ฆฌ์๋ ๋ค์ ์์๊ฐ ํฌํจ๋ ์ ์์ต๋๋ค.
์์ | ํ์์ฑ | ๋ชฉ์ |
---|---|---|
์ฟผ๋ฆฌ | ํ์ ์ฌํญ | ์ฐพ๊ณ ์ ํ๋ ํ๋์ ๊ฐ ์ง์ . |
์ต์ | ์ต์ | ์ฟผ๋ฆฌ ์คํ ๋ฐฉ๋ฒ ์ง์ . |
ํ๋ก์ ์ | ์ต์ | MongoDB๊ฐ ๋ฐํํ๋ ํ๋๋ฅผ ์ง์ ํฉ๋๋ค. |
Sort | ์ต์ | MongoDB๊ฐ ๋ฌธ์๋ฅผ ๋ฐํํ๋ ์์ ์ง์ . |
์ด๋ฌํ ์์๋ฅผ ๋์ผํ ์ธ๋ฑ์ค์ ์ง์ ํ๋ฉด MongoDB๋ ์ธ๋ฑ์ค์์ ์ง์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ฉฐ ์ด๋ฅผ ์ปค๋ฒ ์ฟผ๋ฆฌ๋ผ๊ณ ๋ ํฉ๋๋ค.
์ค์
์ ๋ ฌ ๊ธฐ์ค
์ ๋ ฌ ๊ธฐ์ค์ ์ธ๋ฑ์ค์ ์์์ ์ผ์นํ๊ฑฐ๋ ๋ฐ์ ๋์ด์ผ ํฉ๋๋ค.
name
ํ๋์ ์ธ๋ฑ์ค๋ฅผ ์ค๋ฆ์ฐจ์ (A-Z) ์ผ๋ก age
์ธ๋ฑ์ค๋ฅผ ๋ด๋ฆผ์ฐจ์ (9-0) ์ผ๋ก ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค.
name_1_age_-1
MongoDB๋ ๋ค์ ์ค ํ๋๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ๋ ฌํ ๋ ์ด ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํฉ๋๋ค.
name
์ค๋ฆ์ฐจ์,age
๋ด๋ฆผ์ฐจ์name
๋ด๋ฆผ์ฐจ์,age
์ค๋ฆ์ฐจ์
name
๋ฐ age์ ์ค๋ฆ์ฐจ์ ์ ๋ ฌ์ ์ง์ ํ๊ฑฐ๋ name ๋ฐ age
์ ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ์ ์ง์ ํ๋ ค๋ฉด ์ธ๋ฉ๋ชจ๋ฆฌ ์ ๋ ฌ์ ์ํํด์ผ ํฉ๋๋ค.
์ธ๋ฑ์ค๊ฐ ์ฟผ๋ฆฌ ๊ธฐ์ค ๋ฐ ํ๋ก์ ์ ์ ํฌํจํ๋์ง ํ์ธํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์์ธํ ๋ด์ฉ์ ์ฟผ๋ฆฌ ์ปค๋ฒ๋ฆฌ์ง๋ฅผ ์ฐธ์กฐํ์ธ์.
์ด์ ๊ณ ๋ ค ์ฌํญ
์ฟผ๋ฆฌ ์ฑ๋ฅ์ ํฅ์ํ๋ ค๋ฉด ์ ๋ ฌ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ ์ฟผ๋ฆฌ์ ์ ๋ ฌ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ ์์ ์ ์์ฃผ ๋ํ๋๋ ํ๋์ ์ธ๋ฑ์ค๋ฅผ ์์ฑํ์ธ์. ์ถ๊ฐํ๋ ๊ฐ ์ธ๋ฑ์ค๋ ๋์คํฌ ๊ณต๊ฐ๊ณผ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฏ๋ก ์ฉ๋ ๊ณํ์ ์ํด ์ธ๋ฑ์ค ๋ฉ๋ชจ๋ฆฌ์ ๋์คํฌ ์ฌ์ฉ๋์ ์ถ์ ํด์ผ ํฉ๋๋ค. ๋ํ ์ฐ๊ธฐ ์์ ์ด ์ธ๋ฑ์ฑ๋ ํ๋๋ฅผ ์ ๋ฐ์ดํธํ ๋๋ MongoDB๋ ๊ด๋ จ ์ธ๋ฑ์ค๋ ์ ๋ฐ์ดํธํด์ผ ํฉ๋๋ค.
MongoDB๋ ๋์ ์คํค๋ง๋ฅผ ์ง์ํ๋ฏ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด๋ฆ์ด ์๋ ค์ง์ง ์์๊ฑฐ๋ ์์์ ์ด๋ฆ์ ๊ฐ์ง ํ๋์ ์ฟผ๋ฆฌํ ์ ์์ต๋๋ค. MongoDB 4.2๋ ์ด๋ฌํ ์ฟผ๋ฆฌ๋ฅผ ์ง์ํ๊ธฐ ์ํด ์์ผ๋์นด๋ ์ธ๋ฑ์ค๋ฅผ ๋์ ํ์ต๋๋ค. ์์ผ๋์นด๋ ์ธ๋ฑ์ค๋ ์ํฌ๋ก๋ ๊ธฐ๋ฐ ์ธ๋ฑ์ค ๊ณํ์ ๋์ฒดํ๋๋ก ์ค๊ณ๋์ง ์์์ต๋๋ค.
๋ฐ์ดํฐ ๋ชจ๋ธ์ ์ค๊ณํ๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ํฉํ ์ธ๋ฑ์ค๋ฅผ ์ ํํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์ธํ ์์๋ณด๋ ค๋ฉด ์ธ๋ฑ์ฑ ์ ๋ต ๋ฐ ๋ฐ์ดํฐ ๋ชจ๋ธ๋ง ๋ฐ ์ธ๋ฑ์ค๋ฅผ ์ฐธ์กฐํ์ธ์.
์ธ๋ฑ์ค ์ ํ
MongoDB๋ ๋ฐ์ดํฐ ์ฟผ๋ฆฌ๋ฅผ ์ง์ํ๊ธฐ ์ํด ์ฌ๋ฌ ๊ฐ์ง ์ธ๋ฑ์ค ์ ํ์ ์ง์ํฉ๋๋ค. ๋ค์ ์น์ ์์๋ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ์ธ๋ฑ์ค ์ ํ ์์ฑ ๋ฐฉ๋ฒ์ ์ค๋ช ํฉ๋๋ค. ์ธ๋ฑ์ค ์ ํ ์ ์ฒด ๋ชฉ๋ก์ ๋ณด๋ ค๋ฉด ์ธ๋ฑ์ค๋ฅผ ์ฐธ์กฐํ์ธ์.
๋จ์ผ ํ๋ ์ธ๋ฑ์ค
๋จ์ผ ํ๋ ์ธ๋ฑ์ค๋ collection ๋ฌธ์ ๋ด์ ํ๋์ ๋ํ ์ฐธ์กฐ๋ฅผ ๋ณด์ ํฉ๋๋ค.
์ด ์ธ๋ฑ์ค๋ ๋จ์ผ ํ๋ ์ฟผ๋ฆฌ ๋ฐ ์ ๋ ฌ ์ฑ๋ฅ์ ํฅ์์ํค๊ณ ์ผ์ ์๊ฐ์ด ์ง๋๋ฉด ์ปฌ๋ ์ ์์ ๋ฌธ์๋ฅผ ์๋์ผ๋ก ์ ๊ฑฐํ๋ TTL ์ธ๋ฑ์ค์ ์ง์ํฉ๋๋ค.
์ฐธ๊ณ
_id_
์ธ๋ฑ์ค๋ ๋จ์ผ ํ๋ ์ธ๋ฑ์ค์ ์์
๋๋ค. ์ด ์ธ๋ฑ์ค๋ ์ collection์ ์์ฑํ ๋ _id
ํ๋์ ์๋์ผ๋ก ์์ฑ๋ฉ๋๋ค.
์์
๋ค์ ์์์์๋ sample_mflix.movies
collection์ title
ํ๋์ ์ค๋ฆ์ฐจ์์ผ๋ก ์ธ๋ฑ์ค๋ฅผ ๋ง๋ค์ด ๋ด
๋๋ค.
coll := client.Database("sample_mflix").Collection("movies") indexModel := mongo.IndexModel{ Keys: bson.D{{"title", 1}}, } name, err := coll.Indexes().CreateOne(context.TODO(), indexModel) if err != nil { panic(err) } fmt.Println("Name of Index Created: " + name)
Name of Index Created: title_1
๋ณตํฉ ์ธ๋ฑ์ค
๋ณตํฉ ์ธ๋ฑ์ค๋ collection ๋ฌธ์ ๋ด์ ์ฌ๋ฌ ํ๋์ ๋ํ ์ฐธ์กฐ๋ฅผ ๋ณด์ ํฉ๋๋ค. ์ด ์ธ๋ฑ์ค๋ ์ฟผ๋ฆฌ ๋ฐ ์ ๋ ฌ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค.
์์
๋ค์ ์์์์๋ sample_mflix.movies
collection์ fullplot
๋ฐ title
ํ๋์ ๋ณตํฉ ์ธ๋ฑ์ค๋ฅผ ์์ฑํฉ๋๋ค.
coll := client.Database("sample_mflix").Collection("movies") indexModel := mongo.IndexModel{ Keys: bson.D{ {"fullplot", -1}, {"title", 1} } } name, err := coll.Indexes().CreateOne(context.TODO(), indexModel) if err != nil { panic(err) } fmt.Println("Name of Index Created: " + name)
Name of Index Created: fullplot_-1_title_1
๋ค์ค ํค ์ธ๋ฑ์ค(๋ฐฐ์ด ํ๋์ ์ธ๋ฑ์ค)
๋ค์ค ํค ์ธ๋ฑ์ค๋ ๋จ์ผ ํ๋ ์ธ๋ฑ์ค ๋ฐ ๋ณตํฉ ์ธ๋ฑ์ค์ ๋์ผํ ๊ตฌ๋ฌธ์ ์ฌ์ฉํฉ๋๋ค. ์ด ์ธ๋ฑ์ค๋ ๋ฐฐ์ด ํ๋๋ฅผ ์ธ๋ฑ์ค๋ก ์ง์ ํ๋ ์ฟผ๋ฆฌ์ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค.
์์
๋ค์ ์์์๋ sample_mflix.movies
์ปฌ๋ ์
์ cast
ํ๋์ ๋ฉํฐํค ์ธ๋ฑ์ค๋ฅผ ์์ฑํฉ๋๋ค.
coll := client.Database("sample_mflix").Collection("movies") indexModel := mongo.IndexModel{ Keys: bson.D{{"cast", -1}} } name, err := coll.Indexes().CreateOne(context.TODO(), indexModel) if err != nil { panic(err) } fmt.Println("Name of Index Created: " + name)
Name of Index Created: cast_-1
ํด๋ฌ์คํฐํ๋ ์ธ๋ฑ์ค
ํด๋ฌ์คํฐํ ์ธ๋ฑ์ค๋ ํด๋ฌ์คํฐํ ์ปฌ๋ ์ ์์ ์ฝ์ ๊ณผ ์ ๋ฐ์ดํธ ๋ฐ ์ญ์ ์์ ์ ์ฑ๋ฅ์ ํฅ์ํ๋ ์ธ๋ฑ์ค์ ๋๋ค. ํด๋ฌ์คํฐํ ์ปฌ๋ ์ ์ ํด๋ฌ์คํฐํ ์ธ๋ฑ์ค ํค ๊ฐ์ ๊ธฐ์ค์ผ๋ก ์ ๋ ฌ๋ ๋ฌธ์๋ฅผ ์ ์ฅํฉ๋๋ค.
ํด๋ฌ์คํฐํ ์ธ๋ฑ์ค๋ฅผ ์์ฑํ๋ ค๋ฉด collection์ ์์ฑํ ๋ _id
ํ๋๋ฅผ ํค๋ก ์ฌ์ฉํ๊ณ ๊ณ ์ ํ๋๋ฅผ true
๋ก ์ฌ์ฉํ์ฌ ํด๋ฌ์คํฐํ ์ธ๋ฑ์ค ์ต์
์ ์ง์ ํ์ธ์.
์์
๋ค์ ์์์์๋ db.tea
collection์ _id
ํ๋์ ํด๋ฌ์คํฐํ ์ธ๋ฑ์ค๋ฅผ ์์ฑํฉ๋๋ค.
db := client.Database("db") cio := bson.D{{"key", bson.D{{"_id", 1}}}, {"unique", true}} opts := options.CreateCollection().SetClusteredIndex(cio) db.CreateCollection(context.TODO(), "tea", opts)
Text Indexes
ํ ์คํธ ์ธ๋ฑ์ค๋ ๋ฌธ์์ด ์ฝํ ์ธ ์ ๋ํ ํ ์คํธ ๊ฒ์ ์ฟผ๋ฆฌ๋ฅผ ์ง์ํฉ๋๋ค. ์ด ์ธ๋ฑ์ค์๋ ๋ฌธ์์ด ํ๋ ๋๋ ๋ฌธ์์ด ๋ฐฐ์ด์ด ํ์ํฉ๋๋ค. MongoDB๋ ์ฌ๋ฌ ์ธ์ด์ ๋ํ ํ ์คํธ ๊ฒ์์ ์ง์ํฉ๋๋ค. ์ธ๋ฑ์ค๋ฅผ ๋ง๋ค ๋ ๊ธฐ๋ณธ ์ธ์ด๋ฅผ ์ต์ ์ผ๋ก ์ง์ ํ ์ ์์ต๋๋ค.
์ปฌ๋ ์ ์๋ ํ๋์ ํ ์คํธ ์ธ๋ฑ์ค๋ง ํฌํจํ ์ ์์ต๋๋ค. ์ฌ๋ฌ ํ ์คํธ ํ๋์ ๋ํ ํ ์คํธ ์ธ๋ฑ์ค๋ฅผ ๋ง๋ค๋ ค๋ฉด ๋ณตํฉ ์ธ๋ฑ์ค๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค. ํ ์คํธ ๊ฒ์์ ๋ณตํฉ ์ธ๋ฑ์ค ๋ด์ ๋ชจ๋ ํ ์คํธ ํ๋์์ ์คํ๋ฉ๋๋ค.
ํ
ํ ์คํธ ์ธ๋ฑ์ค๋ ๋ ๊ฐ๋ ฅํ Atlas Full Text Search ์ธ๋ฑ์ค์ ๋ค๋ฆ ๋๋ค. Atlas ์ฌ์ฉ์์ ๊ฒฝ์ฐ Atlas ๊ฒ์์ ๊ถ์ฅํฉ๋๋ค.
์์
๋ค์ ์์์์๋ sample_mflix.movies
์ปฌ๋ ์
์ ๊ธฐ๋ณธ ์ธ์ด๋ก italian
์ฌ์ฉํ์ฌ plot
ํ๋์ ํ
์คํธ ์ธ๋ฑ์ค๋ฅผ ์์ฑํฉ๋๋ค.
coll := client.Database("sample_mflix").Collection("movies") indexModel := mongo.IndexModel{Keys: bson.D{{"plot", "text"}, {"default_language", "italian"}}} name, err := coll.Indexes().CreateOne(context.TODO(), indexModel) if err != nil { panic(err) } fmt.Println("Name of Index Created: " + name)
Name of Index Created: plot_text
์ง๋ฆฌ ๊ณต๊ฐ์ ์ธ๋ฑ์ค
MongoDB๋ 2dsphere ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ์ฌ ์ง๋ฆฌ ๊ณต๊ฐ ์ขํ ๋ฐ์ดํฐ๊ฐ ํฌํจ๋ ์ฟผ๋ฆฌ๋ฅผ ์ง์ํฉ๋๋ค. 2dsphere
์ธ๋ฑ์ค๊ฐ GeoJSON ๊ฐ์ฒด ํ๋์ ์์ด์ผ ํฉ๋๋ค.
์ด ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ๋ฉด ๋ค์์ ์ํํ ์ ์์ต๋๋ค.
์ง๋ฆฌ ๊ณต๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ฟผ๋ฆฌํ์ฌ ํฌํจ ์ฌ๋ถ, ๊ต์ฐจ์ , ๊ทผ์ ์ฑ ํ์ธ
์ ํด๋ฆฌ๋ ํ๋ฉด์์์ ๊ฑฐ๋ฆฌ ๊ณ์ฐ ๋ฐ MongoDB 2.2 ์ดํ์์ ์ฌ์ฉ๋๋ '๋ ๊ฑฐ์ ์ขํ ์' ๊ตฌ๋ฌธ ์์
์์
sample_mflix.theaters
์ปฌ๋ ์
์ ๋ฌธ์ ๋ด location.geo
ํ๋๋ ๊ทน์ฅ์ ์ขํ๋ฅผ ์ค๋ช
ํ๋ GeoJSON ํฌ์ธํธ ๊ฐ์ฒด์
๋๋ค.
{ "_id" : ObjectId("59a47286cfa9a3a73e51e75c"), "theaterId" : 104, "location" : { "address" : { "street1" : "5000 W 147th St", "city" : "Hawthorne", "state" : "CA", "zipcode" : "90250" }, "geo" : { "type" : "Point", "coordinates" : [ -118.36559, 33.897167 ] } } }
๋ค์ ์์์์๋ location.geo
ํ๋์ 2dsphere
์ธ๋ฑ์ค๋ฅผ ์์ฑํฉ๋๋ค.
์ค์
์ง๋ฆฌ ๊ณต๊ฐ ์ธ๋ฑ์ค์ ํฌํจ๋ ํ๋์ ์ง๋ฆฌ ๊ณต๊ฐ ์ธ๋ฑ์ค๋ฅผ ์์ฑํ๋ ค๊ณ ํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
indexModel := mongo.IndexModel{ Keys: bson.D{{"location.geo", "2dsphere"}} } name, err := coll.Indexes().CreateOne(context.TODO(), indexModel) if err != nil { panic(err) } fmt.Println("Name of Index Created: " + name)
location.geo_2dsphere
Unique Indexes
๊ณ ์ ์ธ๋ฑ์ค๋ ์ธ๋ฑ์ค๋ ํ๋์ ์ค๋ณต ๊ฐ์ด ์ ์ฅ๋๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก MongoDB๋ _id
ํ๋ ์์ฑ ์ ๊ณ ์ ์ธ๋ฑ์ค๋ฅผ ์์ฑํฉ๋๋ค.
๊ณ ์ ์ธ๋ฑ์ค๋ฅผ ์์ฑํ๋ ค๋ฉด ์ค๋ณต์ ๋ฐฉ์งํ๋ ค๋ ํ๋ ๋๋ ํ๋ ์กฐํฉ์ ์ง์ ํ๊ณ unique
์ต์
์ true
๋ก ์ค์ ํฉ๋๋ค.
์์
๋ค์ ์์์์๋ theaterId
ํ๋์ ๊ณ ์ ํ ๋ด๋ฆผ์ฐจ์ ์ธ๋ฑ์ค๋ฅผ ์์ฑํฉ๋๋ค.
indexModel := mongo.IndexModel{ Keys: bson.D{{"theaterId", -1}}, Options: options.Index().SetUnique(true), } name, err := coll.Indexes().CreateOne(context.TODO(), indexModel) if err != nil { panic(err) } fmt.Println("Name of Index Created: " + name)
Name of Index Created: theaterId_-1
์ธ๋ฑ์ค ์ ๊ฑฐ
_id
ํ๋ ์ ๊ธฐ๋ณธ๊ฐ ๊ณ ์ ์ธ๋ฑ์ค ์ ์ธํ ์ปฌ๋ ์
์์ ๋ชจ๋ ์ธ๋ฑ์ค ์ญ์ ์ ์์ต๋๋ค. ์ธ๋ฑ์ค ์ ๊ฑฐ ํ๋ ค๋ฉด DropOne()
๋ฉ์๋์ ์ธ๋ฑ์ค ์ด๋ฆ์ ์ ๋ฌํฉ๋๋ค.
๋ค์ ์์์๋ title_1
sample_mflix.movies
collection์์ (์ด)๋ผ๋ ์ธ๋ฑ์ค๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
coll := client.Database("sample_mflix").Collection("movies") err := coll.Indexes().DropOne(context.TODO(), "title_1") if err != nil { panic(err) }
์ถ๊ฐ ์ ๋ณด
์ธ๊ธ๋ ์ธ๋ฑ์ค์ ๋ํด ์์ธํ ์์๋ณด๋ ค๋ฉด ๋ค์ ๊ฐ์ด๋๋ฅผ ์ฐธ์กฐํ์ธ์.
์ธ๊ธ๋ ์์ ์ ๋ํด ์์ธํ ์์๋ณด๋ ค๋ฉด ๋ค์ ๊ฐ์ด๋๋ฅผ ์ฐธ์กฐํ์ธ์.
API ๋ฌธ์
์ด ๊ฐ์ด๋์์ ์ค๋ช ํ๋ ๋ฉ์๋์ ๋ํด ์์ธํ ์์๋ณด๋ ค๋ฉด ๋ค์ API ์ค๋ช ์๋ฅผ ์ฐธ์กฐํ์ธ์.