18. 공통 기능 재사용을 위한 클래스 라이브러리 프로젝트
Visual Studio의 프로젝트 템플릿 중에서 C# 클래스 라이브러리 프로젝트를 사용해 한 번 이상 사용할 만한 공통적인 기능을 하나의 프로젝트에 모아서 관리하는 기법을 알아보겠습니다.
이 강의에서 사용된 소스는 다음 VisualAcademy GitHub 경로에 있습니다.
https://github.com/VisualAcademy/AspNetCoreBook
미리보기 동영상 강의
ASP.NET 프로젝트에서 C# 클래스 라이브러리(DLL) 프로젝트를 참조하여 사용하기
18.1. 클래스 라이브러리 프로젝트를 사용하여 컴포넌트(DLL 파일) 만들기
18.1.1. 클래스 라이브러리 프로젝트
ASP.NET을 사용하여 다양한 컨트롤과 기능을 활용하는 프로그래밍을 진행해 왔습니다. 이러한 컨트롤(컴포넌트)을 직접 제작하는 방법에 대해 궁금하실 것입니다. 이번 강의에서는 UI 없이 자주 사용하는 코드를 클래스화하여 DLL 파일로 컴파일한 후, 이 DLL 파일을 웹 사이트에 적용하는 방법을 배웁니다. 참고로 이 강의에서는 클래스 라이브러리, 패키지, 어셈블리, DLL 등을 동일한 의미로 봅니다.
- 컨트롤(Control): Visual Studio의 도구상자에 포함되어 있는, UI가 있는 프로그래밍 처리 단위를 의미합니다. 주로 웹 컨트롤 라이브러리 프로젝트로 제작됩니다.
- 컴포넌트(Component): 데이터베이스 처리 관련 클래스의 집합인 ADO.NET, Dapper처럼 UI 없이 주로 코드 기반 또는 다른 컨트롤에 의해 사용되는 코드 집합을 의미합니다. 주로 클래스 라이브러리 프로젝트로 제작되며 DLL 파일로 관리됩니다. 이 클래스 라이브러리가 이 장의 주제입니다.
- 프레임워크(Framework): 한 개 이상의 프로젝트로 구성된, 특정 분야에 대한 전체적인 클래스, 컨트롤, 컴포넌트의 집합체를 의미합니다. 주로 비즈니스 로직(Business Logic)에 의해 성격이 결정됩니다.
- 포털(Portal): 컨트롤, 컴포넌트, 프레임워크가 결합되어 만들어진 하나의 웹 사이트를 의미합니다.
18.1.2. 자주 사용하는 함수(메서드)를 하나의 클래스에 통합하기
웹 페이지를 만들 때 자주 사용하는 함수(메서드)들을 하나의 DLL 파일에 모아두고, 새로운 웹 페이지를 제작할 때 이 DLL 파일을 참조하여 bin 폴더에 추가한 후, 해당 DLL 파일에 정의된 함수들을 활용하는 방법을 소개합니다. 이제 실습을 통해 자신만의 DLL 파일을 만들어 보겠습니다. 클래스 라이브러리 프로젝트는 C#의 기초를 알고 있다고 가정하며, 실습을 통해 DLL 파일을 만드는 데 중점을 두겠습니다.
지금까지 제 강의를 진행해왔다면, C# 교과서에서도 하나의 DLL 파일을 만들고 사용하는 내용을 다뤄봤을 것입니다.
18.2. [실습] 클래스 라이브러리 프로젝트로 DLL 파일 만들기
18.2.1. 소개
이제까지 컴포넌트 또는 컨트롤이라 불렸던 DLL 파일을 만드는 방법을 배워보겠습니다. 이번 실습과 관련된 동영상 강좌 "ASP NET 4.6 프로젝트에서 C# 클래스 라이브러리(DLL) 프로젝트를 참조하여 사용하기"도 참고해 주세요.
NOTE
이 강의에서 작성한 Dul 이름의 DLL 파일은 NuGet 갤러리에 업로드되어 있습니다. NuGet 갤러리에서 "Dul"을 검색하여 손쉽게 찾을 수 있으며, 이를 참조하여 프로젝트에 사용할 수 있습니다. Dul DLL 파일을 통해 강의에서 다룬 다양한 유틸리티 기능을 즉시 활용할 수 있으며, 프로젝트의 개발 속도를 크게 향상시킬 수 있습니다.
18.2.2. 따라하기
Visual Studio를 열고 새 프로젝트 생성
- Visual Studio를 열고
파일 > 새로 만들기 > 프로젝트
를 선택합니다.Visual C# > 클래스 라이브러리
템플릿을 선택한 후, 프로젝트 이름을Dul
(Development Utility Library)로 설정하여 클래스 라이브러리 프로젝트를 생성합니다. 이름은 원하는 형태로 바꾸어도 상관없습니다.
그림 18-1 클래스 라이브러리 프로젝트 생성
- Visual Studio를 열고
기본 Class1.cs 파일 삭제 및 새로운 클래스 파일 추가
- 기본적으로 생성된
Class1.cs
파일을 삭제한 후,추가 > 클래스
메뉴를 사용하여BoardLibrary.cs
,FileUtility.cs
,HtmlUtility.cs
,StringLibrary.cs
클래스 파일을 네 개 생성합니다. 필요한 경우 더 많은 클래스를 추가할 수 있습니다.
그림 18-2 Dul 프로젝트 솔루션 탐색기 리스트
- 기본적으로 생성된
StringLibrary 클래스 작성
- 문자열의 길이를 잘라주는 유틸리티 메서드를 관리하는
StringLibrary
클래스를 작성합니다. 두 메서드는 확장 메서드로 만들어졌습니다.
// Dul 프로젝트의 StringLibrary.cs 클래스 namespace Dul { public static class StringLibrary { /// <summary> /// 주어진 문자열을 주어진 길이만큼만 잘라서 반환. 나머지 부분은 '...'을 붙임. /// </summary> public static string CutString(this string strCut, int intChar) { if (strCut.Length > (intChar - 3)) { return strCut.Substring(0, intChar - 3) + "..."; } return strCut; } /// <summary> /// 유니코드 이모티콘을 포함한 문자열 자르기 /// </summary> public static string CutStringUnicode(this string str, int length) { string result = str; var si = new System.Globalization.StringInfo(str); var l = si.LengthInTextElements; if (l > (length - 3)) { result = si.SubstringByTextElements(0, length - 3) + "..."; } return result; } } }
- 문자열의 길이를 잘라주는 유틸리티 메서드를 관리하는
HtmlUtility 클래스 작성
- HTML 태그를 특수 기호로 변경해주는
HtmlUtility
클래스를 작성합니다. 이 클래스는 게시판의 상세보기 페이지에서 태그를 순수 텍스트로 변환하여 보여줄 때 사용됩니다.
// Dul 프로젝트의 HtmlUtility.cs 클래스 using System; namespace Dul { public class HtmlUtility { /// <summary> /// HTML을 실행하지 않고 소스 그대로 표현해서 바로 웹 페이지에 보여줌 /// </summary> public static string Encode(string strContent) { if (String.IsNullOrEmpty(strContent)) { return ""; } return strContent .Replace("&", "&") .Replace(">", ">") .Replace("<", "<") .Replace("\r\n", "<br />") .Replace("\"", """); } /// <summary> /// HTML을 실행하지 않고 소스 그대로 표현해서 바로 웹 페이지에 보여줌 /// 추가적으로 탭과 공백도 HTML 코드( )로 처리해서 출력 /// </summary> public static string EncodeWithTabAndSpace(string strContent) { return Encode(strContent) .Replace("\t", " ") .Replace(" ", " "); } } }
- HTML 태그를 특수 기호로 변경해주는
FileUtility 클래스 작성
- 파일 업로드 시 중복된 파일명에 번호를 붙여주는
FileUtility
클래스를 작성합니다.
// Dul 프로젝트의 FileUtility.cs 클래스 using System.IO; namespace Dul { public class FileUtility { /// <summary> /// 중복된 파일명 뒤에 번호 붙이는 메서드 /// </summary> public static string GetFileNameWithNumbering(string dir, string name) { string strName = Path.GetFileNameWithoutExtension(name); string strExt = Path.GetExtension(name); int i = 0; while (File.Exists(Path.Combine(dir, name))) { name = $"{strName}({++i}){strExt}"; } return name; } } }
- 파일 업로드 시 중복된 파일명에 번호를 붙여주는
BoardLibrary 클래스 작성
- 게시판 작성 시 주요 UI를 꾸며주는
BoardLibrary
클래스를 작성합니다.
// Dul 프로젝트의 BoardLibrary.cs 클래스 using System; using System.IO; namespace Dul { public class BoardLibrary { /// <summary> /// 각 글의 Step별 들여쓰기 처리 /// </summary> public static string FuncStep(object objStep) { int intStep = Convert.ToInt32(objStep); string strTemp = ""; for (int i = 0; i < intStep; i++) { strTemp += "<img src=\"/images/dnn/blank.gif\" height=\"0\" width=\"" + (intStep * 15) + "\">"; } if (intStep > 0) { strTemp += "<img src=\"/images/dnn/re.gif\">"; } return strTemp; } /// <summary> /// 댓글 개수를 표현하는 메서드 /// </summary> public static string ShowCommentCount(object objCommentCount) { try { int count = Convert.ToInt32(objCommentCount); return count > 0 ? $"<img src=\"/images/dnn/commentcount.gif\" />( {count} )" : ""; } catch (Exception) { return ""; } } /// <summary> /// 24시간 내에 올라온 글에 new 이미지 표시 /// </summary> public static string FuncNew(object strDate) { if (strDate == null || string.IsNullOrEmpty(strDate.ToString())) return ""; DateTime originDate = Convert.ToDateTime(strDate); if ((DateTime.Now - originDate).TotalMinutes < 1440) { return "<img src=\"/images/dnn/new.gif\">"; } return ""; } /// <summary> /// 넘겨온 날짜 형식이 오늘 날짜면 시간 표시 /// </summary> public static string FuncShowTime(object date) { if (date == null || string.IsNullOrEmpty(date.ToString())) return "-"; DateTime postDate = Convert.ToDateTime(date); return postDate.ToString("yyyy-MM-dd") == DateTime.Now.ToString("yyyy-MM-dd") ? postDate.ToString("hh:mm:ss") : postDate.ToString("yyyy-MM-dd"); } /// <summary> /// 파일 크기를 계산해서 알맞은 단위로 변환 /// </summary> public static string ConvertToFileSize(int intByte) { if (intByte >= 1048576) { return $"{intByte / 1048576:F} MB"; } return intByte >= 1024 ? $"{intByte / 1024} KB" : $"{intByte} Byte(s)"; } /// <summary> /// 파일 확장자를 확인해서 이미지 파일인지 검사 /// </summary> public static bool IsPhoto(string strFileNameTemp) { string ext = Path.GetExtension(strFileNameTemp).Replace(".", "").ToLower(); return ext == "gif" || ext == "jpg" || ext == "jpeg" || ext == "png"; } /// <summary> /// 파일 다운로드 기능 /// </summary> public static string FuncFileDownSingle(int id, string strFileName, string strFileSize) { return strFileName.Length > 0 ? $"<a href=\"/DotNetNote/BoardDown.aspx?Id={id}\">{DownloadType(strFileName, $"{strFileName} ({ConvertToFileSize(Convert.ToInt32(strFileSize))})")}</a>" : "-"; } /// <summary> /// 다운로드할 파일의 확장자를 통해 아이콘을 결정 /// </summary> public static string DownloadType(string strFileName, string altString) { string ext = Path.GetExtension(strFileName).Replace(".", "").ToLower(); return ext switch { "bmp" => $"<img src='/images/ext/ext_bmp.gif' border='0' alt='{altString}'>", "css" => $"<img src='/images/ext/ext_css.gif' border='0' alt='{altString}'>", "gif" => $"<img src='/images/ext/ext_gif.gif' border='0' alt='{altString}'>", "htm" => $"<img src='/images/ext/ext_htm.gif' border='0' alt='{altString}'>", "html" => $"<img src='/images/ext/ext_html.gif' border='0' alt='{altString}'>", "jpg" => $"<img src='/images/ext/ext_jpg.gif' border='0' alt='{altString}'>", "jpeg" => $"<img src='/images/ext/ext_jpeg.gif' border='0' alt='{altString}'>", "js" => $"<img src='/images/ext/ext_js.gif' border='0' alt='{altString}'>", "png" => $"<img src='/images/ext/ext_png.gif' border='0' alt='{altString}'>", "sql" => $"<img src='/images/ext/ext_sql.gif' border='0' alt='{altString}'>", "txt" => $"<img src='/images/ext/ext_txt.gif' border='0' alt='{altString}'>", "zip" => $"<img src='/images/ext/ext_zip.gif' border='0' alt='{altString}'>", _ => $"<img src='/images/ext/ext_unknown.gif' border='0' alt='{altString}'>", }; } } }
- 게시판 작성 시 주요 UI를 꾸며주는
빌드하기
- Dul 클래스 라이브러리 프로젝트에서 마우스 오른쪽 버튼을 클릭하고
빌드
를 선택합니다.
그림 18-3 빌드 완료
- Dul 클래스 라이브러리 프로젝트에서 마우스 오른쪽 버튼을 클릭하고
참고: 클래스 라이브러리 프로젝트 참조
- Dul 프로젝트의 주요 기능을 특정 프로젝트에서 사용하는 방법:
- Dul.dll 파일을 bin 폴더로 복사해 붙여넣습니다.
- Dul 프로젝트를 같은 솔루션에 포함시킨 후 해당 프로젝트의
참조
에 마우스 오른쪽 버튼을 눌러참조 추가
를 클릭합니다. 그리고프로젝트
탭에서 Dul 프로젝트를 체크하여 추가합니다. 전체 솔루션 빌드 시 Dul.dll 파일이 웹 프로젝트의 bin 폴더에 복사됩니다.
다음 그림은 MemoEngine 이름의 웹 프로젝트에서 참조 추가
메뉴를 클릭하는 모습입니다.
MemoEngine 프로젝트에서 참조 추가 메뉴 클릭
참조 관리자
의 솔루션
탭을 선택하면 같은 솔루션 내의 프로젝트가 노출됩니다. Dul 프로젝트를 체크한 후 확인 버튼을 클릭하면 웹 프로젝트의 bin 폴더에 클래스 라이브러리 프로젝트의 어셈블리(DLL 파일)가 포함됩니다.
참조 관리자에서 Dul 프로젝트 선택
클래스 라이브러리 프로젝트를 참조하면 다음과 같이 참조 영역에 Dul이 등록된 상태로 보입니다.
Dul 참조 등록
18.2.3. 마무리
어셈블리 파일(DLL 파일)은 UI가 있을 수도 있고, 현재 Dul.dll 파일처럼 UI 없이 프로그램 로직만 포함할 수도 있습니다. 일반적으로 UI가 있는 DLL 파일을 컨트롤이라 하고, 업무 로직만 담고 있는 DLL 파일을 컴포넌트라고 합니다.
18.3. [실습] 클래스 라이브러리 프로젝트 테스트
18.3.1. 소개
앞서 작성한 Dul 프로젝트를 사용하는 간단한 웹 프로젝트를 만들어 보겠습니다.
18.3.2. 따라하기
새 ASP.NET 웹 응용 프로그램 생성
- Visual Studio에서
Dul.Test
란 이름의 ASP.NET 웹 응용 프로그램을 ASP.NET 4.6의 빈(Empty) 템플릿을 사용하여 생성합니다.
이름: Dul.Test 위치: C:\ASP.NET ASP.NET 템플릿 선택: ASP.NET 4.8 템플릿 - Empty
그림 18-4 Dul.Test 프로젝트 생성
- Visual Studio에서
기존 프로젝트 추가
- 생성된 Dul.Test 솔루션에 마우스 오른쪽 버튼을 클릭해서
추가 > 기존 프로젝트
메뉴를 선택합니다.
그림 18-5 기존 프로젝트 추가
- 생성된 Dul.Test 솔루션에 마우스 오른쪽 버튼을 클릭해서
Dul 클래스 라이브러리 프로젝트 등록
- 앞서 생성한 Dul 클래스 라이브러리 프로젝트 폴더를 찾아가서
Dul.csproj
파일을 선택하여 솔루션에 기존 프로젝트를 등록합니다.
그림 18-6 Dul 클래스 라이브러리 프로젝트 등록
- 앞서 생성한 Dul 클래스 라이브러리 프로젝트 폴더를 찾아가서
프로젝트 추가 확인
- 솔루션 하나에 프로젝트 두 개가 등록된 모습을 확인합니다.
그림 18-7 솔루션에 프로젝트 추가
프로젝트 참조 추가
- 생성된 Dul.Test 웹 프로젝트에서 Dul 클래스 라이브러리 프로젝트를 사용하려면 프로젝트의 참조에 마우스 오른쪽 버튼을 클릭해서
참조 추가
메뉴를 선택합니다.
그림 18-8 참조 추가
- 생성된 Dul.Test 웹 프로젝트에서 Dul 클래스 라이브러리 프로젝트를 사용하려면 프로젝트의 참조에 마우스 오른쪽 버튼을 클릭해서
참조 관리자에서 DLL 파일 참조
참조 관리자
를 띄운 후 Dul.dll 파일을 찾아서 참조하려면 두 가지 방법이 있습니다. 첫 번째 방법은찾아보기
탭 하단에 있는찾아보기
버튼을 클릭하여 참조할 파일이 위치한 곳을 찾아가 참조하는 방법입니다.
그림 18-9 참조 관리자
DLL 파일 직접 참조
- 참조할 파일 선택창이 나타나면 Dul.dll 파일이 위치한 곳을 찾아서 선택하여 참조할 수 있습니다. 다음 그림과 같이 Dul 프로젝트 경로를 찾아가서 bin 폴더의 Debug 폴더에서 Dul.dll 파일을 선택한 후
추가
버튼을 클릭하여 Dul.Test 프로젝트에 추가합니다.
그림 18-10 직접 DLL 파일 추가
참고: Debug와 Release
- 실제 프로젝트라면 빌드 메뉴에서 구성을 Debug에서 Release로 선택하여 Release 방식으로 빌드 후의 결과를 Release 폴더에서 참조 추가하는 것이 기본입니다. 하나의 완성된 컴포넌트(컨트롤)을 빌드할 때에는 Release 모드로 빌드하여 실행 속도를 높일 수 있습니다.
- 참조할 파일 선택창이 나타나면 Dul.dll 파일이 위치한 곳을 찾아서 선택하여 참조할 수 있습니다. 다음 그림과 같이 Dul 프로젝트 경로를 찾아가서 bin 폴더의 Debug 폴더에서 Dul.dll 파일을 선택한 후
참조 추가 확인
- 직접 DLL 파일을 참조하여 추가한 모습을 확인합니다.
그림 18-11 직접 추가된 dll 파일의 모습
프로젝트 탭에서 Dul 프로젝트 참조
- 두 번째 방법은
프로젝트
탭에서 Dul 프로젝트를 체크하여 프로젝트에 Dul.dll 파일을 참조하는 방법입니다.참조 관리자
를 띄운 후프로젝트
탭의솔루션
에서 Dul 프로젝트를 선택하고확인
버튼을 클릭하여 프로젝트에 Dul.dll 파일을 추가합니다.
그림 18-12 참조 관리자 - 프로젝트 선택
- 두 번째 방법은
FrmStringLibraryTest.aspx 페이지 생성
- Dul.Test 프로젝트에
FrmStringLibraryTest.aspx
이름으로 웹 폼 페이지를 생성하고 다음과 같이 작성합니다.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="FrmStringLibraryTest.aspx.cs" Inherits="Dul.Test.FrmStringLibraryTest" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>문자열 자르기</title> </head> <body> <form id="form1" runat="server"> <div> 입력 문자열: <asp:TextBox ID="txtInput" runat="server"></asp:TextBox> <asp:Button ID="btnCut" runat="server" Text="6자만 출력" OnClick="btnCut_Click" /><br /> <asp:Label ID="lblDisplay" runat="server"></asp:Label> </div> </form> </body> </html>
- Dul.Test 프로젝트에
FrmStringLibraryTest.aspx.cs 코드 작성
- 코드 숨김 파일에서 Dul.StringLibrary.CutString() 메서드와 CutStringUnicode() 메서드를 사용하여 텍스트 박스의 문자열을 … 기호를 포함한 여섯 자만 출력합니다. CutStringUnicode 메서드는 확장 메서드로 구현되어 있어 두 번째 코드 스타일처럼 바로 문자열.CutStringUnicode() 형태로 호출해서 사용할 수 있습니다. 다음 코드의 두 가지 방식 중 하나만 사용하면 됩니다.
// FrmStringLibraryTest.aspx.cs using System; namespace Dul.Test { public partial class FrmStringLibraryTest : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } protected void btnCut_Click(object sender, EventArgs e) { //[1] 클래스.메서드로 호출 lblDisplay.Text = Dul.StringLibrary.CutStringUnicode(txtInput.Text, 6); //[2] 확장 메서드로 호출 lblDisplay.Text = txtInput.Text.CutStringUnicode(6); } } }
FrmStringLibraryTest.aspx 페이지 테스트
- FrmStringLibraryTest.aspx 페이지를 웹 브라우저로 실행하여 다음과 같이 문자열 입력 후 버튼을 클릭하면 … 기호를 포함한 6자만 출력됩니다.
그림 18-13 출력 결과 확인
FrmBoardLibraryTest.aspx 페이지 생성
FrmBoardLibraryTest.aspx
라는 이름으로 웹 폼 페이지를 생성하고, 다음과 같이 코드를 입력합니다.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="FrmBoardLibraryTest.aspx.cs" Inherits="Dul.Test.FrmBoardLibraryTest" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>파일 크기 단위 붙이기</title> </head> <body> <form id="form1" runat="server"> <div> 파일 크기: <asp:TextBox ID="txtInput" runat="server"></asp:TextBox> <asp:Button ID="btnClick" runat="server" Text="확인" OnClick="btnClick_Click" /><br /> <asp:Label ID="lblDisplay" runat="server"></asp:Label> </div> </form> </body> </html>
FrmBoardLibraryTest.aspx.cs 코드 작성
FrmBoardLibraryTest.aspx.cs
파일을 열고 다음과 같이 코드를 작성합니다.
// FrmBoardLibraryTest.aspx.cs using System; namespace Dul.Test { public partial class FrmBoardLibraryTest : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } protected void btnClick_Click(object sender, EventArgs e) { // 파일 크기에 단위 붙이기 lblDisplay.Text = Dul.BoardLibrary.ConvertToFileSize( Convert.ToInt32(txtInput.Text)); } } }
FrmBoardLibraryTest.aspx 페이지 테스트
- FrmBoardLibraryTest.aspx 페이지를 웹 브라우저로 실행 후 숫자를 입력해보면 Byte, KB, MB 형태에 맞춰 출력됩니다.
그림 18-14 단위가 적용된 문자열 출력 확인
다음 그림은 123을 입력해서 바로 "123 Byte(s)"가 출력되는 모양을 보여줍니다.
Dul.Test 웹 프로젝트 완료
- Dul 클래스 라이브러리 프로젝트를 포함한 Dul.Test 웹 프로젝트의 전체 구조를 확인합니다.
그림 18-15 Dul.Test 프로젝트 전체 완료 후의 모습
18.3.3. 마무리
클래스 라이브러리 프로젝트와 이를 사용하는 웹 프로젝트를 만들어서 두 가지 함수를 테스트 해보았습니다. 나머지 함수들은 다음 장에서 진행할 웹 폼 게시판 만들기 프로젝트에서 사용해봅니다.