본문 바로가기
C#

C#11. DLL과 웹서비스

by 정양섭 2022. 3. 8.

 여기서는 간단한 계산기를 만들고, 계산 기능(사칙연산)을 수행하는 DLL을 만들어 그 DLL을 사용하여 변경해 본 후, 웹서비스로 만들어 원거리에서 그 계산 기능을 호출할 수 있도록 구성할 것입니다. DLL 만드는 방법과 웹서비스 만드는 방법이 얼마나 간단한지 경험할 수 있는 좋은 기회가 될 것입니다.
   계산기는 다음과 같이 제작하였습니다.

   이 프로그램은 이제 쉽게 만들 수 있으리라 생각되므로 루틴을 하나하나 설명하지는 않을 것입니다.
   이 루틴중 = 버튼을 선택했을 때 호출되는 Method를 보면 다음과 같습니다.
        private void buttonEqual_Click(object sender, System.EventArgs e)
        {
            dInput2 = double.Parse(this.textBox1.Text);
            switch(cCalc)
            {
                case '+':
                    dResult = dInput1 + dInput2;
                    break;

 

                case '-':
                    dResult = dInput1 - dInput2;
                    break;

                case '*':
                    dResult = dInput1 * dInput2;
                    break;

                case '/':
                    dResult = dInput1 / dInput2;
                    break;
            }
            bCalculated = true;
            this.textBox1.Text = dResult.ToString();
        }
   이중 사칙연산을 하는 부분을 DLL로 만들고 사용하도록 수정해 보겠습니다.

DLL을 제작하기 위해 프로젝트를 하나 추가해 보겠습니다. 솔루션 탐색기의 솔루션(Tree중 최상위 항목)에서 마우스 오른쪽 버튼을 선택하여 생성된 팝업 메뉴 추가의 부메뉴 새프로젝트를 선택하면 다음과 같은 대화 상자가 생성됩니다.

   클래스 라이브러리를 선택하고 이름에 ClassLibrary1을 CalcDll로 변경한 후 확인을 선택하면 다음과 같이 CalcDll 프로젝트가 하나 추가됩니다.

  솔루션 탐색기에서 Class1.cs를 CalcDll.cs로 수정하고, Source에서 Class1을 Calc로 수정한 후 다음과 같은 Method를 추가합니다.
        public double Add(double dValue1, double dValue2)
        {
            return dValue1 + dValue2;
        }

        public double Subtract(double dValue1, double dValue2)
        {
            return dValue1 - dValue2;
        }

        public double Multiplex(double dValue1, double dValue2)
        {
            return dValue1 * dValue2;
        }

        public double Divide(double dValue1, double dValue2)
        {
            return dValue1 / dValue2;
        }
  빌드를 수행하면 CalcDll.dll이 생성됩니다.

  이제 CalcDll.dll을 사용해 보겠습니다.

  CalcDll.dll을 사용할 Calculator 프로젝트의 참조에서 마우스 오른쪽 버튼을 선택하여 생성된 팝업 메뉴에서 참조 추가를 선택하면 다음과 같은 대화 상자가 생성됩니다.

   찾아보기 버튼을 선택하여 CalcDll.dll을 선택해도 되나, 같은 솔루션에 들어 있는 파일은 프로젝트 탭을 선택하여 선택하면 됩니다. 다음은 프로젝트 탭을 선택한 모양입니다.

   마우스로 CalcDll를 더블클릭하거나 선택 버튼을 실행 한 후 확인을 선택하면 참조가 됩니다.
   using CalcDll;을 선언하고 앞에서 설명한 buttonEqual_Click Method를 다음과 같이 수정하면 CalcDll.dll을 사용하여 구성한 것이 됩니다.
        private void buttonEqual_Click(object sender, System.EventArgs e)
        {
            dInput2 = double.Parse(this.textBox1.Text);
            Calc calc = new Calc();
            switch(cCalc)
            {
                case '+':
                    dResult = calc.Add(dInput1, dInput2);
                    break;

                case '-':
                    dResult = calc.Subtract(dInput1, dInput2);
                    break;

                case '*':
                    dResult = calc.Multiplex(dInput1, dInput2);
                    break;

                case '/':
                    dResult = calc.Divide(dInput1, dInput2);
                    break;
            }
            bCalculated = true;
            this.textBox1.Text = dResult.ToString();
        }

  이제 웹서비스로 만들어야 합니다. 웹서비스를 만들기 전에 웹서비스의 개념을 먼저 알아 보겠습니다. 웹서비스는 .NET 웹서비스, .NET XML 웹서비스, ASP.NET 웹서비스, ASP.NET XML 웹서비스등으로 다양하게 불리워 집니다.
  인터넷을 통한 원거리 데이터 통신 방식에는 여러 가지 방법이 있습니다. 그 중 가장 많이 사용했던 방식이 TCP를 직접 구성하여 통신하는 방식이었습니다. 이 방식은 많이 사용되다 이제 점점 줄어 들어 잘 사용되고 있지 않다. 이유는 방화벽 때문입니다. Windows XP이상에 방화벽이 설치되어 기본적으로 HTTP 통신을 위한 80번 포트만 열어 놓고 있습니다. 이 경우 특별히 설정을 하지 않는한 80번 외의 포트로는 통신을 수행할 수 없습니다. 따라서 S/W들은 80번 포트로 통신하는 방식이 필요하게 되었습니다.
   그러나 TCP를 직접 구성하여 통신하는 방식에서는 80번 포트를 이미 HTTP 통신을 위해 IIS 서버가 할당 받아 사용하고 있기 때문에 사용할 수 없습니다. 이를 해결하기 위해 고안된 방식이 XML 웹서비스입니다.
  이 방식은 통신하고자 하는 데이터를 XML이라는 표준 문서 형태로 작성하여 IIS 서버에게 전송해 달라고 하면, 수신처에서는 그 문서를 받아 데이터를 해석하여 취득한 후 사용하는 방식입니다.
   즉 데이터 형태는 XML을 사용하고 데이터 전송은 직접 TCP를 구성하여 사용하는 것이 아니라 IIS 서버를 통해 전송을하는 방식입니다.
  이 이론하에서 XML 웹서비스를 구성하고자 한다면 XML 문서 양식, IIS 서버에 전송을 요청하는 방식 등 알아야 할 것이 아주 많을 듯 합니다. 그러나 C#에서는 이런 부분을 전혀 몰라도 됩니다. 이제 그 구성 방식을 살펴 보도록 하겠습니다.
  XML 웹서비스를 구성하기 위해 프로젝트를 하나 추가 해보겠습니다. 솔루션 탐색기의 솔루션(Tree중 최상위 항목)에서 마우스 오른쪽 버튼을 선택하여 생성된 팝업 메뉴 추가의 부메뉴 새프로젝트를 선택하면 다음과 같은 대화 상자가 생성됩니다.

ASP.NET 웹 서비스를 선택하고 위치의 WebService1을 CalcWebService로 수정한 후 확인을 선택하면 다음과 같이 CalcWebService 프로젝트가 추가 됩니다.

Service1.asmx를 CalcWebService.asmx로 변경하고, 해당 파일에서 마우스 오른쪽 버튼을 선택하여 생성된 팝업 메뉴에서 코드 보기를 선택하여 열린 코드에서 Service1을 Calc로  수정한 후 다음과 같은 Method를 추가합니다.

        [WebMethod]
        public double Add(double dValue1, double dValue2)
        {
            return dValue1 + dValue2;
        }

        [WebMethod]
        public double Subtract(double dValue1, double dValue2)
        {
            return dValue1 - dValue2;
        }

        [WebMethod]
        public double Multiplex(double dValue1, double dValue2)
        {
            return dValue1 * dValue2;
        }

        [WebMethod]
        public double Divide(double dValue1, double dValue2)
        {
            return dValue1 / dValue2;
        }
  위의 내용을 보면 DLL 제작과 거의 같고 다른점이라면 [WebMethod]라는 Attribute만 추가된 것을 볼 수 있습니다. 이제 빌드를 수행하면 CalcWebService.dll이 생성됩니다.
   XML 웹서비스 만드는 것이 DLL 만드는 것과 별로 다르지 않다는 것을 알 수 있습니다.
   웹서비스는 네트워크로 서비스를 제공하는 것이므로 클라이언트 사양도 생각해야 합니다. 아직까지 Windows 7이 많이 사용되고 있으나 여전히 XP, VISTA 등도 존재합니다. 배포의 편의를 생각해서 여기서는 .NET Framework 2.0을 사용하도록 합니다.
   CalcWebService 프로젝트에서 속성을 선택하여 생성된 화면에서 다음과 같이 .NET Framework 2.0으로 설정합니다.

  컴파일을 수행하면 .NET Framework 2.0으로 바뀌어 환경이 구축됩니다.
  이제 XML 웹서비스를 사용해 보도록 합니다.
  CalcWebService.dll을 사용할 Calculator 프로젝트의 참조에서 마우스 오른쪽 버튼을 선택하여 생성된 팝업 메뉴에서 웹 참조 추가를 선택하면 다음과 같은 대화 상자가 생성됩니다.

  로컬 컴퓨터의 웹 서비스를 선택하면 대화 상자는 다음과 같이 바뀝니다.

  CalcWebService를 마우스로 클릭하면 대화 상자는 다음과 같이 바뀝니다.

  웹 참조 이름을 WebService(using 할 때 사용하는 이름 중 일부로 그대로 두어도 상관 없습니다.)로 바꾸고 참조 추가 버튼을 선택하면 참조가 됩니다.
   이제 using을 사용하여 namespace를 등록하고 Calc 클래스를 사용하면 됩니다. namespace 명은 일반 DLL과는 다르게 웹서비스를 사용하는 어플리케이션 이름(Calculator) . 웹 참조 이름(WebService, 변경하지 않았으면 localhost)을 사용합니다.
   즉 using Calculator.Webservice;를 선언하고, 나머지는 DLL 사용할 때 와 같은 Source를 사용하면 동작을 합니다.
   이제 실행 하여 처음 = 버튼을 누를 때 속도가 조금 느리고, 그 이후 부터는 똑같이 동작한다는 것을 알 수 있습니다.
  앞에서 설명한 예제는 설명의 편의를 위해 간단한 예제를 사용했으므로, 이걸 어디에다 써야 할 지 크게 와닿지 않을 수도 있습니다. 이 기능은 실행파일이 실행되는 PC의 자원이 아닌 다른 PC(서버 PC)의 자원을 이용하여 서버에서 원하는 기능을 수행하고, 그 결과를 실행되는 PC로 전송하는 기능이 필요할 경우 아주 간단히 구현할 수 있습니다.
  필자가 회사에서 하고 있는 일을 예로 설명해 보겠습니다. 필자는 HMI(Human Machine Interface) 소프트웨어를 개발하고 있습니다. 이 프로그램은 다양한 Controller와 통신하여 현장의 기계장치들을 제어 및 감시 하는 프로그램입니다. 이 프로그램을 Controller와 연결되어 있지 않은 원거리 PC에서 운영을 하고자 할 경우 현장에 설치된 서버와 통신을 통해 데이터를 주고 받아야 합니다. 이 경우 감시하고자 하는 기계의 리스트와 그에 해당하는 값의 리스트(ref로 넘겨줌)를 인자로 넘겨 서버에서 값을 채워 주면, 클라이언트에서는 그 값을 화면상에 표시할 수 있도록 구성하면 간단히 구현이 됩니다. 
   현재 웹서비스를 사용하기는 하지만 같은 PC에서 동작하고 있습니다. 이제 다른 PC에서 동작하도록 하는 부분 설정을 알아보겠습니다.

   솔루션 탐색기에서 WebService를 선택하고 속성을 보면 웹참조 URL이 localhost로 설정되어 있는 것을 알 수 있습니다. 다른 PC에서 동작하기 위해서는 localhost 대신 서버의 IP를 입력하면 됩니다.
   IP를 입력하고 컴파일 한 후 실행하면 다음과 같이 화면에 나타납니다.

 실행 될 때 마다 이렇게 화면에 나타나면 이 프로그램을 사용하는 사람은 없게 될 것입니다. 여러분들은 이 부분을 해결하기 위해 아래의 내용을 사용자들에게 설명서로 제공하여 보안 설정을 하도록 해야 할 것입니다.
   먼저 .NET Framework Configurator 2.0을 아래에서 다운받아 설치합니다.

Netconfigwizard.zip
0.43MB

   제어판을 실행하면 다음과 같이 화면에 나타납니다.

  관리 도구를 선택하면 화면은 다음과 같이 바뀝니다.

   Microsoft .NET Framework 2.0 Configuration을 선택하여 왼쪽 트리를 열심히 펼치면(내컴퓨터 - 런타임 보안 정책 - 컴퓨터 - All_Code) 다음과 같이 화면에 나타납니다.

   코드 그룹 속성 편집을 선택하여 권한 집합 탭을 선택하면 다음과 같이 화면에 나타납니다.

   Nothing을 FullTrust로 선택하면 보안 경고는 없어 지게 될 것입니다.

   앞에서 설명한 방식으로 서버 IP를 설정하게 되면 서버가 바뀌었을 때 수정할 방법이 없습니다. 이를 위해 Reference.cs를 만들어 다음과 같이 입력합니다.

 namespace Calcuator.WebService
{
    public class CalcServiceEx : CalcService{
        public CalcServiceEx(string strAddr)
        {
            base.Url = "http://" + strAddr + "/CalcWebService/CalcService.asmx";
        }
     }
}

  생성자인 strAddr에 주소를 입력하게 되는데 이부분을 파일에서 읽어서 설정하는 등 필요한 형태로 구성하면 서버가 바뀌었을 때 소스 수정하지 않고 구성이 가능하게 됩니다.
   보안 설정을 수동으로하는 방식을 설명했습니다. 이렇게 수동으로 세팅하도록 설명서를 만들어 배포해도 되나 아무래도 실제 제품 개발을 생각하면 무리가 있습니다. 이를 간단히 설정하도록 구성하는 방식에 대해 설명하겠습니다.

   먼저 CalSetup이라는 프로젝트로 콘솔어플리케이션을 만듭니다.
   이 또한 .NET Framework 2.0으로 만듭니다.
   System.Deployment, System.Web, System.Windows.Forms을 참조 추가합니다.
   Program.cs를 열어 다음과 같이 소스를 넣습니다(Copy & Paste 하세요).

using System;
using System.Collections.Generic;
using System.Text;
using System.Security;
using System.Security.Policy;
using System.Windows.Forms;             //참조 추가에서 dll 참조함
using System.Web;                       //참조 추가에서 dll 참조함
using System.Collections.Specialized;
using System.Deployment.Application;    //참조 추가에서 dll 참조함
namespace SmartCas
{
    class Program
    {
        static NameValueCollection GetQueryStringParameters()
        {
            NameValueCollection nameValueTable = new NameValueCollection();
            try
            {
                if (ApplicationDeployment.IsNetworkDeployed)
                {
                    string queryString = ApplicationDeployment.CurrentDeployment.ActivationUri.Query;
                    nameValueTable = HttpUtility.ParseQueryString(queryString);
                }
            }
            catch (Exception)
            {
            }
            return (nameValueTable);
        }

 

        static void MakePolicy()
        {
            try
            {
                string strServer = "";
                NameValueCollection NVC = new NameValueCollection();
                NVC = GetQueryStringParameters();
                if (NVC.Count > 0)
                {
                    strServer = NVC["Server"];
                }
                if (string.IsNullOrEmpty(strServer))
                    strServer = "localhost";
                string strUrl = "http://" + strServer + "/*";
                // Machine(Local) 영역을 접근합니다.
                const string userPolicyLevel = "Machine";
                PolicyLevel level = null;
                System.Collections.IEnumerator ph = System.Security.SecurityManager.PolicyHierarchy();
                //Machine 레벨을 가져온다.

               while (ph.MoveNext())
                {
                    level = (PolicyLevel)ph.Current;
                    if (level.Label == userPolicyLevel)
                        break;
                }
                // 이미 추가가 되었는지 확인합니다.
                foreach (CodeGroup group in level.RootCodeGroup.Children)
                {
                    if (group.Name == "CALC")
                    {
                        level.RootCodeGroup.RemoveChild(group);
                        break;
                    }
                }

               //권한생성
                NamedPermissionSet permissionSet = new NamedPermissionSet("Everything");
                PolicyStatement policyStatement = new PolicyStatement(permissionSet);
                //URL멤버쉽 생성
                IMembershipCondition membership = new UrlMembershipCondition(strUrl);
                //코드그룹에 추가
                UnionCodeGroup cg = new UnionCodeGroup(membership, policyStatement);
                //이름생성
                cg.Name = "CALC";
                cg.Description = " CALC 보안정책";

               // 그룹추가
                level.RootCodeGroup.AddChild(cg);
                //적용
                SecurityManager.SavePolicy();
                MessageBox.Show("서버(" + strServer + ")에 대한 보안 설정이 완료되었습니다.", "알림");
            }

            catch (Exception e)
            {

               System.Windows.Forms.MessageBox.Show(e.ToString(), "알림");

            }
        }
        static void Main(string[] args)
        {
            MakePolicy();
        }
    }
}
  실행을 하게 되면 콘솔창이 화면에 나타나게 되는데 이를 없애기 위해, 프로젝트(CalcSetup)에서 마우스 우측버튼을 선택해서 속성을 선택하면 다음과 같이 대화 상자가 나타납니다.

   콘솔 응용 프로그램을 Windows 응용 프로그램으로 수정합니다.
   프로젝트(CalcSetup)에서 마우스 우측버튼을 선택해서 게시를 선택하면 다음과 같이 대화 상자가 나타납니다.

   게시할 위치를 IIS 서버 위치 내부에 적당히 설정합니다.
 

마침을 누르면 다음과 같이 설치 할 수 있는 웹화면이 화면에 나타납니다.

   설치를 선택하면 설치가 됩니다.
   이제 동적으로 연결한 서버의 정보를 넣어 설치하는 방법을 알아보겠습니다. CalcSetup위치(C:\inetpub\wwwroot\CalcSetup\)에 Html 파일을 하나 만들어 넣고 아래와 같이 작성합니다.
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=euc-kr">
<title>실행방법</title>
<meta name="generator" content="Namo WebEditor v6.0">
<SCRIPT LANGUAGE="JavaScript">
<!--
function ExecuteSetup()
{
    window.location.href = "CalSetup.application?Server=" + window.location.host;   
}
-->
</SCRIPT>
</head>
<BODY ONLOAD="Initialize();">
<b><font size="2">NET 보안 설정을 수행합니다.</font></b><font size="2"></font><p align="left"><b><font size="2">.</font></b><font size="2">NET 보안 설정을 위하여 </font><font size="2"><input type="button" value = "여기" ONCLICK="ExecuteSetup();">
를&nbsp;선택하여 프로그램을 설치하면 됩니다.</font></p>
<p align="center">&nbsp;</p>
</body>
</html>
  Internet Explore를 실행하여 그 위치를 입력합니다.
   Html 파일 이므로 구성을 마음대로 할 수 있을 것입니다.

예제 프로그램 다운로드

Calc.zip
0.03MB

 

'C#' 카테고리의 다른 글

C#00. 목차  (0) 2024.04.22
C#12. Smart Client  (0) 2022.03.08
C#10. MDI 및 인쇄하기  (0) 2022.03.08
C#09. 파일 지원  (0) 2022.03.08
C#08. 메모리, 마우스 및 스크롤  (0) 2022.03.08