.NET 도움말 Datatables .NET (How It Works For Developers) 커티스 차우 업데이트됨:9월 1, 2025 다운로드 IronPDF NuGet 다운로드 DLL 다운로드 윈도우 설치 프로그램 무료 체험 시작하기 LLM용 사본 LLM용 사본 LLM용 마크다운 형식으로 페이지를 복사하세요 ChatGPT에서 열기 ChatGPT에 이 페이지에 대해 문의하세요 제미니에서 열기 제미니에게 이 페이지에 대해 문의하세요 Grok에서 열기 Grok에게 이 페이지에 대해 문의하세요 혼란 속에서 열기 Perplexity에게 이 페이지에 대해 문의하세요 공유하다 페이스북에 공유하기 트위터에 공유하기 LinkedIn에 공유하기 URL 복사 이메일로 기사 보내기 ASP.NET developers often seek efficient ways to present tabular data or HTML tables with advanced features such as sorting, searching, and pagination. DataTables.NET is a powerful jQuery, JavaScript library, and highly flexible tool that facilitates the creation of interactive and feature-rich tables in web applications. In this article, we'll explore how to integrate DataTables.NET distribution files, a table-enhancing library for server-side processing into an ASP.NET project to enhance the presentation and user experience of tabular data. How to use DataTables in an ASP.NET Web Application? Create ASP.NET Web Application Add DataTables Client-Side styling package Install Entity Framework Core Packages, only the core software Add Model Class, Controller, and Razor Page Add JavaScript code in the JS File Set up Configuration Build and Run the Program Export Data into an Excel file using IronXL for Excel Data Export What is DataTables.NET? DataTables.NET is a jQuery JavaScript library that allows you to create and manipulate interactive tables in .NET applications. It is based on the jQuery DataTables plug-in, which provides comprehensive API features like pagination, sorting, filtering, and scrolling for dynamic as well as static HTML tables. It is a table-enhancing library that can work with various data sources, such as SQL databases, AJAX, or in-memory objects. Server Side Processing Consider a scenario where you have an API endpoint delivering a vast dataset of products. The standard approach involves jQuery DataTables making an AJAX call to this API, obtaining a list of products in JSON format, and rendering an HTML table. This is known as client-side processing, which is efficient for smaller datasets, typically ranging from 100 to 1000 records. However, what happens when the dataset expands to 10,000 records or more? When dealing with a substantial number of records, it becomes impractical to send the entire dataset to the browser in one go. Transmitting 10,000 records at once is not only wasteful in terms of bandwidth but also strains browser resources. In such cases, an alternative approach, server-side processing, becomes crucial for optimizing performance. In server-side processing, rather than sending the entire dataset, the API transmits data in manageable chunks, typically paginated with around 50 records per page. By doing this, the load time is significantly improved, as jQuery DataTables now loads a modest number of records (~50) instead of dealing with the entire dataset at once. This approach reduces CPU and bandwidth usage, creating a more efficient interaction between the API and the DataTable. In this article, we will explore the implementation of server-side processing in an ASP.NET Razor Page application, demonstrating how to efficiently handle and display extensive datasets while enhancing the overall performance of your web application. Getting Started with DataTables.NET in ASP.NET 8 To get started we need to add the DataTables.NET Client Side Library to our project. This article will use the ASP.NET Core Web App (Razor Pages) project with .NET 8. You may use any Web App Project as per your requirements. To add a Client-Side Library, right-click on Solution>Add> Client Side Library, and search for data tables as shown below. Now, we need to add Model Class, DB Context, Controller, HTML table, and AJAX Call. But before that, we need to install EntityFramework Nuget Packages to connect our application with the Database. This article will use the Code First Approach, you may use Database first as per your preference. Install the following locally hosted packages: Microsoft.EntityFrameworkCore Microsoft.EntityFrameworkCore.Design Microsoft.EntityFrameworkCore.SqlServer Microsoft.EntityFrameworkCore.Tools Install the above package by using the install-package command from the NuGet Package Manager Console, or install it from the NuGet Package Manager solution by searching it. Add Model Class I am using Product Model Class for this example, you may use it as per your requirement. public class Product { public int Id { get; set; } public string ProductName { get; set; } = string.Empty; public string ProductPrice { get; set; } = string.Empty; public string ProductWeight { get; set; } = string.Empty; public string ProductDescription { get; set; } = string.Empty; public DateTime ProductManufacturingDate { get; set; } public DateTime ProductExpiryDate { get; set; } } public class Product { public int Id { get; set; } public string ProductName { get; set; } = string.Empty; public string ProductPrice { get; set; } = string.Empty; public string ProductWeight { get; set; } = string.Empty; public string ProductDescription { get; set; } = string.Empty; public DateTime ProductManufacturingDate { get; set; } public DateTime ProductExpiryDate { get; set; } } $vbLabelText $csharpLabel Add ApplicationDBContext Class public class ApplicationDBContext : DbContext { public ApplicationDBContext(DbContextOptions<ApplicationDBContext> options) : base(options) { } public DbSet<Product> Products { get; set; } } public class ApplicationDBContext : DbContext { public ApplicationDBContext(DbContextOptions<ApplicationDBContext> options) : base(options) { } public DbSet<Product> Products { get; set; } } $vbLabelText $csharpLabel Add Advanced Interaction Controls We will add the ProductDatatables.js inside the wwwroot/js folder for adding advanced controls such as pagination, search, etc. // Initialize the DataTables plugin for the HTML element with 'productDatatable' ID $(document).ready(function () { $("#productDatatable").DataTable({ "processing": true, // Enable processing indicator "serverSide": true, // Enable server-side processing "ajax": { "url": "/api/Product", // API endpoint for fetching product data "type": "POST", "datatype": "json" }, "columnDefs": [{ // Define properties for columns "targets": [0], "visible": false, // Hide the 'Id' column "searchable": false // Disable searching for the 'Id' column }], "columns": [ { "data": "id", "name": "Id", "autoWidth": true }, { "data": "productName", "name": "ProductName", "autoWidth": true }, { "data": "productPrice", "name": "ProductPrice", "autoWidth": true }, { "data": "productWeight", "name": "ProductWeight", "autoWidth": true }, { "data": "productDescription", "name": "ProductDescription", "autoWidth": true }, { "data": "productManufacturingDate", "name": "ProductManufacturingDate", "autoWidth": true }, { "data": "productExpiryDate", "name": "ProductExpiryDate", "autoWidth": true }, { // Add a 'Delete' button with an onclick event for deleting the product "render": function (data, type, row) { return "<a href='#' class='btn btn-danger' onclick=DeleteProduct('" + row.id + "');>Delete</a>"; } } ] }); }); // Initialize the DataTables plugin for the HTML element with 'productDatatable' ID $(document).ready(function () { $("#productDatatable").DataTable({ "processing": true, // Enable processing indicator "serverSide": true, // Enable server-side processing "ajax": { "url": "/api/Product", // API endpoint for fetching product data "type": "POST", "datatype": "json" }, "columnDefs": [{ // Define properties for columns "targets": [0], "visible": false, // Hide the 'Id' column "searchable": false // Disable searching for the 'Id' column }], "columns": [ { "data": "id", "name": "Id", "autoWidth": true }, { "data": "productName", "name": "ProductName", "autoWidth": true }, { "data": "productPrice", "name": "ProductPrice", "autoWidth": true }, { "data": "productWeight", "name": "ProductWeight", "autoWidth": true }, { "data": "productDescription", "name": "ProductDescription", "autoWidth": true }, { "data": "productManufacturingDate", "name": "ProductManufacturingDate", "autoWidth": true }, { "data": "productExpiryDate", "name": "ProductExpiryDate", "autoWidth": true }, { // Add a 'Delete' button with an onclick event for deleting the product "render": function (data, type, row) { return "<a href='#' class='btn btn-danger' onclick=DeleteProduct('" + row.id + "');>Delete</a>"; } } ] }); }); JAVASCRIPT Now, we need to add an HTML table. Add HTML table Write the following code in the index.cshtml file to add a static HTML page. @page @model IndexModel @{ ViewData["Title"] = "Home page"; } <link href="~/lib/datatables/css/dataTables.bootstrap4.min.css" rel="stylesheet" /> <div class="container"> <br /> <div style="width:90%; margin:0 auto;"> <table id="productDatatable" class="table table-striped table-bordered dt-responsive nowrap" width="100%" cellspacing="0"> <thead> <tr> <th>Id</th> <th>Product Name</th> <th>Product Price</th> <th>Product Weight</th> <th>Product Description</th> <th>Product Manufacturing Date</th> <th>Product Expiry Date</th> <th>Actions</th> </tr> </thead> </table> </div> </div> @section Scripts { <script src="~/lib/datatables/js/jquery.dataTables.min.js"></script> <script src="~/lib/datatables/js/dataTables.bootstrap4.min.js"></script> <script src="~/js/ProductDatatable.js"></script> } We need to add the controller. Add Product Controller Add Product Controller for creating endpoint and direct pull requests. [Route("api/[controller]")] [ApiController] public class ProductController : ControllerBase { private readonly ApplicationDBContext context; public ProductController(ApplicationDBContext context) { this.context = context; } [HttpPost] public IActionResult GetProducts() { try { var draw = Request.Form["draw"].FirstOrDefault(); var start = Request.Form["start"].FirstOrDefault(); var length = Request.Form["length"].FirstOrDefault(); var searchValue = Request.Form["search[value]"].FirstOrDefault(); int pageSize = length != null ? Convert.ToInt32(length) : 0; int skip = start != null ? Convert.ToInt32(start) : 0; int recordsTotal = 0; var productData = context.Products.ToLis(); // Filtering data based on provided search value if (!string.IsNullOrEmpty(searchValue)) { productData = productData.Where(m => m.ProductName.Contains(searchValue) || m.ProductDescription.Contains(searchValue) || m.Id.ToString().Contains(searchValue)).ToList(); } recordsTotal = productData.Count(); var data = productData.Skip(skip).Take(pageSize).ToList(); var jsonData = new { draw = draw, recordsFiltered = recordsTotal, recordsTotal = recordsTotal, data = data }; return Ok(jsonData); } catch (Exception) { throw; } } } [Route("api/[controller]")] [ApiController] public class ProductController : ControllerBase { private readonly ApplicationDBContext context; public ProductController(ApplicationDBContext context) { this.context = context; } [HttpPost] public IActionResult GetProducts() { try { var draw = Request.Form["draw"].FirstOrDefault(); var start = Request.Form["start"].FirstOrDefault(); var length = Request.Form["length"].FirstOrDefault(); var searchValue = Request.Form["search[value]"].FirstOrDefault(); int pageSize = length != null ? Convert.ToInt32(length) : 0; int skip = start != null ? Convert.ToInt32(start) : 0; int recordsTotal = 0; var productData = context.Products.ToLis(); // Filtering data based on provided search value if (!string.IsNullOrEmpty(searchValue)) { productData = productData.Where(m => m.ProductName.Contains(searchValue) || m.ProductDescription.Contains(searchValue) || m.Id.ToString().Contains(searchValue)).ToList(); } recordsTotal = productData.Count(); var data = productData.Skip(skip).Take(pageSize).ToList(); var jsonData = new { draw = draw, recordsFiltered = recordsTotal, recordsTotal = recordsTotal, data = data }; return Ok(jsonData); } catch (Exception) { throw; } } } $vbLabelText $csharpLabel Here, we have implemented pagination & searching on the server side. Now, we need to set up our database and add configuration to the Program.cs class. If you are using .NET 5 or a lower version, you may need to do it in Startup.cs class. First of all, add the following Connection String in the appsettings.json file. "ConnectionStrings": { "ProductDB": "Server=localserver\\SQLEXPRESS;Database=ProductDB;Trusted_Connection=True;MultipleActiveResultSets=true;TrustServerCertificate=True;" } Now add the following code to the Program.cs class. public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext<ApplicationDBContext>(options => { options.UseSqlServer(builder.Configuration.GetConnectionString("ProductDB")); }); builder.Services.AddControllers(); // Add services to the container. builder.Services.AddRazorPages(); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapControllers(); app.MapRazorPages(); app.Run(); } public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext<ApplicationDBContext>(options => { options.UseSqlServer(builder.Configuration.GetConnectionString("ProductDB")); }); builder.Services.AddControllers(); // Add services to the container. builder.Services.AddRazorPages(); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapControllers(); app.MapRazorPages(); app.Run(); } $vbLabelText $csharpLabel We need to run the migration, as we are using a code-first approach. Run the following command in the Package Manager Console. Add-Migration init Add-Migration init SHELL The above command will create a migration. Now we need to apply these migrations to our database. Run the following command in the Package Manager Console. Update-Database Update-Database SHELL The above command will create tables in our database. Add dummy data in the Product Table; you may generate random data from Mockaroo. Now, build and run this application. Output We can see, that we have a very interactive UI with advanced interaction controls. Now, pagination is implemented on the server side as shown below. Output UI The data is then rendered on the Client Side with rich UI Control. You can explore more from the DataTables.NET documentation by clicking explore DataTables.NET documentation. Introduction of IronXL IronXL - Excel Library for .NET is a library that allows you to work with Excel files in .NET applications. It can create Excel spreadsheets, read CSV files, edit Excel files, and export to Excel in various formats, such as XLS, XLSX, CSV, and TSV. It does not require Microsoft Office or Excel Interop to be installed. It supports .NET 8, 7, 6, 5, Core, Framework, and Azure. We often have a requirement to export data into Excel or CSV files. IronXL is the best choice in this case. Now, we will write a code to export our data into an Excel file. Install IronXL Install the IronXL library in our project by entering the following command in the Package Manager Console. Install-Package IronPdf This will install IronXL and the required dependencies in our project. Export Data to Excel Let's write a code to convert our Product list into an Excel File. public void ExportToExcel(List<Product> productList) { WorkBook wb = WorkBook.Create(ExcelFileFormat.XLSX); // Create a new workbook instance WorkSheet ws = wb.DefaultWorkSheet; // Access the default worksheet int rowCount = 1; // Iterate over the product list and fill the worksheet foreach (Product product in productList) { ws["A" + rowCount].Value = product.Id.ToString(); ws["B" + rowCount].Value = product.ProductName; ws["C" + rowCount].Value = product.ProductDescription; ws["D" + rowCount].Value = product.ProductPrice; ws["E" + rowCount].Value = product.ProductWeight; ws["F" + rowCount].Value = product.ProductManufacturingDate; ws["G" + rowCount].Value = product.ProductExpiryDate; rowCount++; } wb.SaveAs("product.xlsx"); // Save the workbook as an Excel file } public void ExportToExcel(List<Product> productList) { WorkBook wb = WorkBook.Create(ExcelFileFormat.XLSX); // Create a new workbook instance WorkSheet ws = wb.DefaultWorkSheet; // Access the default worksheet int rowCount = 1; // Iterate over the product list and fill the worksheet foreach (Product product in productList) { ws["A" + rowCount].Value = product.Id.ToString(); ws["B" + rowCount].Value = product.ProductName; ws["C" + rowCount].Value = product.ProductDescription; ws["D" + rowCount].Value = product.ProductPrice; ws["E" + rowCount].Value = product.ProductWeight; ws["F" + rowCount].Value = product.ProductManufacturingDate; ws["G" + rowCount].Value = product.ProductExpiryDate; rowCount++; } wb.SaveAs("product.xlsx"); // Save the workbook as an Excel file } $vbLabelText $csharpLabel We have created an Excel file from the list in a very simple and easy way. IronXL provides comprehensive tutorials on creating XLSX files, code examples for reading Excel, and API documentation to use its comprehensive API in the best way possible. In optimizing ASP.NET performance, we exclusively rely on Only Core Software, ensuring a lean and efficient development environment. Utilizing DataTables.NET as locally hosted packages further enhances responsiveness, minimizing external dependencies for streamlined data handling and Excel exportation. Additionally, contributing code efficiently becomes seamless within this optimized and self-contained ecosystem. IronPDF is a solution designed to convert webpages, URLs, and HTML into PDF documents. The generated PDFs retain the original formatting and stylistic elements of the source webpages. This tool is particularly effective for creating PDF renditions of web-based content such as reports and invoices. using IronPdf; class Program { static void Main(string[] args) { var renderer = new ChromePdfRenderer(); // 1. Convert HTML String to PDF var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>"; var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent); pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf"); // 2. Convert HTML File to PDF var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath); pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf"); // 3. Convert URL to PDF var url = "http://ironpdf.com"; // Specify the URL var pdfFromUrl = renderer.RenderUrlAsPdf(url); pdfFromUrl.SaveAs("URLToPDF.pdf"); } } using IronPdf; class Program { static void Main(string[] args) { var renderer = new ChromePdfRenderer(); // 1. Convert HTML String to PDF var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>"; var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent); pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf"); // 2. Convert HTML File to PDF var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath); pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf"); // 3. Convert URL to PDF var url = "http://ironpdf.com"; // Specify the URL var pdfFromUrl = renderer.RenderUrlAsPdf(url); pdfFromUrl.SaveAs("URLToPDF.pdf"); } } $vbLabelText $csharpLabel Conclusion In summary, leveraging DataTables.NET for server-side processing in ASP.NET distribution repo projects proves to be a good strategy for handling substantial datasets efficiently. This approach ensures optimized performance by transmitting data in manageable chunks, mitigating bandwidth usage, and enhancing user experience. The integration of IronXL further extends the application's capabilities, enabling effortless export of tabular data to Excel for comprehensive data analysis and reporting. By adopting these technologies, developers can create web applications that strike a balance between rich interactivity and resource efficiency, providing users with a seamless and responsive experience, especially in scenarios where large datasets are involved. IronXL offers various licensing options for IronXL, depending on the number of developers, projects, and redistribution needs. The licenses are perpetual and include free support and updates. 자주 묻는 질문 DataTables.NET을 ASP.NET 프로젝트에 통합하려면 어떻게 해야 하나요? DataTables.NET을 ASP.NET 프로젝트에 통합하려면 ASP.NET 웹 애플리케이션을 만들고, DataTables 클라이언트 측 스타일링 패키지를 추가하고, 엔티티 프레임워크 핵심 패키지를 설치하고, 모델 클래스, 컨트롤러 및 면도기 페이지를 추가하고, 서버 측 처리를 위해 JavaScript를 구성한 다음 프로젝트를 빌드하고 실행해야 합니다. DataTables.NET의 서버 측 처리란 무엇인가요? DataTables.NET의 서버 측 처리에는 전체 데이터 집합을 한 번에 로드하지 않고 관리 가능한 청크로 데이터를 서버에서 클라이언트로 전송하는 작업이 포함됩니다. 이렇게 하면 로드 시간이 단축되고 특히 대용량 데이터 세트의 경우 CPU 및 대역폭 사용량이 최소화되어 성능이 향상됩니다. DataTables.NET에서 서버 측 처리가 중요한 이유는 무엇인가요? 서버 측 처리는 대규모 데이터 세트를 처리할 때 성능을 최적화하는 데 매우 중요합니다. 서버가 필요한 데이터만 클라이언트로 전송하여 브라우저의 부하를 줄이고 전반적인 효율성을 향상시킬 수 있습니다. ASP.NET 애플리케이션에서 표 형식의 데이터를 Excel로 내보내려면 어떻게 해야 하나요? IronXL 라이브러리를 사용하여 ASP.NET 애플리케이션에서 표 형식의 데이터를 Excel로 내보낼 수 있습니다. IronXL을 사용하면 Microsoft Office나 Excel Interop 없이도 데이터 목록에서 직접 Excel 파일을 만들고 조작할 수 있습니다. ASP.NET에서 데이터 테이블용 클라이언트 측 라이브러리를 설정하려면 어떻게 하나요? ASP.NET에서 클라이언트 측 라이브러리를 설정하려면 Visual Studio에서 솔루션을 마우스 오른쪽 버튼으로 클릭하고 '추가'를 선택한 다음 '클라이언트 측 라이브러리'를 선택합니다. 데이터 테이블과 같이 프로젝트의 기능을 향상시킬 수 있는 원하는 라이브러리를 검색하여 추가할 수 있습니다. 서버 측 처리를 위해 DataTables.NET을 구성하는 단계는 무엇인가요? 서버 측 처리를 위해 DataTables.NET을 구성하려면 모델 클래스, DB 컨텍스트, 컨트롤러 및 HTML 테이블을 설정했는지 확인하세요. 또한 데이터 가져오기 및 조작을 처리하기 위해 AJAX 호출을 수행하고 JavaScript 파일에서 서버 측 처리 로직을 구성해야 합니다. DataTables.NET에서 필터링과 페이지 매김은 어떻게 작동하나요? DataTables.NET의 필터링 및 페이지 매김은 서버 측 처리를 통해 관리됩니다. 서버는 검색 기준에 따라 데이터를 필터링하고 데이터 청크를 클라이언트로 전송하여 페이지 매김을 관리함으로써 효율적인 데이터 처리를 보장합니다. 커티스 차우 지금 바로 엔지니어링 팀과 채팅하세요 기술 문서 작성자 커티스 차우는 칼턴 대학교에서 컴퓨터 과학 학사 학위를 취득했으며, Node.js, TypeScript, JavaScript, React를 전문으로 하는 프론트엔드 개발자입니다. 직관적이고 미적으로 뛰어난 사용자 인터페이스를 만드는 데 열정을 가진 그는 최신 프레임워크를 활용하고, 잘 구성되고 시각적으로 매력적인 매뉴얼을 제작하는 것을 즐깁니다. 커티스는 개발 분야 외에도 사물 인터넷(IoT)에 깊은 관심을 가지고 있으며, 하드웨어와 소프트웨어를 통합하는 혁신적인 방법을 연구합니다. 여가 시간에는 게임을 즐기거나 디스코드 봇을 만들면서 기술에 대한 애정과 창의성을 결합합니다. 관련 기사 업데이트됨 12월 11, 2025 Bridging CLI Simplicity & .NET : Using Curl DotNet with IronPDF Jacob Mellor has bridged this gap with CurlDotNet, a library created to bring the familiarity of cURL to the .NET ecosystem. 더 읽어보기 업데이트됨 12월 20, 2025 RandomNumberGenerator C# Using the RandomNumberGenerator C# class can help take your PDF generation and editing projects to the next level 더 읽어보기 업데이트됨 12월 20, 2025 C# String Equals (How it Works for Developers) When combined with a powerful PDF library like IronPDF, switch pattern matching allows you to build smarter, cleaner logic for document processing 더 읽어보기 Sqlite C# .NET (How It Works For Developers)C# Null Coalescing (How It Works Fo...
업데이트됨 12월 11, 2025 Bridging CLI Simplicity & .NET : Using Curl DotNet with IronPDF Jacob Mellor has bridged this gap with CurlDotNet, a library created to bring the familiarity of cURL to the .NET ecosystem. 더 읽어보기
업데이트됨 12월 20, 2025 RandomNumberGenerator C# Using the RandomNumberGenerator C# class can help take your PDF generation and editing projects to the next level 더 읽어보기
업데이트됨 12월 20, 2025 C# String Equals (How it Works for Developers) When combined with a powerful PDF library like IronPDF, switch pattern matching allows you to build smarter, cleaner logic for document processing 더 읽어보기