클래스, 구조체 등 내부 값이 있는 경우에 IComparer<T> 를 이용하여 비교하여 정렬이 가능합니다.

 

using System;
using System.Collections.Generic;

namespace ConsoleApp
{    
    class Program
    {
        class DescCompare : IComparer<Data>
        {
            //작으면 -1, 같으면 0, 크면 1
            //반대인 경우는 Asc 가능
            public int Compare(Data data1, Data data2)
            {
                return data1.A < data2.A ? -1 : 1;
            }
        }

        class Data
        {
            public int A { get; set; }
            public string B { get; set; }
        }

        static void PrintList (List<Data> datas, string message)
        {
            Console.WriteLine(message);
            foreach (Data data in datas)
            {
                Console.WriteLine(string.Format("{0}) {1}", data.A, data.B));
            }
        }

        public static void Main(string[] args)
        {
            List<Data> datas = new List<Data>();
            datas.Add(new Data { A = 30, B = "Test30" });
            datas.Add(new Data { A = 20, B = "Test20" });
            datas.Add(new Data { A = 10, B = "Test10" });

            PrintList(datas, "정렬 전");
            datas.Sort(new DescCompare());
            PrintList(datas, "정렬 후");
        }
    }
}

 

`${함수명}` 을 이용하여 함수 값을 가져올 수 있습니다.

아래는 html전용 예제 코드입니다.

 

function test () { return "test!"; } 가 출력됩니다.

<html>
  <body>
    <div id="show"></div>
    <script>

      function test () {
        return "test!";
      }

       const target = document.getElementById("show");
       target.innerHTML = `${test}`;
    </script>
  </body>
</html>

React 입문하면서 자바스크립트 공부 중 궁금한 사항이 생겨 결과를 정리 해봤습니다.

(테스트를 더 해보고 싶다면 아래 코드에 label, testValue 에 값을 추가해보시면 되겠습니다.)

 

&& 연산자 (0을 제외한 숫자와 문자들은 모두 true로 인식이 됩니다.)

수식 결과
null && 'T'
 
undefined && 'T'
 
'' && 'T'
 
' ' && 'T'
T
0 && 'T'
0
'0' && 'T'
T
1 && 'T'
T
-1 && 'T'
T
true && 'T'
T
"true" && 'T'
T
false && 'T'
 
"false" && 'T'
T

? 연산자 (3항 연산자)

수식 결과
null ? 'T' : 'F'
F
undefined ? 'T' : 'F'
F
'' ? 'T' : 'F'
F
' ' ? 'T' : 'F'
T
0 ? 'T' : 'F'
F
'0' ? 'T' : 'F'
T
1 ? 'T' : 'F'
T
-1 ? 'T' : 'F'
T
true ? 'T' : 'F'
T
"true" ? 'T' : 'F'
T
false ? 'T' : 'F'
F
"false" ? 'T' : 'F'
T

?? 연산자 ( null ?? 'F'   로 입력을 하였는데 내부적으로 아래와 같은 코드로 변경이 되네요.)

 null, undefined 인 경우에만 값을 넣어줄 수 있습니다.

수식 결과
null !== null && null !== void 0 ? null : 'F'      (null ?? 'F')
F
undefined !== null && undefined !== void 0 ? undefined : 'F'     (undefined ?? 'F')
F
'' !== null && '' !== void 0 ? '' : 'F'
 
' ' !== null && ' ' !== void 0 ? ' ' : 'F'
 
0 !== null && 0 !== void 0 ? 0 : 'F'
0
'0' !== null && '0' !== void 0 ? '0' : 'F'
0
1 !== null && 1 !== void 0 ? 1 : 'F'
1
-1 !== null && -1 !== void 0 ? -1 : 'F'
-1
true !== null && true !== void 0 ? true : 'F'
 
"true" !== null && "true" !== void 0 ? "true" : 'F'
true
false !== null && false !== void 0 ? false : 'F'
 
"false" !== null && "false" !== void 0 ? "false" : 'F'
false

|| 연산자 (null, undefined, blank, false, 0 인 경우에 기본 값 지정이 가능합니다.)

수식 결과
null || 'Or Default'
Or Default
undefined || 'Or Default'
Or Default
'' || 'Or Default'
Or Default
' ' || 'Or Default'
 
0 || 'Or Default'
Or Default
'0' || 'Or Default'
0
1 || 'Or Default'
1
-1 || 'Or Default'
-1
true || 'Or Default'
 
"true" || 'Or Default'
true
false || 'Or Default'
Or Default
"false" || 'Or Default'
false

 

아래는 로그에 찍히는 내용으로

xml 형태가 아닌 react에서 실제 변경되어 사용되는 모습이 흥미롭네요!

 

읽어 온 함수 내용 :  value => {
    return /*#__PURE__*/(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxDEV)("div", {
      children: value && 'T'
    }, void 0, false, {
      fileName: _jsxFileName,
      lineNumber: 72,
      columnNumber: 12
    }, undefined);
  }

 

export const OperationExample = () => {
  const label = ['null', 'undefined', "''", "' '", '0', "'0'", '1', '-1', 'true', '"true"', 'false', '"false"'];
  const testValue = [null, undefined, '', ' ', 0, '0', 1, -1, true, "true", false, "false"];
  let keyPrefix = 0;

  //css 한 파일로 하려고 선언...
  const style = {
    border: '1px solid black',
    borderCollapse: 'collapse',
    textAlign: 'center',
  };

  const CustomTable = ({ condition }) => {
    keyPrefix++;

    return (
      <table key={keyPrefix} style={style}>
        <tbody>
          <tr style={style}>
            <td style={style}> 수식 </td>
            <td style={style}> 결과 </td>
          </tr>
          {testValue.map((v, index) => {
            const trKey = keyPrefix + 'tr' + index;
            const tdLabelkey = keyPrefix + 'label' + index;
            const tdValuekey = keyPrefix + 'value' + index;

            const content = GetFunctionCode(condition, index);

            return (
              <tr key={trKey} style={style}>
                <td key={tdLabelkey} style={style}>
                  {content}
                </td>
                <td key={tdValuekey} style={style}>
                  {condition(v)}
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    );
  };

  //`${함수명}` 을 통해 함수 코드를 볼 수 있습니다!
  const GetFunctionCode = (fn, index) => {
    const functionToString = `${fn}`; //재미있는 부분..! 함수 내용을 읽어옵니다.
    const target = 'children: '; //읽어온 함수에서 children 항목을 찾습니다.
    let result = '';
    let i = functionToString.indexOf(target) + target.length;

    console.log('읽어 온 함수 내용 : ', functionToString);

    //children에 담긴 코드 부분만 추출해줍니다.
    for (i; i < functionToString.length; ++i) {
      if (functionToString[i] === '}') {
        break;
      }
      result += functionToString[i];
    }

    return result.replaceAll('value', label[index]).trim(); //함수 핵심 로직만 읽어오기
  };

  const AndCondition = (value) => {
    return <div>{value && 'T'}</div>;
  };

  const SingleQuestionMarkCondition = (value) => {
    return <div>{value ? 'T' : 'F'}</div>;
  };

  const DoubleQuestionMarkCondition = (value) => {
    return <div>{value ?? 'F'}</div>;
  };

  const OrCondition = (value) => {
    return <div>{value || 'Or Default'}</div>;
  };

  return (
    <div>
      <b>&& 연산자</b>
      <CustomTable condition={AndCondition} />
      <b>? 연산자</b>
      <CustomTable condition={SingleQuestionMarkCondition} />
      <b>?? 연산자</b>
      <CustomTable condition={DoubleQuestionMarkCondition} />
      <b>|| 연산자</b>
      <CustomTable condition={OrCondition} />
    </div>
  );
};

Object.prototype.toString.call (  target  )

  해당 오브젝트의 타입을 알려줍니다.

const a = 123;
const b = "test";
const c = [1, 2, 3];
const d = () => { alert("is function!"); }

const aType = Object.prototype.toString.call(a); //[object Number]
const bType = Object.prototype.toString.call(b); //[object String]
const cType = Object.prototype.toString.call(c); //[object Array]
const dType = Object.prototype.toString.call(d); //[object Function]

//응용버전 - 타입 판별 방법.
const isFunction = /Function/.test(dType); //1. 정규식으로 판별
const isFunction2 = dType.indexOf("Function"); //2. indexOf 로 contain 판별

alert(
  "aType : " + aType + "\n" +
  "bType : " + bType + "\n" +
  "cType : " + cType + "\n" +
  "dType : " + dType + "\n" +
  "isFunction : " + isFunction + "\n" +
  "isFunction2 : " + isFunction2
);

/* 결과
aType : [object Number]
bType : [object String]
cType : [object Array]
dType : [object Function]
isFunction : true
isFunction2 : 8
*/

 

 

 

SFTP 구축 및 연결.pdf
0.19MB

 

 

FTP (File Transfer Protocol)  :   파일 폴더 공유

SFTP (Secure File Transfer Protocol) :  암호화로 통신되는 파일 폴더 공유

 

SFTP 사용을 위해 간단히 정리해보았습니다.

 

서버는 freeFTPd(SFTP무료, FTP무료) 또는 Filezilla(SFTP 유료, FTP무료)

로 사용 되고,

 

클라이언트 (접속) 은 WinSCP / FileZilla 가능합니다.

c++ 랜덤 코드!

 

https://learn.microsoft.com/ko-kr/cpp/standard-library/random?view=msvc-170 

 

<random>

자세한 정보:

learn.microsoft.com

 

#include <iostream>
#include <random>

using namespace std;

int main()
{
	random_device rd;
	mt19937 gen(rd());
	uniform_int_distribution<int> distribution(0, 10); // 0 ~ 10
	
	for (int i = 0; i < 10; ++i)
	{
		cout << distribution(gen) << endl;
	}
}

업무 중 필요해서 만들어 본 금액을 한글로 표시해주는 코드입니다.

만들 때 마다 코드가 달라지는데 기본적인 방식은 비슷하기에 저장..

 

using System;

namespace ConsoleApp2
{
	class Program
	{
		private static readonly string[] num = { "", "일", "이", "삼", "사", "오", "육", "칠", "팔", "구" };
		private static readonly string[] digit = { "", "십", "백", "천" };
		private static readonly string[] word = { "", "만 ", "억 ", "조 ", "경 " }; //띄어쓰기 포함시켰습니다.

		//숫자 -> 한글 값
		public static void Main(string[] args)
		{
			string result = string.Empty;
			string sign = string.Empty;
			string readLine = Console.ReadLine();

			int wordIndex = 0;
			long input = 0;

			if (readLine[0] == '-') //음수 양수 확인
			{
				sign = "-";
			}

			//숫자만 추출 (그냥 만들어본거 ㅋ)
			for (int i = 0; i < readLine.Length; ++i)
			{
				if ('0' <= readLine[i] && readLine[i] <= '9')
				{
					input = input * 10 + readLine[i] - '0';
				}
			}

			while (input > 0)
			{
				string subResult = "";

				for (int i = 0; i < 4; ++i) // 1, 10, 100, 1000 단위별로 확인합니다.
				{
					long val = input % 10;
					input /= 10;

					if (val == 0) //0은 출력하지 않습니다.
					{
						continue;
					}

					if (val == 1 && i != 0) //일천, 일백, 일십에서는 일을 제거해줍니다.
					{
						subResult = digit[i] + subResult;
					}
					else //나머지 숫자들에 대해선 정상 출력해줍니다.
					{
						subResult = num[val] + digit[i] + subResult;
					}
				}

				if (subResult != "") //값이 있다면 추가해줍니다.
				{
					result = subResult + word[wordIndex] + result;
				}

				wordIndex++;
			}

			if (string.IsNullOrEmpty(result))
			{
				Console.WriteLine("영원");
			}
			else
			{
				Console.WriteLine("{0}{1}원", sign, result);
			}
		}
	}
}

SendMessage 와 윈도우 콜백 함수 (WndProc) 를 이용하여 다음과 같이 프로그램 간 통신을 할 수 있습니다.

 

프로그램 간 메시지를 송신/수신하여 처리 된 결과

 

 

[보내는 프로그램]

using System;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WindowsForms_SendProcess
{
    public partial class Form1 : Form
    {
        //명령어 모음
        //https://wiki.winehq.org/List_Of_Windows_Messages
        private const int WM_COPYDATA = 0x4A;

        [DllImport("user32.dll")]
        public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, uint wParam, ref COPYDATASTRUCT lParam);

        public struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;

            public string message;
        }

        public Form1()
        {
            InitializeComponent();

            textBox_processName.Text = "WindowsForms ReceiveProcess";
        }

        private void button_sendMessage_Click(object sender, EventArgs e)
        {
            Process[] process = Process.GetProcessesByName(textBox_processName.Text);
            string message = textBox_message.Text;

            for (int i = 0; i < process.Length; ++i)
            {
                COPYDATASTRUCT cds = new COPYDATASTRUCT();

                cds.dwData = IntPtr.Zero;

                //영어 문자 1byte, 한글 2byte
                byte[] buffer = Encoding.Default.GetBytes(message);

                cds.message = message;

                cds.cbData = buffer.Length + 1;  //보내는 string 길이 + 1 (문자의 끝 의미)

                SendMessage(process[i].MainWindowHandle, WM_COPYDATA, 0, ref cds);
            }
        }
    }
}

 

[받는 프로그램]

using System;
using System.Windows.Forms;

namespace WindowsForms_ReceiveProcess
{
    public partial class Form1 : Form
    {
        //명령어 모음
        //https://wiki.winehq.org/List_Of_Windows_Messages
        private const int WM_COPYDATA = 0x4A;

        public struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;

            public string message;
        }

        public Form1()
        {
            InitializeComponent();
        }

        protected override void WndProc(ref Message m)
        {
            try
            {
                switch (m.Msg)
                {
                    case WM_COPYDATA:

                        COPYDATASTRUCT cds = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));

                        listBox1.Items.Add(cds.message);
                        listBox1.SelectedIndex = listBox1.Items.Count - 1;
                        break;

                    default:

                        base.WndProc(ref m);
                        break;

                }

            }
            catch (Exception ex)
            {
                MessageBox.Show("WinForm Error : " + ex.Message);
            }
        }
    }
}

URI (별칭식 경로 : Uniform Resource Identifier 통합 자원 식별자)
URI는 특정 리소스를 식별하는 경로를 의미한다. 웹 기술에서 사용하는 논리적 또는 물리적 리소스를 식별하는 고유한 문자열 시퀀스다.

URL (절대 경로 : Uniform Resource Locator 또는 통칭 web address)
URL은 흔히 웹 주소라고도 하며, 컴퓨터 네트워크 상에서 리소스가 어디 있는지 알려주기 위한 규약이다. URI의 서브셋이다.

 

POST 방식은 기본 (URL)에 요청할 때 BODY 부분에 데이터를 넘겨주는 방식입니다.

Spring 공부를 하면 해당 API 들을 직접 호출 및 테스트 해볼 수 있게 만들면 좋겠네요.

POST 방식은 코드만 올리겠습니다.

1개 보내는 방식, multipart 로 2개 이상의 다른 데이터 보내는 방식입니다.

using System;
using System.IO;  //Stream
using System.Net; //HttpWebRequest, WebRequest 등 사용
using System.Windows.Forms;

using System.Net.Security; //SSL (Secure Sockets Layer) 관련
using System.Security.Cryptography.X509Certificates; //암호화 된 인증서 관련
using System.Text;

namespace WindowsFormsApp_POST_HttpRequest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            PostRequest();
        }

        private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            //인증서에 대한 결과를 보려면 여기서 브레이크 걸고 certificate, chain 등을 살펴보면 됩니다.
            //권장하지 않는 방법이지만 인증 기관에 대해 true로 설정해둡니다.
            return true;
        }

        private void PostRequest()
        {
            //****************************** 이 부분은 첫 사용하기 전에만 넣어주면 됩니다. ***********************************
            //웹 통신 시 System.Net.WebException : 기본 연결이 닫혔습니다. 관련 에러 방지용 프로토콜 정의입니다.
            //Secure Sockets Layer, Transport Layer Secure
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls |
                                                   SecurityProtocolType.Tls11 |
                                                   SecurityProtocolType.Tls12 |
                                                   SecurityProtocolType.Ssl3;

            //https (hyper text transfer protocol Secure : 전송 규약 보안) 보안이 올바른지 확인하는 구문입니다. 
            ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);
            //****************************************************************************************************************

            //[ContentType] : Body에서 전송되는 콘텐츠의 유형을 서버에 알려줍니다.
            //                MIME (Multipurpose Internet Mail Extensions) 표준을 따릅니다.
            //
            //ex)
            //1. multipart/form-data            2개 이상으로 한 번에 보낼 때 boundary와 함께 사용
            //2. application/json               제이슨 형태
            //3. application/x-www-urlencoded   기본 타입
            //4. image/tiff                     이미지, 확장자
            //   등 등

            //한 개의 데이터를 POST 방식으로 보내기
            PostRequestOne();

            //2개 이상의 데이터를 POST 방식으로 보내기
            //multipart/form-data 방식으로 사용되며 줄 구분을 위한 boundary가 필요   
            PostRequestAll();
        }

        private void PostRequestOne ()
        {
            string uri = textBox_uri.Text;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);   //요청 준비
            HttpWebResponse response = null;

            try
            {
                request.Method = "POST"; //기본 값은 GET 입니다.
                request.ContentType = "application/x-www-form-urlencoded"; //url encoded 방식 변수=값&변수1=값..

                string userName = "name";
                string password = "1234"; //서버와 협의하여 해쉬 등으로 암호화
                string data = string.Format("userName={0}&password={1}", userName, password);

                //request body에 데이터 채우기
                byte[] buffer = Encoding.UTF8.GetBytes(data);
                Stream requestStream = request.GetRequestStream(); //request에 보낼 데이터 입력용
                requestStream.Write(buffer, 0, buffer.Length);
                requestStream.Close();

                //응답 결과 받기
                response = (HttpWebResponse)request.GetResponse();
                Stream responseStream = response.GetResponseStream();
                StreamReader responseStreamReader = new StreamReader(responseStream);

                //응답 값 받아서 리턴하거나 사용하면 됩니다.
                string result = responseStreamReader.ReadToEnd();

                responseStreamReader.Close();
                responseStream.Close();
                response.Close();
            }
            catch (Exception ex)
            {
                //로그 남기면 좋을 듯
                MessageBox.Show("Request Error" + Environment.NewLine + ex.ToString());
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                }
            }
        }

        private void PostRequestAll ()
        {
            string uri = textBox_uri.Text;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);   //요청 준비
            HttpWebResponse response = null;

            try
            {
                request.Method = "POST"; //기본값은 GET
                                         //그 밖에도 timeout, credential 등 다양한 옵션을 줄 수 있습니다.

                //https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
                //2개 이상 multipart로 보내는 방법
                //보낼 값) field1 = value, 파일 = byte file

                //경계를 통해 데이터 타입 명시 및 다음과 같은 형태로 만들어서 보내면 됩니다.
                /*
                    Content-Type: multipart/form-data; boundary=isBoundary
                
                    --isBoundary
                    Content-Disposition: form-data; name="field1"

                    value
                    --isBoundary
                    Content-Disposition: form-data; name="파일"; filename="myImage.tiff" (filename은 부가적인 부분으로 없어도 된다고 봤네요.)
                    Content-Type: image/tiff (타입에 대한 명시 필요)

                    byte file
                    --isBoundary-- (경계의 끝은 -- 붙여주기)
                 */

                string endLine = "\r\n";            //웹에서 개행을 나타내는 문자열입니다. 
                string boundary = "isBoundary";     //구분자입니다. --isBoundary ~ --isBoundary-- 로 끝나게 됩니다.

                request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
                byte[] boundaryBytes = Encoding.ASCII.GetBytes(endLine + "--" + boundary + endLine);

                Stream requestStream = request.GetRequestStream();
                requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
                //
                //--isBoundary
                //

                string field1 = "field1";
                string value = "value";
                string data = string.Format("Content-Disposition: form-data; name=\"{0}\"{1}{2}{3}", field1, endLine, endLine, value);
                byte[] dataBytes = Encoding.UTF8.GetBytes(data);

                requestStream.Write(dataBytes, 0, dataBytes.Length);
                //[진행 현황]
                //
                //--isBoundary
                //Content-Disposition; form-data; name="field1"
                //
                //value

                requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
                //[진행 현황]
                //
                //--isBoundary
                //Content-Disposition; form-data; name="field1"
                //
                //value
                //--isBoundary
                //

                string name = "파일";
                string filename = "myImage.tiff";

                string data2 = string.Format("Content-Disposition: form-data; name=\"{0}\" filename=\"{1}\"{2}Content-Type: image/tiff{3}{4}",
                                                name, filename, endLine, endLine, endLine);
                byte[] data2Bytes = Encoding.UTF8.GetBytes(data2);

                requestStream.Write(data2Bytes, 0, data2Bytes.Length);
                //[진행 현황]
                //
                //--isBoundary
                //Content-Disposition; form-data; name="field1"
                //
                //value
                //--isBoundary
                //Content-Disposition: form-data; name="파일" filename="myImage.tiff"
                //Content-Type: image/tiff
                //
                //

                //예시 경로 파일 바이트로 읽어서 보내기
                string imagePath = @"c:\temp\myImage.tiff";
                FileStream fileStream = new FileStream(imagePath, FileMode.Open, FileAccess.Read);
                byte[] imageBuffer = new byte[4096];
                int bytesRead = 0;
                while (true)
                {
                    bytesRead = fileStream.Read(imageBuffer, 0, imageBuffer.Length);
                    if (bytesRead <= 0) //이미지 바이트 다 읽은 경우
                    {
                        break;
                    }
                    requestStream.Write(imageBuffer, 0, bytesRead);
                }
                fileStream.Close();

                byte[] endBoundaryByte = Encoding.ASCII.GetBytes(endLine + "--" + boundary + "--" + endLine);
                requestStream.Write(endBoundaryByte, 0, endBoundaryByte.Length);
                //[진행 현황]
                //
                //--isBoundary
                //Content-Disposition; form-data; name="field1"
                //
                //value
                //--isBoundary
                //Content-Disposition: form-data; name="파일" filename="myImage.tiff"
                //Content-Type: image/tiff
                //
                //byte file
                //--isBoundary--

                response = (HttpWebResponse)request.GetResponse(); //요청 후 결과 반환
                Stream responseStream = response.GetResponseStream();   //요청에 대한 stream 가져오기
                StreamReader responseStreamReader = new StreamReader(responseStream); //해당 stream 읽기 위한 streamReader

                //응답값 받아서 리턴하거나 사용하면 됩니다.
                string result = responseStreamReader.ReadToEnd();

                responseStreamReader.Close();
                responseStream.Close();
                response.Close();
            }
            catch (Exception ex)
            {
                //로그 남기면 좋을 듯
                MessageBox.Show("Request Error" + Environment.NewLine + ex.ToString());
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                }
            }
        }
    }
}

 

URI (별칭식 경로 : Uniform Resource Identifier 통합 자원 식별자)
URI는 특정 리소스를 식별하는 경로를 의미한다. 웹 기술에서 사용하는 논리적 또는 물리적 리소스를 식별하는 고유한 문자열 시퀀스다.

URL (절대 경로 : Uniform Resource Locator 또는 통칭 web address)
URL은 흔히 웹 주소라고도 하며, 컴퓨터 네트워크 상에서 리소스가 어디 있는지 알려주기 위한 규약이다. URI의 서브셋이다.

 

GET 방식은 헤더 부분인 주소(URI)에 변수와 값 을 통해 결과를 얻어오는 방법 입니다.

주소 뒷 쪽에 ? 변수1 = 값1 & 변수2 = 값2

 

식으로 변수와 값을 넘겨줄 수 있습니다. 아래는 구글에 간단하게 hi 를 GET으로 요청한 결과 입니다.

https://google.com/search 에 대해해 뒷 편에 ? q = hi 를 붙인 것이죠.

                                                                    (q는 검색어 변수, hi는 값이 되겠죠)

구글에서 hi 검색한 결과

C#에서 호출 한 소스는 아래와 같습니다.

통신을 위해서 json 을 반환시키기도 하며 200(응답 성공), 400(클라이언트 에러), 500(서버쪽 에러) 를 통해

결과를 알 수도 있습니다.

 

.NET 에 따라 SecurityProtocol 값이 달라질 수 있습니다. (현재 .NET 4.7.2 로 작성 되었습니다.)

(ServicePointManager 첫 연결 시만 등록해주면 됩니다.)

using System;
using System.IO;  //Stream
using System.Net; //HttpWebRequest, WebRequest 등 사용
using System.Windows.Forms;

using System.Net.Security; //SSL (Secure Sockets Layer) 관련
using System.Security.Cryptography.X509Certificates; //암호화 된 인증서 관련

namespace WindowsFormsApp10
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button_request_Click(object sender, EventArgs e)
        {
            //****************************** 이 부분은 첫 사용하기 전에만 넣어주면 됩니다. ***********************************
            //웹 통신 시 System.Net.WebException : 기본 연결이 닫혔습니다. 관련 에러 방지용 프로토콜 정의입니다.
            //Secure Sockets Layer, Transport Layer Secure
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls |
                                                   SecurityProtocolType.Tls11 |
                                                   SecurityProtocolType.Tls12 |
                                                   SecurityProtocolType.Ssl3;

            //https (hyper text transfer protocol Secure : 전송 규약 보안) 보안이 올바른지 확인하는 구문입니다. 
            ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);
            //****************************************************************************************************************

            string uri = textBox_uri.Text;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);   //요청 준비
            HttpWebResponse response = null;

            try
            {
                response = (HttpWebResponse)request.GetResponse(); //요청 후 결과 반환

                Stream stream = response.GetResponseStream();   //요청에 대한 stream 가져오기
                StreamReader reader = new StreamReader(stream); //해당 stream 읽기 위한 streamReader

                string result = reader.ReadToEnd(); //결과 읽어오기

                reader.Close();
                stream.Close();

                textBox_result.Text = result;
            }
            catch (Exception ex)
            {
                textBox_result.Text = "Request Error" + Environment.NewLine + ex.ToString();
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                }
            }
        }

        private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            //인증서에 대한 결과를 보려면 여기서 브레이크 걸고 certificate, chain 등을 살펴보면 됩니다.
            //권장하지 않는 방법이지만 인증 기관에 대해 true로 설정해둡니다.
            return true;
        }
    }
}

 

+ Recent posts