Notice
Recent Posts
Recent Comments
Link
ยซ   2026/04   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
Tags
more
Archives
Today
Total
๊ด€๋ฆฌ ๋ฉ”๋‰ด

...

[WinUI] Lucene.NET ํ…์ŠคํŠธ ๊ฒ€์ƒ‰ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉํ•˜๊ธฐ (1) - ๊ธฐ๋ณธ ๊ฐœ๋…๊ณผ ๊ตฌ์„ฑ ์š”์†Œ ๋ณธ๋ฌธ

WinUI

[WinUI] Lucene.NET ํ…์ŠคํŠธ ๊ฒ€์ƒ‰ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉํ•˜๊ธฐ (1) - ๊ธฐ๋ณธ ๊ฐœ๋…๊ณผ ๊ตฌ์„ฑ ์š”์†Œ

tkdgh816 2025. 10. 10. 16:45

๐Ÿšฉ Lucene.NET์ด๋ž€

โญ Lucene๊ณผ Lucene.NET

  • Lucene์€ Apache Software Foundation์—์„œ ๋งŒ๋“  Java ๊ธฐ๋ฐ˜ ๊ณ ์„ฑ๋Šฅ ์˜คํ”ˆ ์†Œ์Šค ํ’€ํ…์ŠคํŠธ ๊ฒ€์ƒ‰ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค. Lucene์€ ๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ์˜ ์ธ๋ฑ์‹ฑ ๋ฐ ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ์„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค. ์ž์ฒด์ ์œผ๋กœ ์™„์ „ํ•œ ๊ฒ€์ƒ‰ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์•„๋‹Œ, ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ์„ ๊ตฌ์ถ•ํ•˜๊ธฐ ์œ„ํ•œ ํ•ต์‹ฌ ๊ตฌ์„ฑ ์š”์†Œ(๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)์ด๋‹ค. ์—ญ ์ธ๋ฑ์Šค ๊ตฌ์กฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋น ๋ฅด๊ณ  ํšจ์œจ์ ์ธ ๊ฒ€์ƒ‰์„ ์ง€์›ํ•œ๋‹ค.
  • ElasticSearch, OpenSearch ๋“ฑ์˜ ์œ ๋ช… ๊ฒ€์ƒ‰ ์—”์ง„์ด Lucene ๊ธฐ๋ฐ˜์œผ๋กœ ์ œ์ž‘๋˜์—ˆ๋‹ค. ์ด๋“ค ๊ฒ€์ƒ‰ ์—”์ง„์€ Lucene์„ ์ฝ”์–ด๋กœ ์‚ฌ์šฉํ•˜์—ฌ REST API, ๋ถ„์‚ฐ ์ฒ˜๋ฆฌ, ์ƒค๋”ฉ, ๋ฆฌํ”Œ๋ฆฌ์ผ€์ด์…˜, ํด๋Ÿฌ์Šคํ„ฐ๋ง ๋“ฑ์˜ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜์˜€๋‹ค.
  • Lucene์€ JVM(Java, Kotlin, Scala ๋“ฑ) ๊ธฐ๋ฐ˜์—์„œ๋งŒ ๋™์ž‘ํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ์›๋ž˜ Java๋กœ ์ž‘์„ฑ๋œ Lucene์˜ ๊ธฐ๋Šฅ์„ .NET ์–ธ์–ด๋กœ ์žฌ์ž‘์„ฑํ•˜์—ฌ .NET ๋Ÿฐํƒ€์ž„์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก .NET ํฌํŒ… ๋ฒ„์ „์„ ์ œ์ž‘ํ•˜์˜€๋Š”๋ฐ, ์ด๊ฒƒ์ด Lucene.NET์ด๋‹ค.
  • Lucene.NET์€ ์ธ๋ฑ์Šค, ์ฟผ๋ฆฌ, ๋ถ„์„๊ธฐ(Analyzer), ํ† ํฐํ™” ๋“ฑ ๊ธฐ๋ณธ ๊ฐœ๋…๊ณผ API ๊ตฌ์กฐ๊ฐ€ Lucene๊ณผ ๊ฑฐ์˜ ๋™์ผํ•˜๋‹ค. Lucene.NET์€ ๋…๋ฆฝ ํ”„๋กœ์ ํŠธ์ด์ง€๋งŒ, Lucene์˜ ์•„ํ‚คํ…์ฒ˜์™€ ๋ฒ„์ „ ํ˜ธํ™˜์„ ๋”ฐ๋ผ๊ฐ„๋‹ค.
  • Lucene.NET์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์„ค๋ช…์€ Apache Lucene.NET์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 


โญ Lucene.NET ๋ฒ„์ „๊ณผ NuGet ํŒจํ‚ค์ง€

  • NuGet ํŒจํ‚ค์ง€๋กœ Lucene.NET ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ํ˜„์žฌ ์ตœ์‹  ๋ฒ„์ „์€ 4.8.0-beta00017๋กœ NuGet ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์—์„œ "์‹œํ—˜ํŒ ํฌํ•จ"์„ ์„ ํƒํ•˜๋ฉด ์ตœ์‹  ์‹œํ—˜ํŒ์„ ๋‹ค์šด๋กœ๋“œ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.
  • Lucene.NET์€ ์ „ํ†ต์ ์ธ ํ…์ŠคํŠธ ๊ฒ€์ƒ‰(ํ† ํฐํ™”, ์—ญ์ƒ‰์ธ, ๋ถˆ์šฉ์–ด ์ฒ˜๋ฆฌ, ๋ฌธ์„œ ์ •๋ ฌ ๋“ฑ) ์ค‘์‹ฌ์ด๋ฉฐ, ์ตœ์‹  ๊ฒ€์ƒ‰ ํŒจ๋Ÿฌ๋‹ค์ž„์—๋Š” ํ•œ๊ณ„๊ฐ€ ์žˆ๋‹ค.
  • Lucene.NET์— ๊ด€๋ จ๋œ ์—ฌ๋Ÿฌ NuGet ํŒจํ‚ค์ง€๊ฐ€ ์žˆ๋Š”๋ฐ ๊ธฐ๋ณธ์ ์œผ๋กœ Lucene.Net, Lucene.Net.Analysis.Common, Lucene.Net.QueryParser๋ฅผ ์„ค์น˜ํ•œ๋‹ค.

 


๐Ÿšฉ Lucene.NET ๊ตฌ์„ฑ ์š”์†Œ (1): ์ธ๋ฑ์Šค์— ์ž…๋ ฅํ•˜๋Š” ๋ฐ์ดํ„ฐ

โญ Document์™€ Field

  • Document(๋ฌธ์„œ): ์ธ๋ฑ์Šค์˜ ๋Œ€์ƒ์ด ๋˜๋Š” ๊ธฐ๋ณธ ๋‹จ์œ„์ด๋‹ค. ํ•˜๋‚˜์˜ Document๋Š” ๊ฒ€์ƒ‰ ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด ํ•˜๋‚˜๋ฅผ ์˜๋ฏธํ•œ๋‹ค. Document๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ Field๋ฅผ ๊ฐ€์ง„๋‹ค.
  • ์—ฌ๊ธฐ์—์„œ๋Š” Document๋ฅผ ํ•œ๊ตญ์–ด๋กœ ๋ฒˆ์—ญํ•˜์—ฌ "๋ฌธ์„œ"๋ผ๊ณ  ํ‘œํ˜„ํ•˜์˜€๋‹ค. ์ด๋Š” ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ๋‚˜ ๊ธ€๋กœ์„œ ์‚ฌ์šฉํ•˜๋Š” "๋ฌธ์„œ"์˜ ์˜๋ฏธ๊ฐ€ ์•„๋‹ˆ๋ผ, Lucene.Net.Documents.Document ๊ฐ์ฒด๋กœ์„œ ์•ž์„œ ์„ค๋ช…ํ–ˆ๋˜ ์ธ๋ฑ์Šค์˜ ๋Œ€์ƒ์ด ๋˜๋Š” ๋‹จ์œ„๋ฅผ ์˜๋ฏธํ•œ๋‹ค.
  • Field(ํ•„๋“œ): ํ•„๋“œ๋Š” Document์˜ ํ•œ ๋ถ€๋ถ„์œผ๋กœ, Document ๋‚ด๋ถ€์˜ ์†์„ฑ์ด๋‹ค. ๊ฐ ํ•„๋“œ๋งˆ๋‹ค ์ด๋ฆ„, ๊ฐ’, ์œ ํ˜•(์ธ๋ฑ์Šค ์—ฌ๋ถ€, ์ €์žฅ ์—ฌ๋ถ€, ๊ฒ€์ƒ‰ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ๋“ฑ)์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•„๋“œ๋Š” ์„ ํƒ์ ์œผ๋กœ ์ธ๋ฑ์Šค์— ์ €์žฅ๋˜์–ด ๋ฌธ์„œ์— ๋Œ€ํ•œ ์กฐํšŒ ๊ฒฐ๊ณผ๋กœ ๋ฐ˜ํ™˜๋  ์ˆ˜ ์žˆ๋‹ค.
  • Document๊ฐ€ ๊ฒŒ์‹œํŒ ๊ธ€์ด๋ผ๋ฉด, ๊ทธ ์•ˆ์— ์ œ๋ชฉ, ์ž‘์„ฑ์ž, ์ž‘์„ฑ ์‹œ๊ฐ„, ๋ณธ๋ฌธ ๋“ฑ์˜ Field๋“ค์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Document ๊ฐ์ฒด๋Š” Lucene.Net.Documents ๋„ค์ž„์ŠคํŽ˜์ด์Šค์˜ Document ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋งŒ๋“ ๋‹ค. ์ด๋•Œ Document๋Š” IEnumerable ํƒ€์ž…์œผ๋กœ ์ปฌ๋ ‰์…˜ ์ดˆ๊ธฐ์ž๋กœ Field ๊ฐ์ฒด๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์ดˆ๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ Get, Add, RemoveField ๋“ฑ์˜ ๋ฉ”์„œ๋“œ๋กœ ํ•„๋“œ๋ฅผ ํ™•์ธ/๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.
using Lucene.Net.Documents;

(string Id, string Title, string Content) article = ("User Id", "Title 1", "Content 1");

Document doc = new()
{
    new StringField("Id", article.Id, Field.Store.YES),
    new TextField("Title", article.Title, Field.Store.YES),
    new TextField("Content", article.Content, Field.Store.NO)
};
  • Field ๊ฐ์ฒด๋Š” Lucene.Net.Documents ๋„ค์ž„์ŠคํŽ˜์ด์Šค์˜ Field ํด๋ž˜์Šค ๋˜๋Š” Field์˜ ํŒŒ์ƒ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. Field ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ๋Š” ์ฃผ๋กœ ์„ธ ๊ฐœ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›๋Š” ์ƒ์„ฑ์ž๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋กœ๋Š” ์—ฌ๋Ÿฌ ํ•„๋“œ๋“ค์„ ๊ตฌ๋ถ„ํ•  ์ƒ์„ฑํ•˜๋ ค๋Š” ํ•„๋“œ์˜ ์ด๋ฆ„, ๋‘ ๋ฒˆ์งธ ์ธ์ž๋กœ๋Š” ํ•„๋“œ์— ์‚ฝ์ž…ํ•  ๊ฐ’(์ฝ˜ํ…์ธ ), ์„ธ ๋ฒˆ์งธ ์ธ์ž๋กœ๋Š” ํ•„๋“œ๋ฅผ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฃฐ ๊ฒƒ์ธ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ์„ค์ •๊ฐ’์ด ๋“ค์–ด๊ฐ„๋‹ค.
  • Field ๊ฐ์ฒด์˜ FieldType ์†์„ฑ์„ ์กฐ์ •ํ•˜์—ฌ Field ์ธ์Šคํ„ด์Šค ํ•˜๋‚˜๋กœ ๋ชจ๋“  ํŒŒ์ƒ ํด๋ž˜์Šค ํ•„๋“œ ์ธ์Šคํ„ด์Šค๋ฅผ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ๋‹ค. ํŒŒ์ƒ ํด๋ž˜์Šค๋“ค์€ ํƒ€์ž…์„ ๊ณ ์ •ํ•˜๊ณ  ํŽธ๋ฆฌํ•œ ์‚ฌ์šฉ์„ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ ๊ฒƒ์ด๋‹ค. FieldType์œผ๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์†์„ฑ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
์†์„ฑ ํƒ€์ž… ์„ค๋ช… ๊ธฐ๋ณธ๊ฐ’
DocValueType DocValuesType Enum
(BINARY, NONE, NUMERIC, SORTED, SORTED_SET)
DocValue ๊ฐ’ ํƒ€์ž… NONE
IndexOptions IndexOptions Enum
(DOCS_AND_FREQS, DOCS_AND_FREQS_AND_POSITIONS, DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS, DOCS_ONLY, NONE)
์ธ๋ฑ์‹ฑ ์˜ต์…˜ DOCS_AND_FREQS_AND_POSITIONS
IsIndexed bool ์ธ๋ฑ์‹ฑ ์—ฌ๋ถ€ false
IsStored bool ํ•„๋“œ ๊ฐ’ ์ €์žฅ ์—ฌ๋ถ€ false
IsTokenized bool ํ† ํฐํ™” ์—ฌ๋ถ€ true
NumericPrecisionStep int ์ˆซ์ž ๊ฐ’ ์ •ํ™•๋„ PRECISION_STEP_DEFAULT (4)
NumericType NumericType Enum
(DOUBLE, INT32, INT64, SINGLE, NONE)
์ˆซ์ž ๊ฐ’ ํƒ€์ž… NONE
OmitNorms bool omit normalization false
StoreTermVectorOffsets bool   false
StoreTermVectorPayloads bool   false
StoreTermVectorPositions bool   false
StoreTermVectors bool   false

 

  • Field์˜ ํŒŒ์ƒ ํด๋ž˜์Šค๋“ค์€ ํฌ๊ฒŒ ๊ฒ€์ƒ‰ ์กฐ๊ฑด์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ธ๋ฑ์‹ฑ ํ•„๋“œ์™€, ๊ฒ€์ƒ‰์šฉ์ด ์•„๋‹Œ ๋‹ค๋ฅธ ์šฉ๋„์ธ ๋น„์ธ๋ฑ์‹ฑ ํ•„๋“œ์ƒ‰ ์กฐ๊ฑด์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ธ๋ฑ์‹ฑ ํ•„๋“œ์™€, ๊ฒ€์ƒ‰์šฉ์ด ์•„๋‹Œ ๋‹ค๋ฅธ ์šฉ๋„์ธ ๋น„์ธ๋ฑ์‹ฑ ํ•„๋“œ๋กœ ๋‚˜๋ˆˆ๋‹ค.
    • ์ธ๋ฑ์‹ฑ ํ•„๋“œ: ์ธ๋ฑ์‹ฑ ํ•„๋“œ๋Š” ํ•„๋“œ ๊ฐ’ ํƒ€์ž…์— ๋”ฐ๋ผ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.
ํ•„๋“œ(Field) ํ•„๋“œ ๊ฐ’ ํƒ€์ž…(CLR) ์„ค๋ช… ํŠน์ง•
StringField string ๋ฌธ์ž์—ด ๊ฐ’์„ ์ธ๋ฑ์‹ฑํ•˜๋Š” ํ…์ŠคํŠธ ํ•„๋“œ
ํ…์ŠคํŠธ๋ฅผ ํ† ํฐํ™”ํ•จ
์ „์ฒด ๋ฌธ์ž์—ด ๊ฐ’์ด ๋‹จ์ผ ํ† ํฐ์œผ๋กœ ์ธ๋ฑ์‹ฑ๋จ
TextField string ๋ฌธ์ž์—ด ๊ฐ’์„ ์ธ๋ฑ์‹ฑํ•˜๋Š” ํ…์ŠคํŠธ ํ•„๋“œ
ํ…์ŠคํŠธ๋ฅผ ํ† ํฐํ™”ํ•จ
ํ† ํฐํ™”ํ•˜์—ฌ ์ธ๋ฑ์‹ฑํ•˜์ง€๋งŒ TermVector๋Š” ์ €์žฅํ•˜์ง€ ์•Š์Œ
Int32Field int int ๊ฐ’์„ ์ธ๋ฑ์‹ฑํ•˜๋Š” ํ•„๋“œ ํšจ์œจ์ ์ธ ๋ฒ”์œ„ ํ•„ํ„ฐ๋ง ๋ฐ ์ •๋ ฌ์„ ์‚ฌ์šฉ
Int64Field long long ๊ฐ’์„ ์ธ๋ฑ์‹ฑํ•˜๋Š” ํ•„๋“œ ํšจ์œจ์ ์ธ ๋ฒ”์œ„ ํ•„ํ„ฐ๋ง ๋ฐ ์ •๋ ฌ์„ ์‚ฌ์šฉ
SingleField float float ๊ฐ’์„ ์ธ๋ฑ์‹ฑํ•˜๋Š” ํ•„๋“œ ํšจ์œจ์ ์ธ ๋ฒ”์œ„ ํ•„ํ„ฐ๋ง ๋ฐ ์ •๋ ฌ์„ ์‚ฌ์šฉ
DoubleField double double ๊ฐ’์„ ์ธ๋ฑ์‹ฑํ•˜๋Š” ํ•„๋“œ ํšจ์œจ์ ์ธ ๋ฒ”์œ„ ํ•„ํ„ฐ๋ง ๋ฐ ์ •๋ ฌ์„ ์‚ฌ์šฉ

 

  • ๋น„์ธ๋ฑ์‹ฑ ํ•„๋“œ: ๋น„์ธ๋ฑ์‹ฑ ํ•„๋“œ๋Š” ์ €์žฅ ๊ตฌ์กฐ์— ๋”ฐ๋ผ Document์™€ Field ๊ธฐ๋ฐ˜์œผ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.
    • Document(ํ–‰) ๊ธฐ๋ฐ˜: ๋ฌธ์„œ ๋‹จ์œ„๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ์ €์žฅ๋œ๋‹ค. ํŠน์ • ํ•„๋“œ๋งŒ ์กฐํšŒํ•˜๋ ค๋ฉด ํ•ด๋‹น ๋ฌธ์„œ๋ฅผ ๋””์ฝ”๋”ฉํ•ด์•ผ ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๋žœ๋ค ์ ‘๊ทผ์€ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ์ˆœ์ฐจ ์ ‘๊ทผ์€ ๋น„ํšจ์œจ์ ์ด๋‹ค. ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜์šฉ์œผ๋กœ ์„ค๊ณ„๋˜์—ˆ๋‹ค.
    • Field(์—ด) ๊ธฐ๋ฐ˜: ํ•„๋“œ๋ณ„๋กœ ๋ชจ๋“  ๋ฌธ์„œ ๊ฐ’์ด ์—ฐ์† ๋ฐฐ์—ด๋กœ ์ €์žฅ๋˜์–ด DocID์™€ ๊ฐ’ ๋งคํ•‘์ด ๋น ๋ฅด๋‹ค. ๋น ๋ฅธ ๊ฐ’ ์กฐํšŒ, ๋Œ€๋Ÿ‰ ์ˆœ์ฐจ ์ ‘๊ทผ, ํ›„์ฒ˜๋ฆฌ, ์ •๋ ฌ/๊ทธ๋ฃนํ•‘์— ํšจ์œจ์ ์ด๋‹ค. ๊ฒ€์ƒ‰ ๊ณผ์ •๊ณผ ํ›„์ฒ˜๋ฆฌ์šฉ์œผ๋กœ ์„ค๊ณ„๋˜์—ˆ๋‹ค.
ํ•„๋“œ(Field) ์ €์žฅ ๊ตฌ์กฐ ํ•„๋“œ ๊ฐ’ ํƒ€์ž… ์„ค๋ช… ํŠน์ง•
StoredField Document(ํ–‰) ๊ธฐ๋ฐ˜ ๋ชจ๋“  ํƒ€์ž…
(string, int, long, float, double, BytesRef)
d d
BinaryDocValuesField
๋ฐ ํŒŒ์ƒ
Field(์—ด) ๊ธฐ๋ฐ˜ BytesRef d d
NumericDocValuesField
๋ฐ ํŒŒ์ƒ
Field(์—ด) ๊ธฐ๋ฐ˜ ์ˆซ์ž ํƒ€์ž…
(byte, short, int, long, float, double)
d d
SortedDocValuesField
๋ฐ ํŒŒ์ƒ
Field(์—ด) ๊ธฐ๋ฐ˜ BytesRef d d
SortedSetDocValuesField Field(์—ด) ๊ธฐ๋ฐ˜ BytesRef d d

 


๐Ÿšฉ Lucene.NET ๊ตฌ์„ฑ ์š”์†Œ (2): ์ธ๋ฑ์Šค๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๊ณตํ•˜๋Š” ๋ฐฉ์‹

โญ Token๊ณผ Term

  • Token(ํ† ํฐ): Token์€ Analyzer๊ฐ€ ์›๋ณธ ํ…์ŠคํŠธ๋ฅผ ๋ถ„์„ํ•  ๋•Œ ๋งŒ๋“ค์–ด๋‚ด๋Š” ์ค‘๊ฐ„ ์‚ฐ์ถœ๋ฌผ์ด๋‹ค. ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ๋Š” ๊ฒ€์ƒ‰์„ ์œ„ํ•ด ์ดˆ๊ธฐ์— ํ…์ŠคํŠธ๋ฅผ ๋ถ„์„ํ•˜์—ฌ ์ด๊ฒƒ์„ ์ž‘์€ ๋‹จ์œ„๋กœ ๋ถ„ํ•ดํ•˜๋Š” ๊ณผ์ •์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์ด๋•Œ ์ด ๋ถ„ํ•ด๋œ ์กฐ๊ฐ์„ Token์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. Token์€ Analyzer ๋‹จ๊ณ„์—์„œ๋งŒ ์กด์žฌํ•˜๋Š” ์ž„์‹œ ๊ฐ์ฒด์ด๋ฉฐ, ์‹ค์ œ ์ธ๋ฑ์Šค์—๋Š” ์ €์žฅ๋˜์ง€ ์•Š๋Š”๋‹ค.
  • ์˜ˆ๋ฅผ ๋“ค์–ด "The quick brown fox jumps"์™€ ๊ฐ™์€ ์›๋ณธ ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•˜์ž. Analyzer๊ฐ€ ์ด ํ…์ŠคํŠธ๋ฅผ ๋ถ„์„ํ•  ๋•Œ, ๋‹จ์–ด ๋‹จ์œ„๋กœ ๋ฌธ์žฅ์„ ์ชผ๊ฐ  ํ›„ ๋Œ€๋ฌธ์ž๋ฅผ ๋ชจ๋‘ ์†Œ๋ฌธ์ž๋กœ ๋ฐ”๊พผ๋‹ค. ๊ทธ๋ฆฌ๊ณ  "the"์™€ ๊ฐ™์€ ๋ถˆ์šฉ์–ด๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  "jumps"์™€ ๊ฐ™์€ ๋ฌธ๋ฒ•์  ๋‹จ์–ด์—์„œ "jump"๋ผ๋Š” ํ‘œ์ œ์–ด๋ฅผ ์ถ”์ถœ(lemmatization)ํ•œ๋‹ค. ๊ทธ ๊ฒฐ๊ณผ๋กœ "quick", "brown", "fox", "jump"์™€ ๊ฐ™์€ ๋‹จ์–ด๋“ค์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์–ป์€ ๋‹จ์–ด ํ•˜๋‚˜ํ•˜๋‚˜๋ฅผ Token์ด๋ผ๊ณ  ํ•˜๊ณ , ์ด Token๋“ค์„ ๋ชจ๋‘ ๋ชจ์€ ๋ฌถ์Œ(์ปฌ๋ ‰์…˜)์„ TokenStream์ด๋ผ๊ณ  ํ•œ๋‹ค.
  • Term(ํ…€): Term์€ Token์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ธ๋ฑ์Šค์— ์‹ค์ œ๋กœ ์ €์žฅ๋˜๋Š” ๊ฒ€์ƒ‰ ๋‹จ์œ„์ด๋‹ค. Term์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ํ•„๋“œ๋ช…๊ณผ ํ…์ŠคํŠธ์˜ ์กฐํ•ฉ์œผ๋กœ ์ •์˜๋˜๋ฉฐ ์ธ๋ฑ์Šค์—๋Š” Term์ด ์‚ฌ์ „ ํ˜•ํƒœ๋กœ ์ €์žฅ๋œ๋‹ค. ์ธ๋ฑ์Šค์—์„œ ๋ฌธ์„œ๋ฅผ ๊ฒ€์ƒ‰ํ•  ๋•Œ ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ๋Š” Term ๋‹จ์œ„๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค.
  • ์˜ˆ๋ฅผ ๋“ค์–ด ์–ด๋–ค Document์˜ "body"๋ผ๋Š” Field์˜ ๊ฐ’์ด "The quick brown fox jumps"๋ผ๊ณ  ํ•˜์ž. ์ธ๋ฑ์‹ฑ ์‹œ Analyzer๊ฐ€ ํ˜ธ์ถœ๋˜์–ด ํ…์ŠคํŠธ๋ฅผ ํ† ํฐํ™”ํ•˜์—ฌ "quick", "brown", "fox", "jump"์™€ ๊ฐ™์ด ๋งŒ๋“ ๋‹ค. ๊ฐ ํ† ํฐ๋“ค์€ Term์œผ๋กœ ๊ฐ„์ฃผ๋˜์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด Field์™€ Text ์†์„ฑ์ด ํฌํ•จ๋œ Term ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์ธ๋ฑ์Šค์— ์ €์žฅํ•œ๋‹ค.
// ์‹ค์ œ ๊ฐ์ฒด ๊ตฌ์กฐ๊ฐ€ ์•„๋‹Œ ๋…ผ๋ฆฌ์  ๊ตฌ์กฐ๋ฅผ ํ‘œํ˜„ํ•จ
Term body:quick  (Field -> "body", Text -> "quick")
Term body:brown  (Field -> "body", Text -> "brown")
Term body:fox    (Field -> "body", Text -> "fox")
Term body:jump   (Field -> "body", Text -> "jump")
  • ๊ทธ ๋‹ค์Œ ์ธ๋ฑ์„œ๋Š” ํ˜„์žฌ Document์— ๋Œ€ํ•ด ๊ฐ Term์˜ ์ •๋ณด๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. ๊ทธ ์ •๋ณด์—๋Š” ํ˜„์žฌ ๋ฌธ์„œ์˜ Id(DocId), Term์ด ๋ฌธ์„œ์—์„œ ๋ฐœ์ƒํ•œ ๋นˆ๋„(Frequency), ๋ฐœ์ƒ ์œ„์น˜(Position), ํ…์ŠคํŠธ์˜ ๋ฒ”์œ„(Offset) ๋“ฑ์ด ์„ ํƒ์ ์œผ๋กœ ์ €์žฅ๋œ๋‹ค.
  • ๊ฒ€์ƒ‰ ์‹œ ์ฟผ๋ฆฌ ๋ฌธ์ž์—ด(๊ฒ€์ƒ‰์–ด)๊ฐ€ ๋“ค์–ด์˜ค๋ฉด ๊ทธ ๋ฌธ์ž์—ด๋„ Analyzer๋กœ ์ฒ˜๋ฆฌํ•˜์—ฌ Term์„ ์ƒ์„ฑํ•œ๋‹ค. ๊ทธ Term์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ธ๋ฑ์Šค์—์„œ ์ผ์น˜ํ•˜๋Š” Term์„ ์ฐพ์„ ์ˆ˜ ์žˆ๊ณ  ๊ทธ Term์— ํ•ด๋‹นํ•˜๋Š” ์ •๋ณด๋ฅผ ๋ถˆ๋Ÿฌ์™€ ์–ด๋А ๋ฌธ์„œ, ์–ด๋А ์œ„์น˜์— ์กด์žฌํ•˜๋Š”์ง€ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

 


โญ Analyzer

  • Analyzer(๋ถ„์„๊ธฐ): ํ…์ŠคํŠธ๋ฅผ ๋ถ„์„ํ•˜์—ฌ ์ƒ‰์ธ, ๊ฒ€์ƒ‰ ๊ฐ€๋Šฅํ•œ ํ† ํฐ๋“ค์˜ ์ง‘ํ•ฉ์ธ TokenStream์„ ์ƒ์„ฑํ•˜๋Š” ์ •์ฑ…(ํŒŒ์ดํ”„๋ผ์ธ)์ด๋‹ค. ํŒŒ์ดํ”„๋ผ์ธ์€ ์ผ๋ฐ˜์ ์œผ๋กœ CharFilter -> Tokenizer -> TokenFilter ํ˜•ํƒœ๋กœ ๋™์ž‘ํ•˜๊ณ , ๊ฐ ๋‹จ๊ณ„๋Š” ํ…์ŠคํŠธ๋ฅผ ์ •๊ทœํ™”, ๋ถ„ํ•ด, ๊ฐ€๊ณตํ•œ๋‹ค.
  • CharFilter: ์›๋ณธ ํ…์ŠคํŠธ๋ฅผ ๋ฌธ์ž ๋‹จ์œ„๋กœ ์‚ฝ์ž…, ์‚ญ์ œ, ์น˜ํ™˜ํ•˜์—ฌ ์ „์ฒ˜๋ฆฌํ•œ๋‹ค. HTML ํƒœ๊ทธ๋ฅผ ์ œ๊ฑฐ(HTMLStripCharFilter)ํ•˜๊ฑฐ๋‚˜, ํŠน์ • ๋ฌธ์ž์—ด์„ ์น˜ํ™˜ํ•˜๊ณ  ์ถ•์•ฝ์–ด๋ฅผ ํ™•์žฅ(MappingCharFilter)ํ•˜๊ฑฐ๋‚˜, ๋ฌธ์žฅ๋ถ€ํ˜ธ๋ฅผ ๊ณต๋ฐฑ์œผ๋กœ ์น˜ํ™˜ํ•˜๋Š” ๋“ฑ Tokenizer๊ฐ€ ํ…์ŠคํŠธ๋ฅผ TokenStream์œผ๋กœ ๋ถ„๋ฆฌํ•˜๊ธฐ ์ „ ๋” ์ž˜ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์›๋ณธ ํ…์ŠคํŠธ๋ฅผ ์ „์ฒ˜๋ฆฌํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. CharFilter๋Š” ์—ฐ์†์ ์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋ฉฐ ๋‚ด๋ถ€์ ์œผ๋กœ ์˜คํ”„์…‹ ๋ณด์ • ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค.
  • Lucene.NET Analyzer ํด๋ž˜์Šค์—์„œ๋Š” InitReader ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜์—ฌ ๋ฉ”์„œ๋“œ ์ธ์ž๋กœ ๋ฐ›์€ TextReader ๊ฐ์ฒด๋ฅผ CharFilter๋กœ ๋ž˜ํ•‘ํ•˜์—ฌ ๋‹ค์‹œ TextReader ๊ฐ์ฒด๋กœ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•œ๋‹ค. ์ด๋•Œ, TextReader๋Š” .NET์˜ System.IO.TextReader๋ฅผ ์˜๋ฏธํ•œ๋‹ค.
// CharFilter๋ฅผ ์ ์šฉ์‹œํ‚ฌ Analyzer ํด๋ž˜์Šค์˜ ๊ฐ€์ƒ ๋ฉ”์„œ๋“œ
protected virtual TextReader InitReader(string fieldName, TextReader reader)
  • TokenStream: Document์˜ ํ•„๋“œ ๋˜๋Š” ์ฟผ๋ฆฌ ํ…์ŠคํŠธ์—์„œ ํ† ํฐ ์‹œํ€€์Šค๋ฅผ ๋‚˜์—ดํ•˜๋Š” ๊ฐ์ฒด์ด๋‹ค. TokenStream ํด๋ž˜์Šค๋Š” ์ถ”์ƒ ํด๋ž˜์Šค๋กœ, ํŒŒ์ƒ ํด๋ž˜์Šค๋กœ Tokenizer์™€ TokenFilter ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ง„๋‹ค. Tokenizer๋Š” TextReader๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›๋Š” TokenStream์ด๊ณ , TokenFilter๋Š” ๋‹ค๋ฅธ TokenStream์„ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›๋Š” TokenStream์ด๋‹ค.
  • TokenStream ํด๋ž˜์Šค๋Š” AttributeSource ํด๋ž˜์Šค์˜ ํŒŒ์ƒ ํด๋ž˜์Šค๋กœ์„œ, ๋‹ค์–‘ํ•œ Attribute(ํŠน์„ฑ) ๋ชฉ๋ก๊ณผ ํŠน์„ฑ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ๊ฐ€์ ธ์˜ค๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. TokenStream ํด๋ž˜์Šค์— ํŠน์„ฑ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์„ค์ •ํ•จ์œผ๋กœ์จ ํ† ํฐ์˜ ํŠน์„ฑ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • TokenStream์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‹จ๊ณ„๋กœ ํ† ํฐ๊ณผ ๊ทธ์— ๋งž๋Š” ํ† ํฐ ํŠน์„ฑ์„ ์ƒ์„ฑํ•œ๋‹ค. ์„ธ ๋ฉ”์„œ๋“œ๋Š” ๋ชจ๋‘ ์˜ค๋ฒ„๋ผ์ด๋“œ ๊ฐ€๋Šฅํ•˜๋‹ค.
    • Reset() ๋ฉ”์„œ๋“œ: TokenStream์ด ์ƒˆ๋กœ์šด ์ž…๋ ฅ์„ ์ฒ˜๋ฆฌํ•  ์ค€๋น„๋ฅผ ํ•˜๋Š” ๋‹จ๊ณ„์ด๋‹ค. ์ด์ „ ํ† ํฐ ์ƒํƒœ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ณ , TokenStream์ด ์ž…๋ ฅ์„ ์ฒ˜์Œ๋ถ€ํ„ฐ ์ฝ๋„๋ก ์„ค์ •ํ•œ๋‹ค.
    • IncrementToken() ๋ฉ”์„œ๋“œ: ์‹ค์ œ๋กœ ํ† ํฐ์„ ์ƒ์„ฑํ•˜๊ณ  ๋ณ€ํ™˜ํ•˜๋Š” ๋‹จ๊ณ„์ด๋‹ค. ๊ทธ ๋‹ค์Œ ์ŠคํŠธ๋ฆผ์„ ๋‹ค์Œ ํ† ํฐ์œผ๋กœ ์ด๋™์‹œํ‚จ๋‹ค. ํ† ํฐ์€ ์—ฌ๋Ÿฌ TokenStream ์ฒด์ธ์„ ํ•œ ํ† ํฐ์”ฉ ํ†ต๊ณผํ•œ๋‹ค. ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ TokenStream ๋‚ด๋ถ€ ์ƒํƒœ๋ฅผ ๊ฐฑ์‹ ํ•œ๋‹ค(์˜ค๋ฒ„๋ผ์ด๋“œ ์‹œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•œ๋‹ค).
      • ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์‹œ ๋‹ค์Œ ํ† ํฐ์ด ์žˆ์œผ๋ฉด true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ๋”์ด์ƒ ํ† ํฐ์ด ์—†์œผ๋ฉด false๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
      • ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ๋™์•ˆ ํ† ํฐ์„ ์ƒ์„ฑํ•˜๊ณ  ํ† ํฐ ํŠน์„ฑ(term, offset, position ๋“ฑ์˜ attribute)์„ ์ƒˆ๋กœ์šด ํ† ํฐ์— ๋งž๊ฒŒ ๊ฐฑ์‹ ํ•œ๋‹ค.
      • ํŠน์„ฑ์„ ์ง€์ •ํ•˜๊ธฐ ์ „ ๊ธฐ์กด ํŠน์„ฑ์„ ClearAttribute() ๋ฉ”์„œ๋“œ๋กœ ์ดˆ๊ธฐํ™”ํ•œ ํ›„, ํ•„์š”ํ•œ ํŠน์„ฑ์„ ์„ค์ •ํ•˜๊ณ  ๋‹ค์Œ ํ† ํฐ ์กด์žฌ ์—ฌ๋ถ€์— ๋”ฐ๋ผ true ํ˜น์€ false๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
      • ํ† ํฐ ์†์„ฑ์€ ํ† ํฐ(ํ˜น์€ ํ…€) ํ…์ŠคํŠธ๋ฅผ ์ง€์ •ํ•˜๋Š” ICharTermAttribute, ํ…€์˜ ์œ„์น˜(์˜คํ”„์…‹)์„ ์ง€์ •ํ•˜๋Š” IOffsetAttribute, ํ† ํฐ์˜ ํƒ€์ž…(๋‹จ์–ด, ์ˆซ์ž ๋“ฑ)์„ ์ง€์ •ํ•˜๋Š” ITypeAttribute ๋“ฑ์ด ์žˆ๋‹ค.
    • End() ๋ฉ”์„œ๋“œ: TokenStream์ด ๋งˆ์ง€๋ง‰ ํ† ํฐ์„ ์ฒ˜๋ฆฌํ•œ ํ›„ ์ •๋ฆฌํ•˜๋Š” ๋‹จ๊ณ„์ด๋‹ค. ๋งˆ์ง€๋ง‰ ์˜คํ”„์…‹ ์„ค์ •, ๋ฆฌ์†Œ์Šค ์ •๋ฆฌ ๋“ฑ์˜ ์ŠคํŠธ๋ฆผ ์ข…๋ฃŒ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.
  • Tokenizer: ์›๋ณธ ํ…์ŠคํŠธ ๋˜๋Š” CharFilter๋กœ ๋ž˜ํ•‘๋œ TextReader๋ฅผ ์ฝ์–ด ํ…์ŠคํŠธ๋ฅผ ํ† ํฐ๋“ค๋กœ ๋ถ„ํ•ดํ•œ๋‹ค. ํ† ํฐ์„ ๋ถ„ํ•ดํ•  ๋•Œ ํ† ํฐ ๊ฒฝ๊ณ„๋ฅผ ๊ฒฐ์ •ํ•˜๊ณ , ํ† ํฐ ๋‹จ์œ„์˜ ํŠน์„ฑ์„ ์ถ”๊ฐ€ํ•œ๋‹ค. Tokenizer๋Š” TextReader๋ฅผ ๋ฐ›์•„์„œ TokenStream์„ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ Analyzer ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ๋‚ด๋ถ€์—์„œ ์ฒ˜์Œ ํ•œ ๋ฒˆ๋งŒ ์ˆ˜ํ–‰๋œ๋‹ค.
  • TokenFilter: Tokenizer๋กœ ๋ถ„ํ•ด๋œ ๊ธฐ์กด ํ† ํฐ๋“ค์„ ๋ณ€ํ™˜, ํ•„ํ„ฐ๋งํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. ํ† ํฐ ํ…์ŠคํŠธ๋ฅผ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜, ๋ถˆํ•„์š”ํ•œ ํ† ํฐ์„ ์ œ๊ฑฐํ•˜๊ณ , ๋” ์ž‘์€ ํ† ํฐ์œผ๋กœ ๋ถ„ํ•ดํ•˜๋Š” ๋“ฑ ๊ธฐ์กด TokenStream์„ ๋ฐ›์•„์„œ ๋ณ€ํ™˜ ํ›„ ์ƒˆ๋กœ์šด TokenStream์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. Analyzer ํŒŒ์ดํ”„๋ผ์ธ์—์„œ Tokenizer์˜ ํ›„์† ๋‹จ๊ณ„๋“ค๋กœ ์—ฌ๋Ÿฌ TokenFilter๋ฅผ ์ค‘์ฒฉํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

'WinUI' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[WinUI] Lucene.NET ํ…์ŠคํŠธ ๊ฒ€์ƒ‰ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉํ•˜๊ธฐ (2) - ์—ฌ๋Ÿฌ ๊ตฌ์„ฑ ์š”์†Œ  (0) 2025.10.30
[WinUI] ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ (6) - ๋‹ค์–‘ํ•œ ์ž๋ฃŒ๊ตฌ์กฐ์™€ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ด์šฉํ•œ INotifyCollectionChanged ๊ตฌํ˜„ ์ปฌ๋ ‰์…˜ ํด๋ž˜์Šค ๋งŒ๋“ค๊ธฐ  (0) 2025.09.29
[WinUI] ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ (5) - INotifyCollectionChanged ๊ตฌํ˜„ ์ปฌ๋ ‰์…˜ ํด๋ž˜์Šค ๋งŒ๋“ค๊ธฐ  (0) 2025.09.27
[WinUI] ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ (4) - ์ปฌ๋ ‰์…˜ ๋ณ€๊ฒฝ ์•Œ๋ฆผ๊ณผ INotifyCollectionChanged ์ธํ„ฐํŽ˜์ด์Šค  (0) 2025.09.20
[WinUI] ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ (3) - ์†์„ฑ ๋ณ€๊ฒฝ ์•Œ๋ฆผ๊ณผ INotifyPropertyChanged ์ธํ„ฐํŽ˜์ด์Šค  (0) 2025.09.18
[WinUI] ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ (2) - Binding/x:Bind ์‚ฌ์šฉ ์˜ˆ์‹œ  (0) 2025.09.03
[WinUI] ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ (1) - ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ์˜ ํ•„์š”์„ฑ๊ณผ Binding/x:Bind ๋งˆํฌ์—… ํ™•์žฅ  (0) 2025.08.25
[WinUI] ์ฆ๋ถ„ ๋กœ๋“œ (2) - ์ฆ๋ถ„ ๋กœ๋“œ ์ปฌ๋ ‰์…˜์„ ๋ทฐ๋ชจ๋ธ๊ณผ ๋ทฐ ์ปจํŠธ๋กค์— ์ ์šฉ  (0) 2025.08.20