[{"data":1,"prerenderedAt":3459},["ShallowReactive",2],{"blog-ko-tables-in-go-pdfs":3},{"id":4,"title":5,"author":6,"body":10,"date":3421,"description":3422,"draft":3423,"extension":3424,"howTo":3425,"image":3449,"meta":3450,"navigation":490,"path":3451,"seo":3452,"stem":3453,"tags":3454,"updated":3449,"__hash__":3458},"blogKo/ko/blog/022.tables-in-go-pdfs.md","Go PDF 테이블: 컬럼 너비, 줄무늬, 페이지 분할",{"name":7,"url":8,"avatar":9},"Taiki Noda","https://nadai.dev/en/about","https://nadai.dev/og-default.png",{"type":11,"value":12,"toc":3404},"minimark",[13,18,26,184,203,206,210,224,227,265,268,272,275,337,344,448,454,458,473,1590,1593,1608,1612,1622,1640,1646,1652,1691,1698,1729,1737,1741,1768,1778,1797,1800,1821,1833,1837,1840,1850,1876,1879,1900,1903,1910,1914,1920,2359,2396,2405,2414,2420,2424,2427,2488,2505,2511,2514,2708,2711,2715,2718,2856,2864,2876,2880,2883,3178,3181,3189,3193,3198,3222,3227,3250,3255,3258,3263,3276,3281,3287,3295,3302,3306,3313,3320,3323,3327,3330,3347,3359,3363,3400],[14,15,17],"h2",{"id":16},"한-줄-요약","한 줄 요약",[19,20,21,25],"p",{},[22,23,24],"strong",{},"테이블은 PDF 생성에서 주말을 날리는 부분이다."," 합이 안 맞는 컬럼 너비, 2페이지에서 사라지는 헤더, 행 루프 off-by-one으로 그려지는 줄무늬. gpdf는 이걸 한 번의 호출로 접는다:",[27,28,33],"pre",{"className":29,"code":30,"language":31,"meta":32,"style":32},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","c.Table(header, rows,\n    template.ColumnWidths(40, 15, 20, 25),\n    template.TableHeaderStyle(template.TextColor(pdf.White), template.BgColor(brand)),\n    template.TableStripe(pdf.RGBHex(0xF5F5F5)),\n)\n","go","",[34,35,36,68,103,152,178],"code",{"__ignoreMap":32},[37,38,41,45,49,53,56,59,62,65],"span",{"class":39,"line":40},"line",1,[37,42,44],{"class":43},"sTEyZ","c",[37,46,48],{"class":47},"sMK4o",".",[37,50,52],{"class":51},"s2Zo4","Table",[37,54,55],{"class":47},"(",[37,57,58],{"class":43},"header",[37,60,61],{"class":47},",",[37,63,64],{"class":43}," rows",[37,66,67],{"class":47},",\n",[37,69,71,74,76,79,81,85,87,90,92,95,97,100],{"class":39,"line":70},2,[37,72,73],{"class":43},"    template",[37,75,48],{"class":47},[37,77,78],{"class":51},"ColumnWidths",[37,80,55],{"class":47},[37,82,84],{"class":83},"sbssI","40",[37,86,61],{"class":47},[37,88,89],{"class":83}," 15",[37,91,61],{"class":47},[37,93,94],{"class":83}," 20",[37,96,61],{"class":47},[37,98,99],{"class":83}," 25",[37,101,102],{"class":47},"),\n",[37,104,106,108,110,113,115,118,120,123,125,128,130,133,136,139,141,144,146,149],{"class":39,"line":105},3,[37,107,73],{"class":43},[37,109,48],{"class":47},[37,111,112],{"class":51},"TableHeaderStyle",[37,114,55],{"class":47},[37,116,117],{"class":43},"template",[37,119,48],{"class":47},[37,121,122],{"class":51},"TextColor",[37,124,55],{"class":47},[37,126,127],{"class":43},"pdf",[37,129,48],{"class":47},[37,131,132],{"class":43},"White",[37,134,135],{"class":47},"),",[37,137,138],{"class":43}," template",[37,140,48],{"class":47},[37,142,143],{"class":51},"BgColor",[37,145,55],{"class":47},[37,147,148],{"class":43},"brand",[37,150,151],{"class":47},")),\n",[37,153,155,157,159,162,164,166,168,171,173,176],{"class":39,"line":154},4,[37,156,73],{"class":43},[37,158,48],{"class":47},[37,160,161],{"class":51},"TableStripe",[37,163,55],{"class":47},[37,165,127],{"class":43},[37,167,48],{"class":47},[37,169,170],{"class":51},"RGBHex",[37,172,55],{"class":47},[37,174,175],{"class":83},"0xF5F5F5",[37,177,151],{"class":47},[37,179,181],{"class":39,"line":180},5,[37,182,183],{"class":47},")\n",[19,185,186,187,190,191,194,195,198,199,202],{},"컬럼 너비, 줄무늬, ",[22,188,189],{},"페이지 분할 시 헤더 자동 반복"," 까지 한 번에. 행 루프 안 쓴다. ",[34,192,193],{},"PageBreak"," 옵션 없다. 테이블이 안 들어가면 레이아웃 엔진이 알아채고 다음 페이지 위쪽에 ",[34,196,197],{},"Header"," 슬라이스를 다시 그린다. ColSpan, RowSpan, 매 페이지 반복 푸터가 필요할 때만 ",[34,200,201],{},"document.Table","로 내려간다 — 같은 부품을 더 세밀하게 조립하는 층이다.",[19,204,205],{},"이 글은 테이블 설계에서 진짜 중요한 세 축 (컬럼 너비, 줄무늬, 페이지 분할)에 대해 gpdf가 각각 무엇을 하는지, 추상화를 어디서 의도적으로 멈추는지를 다룬다.",[14,207,209],{"id":208},"이-글이-필요한-이유","이 글이 필요한 이유",[19,211,212,219,220,223],{},[213,214,218],"a",{"href":215,"rel":216},"https://github.com/gpdf-dev/gpdf",[217],"nofollow","gpdf","는 Go용 PDF 생성 라이브러리다. MIT, 외부 의존 0, 단일 페이지 렌더링 약 13µs. 고수준 API에서 테이블 부분은 작다 — ",[34,221,222],{},"TableOption","이 8개뿐이다 — 가 거기에 걸린 설계 압력은 크다. Go의 PDF 프로젝트는 거의 다 테이블에서 막힌다.",[19,225,226],{},"Go에서 테이블을 그릴 때 실수가 일어나는 세 가지:",[228,229,230,245,255],"ol",{},[231,232,233,236,237,240,241,244],"li",{},[22,234,235],{},"컬럼 너비."," 웹에는 CSS ",[34,238,239],{},"\u003Ccol>","과 ",[34,242,243],{},"colgroup","이 있다. PDF에는 없다. 점(pt) 단위로 직접 계산하거나 라이브러리의 균등 분할을 받아들이거나 둘 중 하나다.",[231,246,247,250,251,254],{},[22,248,249],{},"줄무늬."," 본문 한 줄 걸러 옅은 회색으로 칠해 가독성을 높이고 싶다. 저수준 라이브러리는 직접 행 루프를 쓰고 ",[34,252,253],{},"i % 2","를 추적해야 한다 — 테이블 렌더링 버그의 절반이 여기서 나온다.",[231,256,257,260,261,264],{},[22,258,259],{},"페이지 분할."," 200행 보고서는 A4 한 페이지에 안 들어간다. 라이브러리는 (a) 적절한 위치에서 본문을 자르고, (b) 현재 페이지를 닫고, (c) 새 페이지를 열고, (d) ",[22,262,263],{},"새 페이지 위쪽에 헤더를 다시 그려야"," 한다. 하나라도 빠지면 그 테이블은 못 쓴다.",[19,266,267],{},"이 글은 gpdf가 각 문제를 어떻게 푸는지와 설계상 트레이드오프를 순서대로 설명한다. 복사-붙여넣기 레시피만 원하면 끝의 관련 링크를 보면 된다. 이 글은 \"10,000행짜리 월간 명세서를 이 API에 맡겨도 되는가\"를 판단하려는 사람을 위한 긴 버전이다.",[14,269,271],{"id":270},"api의-모양","API의 모양",[19,273,274],{},"빌더 층의 진입점은 하나:",[27,276,278],{"className":29,"code":277,"language":31,"meta":32,"style":32},"func (c *ColBuilder) Table(header []string, rows [][]string, opts ...TableOption)\n",[34,279,280],{"__ignoreMap":32},[37,281,282,285,288,292,295,299,302,305,307,309,312,316,318,320,323,325,327,330,333,335],{"class":39,"line":40},[37,283,284],{"class":47},"func",[37,286,287],{"class":47}," (",[37,289,291],{"class":290},"sHdIc","c ",[37,293,294],{"class":47},"*",[37,296,298],{"class":297},"sBMFI","ColBuilder",[37,300,301],{"class":47},")",[37,303,304],{"class":51}," Table",[37,306,55],{"class":47},[37,308,58],{"class":290},[37,310,311],{"class":47}," []",[37,313,315],{"class":314},"spNyl","string",[37,317,61],{"class":47},[37,319,64],{"class":290},[37,321,322],{"class":47}," [][]",[37,324,315],{"class":314},[37,326,61],{"class":47},[37,328,329],{"class":290}," opts",[37,331,332],{"class":47}," ...",[37,334,222],{"class":297},[37,336,183],{"class":47},[19,338,339,340,343],{},"헤더는 문자열 슬라이스, 행은 문자열 슬라이스의 슬라이스, 가변 ",[34,341,342],{},"opts","가 나머지를 설정한다. 옵션 생성자는 8개:",[345,346,347,360],"table",{},[348,349,350],"thead",{},[351,352,353,357],"tr",{},[354,355,356],"th",{},"옵션",[354,358,359],{},"제어 대상",[361,362,363,374,384,394,404,414,424,438],"tbody",{},[351,364,365,371],{},[366,367,368],"td",{},[34,369,370],{},"ColumnWidths(...float64)",[366,372,373],{},"부모 Col 너비에 대한 퍼센트, 컬럼당 하나",[351,375,376,381],{},[366,377,378],{},[34,379,380],{},"TableHeaderStyle(...TextOption)",[366,382,383],{},"헤더 배경색과 글자색",[351,385,386,391],{},[366,387,388],{},[34,389,390],{},"TableStripe(pdf.Color)",[366,392,393],{},"본문 교대 행 배경색",[351,395,396,401],{},[366,397,398],{},[34,399,400],{},"TableCellVAlign(document.VerticalAlign)",[366,402,403],{},"본문 셀의 수직 정렬",[351,405,406,411],{},[366,407,408],{},[34,409,410],{},"WithTableBorder(BorderSpec)",[366,412,413],{},"테이블 전체 외곽선",[351,415,416,421],{},[366,417,418],{},[34,419,420],{},"WithTableCellBorder(BorderSpec)",[366,422,423],{},"모든 셀에 같은 테두리 — 그리드 모양",[351,425,426,431],{},[366,427,428],{},[34,429,430],{},"WithTableBorderCollapse(bool)",[366,432,433,434,437],{},"CSS ",[34,435,436],{},"border-collapse: collapse"," 의미",[351,439,440,445],{},[366,441,442],{},[34,443,444],{},"WithTableBackground(pdf.Color)",[366,446,447],{},"테이블 전체 배경",[19,449,450,451,453],{},"빌더 층 표면은 이게 전부다. 빌더로 만들 수 있는 건 이 8개로 다 만든다. 그 너머 — ColSpan, RowSpan, 푸터, 고정 pt 너비 — 는 ",[34,452,201],{},"로 간다. 뒤에 다룬다.",[14,455,457],{"id":456},"동작-코드-6개월치-청구-원장","동작 코드: 6개월치 청구 원장",[19,459,460,461,464,465,468,469,472],{},"완전 실행 가능한 예시. ",[34,462,463],{},"main.go","로 저장하고 ",[34,466,467],{},"go run ."," 실행, ",[34,470,471],{},"ledger.pdf","가 나온다.",[27,474,476],{"className":29,"code":475,"language":31,"meta":32,"style":32},"package main\n\nimport (\n    \"fmt\"\n    \"log\"\n    \"os\"\n\n    \"github.com/gpdf-dev/gpdf\"\n    \"github.com/gpdf-dev/gpdf/document\"\n    \"github.com/gpdf-dev/gpdf/pdf\"\n    \"github.com/gpdf-dev/gpdf/template\"\n)\n\nfunc main() {\n    doc := gpdf.NewDocument(\n        gpdf.WithPageSize(gpdf.A4),\n        gpdf.WithMargins(document.UniformEdges(document.Mm(20))),\n    )\n\n    brand := pdf.RGBHex(0x1A237E)\n    stripe := pdf.RGBHex(0xF5F5F5)\n    hairline := template.Border(\n        template.BorderWidth(document.Pt(0.5)),\n        template.BorderColor(pdf.Gray(0.85)),\n    )\n\n    header := []string{\"날짜\", \"청구번호\", \"고객\", \"금액\"}\n    rows := make([][]string, 0, 120)\n    for i := 1; i \u003C= 120; i++ {\n        rows = append(rows, []string{\n            fmt.Sprintf(\"2026-%02d-%02d\", (i%6)+1, (i%28)+1),\n            fmt.Sprintf(\"INV-%05d\", 10000+i),\n            fmt.Sprintf(\"고객 #%d\", i),\n            fmt.Sprintf(\"₩%d\", (100+i*7)*1000),\n        })\n    }\n\n    page := doc.AddPage()\n    page.AutoRow(func(r *template.RowBuilder) {\n        r.Col(12, func(c *template.ColBuilder) {\n            c.Text(\"2026 상반기 원장\", template.FontSize(18), template.Bold())\n            c.Spacer(document.Mm(4))\n\n            c.Table(header, rows,\n                template.ColumnWidths(20, 20, 40, 20),\n                template.TableHeaderStyle(\n                    template.TextColor(pdf.White),\n                    template.BgColor(brand),\n                ),\n                template.TableStripe(stripe),\n                template.WithTableCellBorder(hairline),\n            )\n        })\n    })\n\n    data, err := doc.Generate()\n    if err != nil {\n        log.Fatal(err)\n    }\n    if err := os.WriteFile(\"ledger.pdf\", data, 0o644); err != nil {\n        log.Fatal(err)\n    }\n}\n",[34,477,478,486,492,501,512,521,531,536,546,556,566,576,581,586,600,620,642,679,685,690,712,732,749,776,802,807,812,867,895,929,955,1020,1053,1080,1124,1130,1136,1141,1160,1191,1226,1272,1298,1303,1322,1351,1362,1382,1397,1403,1419,1436,1442,1447,1453,1458,1480,1496,1514,1519,1565,1580,1585],{"__ignoreMap":32},[37,479,480,483],{"class":39,"line":40},[37,481,482],{"class":47},"package",[37,484,485],{"class":297}," main\n",[37,487,488],{"class":39,"line":70},[37,489,491],{"emptyLinePlaceholder":490},true,"\n",[37,493,494,498],{"class":39,"line":105},[37,495,497],{"class":496},"s7zQu","import",[37,499,500],{"class":47}," (\n",[37,502,503,506,509],{"class":39,"line":154},[37,504,505],{"class":47},"    \"",[37,507,508],{"class":297},"fmt",[37,510,511],{"class":47},"\"\n",[37,513,514,516,519],{"class":39,"line":180},[37,515,505],{"class":47},[37,517,518],{"class":297},"log",[37,520,511],{"class":47},[37,522,524,526,529],{"class":39,"line":523},6,[37,525,505],{"class":47},[37,527,528],{"class":297},"os",[37,530,511],{"class":47},[37,532,534],{"class":39,"line":533},7,[37,535,491],{"emptyLinePlaceholder":490},[37,537,539,541,544],{"class":39,"line":538},8,[37,540,505],{"class":47},[37,542,543],{"class":297},"github.com/gpdf-dev/gpdf",[37,545,511],{"class":47},[37,547,549,551,554],{"class":39,"line":548},9,[37,550,505],{"class":47},[37,552,553],{"class":297},"github.com/gpdf-dev/gpdf/document",[37,555,511],{"class":47},[37,557,559,561,564],{"class":39,"line":558},10,[37,560,505],{"class":47},[37,562,563],{"class":297},"github.com/gpdf-dev/gpdf/pdf",[37,565,511],{"class":47},[37,567,569,571,574],{"class":39,"line":568},11,[37,570,505],{"class":47},[37,572,573],{"class":297},"github.com/gpdf-dev/gpdf/template",[37,575,511],{"class":47},[37,577,579],{"class":39,"line":578},12,[37,580,183],{"class":47},[37,582,584],{"class":39,"line":583},13,[37,585,491],{"emptyLinePlaceholder":490},[37,587,589,591,594,597],{"class":39,"line":588},14,[37,590,284],{"class":47},[37,592,593],{"class":51}," main",[37,595,596],{"class":47},"()",[37,598,599],{"class":47}," {\n",[37,601,603,606,609,612,614,617],{"class":39,"line":602},15,[37,604,605],{"class":43},"    doc ",[37,607,608],{"class":47},":=",[37,610,611],{"class":43}," gpdf",[37,613,48],{"class":47},[37,615,616],{"class":51},"NewDocument",[37,618,619],{"class":47},"(\n",[37,621,623,626,628,631,633,635,637,640],{"class":39,"line":622},16,[37,624,625],{"class":43},"        gpdf",[37,627,48],{"class":47},[37,629,630],{"class":51},"WithPageSize",[37,632,55],{"class":47},[37,634,218],{"class":43},[37,636,48],{"class":47},[37,638,639],{"class":43},"A4",[37,641,102],{"class":47},[37,643,645,647,649,652,654,657,659,662,664,666,668,671,673,676],{"class":39,"line":644},17,[37,646,625],{"class":43},[37,648,48],{"class":47},[37,650,651],{"class":51},"WithMargins",[37,653,55],{"class":47},[37,655,656],{"class":43},"document",[37,658,48],{"class":47},[37,660,661],{"class":51},"UniformEdges",[37,663,55],{"class":47},[37,665,656],{"class":43},[37,667,48],{"class":47},[37,669,670],{"class":51},"Mm",[37,672,55],{"class":47},[37,674,675],{"class":83},"20",[37,677,678],{"class":47},"))),\n",[37,680,682],{"class":39,"line":681},18,[37,683,684],{"class":47},"    )\n",[37,686,688],{"class":39,"line":687},19,[37,689,491],{"emptyLinePlaceholder":490},[37,691,693,696,698,701,703,705,707,710],{"class":39,"line":692},20,[37,694,695],{"class":43},"    brand ",[37,697,608],{"class":47},[37,699,700],{"class":43}," pdf",[37,702,48],{"class":47},[37,704,170],{"class":51},[37,706,55],{"class":47},[37,708,709],{"class":83},"0x1A237E",[37,711,183],{"class":47},[37,713,715,718,720,722,724,726,728,730],{"class":39,"line":714},21,[37,716,717],{"class":43},"    stripe ",[37,719,608],{"class":47},[37,721,700],{"class":43},[37,723,48],{"class":47},[37,725,170],{"class":51},[37,727,55],{"class":47},[37,729,175],{"class":83},[37,731,183],{"class":47},[37,733,735,738,740,742,744,747],{"class":39,"line":734},22,[37,736,737],{"class":43},"    hairline ",[37,739,608],{"class":47},[37,741,138],{"class":43},[37,743,48],{"class":47},[37,745,746],{"class":51},"Border",[37,748,619],{"class":47},[37,750,752,755,757,760,762,764,766,769,771,774],{"class":39,"line":751},23,[37,753,754],{"class":43},"        template",[37,756,48],{"class":47},[37,758,759],{"class":51},"BorderWidth",[37,761,55],{"class":47},[37,763,656],{"class":43},[37,765,48],{"class":47},[37,767,768],{"class":51},"Pt",[37,770,55],{"class":47},[37,772,773],{"class":83},"0.5",[37,775,151],{"class":47},[37,777,779,781,783,786,788,790,792,795,797,800],{"class":39,"line":778},24,[37,780,754],{"class":43},[37,782,48],{"class":47},[37,784,785],{"class":51},"BorderColor",[37,787,55],{"class":47},[37,789,127],{"class":43},[37,791,48],{"class":47},[37,793,794],{"class":51},"Gray",[37,796,55],{"class":47},[37,798,799],{"class":83},"0.85",[37,801,151],{"class":47},[37,803,805],{"class":39,"line":804},25,[37,806,684],{"class":47},[37,808,810],{"class":39,"line":809},26,[37,811,491],{"emptyLinePlaceholder":490},[37,813,815,818,820,822,824,827,830,834,836,838,841,844,846,848,850,853,855,857,859,862,864],{"class":39,"line":814},27,[37,816,817],{"class":43},"    header ",[37,819,608],{"class":47},[37,821,311],{"class":47},[37,823,315],{"class":314},[37,825,826],{"class":47},"{",[37,828,829],{"class":47},"\"",[37,831,833],{"class":832},"sfazB","날짜",[37,835,829],{"class":47},[37,837,61],{"class":47},[37,839,840],{"class":47}," \"",[37,842,843],{"class":832},"청구번호",[37,845,829],{"class":47},[37,847,61],{"class":47},[37,849,840],{"class":47},[37,851,852],{"class":832},"고객",[37,854,829],{"class":47},[37,856,61],{"class":47},[37,858,840],{"class":47},[37,860,861],{"class":832},"금액",[37,863,829],{"class":47},[37,865,866],{"class":47},"}\n",[37,868,870,873,875,878,881,883,885,888,890,893],{"class":39,"line":869},28,[37,871,872],{"class":43},"    rows ",[37,874,608],{"class":47},[37,876,877],{"class":51}," make",[37,879,880],{"class":47},"([][]",[37,882,315],{"class":314},[37,884,61],{"class":47},[37,886,887],{"class":83}," 0",[37,889,61],{"class":47},[37,891,892],{"class":83}," 120",[37,894,183],{"class":47},[37,896,898,901,904,906,909,912,914,917,919,921,924,927],{"class":39,"line":897},29,[37,899,900],{"class":496},"    for",[37,902,903],{"class":43}," i ",[37,905,608],{"class":47},[37,907,908],{"class":83}," 1",[37,910,911],{"class":47},";",[37,913,903],{"class":43},[37,915,916],{"class":47},"\u003C=",[37,918,892],{"class":83},[37,920,911],{"class":47},[37,922,923],{"class":43}," i",[37,925,926],{"class":47},"++",[37,928,599],{"class":47},[37,930,932,935,938,941,943,946,948,950,952],{"class":39,"line":931},30,[37,933,934],{"class":43},"        rows ",[37,936,937],{"class":47},"=",[37,939,940],{"class":51}," append",[37,942,55],{"class":47},[37,944,945],{"class":43},"rows",[37,947,61],{"class":47},[37,949,311],{"class":47},[37,951,315],{"class":314},[37,953,954],{"class":47},"{\n",[37,956,958,961,963,966,968,970,973,977,980,982,984,986,988,991,994,997,1000,1003,1005,1007,1009,1011,1014,1016,1018],{"class":39,"line":957},31,[37,959,960],{"class":43},"            fmt",[37,962,48],{"class":47},[37,964,965],{"class":51},"Sprintf",[37,967,55],{"class":47},[37,969,829],{"class":47},[37,971,972],{"class":832},"2026-",[37,974,976],{"class":975},"swJcz","%02d",[37,978,979],{"class":832},"-",[37,981,976],{"class":975},[37,983,829],{"class":47},[37,985,61],{"class":47},[37,987,287],{"class":47},[37,989,990],{"class":43},"i",[37,992,993],{"class":47},"%",[37,995,996],{"class":83},"6",[37,998,999],{"class":47},")+",[37,1001,1002],{"class":83},"1",[37,1004,61],{"class":47},[37,1006,287],{"class":47},[37,1008,990],{"class":43},[37,1010,993],{"class":47},[37,1012,1013],{"class":83},"28",[37,1015,999],{"class":47},[37,1017,1002],{"class":83},[37,1019,102],{"class":47},[37,1021,1023,1025,1027,1029,1031,1033,1036,1039,1041,1043,1046,1049,1051],{"class":39,"line":1022},32,[37,1024,960],{"class":43},[37,1026,48],{"class":47},[37,1028,965],{"class":51},[37,1030,55],{"class":47},[37,1032,829],{"class":47},[37,1034,1035],{"class":832},"INV-",[37,1037,1038],{"class":975},"%05d",[37,1040,829],{"class":47},[37,1042,61],{"class":47},[37,1044,1045],{"class":83}," 10000",[37,1047,1048],{"class":47},"+",[37,1050,990],{"class":43},[37,1052,102],{"class":47},[37,1054,1056,1058,1060,1062,1064,1066,1069,1072,1074,1076,1078],{"class":39,"line":1055},33,[37,1057,960],{"class":43},[37,1059,48],{"class":47},[37,1061,965],{"class":51},[37,1063,55],{"class":47},[37,1065,829],{"class":47},[37,1067,1068],{"class":832},"고객 #",[37,1070,1071],{"class":975},"%d",[37,1073,829],{"class":47},[37,1075,61],{"class":47},[37,1077,923],{"class":43},[37,1079,102],{"class":47},[37,1081,1083,1085,1087,1089,1091,1093,1096,1098,1100,1102,1104,1107,1109,1111,1113,1116,1119,1122],{"class":39,"line":1082},34,[37,1084,960],{"class":43},[37,1086,48],{"class":47},[37,1088,965],{"class":51},[37,1090,55],{"class":47},[37,1092,829],{"class":47},[37,1094,1095],{"class":832},"₩",[37,1097,1071],{"class":975},[37,1099,829],{"class":47},[37,1101,61],{"class":47},[37,1103,287],{"class":47},[37,1105,1106],{"class":83},"100",[37,1108,1048],{"class":47},[37,1110,990],{"class":43},[37,1112,294],{"class":47},[37,1114,1115],{"class":83},"7",[37,1117,1118],{"class":47},")*",[37,1120,1121],{"class":83},"1000",[37,1123,102],{"class":47},[37,1125,1127],{"class":39,"line":1126},35,[37,1128,1129],{"class":47},"        })\n",[37,1131,1133],{"class":39,"line":1132},36,[37,1134,1135],{"class":47},"    }\n",[37,1137,1139],{"class":39,"line":1138},37,[37,1140,491],{"emptyLinePlaceholder":490},[37,1142,1144,1147,1149,1152,1154,1157],{"class":39,"line":1143},38,[37,1145,1146],{"class":43},"    page ",[37,1148,608],{"class":47},[37,1150,1151],{"class":43}," doc",[37,1153,48],{"class":47},[37,1155,1156],{"class":51},"AddPage",[37,1158,1159],{"class":47},"()\n",[37,1161,1163,1166,1168,1171,1174,1177,1180,1182,1184,1187,1189],{"class":39,"line":1162},39,[37,1164,1165],{"class":43},"    page",[37,1167,48],{"class":47},[37,1169,1170],{"class":51},"AutoRow",[37,1172,1173],{"class":47},"(func(",[37,1175,1176],{"class":290},"r",[37,1178,1179],{"class":47}," *",[37,1181,117],{"class":297},[37,1183,48],{"class":47},[37,1185,1186],{"class":297},"RowBuilder",[37,1188,301],{"class":47},[37,1190,599],{"class":47},[37,1192,1194,1197,1199,1202,1204,1207,1209,1212,1214,1216,1218,1220,1222,1224],{"class":39,"line":1193},40,[37,1195,1196],{"class":43},"        r",[37,1198,48],{"class":47},[37,1200,1201],{"class":51},"Col",[37,1203,55],{"class":47},[37,1205,1206],{"class":83},"12",[37,1208,61],{"class":47},[37,1210,1211],{"class":47}," func(",[37,1213,44],{"class":290},[37,1215,1179],{"class":47},[37,1217,117],{"class":297},[37,1219,48],{"class":47},[37,1221,298],{"class":297},[37,1223,301],{"class":47},[37,1225,599],{"class":47},[37,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1250,1252,1255,1257,1260,1262,1264,1266,1269],{"class":39,"line":1228},41,[37,1230,1231],{"class":43},"            c",[37,1233,48],{"class":47},[37,1235,1236],{"class":51},"Text",[37,1238,55],{"class":47},[37,1240,829],{"class":47},[37,1242,1243],{"class":832},"2026 상반기 원장",[37,1245,829],{"class":47},[37,1247,61],{"class":47},[37,1249,138],{"class":43},[37,1251,48],{"class":47},[37,1253,1254],{"class":51},"FontSize",[37,1256,55],{"class":47},[37,1258,1259],{"class":83},"18",[37,1261,135],{"class":47},[37,1263,138],{"class":43},[37,1265,48],{"class":47},[37,1267,1268],{"class":51},"Bold",[37,1270,1271],{"class":47},"())\n",[37,1273,1275,1277,1279,1282,1284,1286,1288,1290,1292,1295],{"class":39,"line":1274},42,[37,1276,1231],{"class":43},[37,1278,48],{"class":47},[37,1280,1281],{"class":51},"Spacer",[37,1283,55],{"class":47},[37,1285,656],{"class":43},[37,1287,48],{"class":47},[37,1289,670],{"class":51},[37,1291,55],{"class":47},[37,1293,1294],{"class":83},"4",[37,1296,1297],{"class":47},"))\n",[37,1299,1301],{"class":39,"line":1300},43,[37,1302,491],{"emptyLinePlaceholder":490},[37,1304,1306,1308,1310,1312,1314,1316,1318,1320],{"class":39,"line":1305},44,[37,1307,1231],{"class":43},[37,1309,48],{"class":47},[37,1311,52],{"class":51},[37,1313,55],{"class":47},[37,1315,58],{"class":43},[37,1317,61],{"class":47},[37,1319,64],{"class":43},[37,1321,67],{"class":47},[37,1323,1325,1328,1330,1332,1334,1336,1338,1340,1342,1345,1347,1349],{"class":39,"line":1324},45,[37,1326,1327],{"class":43},"                template",[37,1329,48],{"class":47},[37,1331,78],{"class":51},[37,1333,55],{"class":47},[37,1335,675],{"class":83},[37,1337,61],{"class":47},[37,1339,94],{"class":83},[37,1341,61],{"class":47},[37,1343,1344],{"class":83}," 40",[37,1346,61],{"class":47},[37,1348,94],{"class":83},[37,1350,102],{"class":47},[37,1352,1354,1356,1358,1360],{"class":39,"line":1353},46,[37,1355,1327],{"class":43},[37,1357,48],{"class":47},[37,1359,112],{"class":51},[37,1361,619],{"class":47},[37,1363,1365,1368,1370,1372,1374,1376,1378,1380],{"class":39,"line":1364},47,[37,1366,1367],{"class":43},"                    template",[37,1369,48],{"class":47},[37,1371,122],{"class":51},[37,1373,55],{"class":47},[37,1375,127],{"class":43},[37,1377,48],{"class":47},[37,1379,132],{"class":43},[37,1381,102],{"class":47},[37,1383,1385,1387,1389,1391,1393,1395],{"class":39,"line":1384},48,[37,1386,1367],{"class":43},[37,1388,48],{"class":47},[37,1390,143],{"class":51},[37,1392,55],{"class":47},[37,1394,148],{"class":43},[37,1396,102],{"class":47},[37,1398,1400],{"class":39,"line":1399},49,[37,1401,1402],{"class":47},"                ),\n",[37,1404,1406,1408,1410,1412,1414,1417],{"class":39,"line":1405},50,[37,1407,1327],{"class":43},[37,1409,48],{"class":47},[37,1411,161],{"class":51},[37,1413,55],{"class":47},[37,1415,1416],{"class":43},"stripe",[37,1418,102],{"class":47},[37,1420,1422,1424,1426,1429,1431,1434],{"class":39,"line":1421},51,[37,1423,1327],{"class":43},[37,1425,48],{"class":47},[37,1427,1428],{"class":51},"WithTableCellBorder",[37,1430,55],{"class":47},[37,1432,1433],{"class":43},"hairline",[37,1435,102],{"class":47},[37,1437,1439],{"class":39,"line":1438},52,[37,1440,1441],{"class":47},"            )\n",[37,1443,1445],{"class":39,"line":1444},53,[37,1446,1129],{"class":47},[37,1448,1450],{"class":39,"line":1449},54,[37,1451,1452],{"class":47},"    })\n",[37,1454,1456],{"class":39,"line":1455},55,[37,1457,491],{"emptyLinePlaceholder":490},[37,1459,1461,1464,1466,1469,1471,1473,1475,1478],{"class":39,"line":1460},56,[37,1462,1463],{"class":43},"    data",[37,1465,61],{"class":47},[37,1467,1468],{"class":43}," err ",[37,1470,608],{"class":47},[37,1472,1151],{"class":43},[37,1474,48],{"class":47},[37,1476,1477],{"class":51},"Generate",[37,1479,1159],{"class":47},[37,1481,1483,1486,1488,1491,1494],{"class":39,"line":1482},57,[37,1484,1485],{"class":496},"    if",[37,1487,1468],{"class":43},[37,1489,1490],{"class":47},"!=",[37,1492,1493],{"class":47}," nil",[37,1495,599],{"class":47},[37,1497,1499,1502,1504,1507,1509,1512],{"class":39,"line":1498},58,[37,1500,1501],{"class":43},"        log",[37,1503,48],{"class":47},[37,1505,1506],{"class":51},"Fatal",[37,1508,55],{"class":47},[37,1510,1511],{"class":43},"err",[37,1513,183],{"class":47},[37,1515,1517],{"class":39,"line":1516},59,[37,1518,1135],{"class":47},[37,1520,1522,1524,1526,1528,1531,1533,1536,1538,1540,1542,1544,1546,1549,1551,1554,1557,1559,1561,1563],{"class":39,"line":1521},60,[37,1523,1485],{"class":496},[37,1525,1468],{"class":43},[37,1527,608],{"class":47},[37,1529,1530],{"class":43}," os",[37,1532,48],{"class":47},[37,1534,1535],{"class":51},"WriteFile",[37,1537,55],{"class":47},[37,1539,829],{"class":47},[37,1541,471],{"class":832},[37,1543,829],{"class":47},[37,1545,61],{"class":47},[37,1547,1548],{"class":43}," data",[37,1550,61],{"class":47},[37,1552,1553],{"class":83}," 0o644",[37,1555,1556],{"class":47},");",[37,1558,1468],{"class":43},[37,1560,1490],{"class":47},[37,1562,1493],{"class":47},[37,1564,599],{"class":47},[37,1566,1568,1570,1572,1574,1576,1578],{"class":39,"line":1567},61,[37,1569,1501],{"class":43},[37,1571,48],{"class":47},[37,1573,1506],{"class":51},[37,1575,55],{"class":47},[37,1577,1511],{"class":43},[37,1579,183],{"class":47},[37,1581,1583],{"class":39,"line":1582},62,[37,1584,1135],{"class":47},[37,1586,1588],{"class":39,"line":1587},63,[37,1589,866],{"class":47},[19,1591,1592],{},"A4에 120행은 약 5페이지에 걸친다. 매 페이지 위쪽에 짙은 파랑 헤더가 다시 그려지고, 본문은 이전 페이지가 끝난 곳부터 이어지며, 줄무늬 패턴은 페이지를 넘어도 일관된다. 이걸 위해 추가로 쓸 코드는 없다.",[19,1594,1595,1596,1599,1600,1603,1604,1607],{},"이 코드에서 봐야 할 건 ",[22,1597,1598],{},"없는 것"," 이다. 행 루프도, 페이지 카운터도, ",[34,1601,1602],{},"if i == lastRowOnPage"," 분기도, ",[34,1605,1606],{},"PageBreak()"," 호출도, 헤더 재그리기도 없다. 옵션 4줄이 테이블 모양을 선언하고, 엔진이 \"언제 어디서 자를지\"를 담당한다.",[14,1609,1611],{"id":1610},"컬럼-너비-퍼센트는-무엇의-퍼센트인가","컬럼 너비: 퍼센트는 무엇의 퍼센트인가",[19,1613,1614,1617,1618,1621],{},[34,1615,1616],{},"ColumnWidths(40, 15, 20, 25)","는 CSS의 ",[34,1619,1620],{},"\u003Ccol width=\"40%\">","와 비슷하다. 다른 점이 셋 있다.",[19,1623,1624,1627,1628,1631,1632,1635,1636,1639],{},[22,1625,1626],{},"부모 Col에 대한 퍼센트, 페이지가 아니다."," ",[34,1629,1630],{},"r.Col(6, ...)","은 행 콘텐츠 너비의 절반을 차지한다. 그 안에 ",[34,1633,1634],{},"ColumnWidths(50, 50)"," 테이블을 두면 각 컬럼은 ",[22,1637,1638],{},"행 너비의 25%"," 이지 페이지 너비의 50%가 아니다. 퍼센트는 테이블이 놓인 위치에 로컬이다. 테이블을 전체 너비 행에서 나란한 레이아웃으로 옮길 때 옵션 호출은 안 바꿔도 된다.",[19,1641,1642,1645],{},[22,1643,1644],{},"정규화 안 한다."," 합이 90이면 오른쪽이 10% 빈다. 110이면 가장 오른쪽 컬럼이 부모를 넘어 페이지 밖으로 흘러나간다. gpdf는 계산 결과를 그대로 쓴다. 경고도 없다 — 있어선 안 된다. 사용자가 쓴 값을 자동으로 고치는 게 그 버그보다 더 해롭다.",[19,1647,1648,1651],{},[22,1649,1650],{},"뒤쪽 누락은 자동 분배."," 컬럼 수보다 적은 너비를 주면 남는 컬럼이 나머지를 균등 분배한다:",[27,1653,1655],{"className":29,"code":1654,"language":31,"meta":32,"style":32},"// 5컬럼 테이블, 3개 지정\ntemplate.ColumnWidths(40, 10, 20)\n// → 40% / 10% / 20% / 15% / 15%   (남은 30%를 둘이 나눠 가짐)\n",[34,1656,1657,1663,1686],{"__ignoreMap":32},[37,1658,1659],{"class":39,"line":40},[37,1660,1662],{"class":1661},"sHwdD","// 5컬럼 테이블, 3개 지정\n",[37,1664,1665,1667,1669,1671,1673,1675,1677,1680,1682,1684],{"class":39,"line":70},[37,1666,117],{"class":43},[37,1668,48],{"class":47},[37,1670,78],{"class":51},[37,1672,55],{"class":47},[37,1674,84],{"class":83},[37,1676,61],{"class":47},[37,1678,1679],{"class":83}," 10",[37,1681,61],{"class":47},[37,1683,94],{"class":83},[37,1685,183],{"class":47},[37,1687,1688],{"class":39,"line":105},[37,1689,1690],{"class":1661},"// → 40% / 10% / 20% / 15% / 15%   (남은 30%를 둘이 나눠 가짐)\n",[19,1692,1693,1694,1697],{},"\"이 컬럼들 너비만 신경 쓰고 나머진 알아서\"가 유용한 트릭이다. ",[34,1695,1696],{},"0","을 명시적으로 주면 그 컬럼도 자동:",[27,1699,1701],{"className":29,"code":1700,"language":31,"meta":32,"style":32},"template.ColumnWidths(0, 30, 30) // 3컬럼 테이블 → 40% / 30% / 30%\n",[34,1702,1703],{"__ignoreMap":32},[37,1704,1705,1707,1709,1711,1713,1715,1717,1720,1722,1724,1726],{"class":39,"line":40},[37,1706,117],{"class":43},[37,1708,48],{"class":47},[37,1710,78],{"class":51},[37,1712,55],{"class":47},[37,1714,1696],{"class":83},[37,1716,61],{"class":47},[37,1718,1719],{"class":83}," 30",[37,1721,61],{"class":47},[37,1723,1719],{"class":83},[37,1725,301],{"class":47},[37,1727,1728],{"class":1661}," // 3컬럼 테이블 → 40% / 30% / 30%\n",[19,1730,1731,1732,1736],{},"너비의 코너 케이스 디테일은 ",[213,1733,1735],{"href":1734},"/ko/blog/table-column-widths","컬럼 너비 레시피"," 참고. 요약: 퍼센트가 95%의 레이아웃을 커버한다, 안 되는 5%는 한 층 내려간다. 뒤에 다룬다.",[14,1738,1740],{"id":1739},"줄무늬-직접-안-쓰는-행-루프","줄무늬: 직접 안 쓰는 행 루프",[27,1742,1744],{"className":29,"code":1743,"language":31,"meta":32,"style":32},"template.TableStripe(pdf.RGBHex(0xF5F5F5))\n",[34,1745,1746],{"__ignoreMap":32},[37,1747,1748,1750,1752,1754,1756,1758,1760,1762,1764,1766],{"class":39,"line":40},[37,1749,117],{"class":43},[37,1751,48],{"class":47},[37,1753,161],{"class":51},[37,1755,55],{"class":47},[37,1757,127],{"class":43},[37,1759,48],{"class":47},[37,1761,170],{"class":51},[37,1763,55],{"class":47},[37,1765,175],{"class":83},[37,1767,1297],{"class":47},[19,1769,1770,1771,1773,1774,1777],{},"이게 끝. gpdf는 0부터 시작하는 인덱스 ",[34,1772,990],{},"로 본문 행을 순회하고 ",[34,1775,1776],{},"i % 2 == 1","인 행에 색을 칠한다. 헤더는 별도 슬라이스라 카운트 대상이 아니라서, 첫 본문 행은 깨끗하고 두 번째가 음영이 진다 — Bootstrap 관습.",[19,1779,1780,1781,1784,1785,1788,1789,1792,1793,1796],{},"이 옵션이 있는 이유: ",[34,1782,1783],{},"gofpdf","나 ",[34,1786,1787],{},"gopdf","에서는 직접 루프를 쓰고, 행마다 ",[34,1790,1791],{},"SetFillColor","를 호출하고, ",[34,1794,1795],{},"CellFormat","에 채우기 플래그를 넘긴다. 8〜10줄 코드에 off-by-one 발생률이 너무 높아서 StackOverflow에 전용 답변 세트가 있을 정도. 이걸 옵션 하나로 접으면 버그 클래스가 통째로 사라진다.",[19,1798,1799],{},"제약은 의도적:",[1801,1802,1803,1809,1815],"ul",{},[231,1804,1805,1808],{},[22,1806,1807],{},"줄무늬 색은 하나, 두 색 교대 안 됨."," \"파랑과 회색 교대\" 같은 지정 불가. 페이지가 이미 흰색이니 칠하지 않은 행은 자동으로 흰색이다. 세 번째 색 사이클을 추가하면 독자에게 인지 부담만 늘린다 — 줄무늬는 그 반대를 위해 존재한다.",[231,1810,1811,1814],{},[22,1812,1813],{},"홀짝 반전 수단 없음."," 첫 본문 행은 항상 깨끗, 두 번째는 항상 음영. 정말 반전하고 싶으면 데이터 앞에 빈 행을 넣어라. 하지만 그러고 싶은 사람은 없다.",[231,1816,1817,1820],{},[22,1818,1819],{},"줄무늬는 페이지를 넘어도 정확히 유지."," 본문 14번째 행이 2페이지로 넘어가도 14번째인 채로 패리티를 유지한다. 엔진이 분할을 가로질러 인덱스를 이어 간다.",[19,1822,1823,1824,1828,1829,1832],{},"색 선택과 다크 테마 변형은 ",[213,1825,1827],{"href":1826},"/ko/blog/zebra-striped-table-rows","줄무늬 레시피"," 참조. 이 글의 요지: 테이블의 ",[22,1830,1831],{},"속성"," (교대 패턴) 은 테이블 호출 측에서 선언하는 것이지 행 단위로 지시하는 것이 아니다.",[14,1834,1836],{"id":1835},"페이지-분할-진짜-어려운-부분","페이지 분할: 진짜 어려운 부분",[19,1838,1839],{},"대부분의 Go PDF 이야기가 여기서 무너지고, gpdf 설계가 가장 보상받는 곳도 여기다.",[19,1841,1842,1843,1849],{},"간단 버전: ",[22,1844,1845,1846,1848],{},"한 페이지에 안 들어갈 양의 행을 테이블에 넣으면 gpdf가 자동 분할한다. ",[34,1847,197],{}," 슬라이스는 모든 후속 페이지 위쪽에서 재그려진다."," 켜는 옵션도, 호출할 메서드도 없다. 레이아웃 엔진의 기본 동작이다.",[19,1851,1852,1853,1856,1857,1860,1861,1863,1864,1867,1868,1871,1872,1875],{},"자세히 보면 더 흥미롭다. 블록 레이아웃 엔진 (",[34,1854,1855],{},"document/layout/block.go",") 은 가용 높이로 테이블을 레이아웃한다. 본문이 안 들어가면 결과에 ",[34,1858,1859],{},"Overflow"," 필드가 붙는다 — 같은 ",[34,1862,197],{},", 같은 ",[34,1865,1866],{},"Footer",", ",[22,1869,1870],{},"남은 본문 행"," 으로 된 새 ",[34,1873,1874],{},"*document.Table",". 페이지 시스템은 들어간 부분을 현재 페이지로 내보내고, 새 페이지를 열고, 새 페이지 가용 높이로 오버플로 테이블을 다시 레이아웃 엔진에 먹인다. 오버플로가 빌 때까지 반복.",[19,1877,1878],{},"두 가지 귀결:",[228,1880,1881,1894],{},[231,1882,1883,1890,1891,1893],{},[22,1884,1885,1886,1889],{},"헤더는 행 루프가 아니라 ",[34,1887,1888],{},"tbl.Header","에 산다."," 오버플로 테이블이 같은 ",[34,1892,197],{}," 슬라이스를 재사용하므로 후속 페이지 위쪽에서 헤더가 자동 반복된다. 스타일도 컬럼 너비도 전부 동일.",[231,1895,1896,1899],{},[22,1897,1898],{},"\"헤더가 이 페이지에 안 들어감\" 코너 케이스를 생각할 필요 없음."," 레이아웃 엔진이 본문 행을 측정하기 전에 헤더용 공간을 예약한다. 한 페이지에 헤더와 본문 행 하나도 못 넣으면 테이블 전체를 다음 페이지로 보낸다.",[19,1901,1902],{},"푸터 — 도큐먼트 층에서 쓸 때 — 도 같은 방식. 후속 페이지 아래쪽에서 자동으로 매번 그려진다.",[19,1904,1905,1906,1909],{},"없는 기능: \"이 행 그룹은 분리하지 마\" 어노테이션, 특정 행에서 분할 억제, \"이 테이블은 새 페이지에서 시작\" 지시. 앞 둘은 TODO. 셋째는 페이지 층에서 — 테이블 포함 행 앞에서 ",[34,1907,1908],{},"doc.AddPage()","를 호출.",[14,1911,1913],{"id":1912},"빌더-api를-넘어설-때","빌더 API를 넘어설 때",[19,1915,1916,1917,1919],{},"빌더는 일반적인 경우에 강하다. 셀 합치기, 고정 pt 너비, 매 페이지 반복 푸터, 셀마다 다른 콘텐츠 타입을 섞을 때는 ",[34,1918,201],{},"로 내려간다.",[27,1921,1923],{"className":29,"code":1922,"language":31,"meta":32,"style":32},"import (\n    \"github.com/gpdf-dev/gpdf/document\"\n)\n\nfooter := document.TableRow{\n    Cells: []document.TableCell{\n        {\n            Content: []document.DocumentNode{\n                &document.Text{Content: \"합계\", TextStyle: document.DefaultStyle()},\n            },\n            ColSpan: 3, // ← 앞 3컬럼에 걸침\n            RowSpan: 1,\n        },\n        {\n            Content: []document.DocumentNode{\n                &document.Text{Content: \"₩48,720,000\", TextStyle: document.DefaultStyle()},\n            },\n            ColSpan: 1,\n            RowSpan: 1,\n        },\n    },\n}\n\ntbl := &document.Table{\n    Columns: []document.TableColumn{\n        {Width: document.Pct(20)},\n        {Width: document.Pct(20)},\n        {Width: document.Auto},\n        {Width: document.Pt(80)}, // 페이지 너비와 무관하게 고정 80pt\n    },\n    Header: /* ... */,\n    Body:   /* ... */,\n    Footer: []document.TableRow{footer},\n}\n",[34,1924,1925,1931,1939,1943,1947,1964,1983,1988,2006,2048,2053,2068,2079,2084,2088,2104,2141,2145,2155,2165,2169,2174,2178,2182,2200,2218,2242,2262,2280,2305,2309,2321,2333,2355],{"__ignoreMap":32},[37,1926,1927,1929],{"class":39,"line":40},[37,1928,497],{"class":496},[37,1930,500],{"class":47},[37,1932,1933,1935,1937],{"class":39,"line":70},[37,1934,505],{"class":47},[37,1936,553],{"class":297},[37,1938,511],{"class":47},[37,1940,1941],{"class":39,"line":105},[37,1942,183],{"class":47},[37,1944,1945],{"class":39,"line":154},[37,1946,491],{"emptyLinePlaceholder":490},[37,1948,1949,1952,1954,1957,1959,1962],{"class":39,"line":180},[37,1950,1951],{"class":43},"footer ",[37,1953,608],{"class":47},[37,1955,1956],{"class":297}," document",[37,1958,48],{"class":47},[37,1960,1961],{"class":297},"TableRow",[37,1963,954],{"class":47},[37,1965,1966,1969,1972,1974,1976,1978,1981],{"class":39,"line":523},[37,1967,1968],{"class":43},"    Cells",[37,1970,1971],{"class":47},":",[37,1973,311],{"class":47},[37,1975,656],{"class":297},[37,1977,48],{"class":47},[37,1979,1980],{"class":297},"TableCell",[37,1982,954],{"class":47},[37,1984,1985],{"class":39,"line":533},[37,1986,1987],{"class":47},"        {\n",[37,1989,1990,1993,1995,1997,1999,2001,2004],{"class":39,"line":538},[37,1991,1992],{"class":43},"            Content",[37,1994,1971],{"class":47},[37,1996,311],{"class":47},[37,1998,656],{"class":297},[37,2000,48],{"class":47},[37,2002,2003],{"class":297},"DocumentNode",[37,2005,954],{"class":47},[37,2007,2008,2011,2013,2015,2017,2019,2022,2024,2026,2029,2031,2033,2036,2038,2040,2042,2045],{"class":39,"line":548},[37,2009,2010],{"class":47},"                &",[37,2012,656],{"class":297},[37,2014,48],{"class":47},[37,2016,1236],{"class":297},[37,2018,826],{"class":47},[37,2020,2021],{"class":43},"Content",[37,2023,1971],{"class":47},[37,2025,840],{"class":47},[37,2027,2028],{"class":832},"합계",[37,2030,829],{"class":47},[37,2032,61],{"class":47},[37,2034,2035],{"class":43}," TextStyle",[37,2037,1971],{"class":47},[37,2039,1956],{"class":43},[37,2041,48],{"class":47},[37,2043,2044],{"class":51},"DefaultStyle",[37,2046,2047],{"class":47},"()},\n",[37,2049,2050],{"class":39,"line":558},[37,2051,2052],{"class":47},"            },\n",[37,2054,2055,2058,2060,2063,2065],{"class":39,"line":568},[37,2056,2057],{"class":43},"            ColSpan",[37,2059,1971],{"class":47},[37,2061,2062],{"class":83}," 3",[37,2064,61],{"class":47},[37,2066,2067],{"class":1661}," // ← 앞 3컬럼에 걸침\n",[37,2069,2070,2073,2075,2077],{"class":39,"line":578},[37,2071,2072],{"class":43},"            RowSpan",[37,2074,1971],{"class":47},[37,2076,908],{"class":83},[37,2078,67],{"class":47},[37,2080,2081],{"class":39,"line":583},[37,2082,2083],{"class":47},"        },\n",[37,2085,2086],{"class":39,"line":588},[37,2087,1987],{"class":47},[37,2089,2090,2092,2094,2096,2098,2100,2102],{"class":39,"line":602},[37,2091,1992],{"class":43},[37,2093,1971],{"class":47},[37,2095,311],{"class":47},[37,2097,656],{"class":297},[37,2099,48],{"class":47},[37,2101,2003],{"class":297},[37,2103,954],{"class":47},[37,2105,2106,2108,2110,2112,2114,2116,2118,2120,2122,2125,2127,2129,2131,2133,2135,2137,2139],{"class":39,"line":622},[37,2107,2010],{"class":47},[37,2109,656],{"class":297},[37,2111,48],{"class":47},[37,2113,1236],{"class":297},[37,2115,826],{"class":47},[37,2117,2021],{"class":43},[37,2119,1971],{"class":47},[37,2121,840],{"class":47},[37,2123,2124],{"class":832},"₩48,720,000",[37,2126,829],{"class":47},[37,2128,61],{"class":47},[37,2130,2035],{"class":43},[37,2132,1971],{"class":47},[37,2134,1956],{"class":43},[37,2136,48],{"class":47},[37,2138,2044],{"class":51},[37,2140,2047],{"class":47},[37,2142,2143],{"class":39,"line":644},[37,2144,2052],{"class":47},[37,2146,2147,2149,2151,2153],{"class":39,"line":681},[37,2148,2057],{"class":43},[37,2150,1971],{"class":47},[37,2152,908],{"class":83},[37,2154,67],{"class":47},[37,2156,2157,2159,2161,2163],{"class":39,"line":687},[37,2158,2072],{"class":43},[37,2160,1971],{"class":47},[37,2162,908],{"class":83},[37,2164,67],{"class":47},[37,2166,2167],{"class":39,"line":692},[37,2168,2083],{"class":47},[37,2170,2171],{"class":39,"line":714},[37,2172,2173],{"class":47},"    },\n",[37,2175,2176],{"class":39,"line":734},[37,2177,866],{"class":47},[37,2179,2180],{"class":39,"line":751},[37,2181,491],{"emptyLinePlaceholder":490},[37,2183,2184,2187,2189,2192,2194,2196,2198],{"class":39,"line":778},[37,2185,2186],{"class":43},"tbl ",[37,2188,608],{"class":47},[37,2190,2191],{"class":47}," &",[37,2193,656],{"class":297},[37,2195,48],{"class":47},[37,2197,52],{"class":297},[37,2199,954],{"class":47},[37,2201,2202,2205,2207,2209,2211,2213,2216],{"class":39,"line":804},[37,2203,2204],{"class":43},"    Columns",[37,2206,1971],{"class":47},[37,2208,311],{"class":47},[37,2210,656],{"class":297},[37,2212,48],{"class":47},[37,2214,2215],{"class":297},"TableColumn",[37,2217,954],{"class":47},[37,2219,2220,2223,2226,2228,2230,2232,2235,2237,2239],{"class":39,"line":809},[37,2221,2222],{"class":47},"        {",[37,2224,2225],{"class":43},"Width",[37,2227,1971],{"class":47},[37,2229,1956],{"class":43},[37,2231,48],{"class":47},[37,2233,2234],{"class":51},"Pct",[37,2236,55],{"class":47},[37,2238,675],{"class":83},[37,2240,2241],{"class":47},")},\n",[37,2243,2244,2246,2248,2250,2252,2254,2256,2258,2260],{"class":39,"line":814},[37,2245,2222],{"class":47},[37,2247,2225],{"class":43},[37,2249,1971],{"class":47},[37,2251,1956],{"class":43},[37,2253,48],{"class":47},[37,2255,2234],{"class":51},[37,2257,55],{"class":47},[37,2259,675],{"class":83},[37,2261,2241],{"class":47},[37,2263,2264,2266,2268,2270,2272,2274,2277],{"class":39,"line":869},[37,2265,2222],{"class":47},[37,2267,2225],{"class":43},[37,2269,1971],{"class":47},[37,2271,1956],{"class":43},[37,2273,48],{"class":47},[37,2275,2276],{"class":43},"Auto",[37,2278,2279],{"class":47},"},\n",[37,2281,2282,2284,2286,2288,2290,2292,2294,2296,2299,2302],{"class":39,"line":897},[37,2283,2222],{"class":47},[37,2285,2225],{"class":43},[37,2287,1971],{"class":47},[37,2289,1956],{"class":43},[37,2291,48],{"class":47},[37,2293,768],{"class":51},[37,2295,55],{"class":47},[37,2297,2298],{"class":83},"80",[37,2300,2301],{"class":47},")},",[37,2303,2304],{"class":1661}," // 페이지 너비와 무관하게 고정 80pt\n",[37,2306,2307],{"class":39,"line":931},[37,2308,2173],{"class":47},[37,2310,2311,2314,2316,2319],{"class":39,"line":957},[37,2312,2313],{"class":43},"    Header",[37,2315,1971],{"class":47},[37,2317,2318],{"class":1661}," /* ... */",[37,2320,67],{"class":47},[37,2322,2323,2326,2328,2331],{"class":39,"line":1022},[37,2324,2325],{"class":43},"    Body",[37,2327,1971],{"class":47},[37,2329,2330],{"class":1661},"   /* ... */",[37,2332,67],{"class":47},[37,2334,2335,2338,2340,2342,2344,2346,2348,2350,2353],{"class":39,"line":1055},[37,2336,2337],{"class":43},"    Footer",[37,2339,1971],{"class":47},[37,2341,311],{"class":47},[37,2343,656],{"class":297},[37,2345,48],{"class":47},[37,2347,1961],{"class":297},[37,2349,826],{"class":47},[37,2351,2352],{"class":43},"footer",[37,2354,2279],{"class":47},[37,2356,2357],{"class":39,"line":1082},[37,2358,866],{"class":47},[19,2360,2361,2362,2365,2366,2369,2370,2372,2373,2372,2375,2372,2378,2372,2381,2372,2384,2386,2387,2389,2390,2392,2393,2395],{},"몇 가지. ",[34,2363,2364],{},"TableColumn.Width","는 ",[34,2367,2368],{},"document.Value"," 타입으로 ",[34,2371,768],{}," / ",[34,2374,670],{},[34,2376,2377],{},"Cm",[34,2379,2380],{},"In",[34,2382,2383],{},"Em",[34,2385,2234],{},", 그리고 특별한 ",[34,2388,2276],{},"를 받는다. 한 테이블 안에서 섞을 수 있다. ",[34,2391,2276],{}," 컬럼은 고정과 퍼센트 컬럼을 빼고 남은 걸 공유한다. 빌더의 퍼센트 전용 모델보다 CSS ",[34,2394,239],{}," 요소에 더 가깝다.",[19,2397,2398,240,2401,2404],{},[34,2399,2400],{},"TableCell.ColSpan",[34,2402,2403],{},"RowSpan","은 정수, 기본값 1. 예시는 앞 3컬럼을 합쳐 \"합계\"를 적고 4번째에 금액을 둔다 — 클래식 청구서 푸터.",[19,2406,2407,2365,2410,2413],{},[34,2408,2409],{},"document.Table.Footer",[34,2411,2412],{},"[]TableRow","로 헤더처럼 매 페이지 반복된다. 빌더 API가 노출하지 않는 건 짧은 테이블 대부분이 안 쓰기 때문 — 쓸 필요가 생기면 이미 \"일반 경우\"를 벗어났다.",[19,2415,2416,2417,2419],{},"이게 gpdf 전반의 패턴이다. 고수준 빌더가 90%를 쾌적하게 커버하고, 도큐먼트 층이 나머지 10%를 위해 옆에 앉아 있다. 별개 라이브러리가 아니다. 같은 도큐먼트에 빌더 행과 수동 행을 섞을 수 있다. 빌더는 같은 ",[34,2418,201],{}," 노드의 생성자일 뿐이다.",[14,2421,2423],{"id":2422},"테두리와-박스-모델","테두리와 박스 모델",[19,2425,2426],{},"테두리 옵션은 셋, 각자 다른 일을 한다:",[27,2428,2430],{"className":29,"code":2429,"language":31,"meta":32,"style":32},"template.WithTableBorder(spec)         // 테이블 전체 외곽선\ntemplate.WithTableCellBorder(spec)     // 모든 셀에 같은 테두리\ntemplate.WithTableBorderCollapse(true) // 인접 셀 테두리 병합\n",[34,2431,2432,2451,2468],{"__ignoreMap":32},[37,2433,2434,2436,2438,2441,2443,2446,2448],{"class":39,"line":40},[37,2435,117],{"class":43},[37,2437,48],{"class":47},[37,2439,2440],{"class":51},"WithTableBorder",[37,2442,55],{"class":47},[37,2444,2445],{"class":43},"spec",[37,2447,301],{"class":47},[37,2449,2450],{"class":1661},"         // 테이블 전체 외곽선\n",[37,2452,2453,2455,2457,2459,2461,2463,2465],{"class":39,"line":70},[37,2454,117],{"class":43},[37,2456,48],{"class":47},[37,2458,1428],{"class":51},[37,2460,55],{"class":47},[37,2462,2445],{"class":43},[37,2464,301],{"class":47},[37,2466,2467],{"class":1661},"     // 모든 셀에 같은 테두리\n",[37,2469,2470,2472,2474,2477,2479,2483,2485],{"class":39,"line":105},[37,2471,117],{"class":43},[37,2473,48],{"class":47},[37,2475,2476],{"class":51},"WithTableBorderCollapse",[37,2478,55],{"class":47},[37,2480,2482],{"class":2481},"sfNiH","true",[37,2484,301],{"class":47},[37,2486,2487],{"class":1661}," // 인접 셀 테두리 병합\n",[19,2489,2490,2491,2493,2494,2496,2497,2500,2501,2504],{},"기본은 테두리 없음. 외곽만 원하면 ",[34,2492,2440],{},". 그리드를 원하면 ",[34,2495,1428],{},". 둘 다 더하면 \"외곽 + 그리드\". ",[34,2498,2499],{},"BorderSpec"," 자체는 ",[34,2502,2503],{},"template.Border(template.BorderWidth(...), template.BorderColor(...))","로 만든다.",[19,2506,2507,2510],{},[34,2508,2509],{},"WithTableBorderCollapse(true)","는 CSS 동명 속성과 같은 의미: 인접 셀 테두리가 한 줄로 병합된다 (각 셀의 변에서 두 번 그리지 않음). 헤어라인 그리드에선 이쪽이 깔끔하다, 일부러 두께를 두 배로 보고 싶은 굵은 테두리에선 끄면 된다. 기본은 분리.",[19,2512,2513],{},"실용적인 조합은 헤어라인 셀 테두리 + 옅은 줄무늬:",[27,2515,2517],{"className":29,"code":2516,"language":31,"meta":32,"style":32},"c.Table(header, rows,\n    template.ColumnWidths(40, 20, 15, 25),\n    template.TableHeaderStyle(template.TextColor(pdf.White), template.BgColor(brand)),\n    template.TableStripe(pdf.RGBHex(0xF5F5F5)),\n    template.WithTableCellBorder(template.Border(\n        template.BorderWidth(document.Pt(0.5)),\n        template.BorderColor(pdf.Gray(0.85)),\n    )),\n    template.WithTableBorderCollapse(true),\n)\n",[34,2518,2519,2537,2563,2601,2623,2641,2663,2685,2690,2704],{"__ignoreMap":32},[37,2520,2521,2523,2525,2527,2529,2531,2533,2535],{"class":39,"line":40},[37,2522,44],{"class":43},[37,2524,48],{"class":47},[37,2526,52],{"class":51},[37,2528,55],{"class":47},[37,2530,58],{"class":43},[37,2532,61],{"class":47},[37,2534,64],{"class":43},[37,2536,67],{"class":47},[37,2538,2539,2541,2543,2545,2547,2549,2551,2553,2555,2557,2559,2561],{"class":39,"line":70},[37,2540,73],{"class":43},[37,2542,48],{"class":47},[37,2544,78],{"class":51},[37,2546,55],{"class":47},[37,2548,84],{"class":83},[37,2550,61],{"class":47},[37,2552,94],{"class":83},[37,2554,61],{"class":47},[37,2556,89],{"class":83},[37,2558,61],{"class":47},[37,2560,99],{"class":83},[37,2562,102],{"class":47},[37,2564,2565,2567,2569,2571,2573,2575,2577,2579,2581,2583,2585,2587,2589,2591,2593,2595,2597,2599],{"class":39,"line":105},[37,2566,73],{"class":43},[37,2568,48],{"class":47},[37,2570,112],{"class":51},[37,2572,55],{"class":47},[37,2574,117],{"class":43},[37,2576,48],{"class":47},[37,2578,122],{"class":51},[37,2580,55],{"class":47},[37,2582,127],{"class":43},[37,2584,48],{"class":47},[37,2586,132],{"class":43},[37,2588,135],{"class":47},[37,2590,138],{"class":43},[37,2592,48],{"class":47},[37,2594,143],{"class":51},[37,2596,55],{"class":47},[37,2598,148],{"class":43},[37,2600,151],{"class":47},[37,2602,2603,2605,2607,2609,2611,2613,2615,2617,2619,2621],{"class":39,"line":154},[37,2604,73],{"class":43},[37,2606,48],{"class":47},[37,2608,161],{"class":51},[37,2610,55],{"class":47},[37,2612,127],{"class":43},[37,2614,48],{"class":47},[37,2616,170],{"class":51},[37,2618,55],{"class":47},[37,2620,175],{"class":83},[37,2622,151],{"class":47},[37,2624,2625,2627,2629,2631,2633,2635,2637,2639],{"class":39,"line":180},[37,2626,73],{"class":43},[37,2628,48],{"class":47},[37,2630,1428],{"class":51},[37,2632,55],{"class":47},[37,2634,117],{"class":43},[37,2636,48],{"class":47},[37,2638,746],{"class":51},[37,2640,619],{"class":47},[37,2642,2643,2645,2647,2649,2651,2653,2655,2657,2659,2661],{"class":39,"line":523},[37,2644,754],{"class":43},[37,2646,48],{"class":47},[37,2648,759],{"class":51},[37,2650,55],{"class":47},[37,2652,656],{"class":43},[37,2654,48],{"class":47},[37,2656,768],{"class":51},[37,2658,55],{"class":47},[37,2660,773],{"class":83},[37,2662,151],{"class":47},[37,2664,2665,2667,2669,2671,2673,2675,2677,2679,2681,2683],{"class":39,"line":533},[37,2666,754],{"class":43},[37,2668,48],{"class":47},[37,2670,785],{"class":51},[37,2672,55],{"class":47},[37,2674,127],{"class":43},[37,2676,48],{"class":47},[37,2678,794],{"class":51},[37,2680,55],{"class":47},[37,2682,799],{"class":83},[37,2684,151],{"class":47},[37,2686,2687],{"class":39,"line":538},[37,2688,2689],{"class":47},"    )),\n",[37,2691,2692,2694,2696,2698,2700,2702],{"class":39,"line":548},[37,2693,73],{"class":43},[37,2695,48],{"class":47},[37,2697,2476],{"class":51},[37,2699,55],{"class":47},[37,2701,2482],{"class":2481},[37,2703,102],{"class":47},[37,2705,2706],{"class":39,"line":558},[37,2707,183],{"class":47},[19,2709,2710],{},"회계사의 Excel 인쇄 미리보기 그 느낌. 청구서, 명세서, 원장, 경비 정산 — 재무 인접 문서의 합리적 기본값이다.",[14,2712,2714],{"id":2713},"다른-라이브러리와-비교","다른 라이브러리와 비교",[19,2716,2717],{},"참고로 같은 \"다중 페이지 + 줄무늬\" 테이블이 보통 gpdf로 대체되는 라이브러리에서 어떻게 나오는지:",[345,2719,2720,2739],{},[348,2721,2722],{},[351,2723,2724,2727,2730,2733,2736],{},[354,2725,2726],{},"라이브러리",[354,2728,2729],{},"테이블 코드 줄 수",[354,2731,2732],{},"페이지 분할 시 헤더 반복",[354,2734,2735],{},"줄무늬",[354,2737,2738],{},"비고",[361,2740,2741,2767,2789,2804,2820,2840],{},[351,2742,2743,2747,2752,2757,2764],{},[366,2744,2745],{},[22,2746,218],{},[366,2748,2749],{},[22,2750,2751],{},"약 10줄",[366,2753,2754],{},[22,2755,2756],{},"자동",[366,2758,2759],{},[22,2760,2761],{},[34,2762,2763],{},"TableStripe(...)",[366,2765,2766],{},"빌더와 저수준 둘 다 사용 가능",[351,2768,2769,2772,2775,2781,2786],{},[366,2770,2771],{},"jung-kurt/gofpdf (2021 보관)",[366,2773,2774],{},"40〜60줄",[366,2776,2777,2778,2780],{},"수동: Y 추적, ",[34,2779,1156],{},", 헤더 재그리기",[366,2782,2783,2784],{},"행 루프 안에서 ",[34,2785,1791],{},[366,2787,2788],{},"토대지만 유지 보수 종료",[351,2790,2791,2794,2796,2799,2801],{},[366,2792,2793],{},"go-pdf/fpdf (2025 보관)",[366,2795,2774],{},[366,2797,2798],{},"동일",[366,2800,2798],{},[366,2802,2803],{},"gofpdf 포크. 같은 모델",[351,2805,2806,2809,2812,2815,2817],{},[366,2807,2808],{},"signintech/gopdf",[366,2810,2811],{},"50〜80줄",[366,2813,2814],{},"수동",[366,2816,2814],{},[366,2818,2819],{},"더 저수준",[351,2821,2822,2825,2828,2830,2837],{},[366,2823,2824],{},"johnfercher/maroto v2",[366,2826,2827],{},"약 15줄",[366,2829,2756],{},[366,2831,2832,2833,2836],{},"행마다 ",[34,2834,2835],{},"WithBackgroundColor"," 수동",[366,2838,2839],{},"gofpdf 위에 구축. API는 깔끔하지만 의존성 상속",[351,2841,2842,2845,2848,2850,2853],{},[366,2843,2844],{},"unidoc/unipdf",[366,2846,2847],{},"약 12줄",[366,2849,2756],{},[366,2851,2852],{},"행 스타일 헬퍼 있음",[366,2854,2855],{},"상용 라이선스 필수",[19,2857,2858,2859,1784,2861,2863],{},"빌더 줄 수만 보면 차이가 좁아 보인다. 진짜 차이는 6개월 후에 드러난다. 요구가 흘러갈 때 — 새 컬럼이 다른 정렬을 원하고, 보고서가 일본어 버전을 필요로 하고, 고객이 푸터에 행 수 표시를 요구하고 — ",[34,2860,1783],{},[34,2862,1787],{},"로는 매번 행 루프를 건드려야 한다. gpdf는 옵션 리스트가 길어지고 본문은 그대로다.",[19,2865,2866,2867,2871,2872,48],{},"µs 단위 벤치마크는 ",[213,2868,2870],{"href":2869},"/ko/blog/why-gpdf-is-faster","gpdf가 빠른 이유",". 더 넓은 축의 비교는 ",[213,2873,2875],{"href":2874},"/ko/blog/go-pdf-library-showdown-2026","2026 라이브러리 총람",[14,2877,2879],{"id":2878},"테이블-안의-cjk","테이블 안의 CJK",[19,2881,2882],{},"위 비교표에서 안 보이는 사실: gpdf는 CJK 글리프를 네이티브로 렌더링한다. 한국어용 \"테이블 모드\"는 없다 — 폰트를 한 번 등록하면 테이블도 그걸 사용한다.",[27,2884,2886],{"className":29,"code":2885,"language":31,"meta":32,"style":32},"ttf, _ := os.ReadFile(\"NotoSansKR-Regular.ttf\")\ndoc := gpdf.NewDocument(\n    gpdf.WithPageSize(gpdf.A4),\n    gpdf.WithFont(\"NotoSansKR\", ttf),\n    gpdf.WithDefaultFont(\"NotoSansKR\"),\n)\n\nc.Table(\n    []string{\"날짜\", \"청구번호\", \"고객\", \"금액\"},\n    [][]string{\n        {\"2026-04-01\", \"INV-10001\", \"샘플 주식회사\", \"₩120,000\"},\n        {\"2026-04-02\", \"INV-10002\", \"야마다 상점\", \"₩38,500\"},\n    },\n    template.ColumnWidths(20, 20, 40, 20),\n)\n",[34,2887,2888,2918,2933,2952,2977,2996,3000,3004,3014,3055,3064,3104,3144,3148,3174],{"__ignoreMap":32},[37,2889,2890,2893,2895,2898,2900,2902,2904,2907,2909,2911,2914,2916],{"class":39,"line":40},[37,2891,2892],{"class":43},"ttf",[37,2894,61],{"class":47},[37,2896,2897],{"class":43}," _ ",[37,2899,608],{"class":47},[37,2901,1530],{"class":43},[37,2903,48],{"class":47},[37,2905,2906],{"class":51},"ReadFile",[37,2908,55],{"class":47},[37,2910,829],{"class":47},[37,2912,2913],{"class":832},"NotoSansKR-Regular.ttf",[37,2915,829],{"class":47},[37,2917,183],{"class":47},[37,2919,2920,2923,2925,2927,2929,2931],{"class":39,"line":70},[37,2921,2922],{"class":43},"doc ",[37,2924,608],{"class":47},[37,2926,611],{"class":43},[37,2928,48],{"class":47},[37,2930,616],{"class":51},[37,2932,619],{"class":47},[37,2934,2935,2938,2940,2942,2944,2946,2948,2950],{"class":39,"line":105},[37,2936,2937],{"class":43},"    gpdf",[37,2939,48],{"class":47},[37,2941,630],{"class":51},[37,2943,55],{"class":47},[37,2945,218],{"class":43},[37,2947,48],{"class":47},[37,2949,639],{"class":43},[37,2951,102],{"class":47},[37,2953,2954,2956,2958,2961,2963,2965,2968,2970,2972,2975],{"class":39,"line":154},[37,2955,2937],{"class":43},[37,2957,48],{"class":47},[37,2959,2960],{"class":51},"WithFont",[37,2962,55],{"class":47},[37,2964,829],{"class":47},[37,2966,2967],{"class":832},"NotoSansKR",[37,2969,829],{"class":47},[37,2971,61],{"class":47},[37,2973,2974],{"class":43}," ttf",[37,2976,102],{"class":47},[37,2978,2979,2981,2983,2986,2988,2990,2992,2994],{"class":39,"line":180},[37,2980,2937],{"class":43},[37,2982,48],{"class":47},[37,2984,2985],{"class":51},"WithDefaultFont",[37,2987,55],{"class":47},[37,2989,829],{"class":47},[37,2991,2967],{"class":832},[37,2993,829],{"class":47},[37,2995,102],{"class":47},[37,2997,2998],{"class":39,"line":523},[37,2999,183],{"class":47},[37,3001,3002],{"class":39,"line":533},[37,3003,491],{"emptyLinePlaceholder":490},[37,3005,3006,3008,3010,3012],{"class":39,"line":538},[37,3007,44],{"class":43},[37,3009,48],{"class":47},[37,3011,52],{"class":51},[37,3013,619],{"class":47},[37,3015,3016,3019,3021,3023,3025,3027,3029,3031,3033,3035,3037,3039,3041,3043,3045,3047,3049,3051,3053],{"class":39,"line":548},[37,3017,3018],{"class":47},"    []",[37,3020,315],{"class":314},[37,3022,826],{"class":47},[37,3024,829],{"class":47},[37,3026,833],{"class":832},[37,3028,829],{"class":47},[37,3030,61],{"class":47},[37,3032,840],{"class":47},[37,3034,843],{"class":832},[37,3036,829],{"class":47},[37,3038,61],{"class":47},[37,3040,840],{"class":47},[37,3042,852],{"class":832},[37,3044,829],{"class":47},[37,3046,61],{"class":47},[37,3048,840],{"class":47},[37,3050,861],{"class":832},[37,3052,829],{"class":47},[37,3054,2279],{"class":47},[37,3056,3057,3060,3062],{"class":39,"line":558},[37,3058,3059],{"class":47},"    [][]",[37,3061,315],{"class":314},[37,3063,954],{"class":47},[37,3065,3066,3068,3070,3073,3075,3077,3079,3082,3084,3086,3088,3091,3093,3095,3097,3100,3102],{"class":39,"line":568},[37,3067,2222],{"class":47},[37,3069,829],{"class":47},[37,3071,3072],{"class":832},"2026-04-01",[37,3074,829],{"class":47},[37,3076,61],{"class":47},[37,3078,840],{"class":47},[37,3080,3081],{"class":832},"INV-10001",[37,3083,829],{"class":47},[37,3085,61],{"class":47},[37,3087,840],{"class":47},[37,3089,3090],{"class":832},"샘플 주식회사",[37,3092,829],{"class":47},[37,3094,61],{"class":47},[37,3096,840],{"class":47},[37,3098,3099],{"class":832},"₩120,000",[37,3101,829],{"class":47},[37,3103,2279],{"class":47},[37,3105,3106,3108,3110,3113,3115,3117,3119,3122,3124,3126,3128,3131,3133,3135,3137,3140,3142],{"class":39,"line":578},[37,3107,2222],{"class":47},[37,3109,829],{"class":47},[37,3111,3112],{"class":832},"2026-04-02",[37,3114,829],{"class":47},[37,3116,61],{"class":47},[37,3118,840],{"class":47},[37,3120,3121],{"class":832},"INV-10002",[37,3123,829],{"class":47},[37,3125,61],{"class":47},[37,3127,840],{"class":47},[37,3129,3130],{"class":832},"야마다 상점",[37,3132,829],{"class":47},[37,3134,61],{"class":47},[37,3136,840],{"class":47},[37,3138,3139],{"class":832},"₩38,500",[37,3141,829],{"class":47},[37,3143,2279],{"class":47},[37,3145,3146],{"class":39,"line":583},[37,3147,2173],{"class":47},[37,3149,3150,3152,3154,3156,3158,3160,3162,3164,3166,3168,3170,3172],{"class":39,"line":588},[37,3151,73],{"class":43},[37,3153,48],{"class":47},[37,3155,78],{"class":51},[37,3157,55],{"class":47},[37,3159,675],{"class":83},[37,3161,61],{"class":47},[37,3163,94],{"class":83},[37,3165,61],{"class":47},[37,3167,1344],{"class":83},[37,3169,61],{"class":47},[37,3171,94],{"class":83},[37,3173,102],{"class":47},[37,3175,3176],{"class":39,"line":602},[37,3177,183],{"class":47},[19,3179,3180],{},"헤더가 한국어, 본문이 한국어, 컬럼 너비는 여전히 퍼센트, 페이지 분할 시 헤더 반복도 그대로 작동. 폰트는 도큐먼트가 사용하는 글리프만 서브셋되므로 단일 페이지 출력은 50KB 정도, 전체 Noto Sans KR는 약 6MB와 대비된다.",[19,3182,3183,3184,3188],{},"폰트 등록 자체는 ",[213,3185,3187],{"href":3186},"/ko/blog/embed-japanese-font","한국어 TrueType 폰트 임베딩"," 레시피 (같은 패턴이 한국어에도 적용). 이 글의 요점: 데이터가 CJK여도 테이블 API는 변하지 않는다.",[14,3190,3192],{"id":3191},"자주-묻는-질문","자주 묻는 질문",[19,3194,3195],{},[22,3196,3197],{},"Q: 행별 스타일 지정 가능한가?",[19,3199,3200,3201,3204,3205,3208,3209,3211,3212,3214,3215,3218,3219,3221],{},"빌더 API에선 불가. 빌더는 본문에 ",[34,3202,3203],{},"[][]string","을 받으므로 모든 본문 셀이 컬럼 유래의 같은 ",[34,3206,3207],{},"Style","을 공유한다. 행마다 다른 스타일을 원하면 ",[34,3210,201],{}," 층에서 조립 — 각 ",[34,3213,1980],{},"이 자체 ",[34,3216,3217],{},"CellStyle","을 가진다. 패턴은 단순, ",[34,3220,3203],{},"의 편의만 잃는다.",[19,3223,3224],{},[22,3225,3226],{},"Q: 셀 안에 이미지나 중첩 테이블을 넣을 수 있나?",[19,3228,3229,3231,3232,2365,3235,3238,3239,1867,3242,3245,3246,3249],{},[34,3230,201],{}," 층이면 가능. ",[34,3233,3234],{},"TableCell.Content",[34,3236,3237],{},"[]DocumentNode","로 ",[34,3240,3241],{},"*Text",[34,3243,3244],{},"*Image",", 심지어 중첩된 ",[34,3247,3248],{},"*Table","까지 받는다. 빌더의 문자열 API는 노출하지 않지만 (대부분 사용자에게 날카로운 모서리이기 때문) 기저 모델은 지원한다.",[19,3251,3252],{},[22,3253,3254],{},"Q: gpdf는 어디서 페이지를 자르는지 어떻게 결정하나?",[19,3256,3257],{},"행 단위로. 레이아웃 엔진이 본문 행을 순서대로 측정해서 다음 행이 가용 높이를 초과할 직전까지 현재 페이지에 더한다. 그 행이 오버플로 테이블의 첫 행이 된다. \"이 행들은 떼지 마라\" 어노테이션은 아직 없다 — 모든 행이 분할 가능하다. 청구서 라인 항목의 논리 그룹을 한 페이지에 두고 싶으면 그룹 앞에서 수동으로 페이지를 열거나 도큐먼트 층에서 분할 힌트를 끼워 넣어야 한다.",[19,3259,3260],{},[22,3261,3262],{},"Q: gpdf가 렌더링할 수 있는 최대 테이블 크기는?",[19,3264,3265,3266,3269,3270,3272,3273,3275],{},"A4에서 본문 10,000행은 검증됨. 정확히 페이지 분할되고 매 페이지 헤더가 다시 그려지며 출력 PDF는 약 150페이지 수백 KB. 병목은 테이블 레이아웃이 아니라 셀 콘텐츠의 텍스트 셰이핑, ",[34,3267,3268],{},"O(행 × 열)",". 100,000행 이상이 필요하면 디스크에 청크로 쓰거나 (10,000행마다 ",[34,3271,1477],{},") ",[34,3274,201],{}," 층에서 사전 셰이핑된 run을 넘긴다.",[19,3277,3278],{},[22,3279,3280],{},"Q: 푸터를 마지막 페이지에만 표시할 수 있나?",[19,3282,3283,3284,3286],{},"내장 기능 아님. ",[34,3285,2409],{},"는 설계상 매 페이지 반복된다 — 흔한 용도가 페이지별 컬럼 합계라서. 도큐먼트 끝에 한 번만 띄우는 요약을 원하면 테이블 안이 아니라 테이블 다음에 별도 행 블록으로 추가해라.",[19,3288,3289],{},[22,3290,3291,3292,3294],{},"Q: ",[34,3293,1428],{},"는 헤더에도 영향을 주나?",[19,3296,3297,3298,3301],{},"영향을 준다. 셀 테두리는 헤더와 본문에 일관되게 적용. 헤더만 다른 테두리 (예: 헤더 아래쪽이 더 두껍게) 를 원하면 도큐먼트 층에서 헤더를 만들고 셀별 ",[34,3299,3300],{},"CellStyle.Border","를 지정해라.",[14,3303,3305],{"id":3304},"설계의-큰-그림","설계의 큰 그림",[19,3307,3308,3309,3312],{},"하나만 가져간다면: ",[22,3310,3311],{},"gpdf 테이블 API가 작은 건 테이블 문제 거의 전부가 결국 같은 세 문제로 귀결되기 때문이다."," 컬럼 너비, 줄무늬, 페이지 분할. 나머지는 long tail이다. 일반적인 경우를 빌더에, long tail을 도큐먼트 층에 두는 게 그 거래 — 매일 나오는 용도는 5줄로 쓰고, 빌더로 표현 못 하는 일을 할 때 추상화 비용을 안 낸다.",[19,3314,3315,3316,3319],{},"대가는 솔직하다: ",[34,3317,3318],{},"setRowStyle(i, ...)"," 단축키는 없다, 앞으로도 없을 것이다. 4행과 5행을 다른 스타일로 만들고 싶다면 빌더가 다루지 않으려는 복잡도 선을 이미 넘은 것이다. 한 층 내려가라. 경계는 명확하고 안정적이다.",[19,3321,3322],{},"전체는 여기까지. 한 번 읽고 이후엔 더 생각 안 해도 되는 API 부분에 대한 20분짜리 글이다.",[14,3324,3326],{"id":3325},"gpdf-시도해-보기","gpdf 시도해 보기",[19,3328,3329],{},"gpdf는 Go용 PDF 생성 라이브러리. MIT, 외부 의존 0, 네이티브 CJK.",[27,3331,3335],{"className":3332,"code":3333,"language":3334,"meta":32,"style":32},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","go get github.com/gpdf-dev/gpdf\n","bash",[34,3336,3337],{"__ignoreMap":32},[37,3338,3339,3341,3344],{"class":39,"line":40},[37,3340,31],{"class":297},[37,3342,3343],{"class":832}," get",[37,3345,3346],{"class":832}," github.com/gpdf-dev/gpdf\n",[19,3348,3349,3353,3354],{},[213,3350,3352],{"href":215,"rel":3351},[217],"⭐ GitHub에서 별 주기"," · ",[213,3355,3358],{"href":3356,"rel":3357},"https://gpdf.dev/ko/docs/quickstart",[217],"문서 읽기",[14,3360,3362],{"id":3361},"관련-읽을거리","관련 읽을거리",[1801,3364,3365,3374,3380,3387,3394],{},[231,3366,3367,3370,3371,3373],{},[213,3368,3369],{"href":1734},"gpdf 테이블에서 컬럼 너비를 어떻게 설정하나?"," — ",[34,3372,78],{}," 코너 케이스",[231,3375,3376,3379],{},[213,3377,3378],{"href":1826},"줄무늬 (제브라) 테이블 행을 어떻게 만드나?"," — 색 선택과 다크 테마",[231,3381,3382,3386],{},[213,3383,3385],{"href":3384},"/ko/blog/bootstrap-grid-thinking-for-pdf","PDF를 위한 Bootstrap 사고: gpdf의 12컬럼 그리드"," — 테이블 퍼센트가 무엇의 너비에 대한 퍼센트인지",[231,3388,3389,3393],{},[213,3390,3392],{"href":3391},"/ko/blog/invoice-pdf-go-under-50-lines","Go로 50줄 미만 청구서 PDF 만들기"," — 완전한 도큐먼트 안의 실세계 테이블",[231,3395,3396,3399],{},[213,3397,3398],{"href":2869},"gpdf가 gofpdf / gopdf / Maroto보다 빠른 이유"," — 비교표 뒤의 µs 숫자",[3401,3402,3403],"style",{},"html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":32,"searchDepth":70,"depth":70,"links":3405},[3406,3407,3408,3409,3410,3411,3412,3413,3414,3415,3416,3417,3418,3419,3420],{"id":16,"depth":70,"text":17},{"id":208,"depth":70,"text":209},{"id":270,"depth":70,"text":271},{"id":456,"depth":70,"text":457},{"id":1610,"depth":70,"text":1611},{"id":1739,"depth":70,"text":1740},{"id":1835,"depth":70,"text":1836},{"id":1912,"depth":70,"text":1913},{"id":2422,"depth":70,"text":2423},{"id":2713,"depth":70,"text":2714},{"id":2878,"depth":70,"text":2879},{"id":3191,"depth":70,"text":3192},{"id":3304,"depth":70,"text":3305},{"id":3325,"depth":70,"text":3326},{"id":3361,"depth":70,"text":3362},"2026-05-07","Go에서 PDF 테이블 그리는 일은 사고 나기 쉽다. gpdf는 컬럼 너비·줄무늬·헤더 반복을 단 한 번의 Table 호출로 압축한다. API 전체와 트레이드오프.",false,"md",{"name":3426,"totalTime":3427,"tools":3428,"steps":3430},"gpdf로 컬럼 너비, 줄무늬, 헤더 반복을 갖춘 다중 페이지 테이블을 Go에서 그리기","PT20M",[3429,543],"Go 1.22+",[3431,3434,3437,3440,3443,3446],{"name":3432,"text":3433},"gpdf 설치","Go 1.22+ 모듈에서 go get github.com/gpdf-dev/gpdf를 실행한다. 코어 라이브러리는 외부 의존이 없으므로 이 줄이면 끝.",{"name":3435,"text":3436},"Col 안에서 Table 호출 한 번","page.AutoRow → r.Col(12, ...) 안에서 c.Table(header, rows)를 호출한다. header는 []string, rows는 [][]string. 옵션 없으면 컬럼은 균등 분할.",{"name":3438,"text":3439},"컬럼 너비를 퍼센트로 지정","template.ColumnWidths(40, 15, 20, 25)을 전달한다. 각 값은 부모 Col 너비에 대한 퍼센트. 누락된 뒤쪽 컬럼은 자동 분배.",{"name":3441,"text":3442},"헤더 스타일과 줄무늬 추가","template.TableHeaderStyle(template.TextColor(pdf.White), template.BgColor(brand))과 template.TableStripe(pdf.RGBHex(0xF5F5F5))을 추가. 줄무늬는 본문 행에만 적용되고 헤더는 제외.",{"name":3444,"text":3445},"gpdf가 페이지 분할. 헤더는 자동 반복","한 페이지에 안 들어갈 양의 행을 넣는다. gpdf가 본문을 페이지 사이로 분할하고 모든 후속 페이지 위쪽에 Header를 다시 그린다. PageBreak 옵션도 행 카운트도 불필요.",{"name":3447,"text":3448},"ColSpan / RowSpan / 고정 너비 / 푸터가 필요하면 document.Table로 내려가기","&document.Table{Columns, Header, Body, Footer}를 직접 만든다. 셀 합치기, 고정 pt 컬럼, 매 페이지 반복 푸터는 이 층에서 처리. 빌더 API가 의도적으로 노출하지 않는 부분.",null,{},"/ko/blog/tables-in-go-pdfs",{"title":5,"description":3422},"ko/blog/022.tables-in-go-pdfs",[3455,3456,3457],"tutorial","templates","comparison","TrJAQby7-mU-tlLFT0o6W68ae0ftlACO9gO6FFodo84",1779199026754]