React Native는 진화된 하이브리드 앱 개발 프레임워크다 

기존의 웹에서 하이브리드를 지원하기 위해 다양한 개발방법이 나타났다 

React Native와 비교할 군은 크게 2가지 이다. 


1. HTML5 웹 앱 

   기본적으로 HTML CSS Javascrip를 통해 만든다 

   따로 앱스토어에서 설치하지 않아도 되지만 DOM이라는 웹 문서를 로딩하는 것이 성능적으로 최악의 단점이다. 

   네이티브 기능을 사용하지 못하고 웹브라우저에서 보는 것과 비슷하다 


2. WebView 기반의 하이브리드 앱 

   단순히 모바일 플랫폼만 공유되는 것이 아니라 Web 기술과 Native 기술도 혼합되어 있다 

   네이티브 앱처럼 동작하는 것처럼 보일 수 있으나 Native 위의 WebView에서 호출하는 구조이다.  느리다고 한다 


React Native의 React는 기본적으로 1. React 웹 앱 기반이다. 즉 HTML과 CSS JavaScript를 사용한다. 

단, 차이가 있다 아래는 그 차이가 기존 웹 앱의 성능을 개선한 점을 설명한다. 


React Native가 다른 웹앱 or 하이브리드 앱보다 성능적으로 좋은 이유 


1. 기존 웹 처럼 HTML을 사용하지만 실제로 호출되는 것은 Native Module 이다. 

   <div> <span> 등 HTML의 태그 형식을 따르지만 실제로 보여지는 것은 Native View의 Component로 치환된다. 

   실제 코딩도 HTML과 똑같지 않고 치환되는 Tag 선언을 따른다. 즉 네이티브를 호출할 수 있는 React Native만의 문법이 있다. 

   내부에서는 Native를 호출해서 구현하기 때문에 빌드과정에서 Object C나 Java 코드와 같은 Native Code와 매칭된다. 


2. 기존의 Native앱은 Compile 과정을 거치기 때문에 변경사항이 생기면 새로 Compile을 거쳐 수정사항을 반영하는 시간이 있었다 

   React Native는 이런 Recompile 거치지 않고도 View의 Tag를 변경해서 Reload 만으로 수정사항을 확인할 수 있다 이것은 개발 생산성과 연관이 있다. 


3. Native Code로 치환되고 그것과 Bridge로 연결된다는 이점은 필요한 Native Module을 직접 제작하거나 다른 사람이 만든 Module을 재활용할 수 

   있다는 이점이 있다.

   React Native는 Java나 Object-C, Swift로 만든 Module과 연결되기 때문에 자유도가 높은 Native 개발이 가능하다. 단 웹언어외에 Native 언어로도 

   구현을 해야 한다는 개발자의 역량에 대한 부담이 생긴다. 이것은 장점이자 단점이다.  


4. 위에서 웹 언어의 DOM 문서의 로딩이 오래 걸린다는 단점을 지적했다. 그 부분을 개선하기 위해 React Native는 Virtual DOM이라는 기술이 도입되었다

   이 기술은 간단히 말하면 해당 페이지의 모든 DOM을 로딩하는 것이 아니라 변경사항이 생긴 DOM 부분만 로딩해서 반영한다. Virtual DOM은

   WebView 그리고 웹앱의 단점을 커버해줄 것으로 보인다 단 객관적인 비교 수치나 테스트는 해봐야 알 것 같다 


5. WebView를 거치지 않고 Native Module을 호출할 수 있기 때문에 WebView에 의한 지연이 개선되었고 내부에서 JS Thread와 UI Thread가 단일 Process

  로 동작하는 것이 아니라 병렬과 비동기로 동작 하도록 설계되었기 때문에(이 부분은 확인해 볼 것) 단일 Thread의 단점을 커버해준다. 즉 이런 부분을 

  보면 기존의 하이브리드 앱과 웹앱의 단점을 모두 개선하려고 노력한 부분이 느껴진다.   

'Developer > Mobile(React Native)' 카테고리의 다른 글

강의 공부 자료  (0) 2018.07.27
React Native -Props-  (0) 2018.07.17
리액트 네이티브 개발자와 대화2  (1) 2018.07.17
리액트 네이티브 개발자와 대화  (0) 2018.06.29
개발환경(Windows)  (0) 2018.06.28

React Native 란? 

JavaScript 기반의 React를 사용해서 모바일 앱을 제작할 수 있는 오픈소스 프로젝트 (또는 어플리케이션 개발 프레임워크)

단순히 라이브러리라고 하기에는 개발 방법에 대한 구체적인 방법과 지원해주는 API들이 있으니 프레임워크라고 생각 할 수 있다 다만 React Native는 자체적으로 Native App 개발에 대한 컴파일러나 인터프리터가 해석해서 개발자가 작성한 코드가 프레임워크에 의해서 Callee(피호출자)로 동작하는게 아니라 실제 Native API를 Caller로서 동작하기에 API들을 호출하기 위한 집합 즉 라이브러리 성격이 강하다. 

위의 구분을 타이트하게 잡을 필요는 없을 것 같다 MFC도 Win32API를 감싼 라이브러리로 해석되지만 개발 프레임워크로도 불린다. 즉 개발규칙의 자유도가 저수준인지 고수준인지에 대한 구분정도에서 프레임워크와 라이브러리를 구분하면 될 것이다. 

관련 링크 : http://web-front-end.tistory.com/63 (그나마 구분이 가는 내용)



특징 (https://facebook.github.io/react-native/)

1. React Native는 모바일 웹앱, HTML5앱, 또는 Web View 기반의 하이브리드앱이 아니라 실제 Native 성격의 앱 개발이 가능하다 


2. JavaScript Code가 변했을 때 다시 빌드를 하지 않아도 재로딩만으로도 변경된 코드를 적용가능하다 


3. 필요한 경우 JavaScript Code에서 연결되는 Bridge를 통해 Object C, Swift, JAVA로 작성된 Native Module를 작성하거나 호출할 수 있습니다. 



필수설치 모듈 (Windows에서 Android App 개발) 

1. Chocholatey (https://chocolatey.org/)  -> 이걸안쓰면 Yarn 이라는 Package Manager도 있다 

  

 - Package Manager로 인터넷 연결이 되어 있으면 쉽게 Node.js, Python2 를 설치 가능 

   choco install -y nodejs.install python2 jdk8

   Node.js (오프라인 설치 : https://nodejs.org/en/download/)

   Python2 (오프라인 설치 : https://www.python.org/downloads/windows/)


2. NPM 설치 (Node.js command prompt) 

   npm install -g react-native-cli


3. JDK8 설치 

   Java Develop Kit (http://www.oracle.com/technetwork/java/javase/downloads/index.html)

   최신버전인 10버전으로 설치를 진행해봤으나 React Native 빌드시 Java 버전 오류 발생으로 8로 다운그래이드

   JAVA_HOME 환경변수로 등록

 

3. Android Studio 

   Android Studio (https://developer.android.com/studio/)

  • Android SDK
  • Android SDK Platform
  • Performance (Intel ® HAXM)
  • Android Virtual Device

4. Android SDK Manager 

    Android 6.0 (Marshmallow)  

  • Google APIs
  • Android SDK Platform 23
  • Intel x86 Atom_64 System Image
  • Google APIs Intel x86 Atom_64 System Image

   Android SDK Build-Tools (Marshmallow의 API 레벨이 23이다 안드로이드는 플랫폼(OS)과 API 레벨이 같이 올라간다)

  • 23.0.1

   ANDROID_HOME 환경변수로 등록


5. 애뮬레이터 설치  

  Android Studio 에서 Android Virtual Device Manager -> Create Virtual Device 

  주의사항 : HAXM 이 설치 되어야 하며 그 기술을 사용하려면 Intel Virtualization Technology 기능이 켜져 있어야 함 

                해당 기능이 꺼저있으면 경고문구가 나오고 Mainboard의 BIOS 메뉴에서 켜줘야 함


6. 편집기 설치 

   Visual Studio Code 설치 (https://code.visualstudio.com/docs?start=true)

   확장기능 설치해서 툴 기능 강화 

   디버깅이 지원된다. (필수) 

(https://www.vobour.com/vscode-%EC%B6%94%EC%B2%9C-%EC%9D%B5%EC%8A%A4%ED%85%90%EC%85%98%EA%B3%BC-%EC%84%B8%ED%8C%85-vscode-recommended-e)


7. Expo 설치 (https://expo.io/tools#xde) 

   Expo는 필수설치는 아니지만 쉽게 빌드해서 스마트폰까지 배포가 가능하다 

   Expo를 사용하면 장점 

   - 지원해주는 Library 설치

   - 쉽게 빌드 

   - 쉽게 배포?? 아닐 수 도 있음 

(이것은 수정하고자 한다. 따로 네이티브 모듈을 붙여서 배포하려면 expo에서 detach를 해야 한다고 한다. 이런 제한된 기능 때문에 데모앱을 만들기에 좋고 실제 서비스 앱용으로는 적합하지 않을 수 있다. )  

   - Expo에서 개발자 옵션에서 핫 리로딩을 키려면 Ctrl + M 을 누른다


8. Git을 통한 소스버전 관리 설치 

   Git (https://git-scm.com/downloads)

   VS Code에서 GitHub 연동으로 버전관리 설정 


9. 단위 테스트를 위한 Jest 연동 

   JavaScript Unit Test (http://jestjs.io/)


10. Create Project (Example)

   프로젝트를 설치할 경로를 정하고 (ex: C:\dev 생성)

   

   react-native init AwesomeProject


11. Run react-native App 

   애뮬레이터가 켜저있는 상태에서 command 명령 실행

  

   cd AwesomeProject 

   react-native start         (이것은 npm start로 해도 동일하고 하지 않아도 아래 run-android를 하면 동일하게 시작된다.) 


   새로 cmd 창을 뛰어서 아래 명령어로 빌드 한다

   

   react-native run-android (공식 문서에는 이 명령어만 되어 있음 실행시 node.js 구동)

   

   Hello world 같은 화면이 구동되면서 기본 셋팅 완료


12. react-native 확인 -> 기본설치 되는 폴더의 설치되어 있는 node module에 가면 있다   

   C:\WeatherProject\node_modules\react-native

용어 정리

 

DB의 조인

-       논리적: 내부조인(자연조인, Inner), 외부조인(Outer), 크로스 조인(크로스 프로덕트)

-       물리적: Nested Roof, Sort Merge, Hash 조인(그 밖에 더 있으나 여기까지만)

 

조인 수행 원리

PPT(애니메이션 가능)

 

옵티마이저

-       옵티마이저를 이해하는 것이 튜닝의 시작이고 옵티마이저를 제어하는 것이 튜닝의 기본이다.

-       옵티마이저에 의해 발생하는 조인 3가지: NL조인 , Sort Merge 조인, Hash 조인 이 있다 이것은 물리적인 조인이기 때문에 개발자가 직접 사용하게 되는 조인은 아니다

-       개발자가 직접 제어하는 조인은 내부조인이나 외부조인과 같은 논리적인 조인을 선언해서 만든다.

n  Ludy의 경우 Merge Into 구문도 조인이 있다  

-       즉 이런 논리적인 조인을 옵티마이저라는 녀석이 DBMS 내부에서 물리적인 조인으로 표현하고 만드는 것이다

-       옵티마이저는 사용자가 질의한 SQL문에 대해 최적의 실행 방법을 결정하는 역할을 수행

-       옵티마이저가 정한 최적의 실행 방법을 실행 계획이라고 함

-       다양한 실행 방법들 중에서 최적의 실행 방법을 결정하는 것이 옵티마이저의 역할

-       실제로 SQL문을 처리해 보지 않은 상태에서 결정해야 하는 어려움이 있다

n  DBMS 별로 옵티마이저의 성능을 비교해 볼 수 있는 부분이라고 볼 수 있겠다

-       보통 CBO(비용기반 옵티마이저를) 생각하면 된다

-       최적의 실행방법 결정이라는 것은 어떤 방법으로 처리한 것이 최소 일량(비용)으로 동일한 일을 처리할 수 있을 지 결정하는 것이다

-       즉 옵티마이저 최적의 실행 방법을 결정하는 것을 개발자는 도와주어야 한다

-       단순히 조인의 원리를 아는 것보다는 이 옵티마이저가 어떻게 물리적인 조인으로 변경시키는지를 알아야 한다

 

 

카디널리티

-       Cardinality: 사전적 의미로는 집합원의 개수

-       카디널리티가 낮은 경우에서 속성의 예를 들면 성별, 부서, 지역이 있다.

n  성별의 경우 남자, 여자 두 가지 경우만 가능하므로 매우 낮다고 할 수 있다

n  주민번호, 사원번호와 같은 경우 조직원이 많을수록 카디널리티가 높다

-       간단히 생각하면 한 개를 뽑는 뽑기를 했을 때 그 뽑는 모집단의 수가 많으면 높다고 할 수 있다

-       데이터베이스로 한정해보면 테이블에서 Primary Key에 해당 되는 경우의 수 라고도 볼 수 있겠다

 

카디널리티 설명 예제

PPT

예를 들면 학급 엔터티로 학년의 성적표를 만든다면 반 번호가 기본키가 되면 그 학급의 학생의 수가 카디널리티가 될 수 있다 (학급(1) : 학생(N))

다른형태로는 특정 쿼리문을 실행시켜서 나오는 결과 값(Row)를 카디널리티라고 한다

즉 학교라는 개념에서는 학급이 카디널리티일 수 도 있고 학급이라는 개념에서는 학생이 카디널리티일 수도 있다

예를 들면 사원테이블의 전체 레코드 수가 1000개일 때

WHERE 부서 = ‘인사팀이면 그 중 인사팀 사원이 10명이면 선택도는 10/1000 = 0.01이 됩니다. 즉 전체 rows * 선택도 = 결과수, 즉 카디널리티 가 결과 수라면 10이 카티널리티 입니다.

 

카디널리티를 이해해야 하는 이유

DB의 옵티마이저에서 조인을 맺어주는 항목으로 인덱스를 사용하게 됩니다. 물론 없으면 따로 사용하지 않고 Full Scan 이 되겠지요. 중요한 건 현재 접근하는 컬럼을 조건으로 접근할 때 얼마나 많이 걸러지느냐 입니다.

선택도가 확률이라고 하면 해당 카디널리티 즉 경우의 수는 전체 데이터의 개수에 영향을 받게 됩니다. 데이터가 많을 때는 해당 조건으로 얼마나 많이 걸러지는 지 즉 중복이 최소한일수록 해당 조건으로 많이 걸러지게 됩니다. 중복된 data를 검색 즉 중복이기 때문에 해당 data 전체를 Scan 해야 하기 때문에 원하는 하나를 찾는 경우에 범위를 좁혀가는 검색에서는 시간이 더 걸리게 됩니다.

순차적인 선형 검색일 경우 순서대로 전체를 보게 되지만 범위를 좁혀가는 이진검색이 성능이 더 좋다고 합니다.

이렇게 집합에서 원소가 어떻게 분포되었냐에 따라 스캔속도가 차이가 나므로 옵티마이저는 인덱스의 설계가 어떻게 되었냐에 따라 영향을 받게 됩니다. 개발자는 물리적인 조인에 대해 직접 관여는 하지 않지만 인덱스 설정에 따라 영향은 줄 수 있다는 말입니다.

일반적으로 옵티마이저는 여러 인덱스가 있을 때 선택도가 낮은 즉 중복발생확률이 낮은 인덱스를 사용합니다.

인덱스

인덱스는 검색을 빨리 하기 위한 용도로 사용합니다.

인덱스를 여러 개 사용할 때는 넌클러스터 인덱스를 사용합니다.

인덱스를 여러 개 사용할수록 옵티마이저가 잘못된 인덱스를 선택할 확률이 높아집니다.

인텍스를 하나의 컬럼에만 걸어야 한다면 카디널리티가 가장 높은 경우 즉 중복을 제거 했을 때 집합 원소의 개수가 가장 많은 속성을 지정합니다.

예를 들면 성별을 인덱스로 지정하면 카디널리티가 2밖에 되지 않으므로 인덱스로 걸러지는(Range로 걸러진다고 할 때) 경우가 50% 밖에 걸리지지가 않습니다.

100 개 중에 유일한 하나일 경우라면 1%이나 99%가 걸리지는 경우이겠습니다.

인덱스로 걸러낸다는 개념은 무엇일까요???

그리고 우리가 사용하는 테이블은 기본적으로 어떻게 설계하길래 성능이슈가 있게 된 것일 까요??

어려워 지는데 하나 확실히 아는 것은 사원번호나 주민번호와 같은 속성의 값을 대표값으로 할 수 있는 것은 현재 구성원을 구성하는 큰 집합에서 유일한 속성으로 취급할 수 있는 것입니다. 10이하의 자연수의 집합일 경우라면 {1,2,3,4,5,6,7,8,9,10} 원하는 숫자를 찾을 때 중복이 없으므로 유일한 값 하나를 찾습니다. 이렇게 유일한 속성의 인덱스는 내가 찾는 요소 하나로 최대한으로 나머지 원소를 거를 수 있습니다. 이런 개념에서 카디널리티를 이해하고 넘어가고자 합니다.

위의 개념에서 인덱스의 유일성이 필요에 대해서 이해가 되었으면(모든 인덱스가 유일성을 가지는 것은 아닙니다)

낫널에 대해서 이야기 해 볼까요? 기본적으로 데이터베이스의 엔터티 혹은 릴레이션 혹은 테이블이라고 하는 개체는 해당 컬럼이 동일 선상에서 이미 다른 컬럼들과 원자적인 구조로 만들어져야 합니다. 즉 본인이 변경되었다고 다른 컬럼의 값도 변경이 된다는 것은 정규적이지 않은 관계입니다. 그리고 data의 중복을 최소화 한다는 것은 하나의 Row, 튜플 이런 값이 다른 Row, 튜플과 구별되는 대표값이 있어야 한다는 것입니다. 그렇다면 대표값이 널이 되어버리면 일단 다른 Row들과 구별되거나 해당 Row를 대표할 수 없습니다.

유일한 Row이고 그 값이 비어있지 않으며 속성들끼리 원자적인 테이블에서 대표값만 가지고 그 Row, 튜플을 찾거나 맵핑 할 수 있습니다. 대표값만 가지고 데이터를 찾는다.. 인덱스가 그런 용도의 느낌입니다.

 

확률

확률이 예를 들기 좋은 것 같습니다.

카디널리티라는 주머니를 만들고 거기에 빨주노초파남보 의 무지개 색 공을 집어넣으면 이 경우 선택도는 1/7 입니다.

그러면 빨간공 3개 노란공 2개 보라색공 4개를 넣으면 이 경우 선택도는 몇 일 까요?? 빨간공의 확률은 1/3 노란공은 2/9 보라색공은 4/9 입니다 이건 단순히 시행(반복)이라는 시도와 맞물려서 말할 수 있는 확률 인 것이고

공이라는 개념으로 접근하면 3개의 색만을 가지므로 그 공이라는 릴레이션은 엔터티는 테이블의 색깔이라는 속성은 선택도가 1/3 0.33 입니다.

 

그리고 그 빨주노초파남보 이면서 각각 1~7까지의 숫자가 매겨저 있는 상황이라면

빨 주 노 초 파 남 보

1  2  3  4  5  6  7

 

이런 상황에서 숫자와 색깔이라는 속성의 선택도는 어떻게 될 까요??

제가 확률을 얘기 했으니 숫자로 하면 1/7 색으로 하면 1/7입니다. 단 이것은 전에 말했듯이 시행에 의해 획득할 수 있는 한번의 공입니다 다만 유일성이 확보가 되니 선택도는 1/전체 이고 뭘로하든 카디널리티는 1 입니다.

근데 예제를 바꾸면

빨 주 노 초 파 남 보

1  2  2  2  3  4  4

 

이런 상황에서는 선택도가 변하겠죠? 색으로는 1/7이고 숫자로는 1/4 입니다.

여기서 어떤 속성을 기준으로 하느냐에 따라 확률이 달라졌고 그에 따라 선택도(카디널리티)도 달라졌습니다.

여기서 속성을 색과 숫자로 나눈 이유는 인덱스를 어디다 거는 기준이 뭐냐?? 라는 말을 하고 싶어서 입니다.

 

최소한의 기준은 앞에서 선택도가 낮고 카디널리티가 높은 경우를 말했습니다. 그리고 여기서 선택도라는 확률에서 분모 즉 유일성이 보장되는 모집단의 개수입니다. 경우의 수라고도 보이겠네요

이게 더 큰 경우로 색깔이 나오기 때문에 공이라는 릴레이션 엔터티 테이블은 인덱스를 색깔로 잡아야 숫자보다 효율이 좋습니다.

즉 숫자로 해야 걸러지는 케이스가 많아진다는 말입니다.

확률 공식을 보면

 즉 카디널리티는 일정한 기댓값 즉 평균의 속성을 가지고 있습니다.

위의 내용은 확률 분포 내용으로 기댓값이란

사실 위의 내용을 고민하지 않아도 인덱스를 만들거나 하는 것에는 크게 상관이 없습니다. 조인을 만드는 것도 또 옵티마이저에게 성능판단을 위임하는 것도 개발자가 DBMS를 이해해야 하나? 라는 의문을 가지면 딱히 할말은 없지만 옵티마이저는 분명 만능이 아니고 최적화에 실패할 수 있습니다. 그리고 인덱스를 가지고 검색을 할 때 동작하는 거나 원리는 DBMS마다 조금씩 다를 수 있습니다. 모든게 같으면 DB가격이나 성능이 같아야 할 테니까요 위에 내용에 대해 궁금하게 접근한 이유는 이미 누구나 알고 있는 인덱스의 동작원리보다는 어떤 녀석이 인덱스가 되어야 하지?? 넌 어떤 점이 좋으니 인덱스가 되고 넌 어떤 점이 안좋으니 인덱스가 될 수 없다 하는 어떤 녀석이 인덱스로 고민하고 또 그것을 활용하는 옵티마이저는 이 인덱스의 어떤 점에 끌려 자기만의 인공지능적인 최적화를 수행 할 수 있을까? 라는 부분에서의 물음입니다.

즉 가능하면 내부적으로 개발자가 직접 인덱스를 만든다면 적어도 그 테이블이나 데이터를 보고 그 기준이 되는 부분을 찾아보고 싶기 때문입니다. 물론 옵티마이저에서 제가 생각한 선택도나 카디널리티나 기댓값이나 이런 부분에 영향을 미쳐서 판단한다고 증명된 것은 없습니다. 다만 저의 위키의 내용은 제가 인덱스를 고려할 컬럼을 정한다면 (PK 외적으로) 저런 수치적인 부분이나 그 속성의 고유한 특성을 고려해서 해당 컬럼에 인덱스를 걸고 그 인덱스를 옵티마이저가 제가 원하는 기준(작은 수량은 NL조인, 대량의 데이터는 Sort Merge 조인, 메모리 성능도 좋고 양도 많으면 Hash 조인으로 동작하기를 희망하기 때문에 인덱스를 재물로 삼았습니다. )

인덱스가 아니라면 일단 옵티마이저에게 어떻게 말을 걸고 접근할지 막연하기 때문에 인덱스로 그리고 그것이 조건이 되었을 때 옵티마이저 안녕? 이것을 하려고 합니다.

 

위의 내용까지가 서론이고 이제 본론에서는 실제 데이터의 수량을 달리하면서 실행 계획에서 어떻게 성능적으로 달라진는지 확인해 보겠습니다.

 

조인을 깊이 이해하는 것은 어렵고 동일한 결과를 얻을 수 있는 조인 방법은 많이 있지만 주어진 환경에 따라 효율성이 차이가 난다

즉 어떻게 사용하느냐에 따라 결과가 천지만별이라는 것이다.

실행계획을 이해했고 조인의 기본적인 처리 절차를 파악해둠으로서 나중에 조인을 깊이 이해 하기 위한 사전준비일 뿐이다…(책에서)

1.         내포조인

2.         정렬병합

3.         해시조인

4.         세미조인

5.         카티전 조인

6.         아우터 조인

7.         인덱스 조인

엔코아 책에서는 저렇게 만 다룬다고 하니 더 있나보다

 

간단히 말하면 일단..

기본적으로 조인의 원리를 생각하려면 SQL 즉 코드로 인해 조인을 만들 것이고 그 조인을 구성하는 Table 즉 이 대상으로부터 data를 취득할 때 DBMS가 어떻게 데이터를 취합하고 어떻게 데이터를 저장하고 그 저장된 데이터에서 원하는 조건에 맞게 가져오는 지 궁금증을 가지는 데에서부터 시작한다.

 

즉 내부조인이나 외부조인 같은 방법을 사용해서 쿼리(질의)를 하고 그 결과는 DBMS에서 반환되며 디스크 or 메모리 상에서 어떠한 연산??(알고리즘) 에 의해 빠른 속도 or 느린 속도로 결과를 만들어주게 된다.

여기서 어떠한 연산?? 이 부분을 아는 것이 일단 지금 단계서의 목표이다.

기본적으로 생각 해야 하는 것은 적어도 우리는 최대한의 정규테이블로 구성된 DB에서 작업이 일어날 것이며 그렇기 때문에 정규테이블간의 관계에 따라 필요한 데이터를 얻기 위해 조인을 하게 되고

그 때 그 테이블을 필터하는 범위나 컬럼의 선택도나 사용하고 있는 인덱스에 의해 쿼리의 성능이 정해진다

 

자 그렇다면 1.내포조인 2. 정렬병합 3. 해시조인에 대해 간략히 언급하고 넘어간다

 

일단 기본은 내포조인이다. 즉 중첩된 루프를 돌면서 Outer table에서 Inner Table로 조건이 일치되는 data를 찾는 것이 가장 보편적으로 사용되는 조인이다

여기서 기본적으로 사용되는 자료구조는 B+Tree 이며 Root 부터 Branch를 지나 Leaf를 찾는 것이 알고리즘의 핵심이다

이 알고리즘을 사용할 때 정렬되냐 정렬이 안되냐에 따른 차이는 있지만 기본적으로 NL 조인은 랜덤엑세스를 해서 찾아간다 그래서 (Index)Table Scan을 하면 안 되고 Index Seek or Range Scan을 해서 범위로 접근해야 기본적인 성능이 좋다고 본다

그 한번의 랜덤엑세스가 중첩된 Roof를 돌면서 반복되므로 Scan이 아닌 Seek or Range를 가지는 부분이 성능의 핵심이다.

Sort Merge의 경우는 위의 Case에 정렬된 자료구조를 가지고 있다고 생각하면 된다 즉 내부적으로 정렬 프로세스를 거치니 초기 작업은 오래 걸려도 실제 찾는 프로세스는 적게 걸릴 수 있다 NL의 단점을 극복하기 위해 생겼다고 한다

Hash 의 경우는 Sort Merge가 정렬프로세스를 가지고 있다면 단점을 극복하려고 생겼다고 한다 즉 이 부분은 알고리즘적으로 접근해야 하는데 O(logn)도 충분히 훌륭한 것이지만 해시 맵을 만들면 해시 알고리즘은 O(1)이기 때문에 정렬을 하지않아고 검색이 가능하다고 한다 단 해시결과가 유일한 지 검증하는 부분이 추가되므로 꼭 O(1)은 아니라고 한다 어쨌든 알고리즘 적으로 해시 맵을 만들어서 검색하는 것이 더 탁월해 사용하는 조인방법이다.

 

즉 조인은 기본적으로 복수의 대상간 중첩된 루프를 돌며 조건이 맞는 경우를 찾는 것이고 NL의 경우 B+Tree 구조상에 랜덤엑세스의 부담 때문에 그 부담을 줄이고자 정렬된 상태에서 엑세스를 하는 Sort Merge 조인이 생겨났고 정렬을 미리 해야 하는 전처리에 대한 부담으로 아예 유일한 해시값을 생성해서 그 해시를 이용해 조인을 하는 것이 해시 조인이다라고 까지 생각하고 더 붙이자.

 

자 여기서 중요한 것은 인덱스 설계를 잘하는 것이다 인덱스에 따라 옵티마이저가 보다 좋은 엑세스경로를 찾을 수있게하는 근본적인 방법이다.

인덱스는 현재 발생할 수 있는 상황과 데이터의 분포도나 결합도 선택도등을 고려해서 설계되어야 한다

 

다른 사람의 구직 수기인데 읽어볼 만한 포인트가 있어서 첨부해 봤다 

http://multifrontgarden.tistory.com/202?category=471261


아마 배달의민족, 라인플러스, SK컴즈, 스마일게이트, 네이버랩스, 카카오 중 하나인데 국내 탑이라고 생각하고 자바기반이라면 네이버랩스?? 


어쨌든 중요한 건 잘읽히고 공감도 많이 갔다 



 취업 시장에 뛰어들었다. 남들 다 다니는 국비지원 학원조차도 다니지않은 상태에서 참으로 운좋게도 작은 SI업체에 취업이 됐었다. 연봉은 무척 낮은곳이었으나 무작정 경력 뻥튀기가 없고, 가급적 2명 이상 파견을 지향하며, 자바 위주의 회사라는 점에서 정말 세상물정도 모르고 실력마저도 전혀 없던 당시의 나에게 이런 회사를 들어간건 참 운이 좋았다는 생각밖에 안든다. 이때 이상한 회사로 빠졌다면 지금의 나는 없지 않을까...

분명 운만은 아닐 것이다 적어도 어느정도 괜찮은 환경에서 배울 수 있었고 필자가 말한 그대로 퇴근 후 야간에 주말에 계속 스터디를 진행해 왔기에 그 운과 환경과 노력이 시너지가 난 것이다. 


 어찌저찌 회사엔 들어왔는데 아무것도 모르다보니 이대로는 안되겠다는 생각을 했었고, 여기저기 스터디 모임들에 참여하면서 공부를 이어갔다.

 지금생각하면 어떻게 했는지 정말 모르겠는데 아무것도 모르는 상태에서도 어찌저찌 시킨건 해나갔다. 미숙하더라도 만들었고, 잘한다는 소리는 못들어도 어쨋건 일은 지속적으로 해나갈 수 있었다. 당시 회사는 MiPlatform, xPlatform과 같은 x인터넷 툴을 이용한 개발을 위주로 했었는데 SI회사치고는 생각보다 야근도 많지 않았고, 주말출근도 많지 않았던 탓에 스터디 활동같은건 꾸준히 이어갈 수 있었다.



어찌저찌 하는 건 지금 생각해보면 문제를 푼다라고 생각된다 수학문제를 푸는 것이고 방정식을 푸는 것이다. 그 미지수 X를 구하는 것을 인터넷 검색이나 다른사람의 소스나 책이나 디버깅이나 해서 그 문제들을 풀게 된다 

다만 그 문제에 대한 증명을 못하면 그저 문제집 풀 듯이 무의미한 작업만 하는 것 같다 증명을 할 줄 알아야 한다.  


저 사람처럼 되지 못한 부분이 

1. 기본적인 컴퓨터 언어 책 조차 제대로 읽어 보지 않았고... 맨 처음에 어떻게 해야할지 노력이 부족했다.. 머리로 분석한 패턴을 적용하는 게 개발은 아니다

2. 첫 회사로 개발자 회사를 가지 못한 점.. 혜안이 없었다..

3. 꾸준한 스터디는 했지만 과연 충분히 공부가 되었는지.. 무늬만 공부는 하지 말자.. 


그래서 앞으로는 이렇게 해야 한다 

1. 가능한 전공 관련 모든 기본책 하다못해 그림책이나 아동용이라도 구해서 읽어봐야 할 것이고 

2. 이제는 개발자 거기서 연구하는 개발자가 있는 즉 SW가 메인인 회사를 가야한다 

3. 꾸준한 스터디를 하되 단순히 머리에 쑤셔넣기 식이 아닌 머리에 남는 공부를 해야한다는 것이다. 

4. 무경험에서 오는 괴리감?? 질문을 받았을 때 알거나 들어본 개념인데 불확실성을 해소를 못한 것은 자신이 없고 말을 못하겠다. 

    이 경우는.... 내가 묵은지처럼 숙성이 되서 진짜진짜 많이 알게되었을 때 라고.. 밖에 답이 없다  

이 글의 문체중에 기억에 남는 부분이 저런식으로 정리를 한다는 것이다. 


* 비 SI

* 가능하면 서비스업체(솔루션도 솔루션 만들어놓고 고객사마다 커스터마이징하는 SI성은 가고싶지 않았다.)

* Java 기반 시스템

* 가급적 판교(개발자라면 판교에 있어야한다는 나름의 의지(?)가 있었다.)


내가 두 번째에 해당되는 회사였다.... 저건 앞으로도 계속 체크해야하는 항목이다. SI는 해본적이 없지만.. 진짜 뭔가 아닌가 보다 사실 커스터마이징만 겪어봐도 이렇게 일할 거면 차라리 이 업계를 은퇴하는 것이 낫다 이 사람은 어떻게 저런 것을 판단하게 된 것이지????

판교랑 강남은 나의 데이터에 의해서도 선호되는 지역이다 대중소를 통틀어 좋은 회사일 확률이 높다



초반엔 서류 통과가 잘 안돼서 이력서를 어떻게 써야하나 라는 고민도 했었는데 블로그를 첨부하고나니 서류통과의 비율이 월등히 높아짐도 느낄 수 있었다. 서류 통과 이후 면접을 보면 합격률도 꽤나 높았다. 다만 구직자를 대하는 회사의 태도, 회사의 기술기반(.net이라던가...) 등등이 맞지않아 합격한 곳도 거절하기도했다. 대충 붙는데 가는게 아니라 이번에 확실히 탈SI+괜찮은 분위기의 자바개발자로 성장할 수 있는 곳을 가고싶었다. 



나름 합격되는 비법이 블로그 첨부가 아니라 블로그를 쓰면서 공부했다고 읽혀진다. 근데 그 블로그가 수준이 높다기 보다는 고민이 녹아 있는게 느껴지는 글들이 많은 듯 했다.



* 가급적 판교

* IDE는 IntelliJ

* 가급적 테스트케이스를 작성하는 팀(TDD까지는 아니라도)

* 코드리뷰 시스템이 갖춰진 팀

* 가급적 Java8 이상을 사용



재밌는 부분은 VC++ 6.0 or VS 2003 같은 툴로 개발을 하니 VS 2013이나 VS2015 이런건 시간이 지나 컴파일러가 안정화가 된 후 사용하는 것 인줄 알았다 실제로 구식을 사용하는 사람의 입에서는 도구 탓을 할 필요가 없다고 했다.. 틀린말이 아니지만 내가 있던 구식 도구를 쓰는 조직은 변화에 대처하지 못했고 캐시카우 하나만 보고 개발자의 자부심이란 1도 없는 그런 곳이 었다 

신기술은 겉멋들어서 허세부리려고 보거나 하는 게 아니다 궁금하고 공부하고 싶어서 신기술이나 새로운 도구를 하는 것이다 나 또한 도구 탓한다는 말을 듣고 싶지 않아서 나 혼자만의 기준점인 줄 알았는데 동지를 만난 기분이었다 


TDD라는 말이 나와서 말인데 제일 궁금했던 것 중 하나가 SW개발 방법론이었다 천재 혹은 누군가 엄청난 고민을 해서 많은 이론을 적용도 못하거나 조직자체의 고민이 없어 아무런 체계도 없는 회사는 가지 않는 게 낫다

즉, 뭔가 시도 조차 아무것도 안 한다면 그 회사의 성장은 죽은 것이다. 죽은 회사에서 빛나는 보석? 뭐 어쨌든 난 그런 천재도 아니고 역경헤치는 드라마 주인공일 생각도 없고 제발 환경만이라도 제발 쉽고 재밌게 일해보고 싶다.. 진심.. 



 회사를 옮기고나니 당연히 나의 부족함도 눈에 띄었고 이전부터 해오던 습관을 바꾼건 없었다. 스터디는 여전히 진행했고, 퇴근 후나 주말에 공부하는건 여전히 유지했다. 여기서도 좋았던건 이전회사는 이렇게 공부하고있으면 왜 공부하냐는 소리를 들었지만 여기서는 그걸 독려하고 칭찬해준다는점이 좋았다. 그리고 그런분위기를 조성하려는 것도 좋았다. 개발자로 성장하기에 환경이 참 좋다는 생각과 여기가 시작인 분들에게 부러운 마음이 들기도했다. 그분들의 3년차와 나의 3년차는 다를테니.


 뭐 쨋건 공부도 열심히 했고, 일도 열심히 했다. 이전에는 객체지향, SOLID, Design pattern 같은건 그냥 책에만 나오는 내용이고 면접에서만 나오는 내용인줄 알았는데, 여기는 정말 그걸 코드 내에 녹여내고있었다. 코드리뷰에서 된통 깨지고나면 그걸 수정하기도하고, 이후엔 코드리뷰 전에서부터 코드에 대해 고민을 하게되면서 내가 작성하는 코드의 질이 좋아진다는걸 스스로 체감하기도 했다. 이전 회사의 2년은 지식을 쌓아올리는 시기였다면 여기서의 2년은 그 지식들을 코드에 녹여넣는 시기가 된것같다.



고민하는 개발자.. 의 한 예를 본것 같다 



출처: http://multifrontgarden.tistory.com/202?category=471261 [우리집앞마당]



아래 내용은 트랜잭션 2탄이다. 

다만 코드로 나타내보고 싶은에 일단 글로 남겨본다 구현의 문제는 좀 더 나중에 고민 


관련된 책은 계속 읽어 봐야 겠다 

지금 총 5권이 있는데 난이도로는 


초급

Head First SQL 


중급 이상

SQL Server(개발편)

SQL 전문가 가이드 

대용량 데이터베이스 솔루션 Vol1(엔코아)

웹 프로그래머를 위한 데이터베이스를 지탱하는 기술 


이렇게 다 봐야 할 것 같다 


지금 정리할 내용은 중첩 트랜잭션 즉 트랜잭션이 이중 For문 이상 처럼 중첩되서 시작될 때 과연 트랜잭션 개수나 명시적 혹은 묵시적 이나 Auto Commit이면 어떻게 되는 것인가에 대한 고민이다. 


일단 몇가지 주의?? 사항이 있다 


1. 트랜잭션 선언 방법 

명시적

묵시적(오라클 기본)

Auto(SQL Server 기본)


2. 트랜잭션의 관리주체

로컬

분산(or Global)


3 중첩 영역 (트랜잭션 허용범위?)

Code(.Net)

Stored Procedure(DBMS)


총 3가지 요소로 나누고 사용하는 방법을 생각해보자 

현재 내가 다루는 부분에서는 어플리케이션 계층 즉 Biz 영역을 가지고 있다 그래서 기본은 Biz에서 트랜잭션을 처리하는 것이 기본이다. 


이걸 가지고 가설(또는 주장)을 세우자 

가설 : app에 Biz영역이 있으면 어플리케이션 계층에서 트랜잭션 처리를 한다!

라는 가설을 세우고 그것에 대한 타당성 검증을 하자 


그러면 고려되는 부분이 Code에서 트랜잭션 처리를 해야 한다는 것이다. 이것에 대한 기술은 .Net의 TrasactionScope를 사용하거나 IDbTransaction을 사용해서 트랜잭션 단위를 묶어서 처리할 수 있다 

기술적으로는 문제가 없다 


그렇다면 Biz영역을 왜 만들었나에 대한 질문을 할 수 있는데 나의 답은

DAO(Database Access Object)를 통해 DB를 변경하기 전에 로직에 따라 데이터를 수정하고 원하는 타입(예를 들면 Table Value Parameter)와 같이 변경해서 사용하거나 필요에 의한 가공을 하고 여러 Table(Entity)애 접근 할 수 있으니 그건 업무에 따라 달라지는 부분을 묶어서 업무 로직을 트랜잭션으로 처리하기 위해서 라고 길게 말하고 DB에 반영하기 이전에 데이터나 모델의 수정을 한 곳에서 일괄적인 작업단위로 분리하기 위해서 라고 간단히 말 할 수 있다 


그러면 SP에서 트랜잭션이 걸리면 어떻게 할거냐?? 라는 반론이 생길 수 있는데 

이때 중첩 트랜잭션이 생기고 그것에 따라 트랜잭션 개수가 복수로 생길 수 있다 

즉 Code에서 Begin Tran을 하면 하나의 트랜잭션이지만 SP에서도 Begin Tran을 하면 2개이상의 트랜잭션이 생긴다는 것이다. 

이렇게 되면 2번의 Commit이나 Rollback에 의한 초기화가 되야 짝이 맞아진다 

Scope가 중요해지는 부분이 생기는데 이렇게 되면 Code나 SP에서 둘 다 관리포인트가 생기니 일련의 과정을 모두 확인해봐야 하는 번거로움이 생긴다 


이때 유효하게 사용할 수 있는 부분이 TM이다 즉 트랜잭션 매니저가 있어서 Commit과 Rollback을 제어해 줄 수 있고 관리를 위임할 수 있으면 개발자 입장에서는 편해진다. 

그러니 Code에서 트랜잭션 처리를 할거면 TM역할을 하는 TransactionScope나 IDbTransaction을 이용해서 Work 단위를 만들면 중첩된 부분을 커버해주지는 않더라도 한 곳에서 트랜잭션을 시작하고 끝낼 수 있다 


한 곳에서 트랜잭션을 시작하고 끝낸다는 것에 대한 고찰 

사실 답은 억지로 끌어낸 감이 없잖아 있지만 중첩트랜잭션이 필요한가?? 에 대한 경우가 일관되게 적용하기가 아직 경험이 없다 그렇게 되니 일단 한곳에서 집중하고 필요한 경우 SP에서 중첩되게 사용할 수 있다고 말하고 싶다 

트랜잭션은 성능과 연관될 수 있다 트랜잭션이 길어지면 선행 처리가 길어진다는 것이고 그러면 후행처리는 그만 큼 느려지니 타임아웃에 의한 실패나 시스템 전체에 Sleep이 걸린 것 처럼 처리속도에 영향을 줄 수 있다 

그렇기 때문에 트랜잭션은 짧게 가져가되 성능감소는 최소화 하고 처리하는 Data는 무결성을 지켜주는 그런 식의 보완을 개발자가 제어해줘야 한다고 생각한다. 


간단히 의사 코드로 표현 해 보면 

TransactionScope Start 

{

Begin Tran()                // Transation Count +1 증가


Excute SP(insert Model)


Commit()


Excute SP(insert Model)

{

// 아래 내용은 SP의 내용

// insert into Table (Columns) values (Model)

Insert(Model) 

}


위와 같이 하면 Transaction Count가 1인 것이고 

아래와 같이 SP에 트랜잭션을 다시 걸면


TransactionScope Start 

{

Begin Tran()                // Transation Count +1 증가


Excute SP(insert Model)


Commit()


Excute SP(insert Model)

{

// 아래 내용은 SP의 내용

// Begin Tran            // Transaction Count +1 증가 

//     if(@@Transaction Count = 2)

//        insert into Table (Columns) values (Model)

// Commit Tran

Insert(Model) 

}


위 구문은 트랜잭션 카운트가 2가 되어서 Table에 Insert가 된다 
물론 위의 코드가 정확하다고 할 수 없다 Test Code를 작성할 때 Transaction Count를 사용할 때 생각지 못한 error 가 발생 했었기 때문에 
(@@는 Count를 반환하는 함수정도로 생각하면 될 것 같다 : http://forums.codeguru.com/showthread.php?493155-What-does-mean-in-MS-Sql-Server)
Test Case를 모두 Code로 해보려는 것은 실패했다 

일단 Code에서 시작한 Begin Tran이 SP의 Script 에서 @@TranCount를 만났을 때 호환이 안되는 것 처럼 보인다. 위의 SP가 실행되려면 상단에 Rollback Tran을 넣어주면 0으로 초기화가 되어서 Transaction Count가 2가 되지 않아 위의 SP는 Insert가 되지 않는다 (Rollback은.. 사실 강제로 SP에서 TranCount를 세기 위한 꼼수 같은 것이다.)
아마도 Code와 SP 모두 Begin Tran이 발생했을 때 그것을 받아들이는 DBMS에서 그 차이를 인지하지 못해서 문제가 발생될 수 있다고 해석된다. 

2개 이상의 중첩 트랜잭션의 필요여부 
꼭 그런것은 아니지만 로직을 짤 때 이중For문 이상 삼중 사중의 For은 피해야 하는 권장사항을 들은 적이 있다 즉 필요하면 써먹어야 겠지만 중첩 구조가 복잡한 것을 일부러 할 필요는 없다 그렇다면 비슷한 형태의 트랜잭션도 굳이 로직 사이사이에 필수로 라도 부분 Commit으로 처리해야하는 경우가 있는 것이 아니라면 Data의 수정을 All or Nothing 으로 하면 될 것으로 보인다 
그러면 부분적으로 SP에서 Begin Tran을 하는 경우는 부분 Commit이 있는 경우에 한정지어서 생각할 수 있다 만약 처리해야하는 부분이 많은데 부분 실패가 났을 때 완전 Rollback이 아니라 부분적으로 반영하고 재시도에서는 기존 Commit을 거치지 않는 그런 식으로 Retry인 경우에 이점이 있는 로직에서 처리할 수 있다 아직 그런 Case를 해본적이 없어서 가정일 뿐이다. 

위의 상황은 로컬 트랜잭션에 대한 과정이라는 것
분산트랜잭션을 경험해 보지 못해서인지 막연한 점이 있지만 하나 기준을 잡자면 어느 Resource 대상인지와 물리적인 대상이 변경되는지 2가지로 압축하고자 한다 위의 Insert는 특정 DB의 Table이다 그러니 하나의 DB만 수정하므로 분산된 Resource를 건드리는 것이 아니라 그리고 물리적으로 여러개의 DB를 건드리거나 통신적으로 (예를 들면 TCP / HTTP 를 사용해서 물리적인 Server가 달리지거나) 달라지는 것이 없고 하나의 Connection으로 단일 DB를 처리하므로 이런 case에는 단일 지역 트랜잭션 즉 로컬 트랜잭션으로 본다 
분산 트랜잭션을 구현하게 되면 여러개의 다른 Resource DB나 물리적으로 다른 Server 혹은 App에서 통신 구간이 변경되어 각각의 Data가 제대로 요청과 응답이 있었는지의 확인 과정을 거쳐야 해서 새로운 개념의 Scope의 Begin Tran이나 Commit or Rollback으로 묶어서 처리하는 부분이 있는 경우로 고려해 볼 수 있다. 

관련 내용 링크
https://ko.wikipedia.org/wiki/%EB%B6%84%EC%82%B0_%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98
https://technet.microsoft.com/ko-kr/library/ms191440(v=sql.105).aspx
http://krids.tistory.com/96

즉 분산된 트랜잭션을 쓰는 경우는 하나의 작업에서 다른 Server 접근 다른 DB 접근과 같이 상태가 변하는 경우로 간단히 볼 수 있다 
나중에 2PC(begin -> end -> prepare  -> commit)도 검증해보도록 하자 글로벌 트랜잭션이 이루어지는 과정이라고 한다 

MS Tech 쪽 설명을 보다보면 아래와 같은 내용이 나오는데

분산 트랜잭션은 리소스 관리자라고 하는 둘 이상의 서버에 분산됩니다. 트랜잭션 관리는 트랜잭션 관리자라고 하는 서버 구성 요소에 의해 리소스 관리자 간에 조정되어야 합니다. MS DTC(SQL Server 데이터베이스 엔진은 Microsoft Distributed Transaction Coordinator) 등의 트랜잭션 관리자 또는 분산 트랜잭션 처리용 Open Group XA 사양을 지원하는 기타 트랜잭션 관리자에 의해 조정되는 분산 트랜잭션에서 리소스 관리자 역할을 합니다. 자세한 내용은 MS DTC 설명서를 참조하십시오.  

트랜잭션 관리자라는 용어가 나오는데 아마도 위의 TM이라고 한 TransactionScope나 IDbTransaction 과 연관되어 있을 것으로 보인다
위키 백과에서는 

일반적으로 시스템은 트랜잭션 리소스(transaction resource)의 역할을 하고, 트랜잭션 매니저(transaction manager)는 이러한 리소스에 관련된 모든 동작에 대해 트랜잭션의 생성 및 관리를 담당한다

이 시스템이란 말은 데이터베이스로 대입해도 될 듯 하다 그렇다면 데이터베이스라는 리소스에 접근하는 부분에서 데이터베이스 엔진이라거나 MS DTC 이런 녀석들이 트랜잭션을 관리할 수 있고 Code에서는 위의 TransactionScope나 IDbTransaction 를 통해 관리자의 역할을 수행한다고 보인다. 

왜 마지막에 트랜잭션 매니저가 나왔냐 하면 위의 3가지 트랜잭션 선언방법 중 

명시적

묵시적(오라클 기본)

Auto(SQL Server 기본)

Auto Commit 이라는 것이 있다 이 녀석이 나에게 혼란을 주었다 


하나의 의사코드로 예를 들자면 

Begin Tran 

insert A

insert B

insert C

Commit Tran


insert A (commit)

insert B (commit)

insert C (commit)


위 2개의 방식에서 차이는 명시적 트랜잭션과 Auto Commit이다. 
아래의 경우에서 Auto Commit이 이루어 질때는 트랜잭션 개수가 3개인가?? 의문이 생겨버렸다. 
물론 하나의 작업으로 생각하면 3번의 트랜잭션이 있었다고 볼 수 있고 각각 한줄을 지날 때마다 영구적인 data의 변화를 줬기 때문에 트랜잭션의 영구성 원칙에 따라 트랜잭션 3번으로 보인다. 
그러면 트랜잭션으로 묶을 때와 아닐 때에 대해 트랜잭션에 대해 혼란이 가중된다. 뭐 일일이 트랜잭션 개수를 고려하는 것이 중요한 것은 아니겠지만 auto commit이 일어나는 것에 대해 어떻게 대처할 것인가에 대해 고려해줘야 한다.
이 때 정확한 Count는 알 수 없었지만 MS DTC가 되었든 DBMS가 되었든 단순 insert가 여러번 발생하면 그 하나에도 트랜잭션이 Begin ~ Commit이 일어났다고 봐야 할 것 같다 다만 사용자가 제어할 수 있는 트랜잭션이 아니기 때문에 Count를 확인하기 전에 트랜잭션이 끝나버렸다 
SQL Profiler로 확인 해 본 결과 TM이 아닌 각각의 BEGIN TRAN ~ COMMIT TRAN으로 잡혔기 때문에 트랜잭션 3개로 보는 게 옳은 것으로 보인다. 
TM이 관여한 트랜잭션도 아닌 것으로 로그가 남았다 명시적으로 BEGIN TRAN ~ COMMIT TRAN 을 사용하지 않았는데 해당 구문을 추적하는 이벤트에 남은 것으로 보아 명시적으로 선언하지 않으면 DBMS에서 DML 구문 하나가 끝날 때 Auto COMMIT TRAN을 만들어 주는 것으로 예상된다 

어쨌든 그렇다면 트랜잭션 개수는 카운팅되어야 하는 것으로 보인다. 

자 마지막 결론을 내린다. 
위의 일련의 과정은 결국 트랜잭션 처리는 어플리케이션에서 Biz 계층이 있다는 경우면 단순하게 DAO 영역에서 데이터베이스에 접근해서 CRUD를 하는 것이 아니라 필요한 로직처리가 있는 것이고 그 로직에서 Code에서 트랜잭션을 처리하기 때문에 기술적으로 TransactionScope나 IDbTransaction 을 통한 트랜잭션 매니저를 이용하게 되고 그 트랜잭션 매니저에서는 일단 하나의 트랜잭션 Count를 만들고 내부에서 호출한 SP에 BEGIN TRAN이 있으면 또 새로운 트랜잭션 Count가 생기는 것이다. 다만 이렇게 사용해야 하는 경우가 있다면 중첩된 For문을 쓰는 것과 같이 중첩된 트랜잭션이기 때문에 가급적 부분처리를 해야하는 것이 아니면 Code에서 일관되게 트랜잭션의 원자성과 격리성을 지켜주어서 All or Nothing 을 지켜준다
그러니 Biz를 어떻게 나누냐에 따라 트랜잭션을 고려한 개발을 하는 것이라고 할 수 있다는 것이다 
그리고 이것은 필수 사항은 아닌 것이다 왜냐하면 Code에서 하지 않으면 SP에서 BEGIN TRAN ~ COMMIT TRAN or ROLLBACK TRAN을 하는 경우이면 SP에게 트랜잭션 처리를 위임하게 되므로 DB에서 SP 내부처리로 할지 Code에서 Biz로 처리하는 것을 구분할 줄 알고 Biz에서 처리할 때는 일관된 DB Connection이 유지되어서 DB로의 접근을 가장 단순하게 해야 하는 이유가 생기는 것이다. 헷갈리지 말자 

만약 Biz 가 없고 정말 단순히 DB의 data를 변경하는 경우라면 SP에서 트랜잭션을 시작해서 BEGIN TRAN ~ COMMIT TRAN or ROLLBACK TRAN 로 처리 할 수도 있다는 것이다. 
그리고 트랜잭션 매니저의 내부처리에 대해서 궁금할 수도 있지만 단순히 각각의 SP를 큐에 모아놨다가 Commit이 일어날 때 큐에 모인 SP 전체를 실행해서 비우는 것처럼 은유적으로만 생각하고 깊게 생각하지 말자 트랜잭션 매니저는 단지 이용하는 수단일 뿐이다

트랜잭션 카운트 계산 법

Begin Tran 

insert A

insert B

insert C

Commit Tran

= 1개

insert A (commit)

insert B (commit)

insert C (commit)

= 3개 

TransactionScope.BeginTran
Excute SP
TransactionScope.Commit 
= 1개

TransactionScope.BeginTran
Excute SP A
SP.BeginTran
Insert data a
SP.Commit
TransactionScope.Commit 
= 2개

TransactionScope.BeginTran
Excute SP A
SP.BeginTran
Insert data a
SP.Commit
SP.BeginTran
Insert data b
SP.Commit
Excute SP A
SP.BeginTran
Insert data c
SP.Commit
Excute SP A
SP.BeginTran
Insert data d
SP.Commit
TransactionScope.Commit 
= 1 + (1 * 2) + (1 * 1) + (1 * 1)  = 5개 


트랜잭션 간단 정리 


그냥 간단하게 남기려고 쓴다 

주 내용은 서비스개발실 SQL Server 책이랑 SQL 전문가 가이드 내용을 보고 남긴다. Head First SQL 보고 추가할 내용이 있으면 수정한다.  


트랜잭션이란? 

- 처리하는 작업의 논리적인 처리 단위

- 작업 단위는 그것을 구성하는 세부적인 작업의 연산(더하기 빼기 등등)들의 집합

-  데이터베이스 응용 프로그램을 트랜잭션 들의 집합으로도 볼 수있다고 한다 (기능 하나하나가 트랜잭션이라고 볼 때)


트랜잭션을 이해해야 하는 이유

- 불필요한 잠금을 피하고 잠금(Lock)을 원천적으로 피할 수 없지만 최대한으로 관리하기 위해서 


트랜잭션의 범위

- 트랜잭션 하나에 데이터 처리작업(입력, 수정, 삭제) 하나가 포함될 수도 있고 처리작업 여러개가 하나의 묶음으로 포함될 수 있다


All of Nothing 

- 말 그대로 여러데이터를 변경할 때 변경 처리가 모두 완료되거나 아니면 일부가 처리되지 못하면 이미 처리된 작업마저 취소해서 전부 되거나 전부 안되거나 그런 말이다. 


4대 속성 

- 원자성 : All of nothing

- 일관성 : 트랜잭션이 완료된 데이터는 일관되게 유지되어야 하는 것

- 격리성 : 동시에 트랜잭션이 실행될 때 서로간에 간섭하지 않는 것 

- 영속성 : 트랜잭션이 완료된 데이터베이스 변경사항이 영구적으로 저장되는 것


TCL(Transaction control language) 

- Commit : 올바르게 반경된 데이터를 데이터베이스에 반영시키는 것

- Rollback : 트랜잭션 시작 이전의 상태로 되돌리는 것

- Savepoint : 데이터 변경을 사전에 지정한 저장점 까지만 롤백하라는 것 


트랜잭션의 대상 

- UPDATE, INSERT, DELETE등 데이터를 수정하는 DLM문

- SELECT 문은 직접적인 트랜잭션의 대상이 아니지만 SELECT FOR UPDATE 등 배타적 LOCK을 요구하는 SELECT 문장은 트랜잭션의 대상이 된다고 한다

  --> 나중에 Lock 정리할 때 내용 추가


Commit이나 Rollback 이전의 데이터 상태 

- 메모리 Buffer에만 저장되어 있어서 데이터의 변경 이전 상태로 복구 가능

- 현재 사용자가 SELECT 문장으로 결과를확인 가능 (이런건 테스트 해보자)

- 다른 사용자는 현재 사용자가 수행한 명령의 결과를 볼 수 없다 (Lock?)

- 변경된 행은 잠금(Lock)이 설정되어서 다른 사용자가 변경할 수 없다. 


Commit 이후의 데이터 상태 

- 데이터에 대한 변경 사항이 데이터베디읏에 반영된다

- 이전 데이터는 영원히 잃어버린다. 

- 모든 사용자는 결과를 볼 수 있다 

- 관련된 행에 대한 잠금(Lock)이 풀리고 다른 사용자들이 행을 조작할 수 있게 된다


Auto Commit (이놈은 트랜잭션이냐... 아니냐...)

- SQL Server 기본값 

- DDL, DML 수행시 DBMS가 트랜잭션을 컨트롤하는 방식 명령어가 성공적으로 수행되면 Auto Commit이 되고 오류가 발생하면 Rollback을 자동으로 수행


암시적 트랜잭션

- Oracle 기본 값

- 트랜잭션의 시작은 DBMS가 처리하고 트랜잭션의 끝은 사용자가 명시적으로 Commit 또는 Rollback으로 처리하는 것

- 인스턴스(데이터베이스 자체 연결??)나 세션 단위(사용자 단위????)로도 설정할 수 있다????


명시적 트랜잭션

- 트랜잭션의 시작과 끝을 사용자가 명령어를 써서 지정하는 방식 

- BEGIN TRAN ~~~~ COMMIT or ROLLBACK 


Commit과 Rollback 으로 얻는 효과 

- 데이터 무결성 보장 (명령이 실행되어야만 반영되고 트랜잭션의 고립성 특성으로 데이터 접근이 제어되기 때문)

- 영구적인 변경을 하기 전에 데이터의 변경사항 확인 가능(이건 현재 사용자만 가능할 듯 다른 사용자는 안 됨)

- 논리적으로 연관된 작업을 그룹핑하여 처리 가능 (작업 내부의 세부적인 연산을 처리한다는 말과 같은 말)


트랜잭션 주의사항 

- Create, Alter, Drop, Rename, Truncate 등 DDL 문장을 실행하면 그 전후 시점에 자동으로 커밋된다

- DML 이후에 DDL이 수행되면 DDL 수행전에 자동으로 커밋된다는 말이다 

- 데이터베이스를 정상적으로 접속을 종료시키면 자동으로 트랜잭션이 커밋된다.

- 어플리케이션의 이상 종료로 데이터베이스와의 접속이 단절되면 트랜잭션이 자동으로 롤백된다 (진짜????? connection이 어떻게 관리되는데???)


트랜잭션의 개수 

- 트랜잭션 카운트라는 것이 있다 MS SQL에서는 @@TRANCOUNT 라는 것이 있어서 현재 BEGIN TRAN이 몇개나 있는지 알 수있다 

예를들면 중첩 트랜잭션을 보면 이해가 쉽다 

BEGIN TRY

             BEGIN TRAN

                           SELECT @@TRANCOUNT  -- 1

                           BEGIN TRAN

                                        SELECT @@TRANCOUNT -- 2

                                        SELECT TOP 1 * FROM sys.sysobjects

                           ROLLBACK TRAN

                           SELECT @@TRANCOUNT -- 0

             COMMIT TRAN  -- error

             SELECT @@TRANCOUNT -- 0

END TRY

BEGIN CATCH 


END CATCH

출처: http://ddoung2.tistory.com/178 [DDoung2]


뭐 저렇다는 것인데 저건 예시고 실제로는 .NET의 C# 코드에서 한번 DBMS가 실행하는 SP에서 한번이상 이런 식으로 BEGIN TRAN을 할 수 있다.

아래 훈스닷넷 커뮤니티에 예시가 잘되어 있는데 

http://ucclight.hoons.net/Board/qacshap/Content/97132


여기서 보면 C# 코드에서는 TransactionScope로 트랜잭션을 시작했고 SP안에도 Begin Tran이 있다 즉, TRANCOUNT가 2가 되는 것인데 

위의 중첩 트랜잭션 예시는 Try로 감싸서 오류가 나도 예외처리가 된다 Try를 제거하면 두 번의 트랜잭션이 시작되고 Rollback이 되면서 TRANCOUNT가 0이 되고 나서 다시 COMMIT 을 하게 되니 트랜잭션 처리할 것이 없는데 처리하라고 해서 생기는 오류가 난다


훈스닷넷의 예시를 보면 Code에서 시작한 트랜잭션이 SP 스크립트 안에서도 트랜잭션이 동작하면서 관리가 양쪽에서 다하니 힘들어지는?? Code, SP 양쪽에서 관리 한다니 ㅠㅠ 어쨌든 error가 나는 case이고 이것에 대한 트랜잭션 개수는 좀 더 정확히 파악해서 테스트를 하도록 한다 

또 한가지... Auto Commit이 일어 날 때 뭐가 달라지는 지 확인해 보자.. 어렵다 Auto Commit은 개수를 무시해야 하나???


어쨌든 훈스닷넷 예시에서는 기본적으로 트랜적션은 프로그램으로 하실꺼면 프로그램에서만 프로시저에서 할꺼면 프로시저에서만 하시는걸 추천드립니다. 

이렇게 말 하고 있다 그리고

개인적으론 특별한 경우가 아니면 프로시져에서만 합니다.  한쪽에서 하지 않으면 논리적인 오류가 날 가능성이 매우 큽니다.그리고 추적역시 쉽지 않지요. 그리고 프로그램에서 하실꺼면 .net2.0 이상이면 TransactionScope로 싸시는걸 추천드립니다.

이렇게 자신의 추천하는 방법도 제시해 주고 있다. 


약간 정답이 없는 문제이다. 모든 트랜잭션을 SP내부에 위임할 수도 있고 코드로 제어하는 것이 좋아서 .NET에서 TransactionScope나 ITransaction 인터페이스를 사용해 구현한 UnitOfWork(라이브러리 아님 커넥션 하나에서 트랜잭션을 처리하는 패턴 같음(회사에서 사용)) 에서 트랜잭션 관리를 위임할 수 있는 선택의 문제가 같이 있다 

어짜피 코드가 좋을지 SP에서가 좋을지 판단할 만한 경험이나 통찰력이 부족하다 일단 양쪽에 다 Transaction 관리가 된다는 것만 이해하고 나중에 개념을 업그레이드 시켜보자.



기본적인 내용은 여기까지!!!

 

Entity Framework

 

- 추억의 Entity Framewok이다. 이 내용을 보다가 좀 화가 났다.

  사실 C#을 처음 접하게 된 계기가 ASP.NET MVC3 이다.  ActiveX(ocx) 환경의 웹 화면을 ASP.NET MVC3 로 변경하게 되면서 보게 되었는데 문제는 이걸 하기로 한 C# 개발자 과장님이 실패하고 쫓겨나면서 이제 일한지 6개월도 안된 나에게 넘어 온 프레임워크이다.

 젠장 C#도 처음보고 DB도 모르고 ORM은 기억이 안나는 거 보니 검색도 못했던 것 같고 웹 개발이랑 console 개발이랑 차이도 모르니 당연히 프론트 쪽의 javascript나 html 도 잘 모르는데 다 다루고 앉아 있고 힘든건 이게 메인업무도 아닌데 매일마다 어디까지 했냐고 압박받으면서 ㅠㅠ 거의 10년차도 포기한 걸 억지도 떠맡아서 개고생하면서 XXXXXXXXXXXXXXXXXXXXXXXXXXX 어쨌든 웹 페이지 호출이랑 CRUD 기능 동작하는 웹 어플리케이션 개발한 것을 시연하고 풀려났던 기억이 있다.. 내가 틈틈히 주말 야간으로 2달간 고생한 걸 경력직 과장님이 와서 1주일도 안되서 해결한 걸 보고 자괴감은.. 플러스..

 이번에는 Code-First 에 대한 내용을 보다가 여기까지 올라왔는데 갑자기 첫 회사 신입때가 생각나서 울컥하는 마음에 남기게 되었다.... 결국은 내가 완성할 수 있는 솔루션 규모가 아니었는데 왜 그런식으로 시험을 받아야 했었는지..모르겠다 문제 해결 능력만으로 개발을 할 수 있는(최대한 좋게 말해서이다.) 것도 장점이 있었겠지만.. 단점이 너무 많았던 것도 같다 집에와서 해야 하니 머릿속에 온통 How에 대한 생각밖에 없었으니..

 그냥.. 잊자.. 어짜피 퇴사전이나 퇴사 이후에 충분히 내 몫을 해내고 내 스스로 다 했다는 말도 들었으니.. 그것으로 만족하자 다른 회사 면접날 전에 술먹인 회사는 여기밖에 없다  

 

간단히 남기려는 것은 2가지 이다.

 1. Entity Framework에서 Code-First로 Model을 생성하는 것에 대한

 2. Code-First Model에서 다른 Table과의 관계에 대한

내용을 간단히 남기고자 한다

 

일단 위에랑 직접적인 관련은 아니지만 위로 개념을 올린 김에 ORM 을 보자

C#과 같은 객체 지향형 프로그래밍 언어에서 데이터베이스를 쉽게 사용하기 위한 도구라고 한 줄로 말할 수 있다

OOP개념의 객체(Object)와 관계(Relation)형 DB의 테이블을 맵핑(Mapping)해서 (native)SQL 작성을 안하고 쉽게 DB의 데이터에 Access 할 수 있는 기술이라고도 할 수 있다

여기서 나오는 3개의 단어 Object / Relation / Mapping 이 것이 ORM에서 쓰는 핵심 단어이다. ASP.NET 에서는 데이터 엑세스하는 기본 프레임워크로 Entity Framework를 쓰기 때문에 기본값 처럼 사용하는 것이다. MFC를 했을 때 DB 엑세스 하는 기술은 OLE DB를 사용 했기 때문에 그런 기술로 생각하면 된다.

 

Entity Framwork 모델

크게 3가지가 있다고 한다

1. Code First

2. Model First

3. Database First   

Model First와 Database First 접근 모델은 Visual Studio 의 Visual Model Designer (EDMX) 를 통해 객체/테이블 매핑을 디자인 하는 방식으로 두 개간 차이점은 Database Frist는 기존 DB로 부터 테이블 구조를 읽어와서 디자이너를 통해 Visual Model로 구성되는 것을 말하고 Model First는 기존 DB가 없을 때 직접 Model Designer를 써서 Entity들을 추가해 가면서 모델을 구성하는 방식이다. 위 두가지는 Visual Model Designer로 디자인한 것을 edmx 파일에 저장하게 된다.

Code First 방식은 Model Designer / EDMX를 사용하지 않고 데이터 모델을 C# 클래스로 직접 코딩하는 방식으로 앞으로의 EF는 Code First 방식만을 지원한다고 한다. (http://www.csharpstudy.com/web/article/8-Entity-Framework)

 

Code First

C# 클래스로 테이블의 구조를 정의하고 클래스의 프로퍼티를 테이블 컬럼으로 맵핑한다.

Code First란 말 그대로 DB를 미리 설계하지 않고 C# 클래스로 Domain Object(Model???) 를 정의하고 프로그램 실행 시 DB가 없으면 자동으로 DB를 생성하는 방식을 취한다

-> 이 말은 코드 우선이니까 테이블 모델이 Code 기반에서 생성되고 DB에 대한 생성과 추가 수정이 Code 기반의 Class Model에서 된 다는 것을 말한다

     MS SQL의 management studio를 통해 추가/수정/설정을 하는 것이 아니라 code로 구현해서 DB 관리자가 설정하는 것 처럼 추가하고 변경 사항을

    할 수 있다는 것을 말한다

 

재밌는 부분은 Table 과 맵핑되는([Table("name")] 이런 형태의 단순한 Entity Class를 POCO(Plain Old CLR Obect) 라고 부른다고 한다. 기본적인 단순히 테이터를 저장하고 담아저 전달되는 모델을 말하는데 자바에서는 POJO라는 것이 있었다 (Plain Old Java Object) 두 개가 같은 개념으로 보인다. 제일 기본이 되는 Model 객체?? (비즈니스가 딱히 없는??) 이라고 생각하면 쉬울 것 같다

 

Code First를 활용하는 부분을 보다보면 크게 3가지가 나온다

1. DbContext

2. Fluent API

3. Data Annotation

위 내용을 깊게 들어가면 EF로 DB Table 추가하고 컬럼 변경 및 키지정 관계 지정 까지 프레임워크 사용법 까지 다루게 되어서 저런게 있다는 것만 간략히 말한다. DbContenxt는 간단히 System.Data.Entity의 클래스 이며 DB와 관련된 여러 API를 사용할 수 있다 Context란 말에서 뭔가 저장소Repository 란 단어가 생각나는데 Domain Classes 와 Database의 중간에 있는 녀석으로 생각하면 될 것 같다 간단히 그림으로

 

http://www.entityframeworktutorial.net/entityframework6/dbcontext.aspx 참고하자

 

DbContext가 DB 전체를 관리할 수 있는 API를 제공하는 느낌이라면 Fluent API는 Table에 대한 설정을 할 수있다 테이블 간의 관계나 키 설정과 관련된 매서드들을 사용할 수 있다 Data Annotation은 C#의 Attribute로 컬럼의 값에 대한 Data Validation이나 컬럼의 속성(기본키(Key, notMapped))에 대해 프로터티 바로 위에 지정할 수 있다

즉 DB 제어 / Table 제어 같은 것이지 않겠나

 

마지막으로

Code-First Model에서 다른 Table과의 관계에 대한 표현은 크게 3가지가 있다

1. 1:1 관계

2. 1:N 관계

3. N:M 관계

아마도 관계형 데이터베이스라는 개념에서 관계라는 것이 핵심일 듯 하다 이놈의 관계에서 정규화도 고려되고 인덱스 키나 Join 할 테이블도 고려된다 그냥 테이블 간의 관계라고만 생각하기보다는 Object 간의 연관된 관계로 생각해야 그 객체 안의 속성이 어떤 특성이며 이 특성은 어떤 요소들의 집합 모임인지까지 생각할 수 있을 것 같다

(수학에서 집합/확률통계/방정식(변수를 통한 식만들기) 는 체감적으로 많이 나오는 것 같다 (선형대수학이나 행렬은 아직 뭔가 더 해봐야 알 것 같다)

 

관계는 코드로 보는게 편하다 (https://www.c-sharpcorner.com/UploadFile/3d39b4/relationship-in-entity-framework-using-code-first-approach-w/)

일대일 관계

  1. namespace EF.Core.Data  
  2. {  
  3.    public class User : BaseEntity  
  4.     {  
  5.         public string UserName { getset; }  
  6.         public string Email { getset; }  
  7.         public string Password { getset; }  
  8.         public UserProfile UserProfile { getset; }  
  9.     }  
  10. }  

 

  1. namespace EF.Core.Data  
  2. {  
  3.    public class UserProfile : BaseEntity   
  4.     {  
  5.         public string FirstName { getset; }  
  6.         public string LastName { getset; }  
  7.         public string Address { getset; }  
  8.         public virtual User User { getset; }  
  9.     }  
  10.  

 

두 클래스간 virtual 속성으로 각각의 class 간 연결을 만들었다 즉 연결되어 있는 다른 테이블의 속성을 알 수 있다

 

일대다 관계

  1. using System.Collections.Generic;  
  2.   
  3. namespace EF.Core.Data  
  4. {  
  5.   public  class Customer : BaseEntity   
  6.     {  
  7.       public string Name { getset; }  
  8.       public string Email { getset; }  
  9.       public virtual ICollection<Order> Orders { getset; }  
  10.     }  
  11.  

 

  1. using System;  
  2.   
  3. namespace EF.Core.Data  
  4. {  
  5.     public class Order : BaseEntity  
  6.     {  
  7.         public byte Quanatity { getset; }  
  8.         public Decimal Price { getset; }  
  9.         public Int64 CustomerId { getset; }  
  10.         public virtual Customer Customer { getset; }  
  11.     }  
  12.  

 

virtual로 선언된 객체를 보면 한쪽이 Collection이다 Code First로 생성한 Entity는 HashSet(ICollection 상속된 클래스)으로 자료형이 되어 있는데 어쨌든 .Net 적으로 얘기하면 Collection 객체를 포함하고 있다는 것이다. 그러니 단순 List도 포함된다

하나의 객체가 다수의 다른 객체를 가지고 있으니 1:N 관계가 성립되는 것이고 부모하나에서 파생된 자식들이라고도 표현이 되고 Has 관계로 연관된 Object / Entity / Table 라는 개념을 포함할 수 있다

(OOP는 진짜 용어들만 이해해도... (개념적/논리적/물리적) 이런 구분인건가? 누군가에게 설명하기도 어렵고 하고 싶지 않는 부분이다...  

어쨌든 일대다 관계는 하나의 객체가 다수의 객체를 포함한다.. 이렇게 정의할 수 있다

 

다대다 관계

  1. using System.Collections.Generic;  
  2.   
  3. namespace EF.Core.Data  
  4. {  
  5.     public class Student : BaseEntity  
  6.     {  
  7.         public string Name { getset; }  
  8.         public byte Age { getset; }  
  9.         public bool IsCurrent { getset; }  
  10.         public virtual ICollection<Course> Courses { getset; }  
  11.     }  
  12.  
  1. using System;  
  2. using System.Collections.Generic;  
  3.   
  4. namespace EF.Core.Data  
  5. {  
  6.    public class Course : BaseEntity  
  7.     {  
  8.        public string Name { getset; }  
  9.        public Int64 MaximumStrength { getset; }  
  10.        public virtual ICollection<Student> Students { getset; }  
  11.     }  
  12.  

 

위의 일대다를 보고 다대다를 보면 매우 간단히 답이 나온다 각각 서로에 대한 Collection 객체를 가지고 있으면 다대다 관계이다.

여기서 포인트랄 하나 잡자면 다대대 관계를 그대로 쓰지 않는다 두개 간의 관계를 연결해주는 연결테이블 or 맵핑테이블 or 조인테이블 이런 단어로 사용되는 테이블이 가운데 있다 간단히 생각하면 다대다 관계를 다이렉트로 연결하는 것이 아니라 중간에 맵핑테이블을 두어서 일대다 관계 두 개로 쪼개는 것이다. 그러면 EF의 Database First에서 EDMX 파일에서는 맵핑 Class가 생기고 그 맵핑 정보를 각각 가지고 있는다 위의 코드는 관계만 정의된 것이고 맵핑 Entity에 대한 포함 객체는 없는 것이다. 여기서 DB의 관계와 객체인 Class간에 차이가 생길 수 있는데 (회사 업무에서 발견)

간단히 생각하면 객체에 대한 역정규화 기법?? 이라고 보인다

 

맵핑 객체를 EF가 만들어 준대로 바로 쓰는 것이 아니라 Business Model로 변경 시 해당 컬럼을 프로퍼티의 일부로 포함 할 수도 있고 이미 관계테이블에 포함한 프로퍼티일 경우 중복된 프로퍼티(컬럼)을 쓰지 않아도 되는 것이다.

물론 Entity 형태의 Model을 그대로 쓰는 것이 아니라 모델이 Customizing 되기 때문에 모델이 합쳐지거나 Colection이 포함되는 관계를 맺을 때 중복된 data를 제거하거나 1:N 으로 변경된 Class 내부에 포함하거나 해서 다른 class의 속성을 가져 올 수 있는 것이다.

 

DB에서 중복을 만들거나 두 개의 Entity를 합치는 경우 보통 역정규화라고 하는 것 처럼

Class에서도 맵핑 Class를 포함 하거나 Class를 해체해서 관련 Class의 프로퍼티로 포함 시키는 부분이 모델의 역정규화 인 것 처럼 보인다.

물론 Business Model / Customizing Model에서 쓰이는 부분이다.

 

예제로 만들면 좋겠지만... 개념적인 부분에 시간이 너무 들어가서 말로 압축한다.. 길어야 하루면 될게 몇시간 초과되었다... ㅠㅠ

기본 개념은 1:N 관계 2개의 Class가 생기고 그 Mapping Entity도 Class로 생성이 되나 Business Model을 만들면서 중복을 합치거나 Class를 해체해서 관계 Class에서 자기 속성으로 바로 접근하게 만드는 건 그때그때 다르다고 생각하면 된다. 


회사에서 블록체인이라는 주제로 세미나가 열렸다 참여인원이 약 100여명 이상으로 다른 계열사 직원들도 같이 참여하는 세미나이다. 

IT회사의 특성상 대부분 엔지니어가 많겠지만 기타 다른 직군에서도 자유롭게 들을 수 있는 세미나이다. 


정기적으로 기술이나 게임산업과 관련된 엔터테인터먼트 분야에서 전문가를 초빙해서 열리는 세미나로 작년에는 인기 유투버, 게임 시나리오 작가, 인문학?(통섭형 인재?), AR and VR?  라는 주제로 열렸던 것으로 기억한다. 기술적인 부분도 있고 비기술적인 부분도 있어서 관심있는 부분이라면 캐주얼하게 듣기 괜찮을 것 같다. 이번에는 4차 산업혁명이라는 것과도 연관있는 블록체인이라는 기술적인 세미나 였다 


- 블록체인 or 가상화폐 

요세 한창 많이 떠오르고 있는 용어이다. 많은 사람들이 저 두개의 차이를 알고 접하기는 쉽지 않을 것 같다. 

주위에도 재테크를 위해 가상화폐를 공부한다는 사람을 보았어도 불록체인을 공부한다는 사람은 보지 못했다. 

아직까지는 알려진 블록체인 서비스나 실제 화폐로서 거래되는 가상화폐의 가치를 느끼지 못했다. 그저 부동산, 환율, 주식, 다른 경제지표처럼 거품을 머금고 부피만 커져가고 있었다. 기타 경제지표들이 그렇듯 가상화폐라는 가치도 상승 변곡점과 하강 변곡점을 가지고 요동치고 그 사이에서 투기자본들이 시세차익을 보았으리라 보인다. 왜 경제라는 것을 지탱하는 여러 수단들이 스스로 거품을 품게 만드는지는 모르겠지만 심전도 검사처럼 올라갔다 내려갔다를 반복하며 그 거품안에서 신기하게도 재화가 생산된다. 

뭐 본질적인 목적은 투기성이 아닌 것으로 생각되지만 많은 도박게이머들의 구미를 당기게 한 것은 틀림없다.  


블록체인이라는 단어는 2016년 말 ~ 2017년도 초에 접해본 것 같다 그 당시 간편결제를 하는 핀테크 회사에 재직중이기도 했고 금융과 IT의 결합이라는 부분에서 몇몇 블로그들을 봤던 것 같다 그 때 본것을 찾으면 링크로 올려야겠다. 그 당시는 투기성 짙은 설명은 없던 것 같다 


(2016년도 12월기사.. 당시만해도 80만원 정도였다..) 

http://news.naver.com/main/read.nhn?mode=LSD&mid=sec&sid1=101&oid=022&aid=0003128724&viewType=pc

그 이후 작년 5월에서 6월 쯤 이더리움이라는 것도 생기고 비트코인 가격이 집중적으로 상승곡선에 들어갔던 것 같다 아마 현재 저 당시에 구매했다면 폭락한 지금과 비교해도 엄청 이익이다. 언제나 그렇겠지만 돈은 없고 그저 분석만 할 듯....




어쨋든 중요한건 단순히 통계수치가 아니라 가상화폐의 기반이 되는 블록체인이 뭐길래 그 산출물인 가상화폐가 사람들의 이목을 끌었는지 확인해 볼 필요가 있지만 서론은 여기까지 한다 그래프만 보면 주식 그래프와 매우 닮아 보인다. 경제학적으로 더 알고자 하면 썰전의 유시민작가 편을 보는 것도 좋다. 


- 블록체인과 분산원장 

블록체인을 알기전에 한글로서 표현하는 말이 있다 분산원장이라는 말을 많이 한다. 분산된 거래장부라고 한다. 

원장이 거래내역이라면 그 거래내역을 분산되어 저장(DB?) 하는 기술로 보여진다. 

- 암호화폐가 거래(트랜잭션)를 하는 수단이라고 할 떄 그 거래가 승인되면 거래내역이 되고 그 승인된 거래내역(원장)이 분산되어 저장되기 때문에 거래정보가 한곳에 집중되지 않고 암호화된 화폐를 통해 거래를 하기 때문에 허가되지 않은 사람은 해당 거래를 훼손할 수 없다. 


좀 더 쉽게.... 

 1. 거래정보가 한곳에 집중되지 않는다는 것 

    - 상대방과 거래한 내역이 분산되어 저장되기 때문에 기존처럼 금융기관에 의존하지 않아도 정보가 유실되거나 다른사람 마음대로 변경할 수 없다. 

      만약 변경하려면 분산된 원장 모두를 수정해야 가능하게 된다.    

2. 암호화된 화폐를 통해 거래 

    - 암호화된 화폐정보라는게 보안기술의 핵심인 것 같다 복호화를 하는 대상이 확실하게 보증되어 해킹이 되더라도 그 거래를 열 수 있는 사람이 

     유일하게 정해져 있다면 신뢰할 수 있는 화폐거래를 할 수 있다. 


위의 내용 정도가 세미나 이전의 알고 있던 정도이다. 

용어를 정리해 보자면 

암호화폐(대상/who) - 거래에 대한 정보를 암호화된 정보로 저장한 대상 

트랜잭션(행위/What) - 암호화폐로 거래를 하는 것 

분산원장(방법/How) - 거래내역을 분산되어 저장하는 것 


어디서(Where) 는 블록체인 기반에서 라고 설명하면 되겠다.


암호화폐(대상)로 트랜잭션(행위)거래를 분산원장(방법)으로 완벽하고 신회할 수 있는 정보로 만들 수 있는 기술 

--> 한 문장으로 정리하자면 이렇다. 


----------------------------------------------------------------------------------------------------------------------------------------------스마일 게이트 세미나


- 금융기관에 대한 불신 

왜 가상화폐가 생겼는지에 대한 설명이 있었다 2007년? 미국발 금융위기였던 서브프라임 모기지 론 즉 은행돈 빌리고 채무자들이 폭락한 부동산 경제로 인해 파산하거나 빚을 못 값아 경제가 휘청거리고 엄청난 국고지원에도 불구하고 책임감을 느끼지 않는 월가의 모럴해저드를 비판해서 생겼다고 했다. 

(비트코인 창시자의 논문의 개요에 있는 내용이라고 해서 검색해 봤는데 딱 잡아서 금융위기라는 말은 없었다... 어쨌든 번역본은 첨부로 올린다. )

너무 자연스러워서 반발할 생각지 못했지만 따지고 보면 금융기관도 제 3자 중개인 입장인 것이다. 

중개인 입장을 독점하다 보니 금융기관이 없는 거래는 기록도 남기기 어렵고 지하경제라는 이름이 나올 정도로 화폐거래에 있어 절대적인 기관이 되었다. 

태초에 거래했을 때는 금융기관이라는 것이 없이 거래가 이루어졌을 것이고 지금처럼 온라인계좌에 기록되는 것이 아니라 현금거래가 대부분일 것이다. 

아마도 개발자는 2가지는 생각했을 것이다.  


중개인이 없어도 신뢰할 수 있는 1:1 개인간의 거래 

중개인이 없어도 정보를 분산시켜 외부의 훼손으로 부터 보호하는 거래

즉 기존 금융기관을 신뢰할 수 없다고 판단한 엔지니어가 금융기관의 개입이 없는 화폐의 교환 시스템을 만들어 버린 것이다. 

(은행을 없애버린다는 것인가...?)


- 중요한 공개키 암호화 기술 

따로 암호학에 대해 접해 본 적이 없어서 개념이 없다. 그저 암호화랑 복호화가 있다는 것과 해시 알고리즘을 통해 해석 불가능한 해시값을 만든다는 것 정도.. 어쨌든 블록체인의 암호화폐를 구성하는 가장 중요한 기술이라고 했다 대충 그림은 아래와 같다 

공개키와 개인키가 있다는 것 정도는 필수로 알아야 겠다. 

공개키 암호화 기술은 공개키와 개인키를 쌍으로 가지고 있는다 즉 개개인은 각자의 공개키와 개인키를 가지고 있는다. 

공개키는 모든 사람에게 공개하는 것이고 개인키는 자신만이 간직 하는 것이다. 

중요한 것은 공개키로 잠근 거래는 개인키로만 열 수 있고 개인키로 잠근 문서는 공개키로만 열 수 있다. 


 


대충 기억을 떠올려 만들었다 앨리스나 밥은 각자 2개의 키를 가진다. 

공개키 - 어느 누구에게나 공개되는 키

개인키 - 개인이 가지고 있는 키

위의 그림에서는 밥의 공개키로 잠근 내용은 밥의 개인키로 열 수 있고

앨리스의 개인키로 잠근 내용은 앨리스의 공개키로 열 수 있다.


중요한 것은 밥의 공개키로 암호화를 하면 밥의 개인키로 열 수 있다는것이고 

앨리스의 개인키로 암호화를 하면 앨리스의 공개키로 열 수 있다는 것이다. public / private 에 따라 역방향으로 열리게 했다 

(그림만 보면 거래할 때 개인키를 보내는 것 같아 개인키로 잠근 내용이라고 수정 함)

위 그림이 헷갈려서 다른 내용을 찾아 보았다 (위 그림만 보면 공개키 암호화화 디지털 서명이 동시에 되는 것이다) 

아래 링크에서 관련 내용을 보면 이해가 잘된다. 

https://organicmedialab.com/2014/02/20/bitcoin-addresses-transactions-and-wallets/

http://ulismoon.tistory.com/10

  


**P2P Netwwork 

내가 가장 관심가는 기술 부분이다. 

암호화폐에서는 위의 공개키 암호화가 더 중요한지 모르겠지만 저 부분은 이미 개발된 알고리즘이 있고 크게 변할 수 있는 내용이 없다. 

다만 서비스 제공자로서 인프라 역할을 할 수 있고 실제 블록체인의 체인을 형성하는 부분인 P2P Network에는 많은 관심이 있다. 

  


기존 C/S 구조에서 Server는 선형 구조라고 할 수 있고 P2P Network는 그래프 구조라 할 수 있겠다 

P2P의 장점으로는 가용성 확보가 있다. 어느 Node 하나가 끊기더라도 분산 원장에 의해 거래에 필요한 정보는 분산 저장되어 있으니 다른 Node를 통해 처리하면 되므로 Node로 인한 장애가 생기더라도 바로 복구가 가능하다는 것이다. 

기존의 C/S 구조에서는 Server에서 처리할 수 있는 용량이 한정되어 있기 때문에 부하를 줄이기 위해 Server를 늘리거나 서버 앞에 L4같은 네트워크 장비나 분산처리를 해주는 서버를 따로 설치해야 하지만 P2P Network자체가 분산된 Server와 Client 구조를 가진다 


그렇다면 의문점이 생긴다..

1. 그래프 구조가 복잡해질 수록 중첩된 Node간의 통신 시간이 오래 걸리는가? 

2. 각각의 Node는 Server이면서 Client 역할을 같이 하게 되면 각각의 개개인은 물리적 저장소를 제공해야 하는것인가?? 그렇다면 원장과 관련없는 

   Private 한 data까지도 노출될 위험이 있는 것인가? 

3. Node가 계속 증가되면 이중지불(P2P 네트워크 단점: http://simsimjae.tistory.com/188https://steemit.com/kr/@twinbraid/25pexx)문제를 해결하기 

  위해 어떤 승인된 Node에서 확인해야 하는가? 그렇다면 서비스를 지속할 수록 더 많은 Node에서 확인을 하고 거래가 더 오래 걸리는 것은 아닌가? 

4. P2P로 운영되면 admin 역할을 하게될 운영 주체가 아예 필요 없는가? 그렇다면 Node들의 상태를 확인하지 않는 다는 것인가? 

   기존 중앙집중형식은 모니터링이 가능했지만 P2P 상에서는 관리자의 역할을 어떻게 할 것인가? 

5. 금융기관의 개입 없이도 빠른 거래를 할 수 있는것처럼 표현하지만 실제로는 금융기관처럼 검증을 해주는 주체가 없기 때문에 더 오래 걸리는 것은 

   아닌가? 실제로 비트코인 거래 시간이 수십분에서 몇일이 걸린다는 기사를 본적이 있다. 

6. 분산 원장을 구성하게되는 각각의 Node의 database는 어떻게 생겼으며 어떤 data modeling과 schema를 가지고 있는가??

7. 토렌트 네트워크와 차이점은 무엇인가? (분산과 P2P에서 공통점이 있다) (https://steemkr.com/kr/@loum/p2p)


P2P Network에서는 의문점이 끝도 없이 생긴다.. 공개키와 암호화폐에 대한 내용은 핵심기술이긴 하지만 이미 끝난 요리 같다. 

반면에 Infra 역할을 하는 P2P Network는 요리할게 많아 보인다. 그리고 아직 실체화가 부족했던 이유는 Infra 기반이 아직 개발중이 때문이지 않을가? 

많은 IT 기업과 금융권들이 가상화폐를 만드는 것이 아니라 그 Infra(또는 플랫폼) 부터 만들 것이다. 

앞으로 서비스 기업들은 인프라를 만들고 그 인프라위에 가상화폐를 태우면 된다. 


- 공유 경제로서 가상화폐와 DAPP

공유 경제라는 말은 아마 4차 산업과 별개로 서비스 혁명과 같은 말일 것이다. 

1차산업이 농업 2차산업이 중화학 공업 3차산업이 서비스 산업이었던 것으로 중학교 때 배운 것 같다 금융권도 서비스 산업과 같다. 그리고 IT 기술과 더불어서 다양한 인터넷 서비스들이 생겼고 이제는 그 부피가 커져서 인터넷 망을 이용한 공유경제라는 것도 만들어졌다.  

P2P Network 이어서 인지는 모르겠지만 공유경제와 관련성을 지어서 블록체인의 성장성을 설명했다.  

DAPP(Decentralized Application) 이라는 탈중앙화 앱이라는게 생겨나고 있다고 한다. 블록체인 플랫폼을 이용하는 실체화된 서비스가 앱으로 생기고 있는 것이다. 

관련 내용을 더 찾아보긴 했지만 쉽게 생각해서 공통화된 화폐를 사용하기 위해 블록체인 기반의 가상화폐를 사용하는 앱이라고 생각하면 될 것 같다. 

아래 링크들도 읽어 보자 

http://amust.tistory.com/51

https://steemit.com/kr/@waystobecalm/dapp


- 블록체인이라는 단어를 한문장으로 설명 - 블록이 노드로 구성된 체인위에서 돌아다녀서 블록 체인 

두 번째 시간은 실무에서 글로벌 블록체인 프로젝트? 에서 참여하고 있는 젊은 분이 나왔다. 젊은 나이에 저 정도 경지에 올라 새로운 기술을 논할 수 있다는 부분이 매우 부러웠다. 

나처럼 말이 빠르거나 이 다음에 무슨말을 해야할지 머릿속에 수천가지 단어가 헤매지도 않고 여유와 천천히 말하는 점은 내가 배울 점이었다. 

첫 시간이 엔지니어가 아닌 사람에게도 설명할 수 있는 수준이었다면 이번 시간은 전문 용어와 실제 블록체인에서 블록이 어떻게 움직이는지 프로세스의 설명이 었다. 좀 어의없던 점은 자신들이 하고 있는 로직을 시퀀스 다이어그램으로 설명하는 부분은 놀랬다. 

관련 산업 종사자가 없고 관련 비즈니스로직을 모르는데... 입문 수준의 설명차원을 넘어가서인지 발표자도 이해시키려고 는 하지 않았다. 

어쨌든 이번에 확인한 사항은 Node와 Block이다. 

거래가 이루어 지는 것이 Block이고 하나의 원장이라면 이 Blocks이 Node에서 처리되는 과정이 거래를 확인하는 것이 비즈니스 로직이 되겠다. 


아래 3가지 용어가 핵심이 되겠으나 설명할 수 있는 수준이 아니어서 생략한다. 

- 합의 알고리즘

- Smart contract 

- BTP(blockchain transmission protocol)

간단히 얘기하면 합의 알고리즘은 거래의 신뢰성(이중지불 문제 같은)을 증명하기 위한 과정이고 

Smart Contract 는 합의 알고리즘을 전문화/자동화하기 위해 만든 프로그램이다. 

BTP는 블록체인에서 Block을 주고받는 Protocol 정도로 이해되었다.  

아래 링크도 읽어보면 좋다.  

http://www.hanbit.co.kr/channel/category/category_view.html?cms_code=CMS6102653917

https://www.bloter.net/archives/299780

 

 


간단하게 그림으로 도식화 해보았다. 

마지막 강의를 들으면서 블록과 체인이 뭔지 생각하되 었다. 

Chain : 그래프 구조로 만들어진 Node의 집합 

Block : 거래정보(원장) 


하나 궁금한 점은 Node의 실체가 무었이냐이다. Node는 하나의 Person로 보기에는 합의 알고리즘이나 BTP를 받아 들일 수 있어야 한다. 그렇다면 단순히 개인으로만 치부하기에는 컴퓨터에서 많은 일을 해야 한다. 개인 용도의 PC가 전혀 private 하지 않다는 질문이 나온다. 

물론 따로 install을 거치지 않는 웹서비스 기반으로 동작하리라 생각한다 그렇다면 웹서버는 어떻게 구성이되고 웹 어플리케이션은 어떻게 설치할 것인가?? 짐작되는 부분이 있지만 말로만 설명들이니 실제 코드레벨의 구축과 구현이 의심적인 부분들이 있다. P2P Network는 꼭 나중에 공부하자


어쨌든 "블록이 노드로 구성된 체인위에서 돌아다녀서 블록체인이다." 라는 한 문장이 이번 세미나에서 얻은 점이다. 


-----------------------------------------------------------------------------------------------------------------------------------------------------------------------


- 클라우드 서비스가 생각나는 이유 

공유경제라는 말이 나오기 전일 수 있다. 약 6년 전으로 보인다. 아직 학생이었을 때 IT 업계에 클라우드라는 말이 나타났다 

그때 당시는 관련된 내용을 찾아봐도 구름밖에 생각나지 않았던 것 같다. 그리고 지금에야 이해되는 것은 그저 거대한 웹서비스란 말이다. 

6년 전에도 웹서비스는 있었겠지만 지금처럼 특정 플랫폼 서비스를 이용한다는 느낌보다는 하나의 웹 어플리케이션 즉 독립적인 프로그램 하나를 사용한다는 그런 의미? 였던 것 같다. 

월 정액식 비즈니스 모델로 비용을 지불하는 웹 서비스도 그 이후에 많이 보인 것 같다. 

아무래도 SW만 하는 개발자 그룹입장에서 내부 Infra나 운영 관리에 편리해지면서 다양한 웹서비스 회사들이 생겨나게 된 것 같다.

사실 내부까지 보면 IaaS, PasS, SaaS 로 그 정도를 구분할 수 있지만 지금 하고 싶은 말은 어쨌든 새로운 금융 서비스라는 것이다. 

클라우드 서비스가 정착되면서 누구나 손쉽게 웹 서비스를 만들 수 있게 되었다. 

블록체인이 클라우드 환경만큼의 파급력이 생길 지 모르겠지만 완전히 없던 것이 만들어진것은 아니라 기존것을 대체하기 위해 나왔다는 것이다. 

새로운 것이 대세가 되는 것이 이제는 낯선 풍경은 아니다. 

다만 클라우드는 EMC나 Cisco나 HP와 같은 HW 업체들과 같이 발전해서 생긴 것이지만.. 기존 금융권에 대한 저항으로 새로운 서비스가 인정받을 수 있을지는 정확하지 않다.


- 돈의 가치에 대한 철학

발표자분도 94년생인 이더리움의 창시자를 보고 혁명가라고 말했다. 

비트코인의 창시자도 마찬가지겠지만 내가 이들한테 제일 놀랍고 궁금한 것은 돈의 단위를 어떻게 생각하고 만들었나? 이다. 

내가 만드는 암호화폐가 어떻게 1코인(ex: 원)이 되고 어떻게 1이라는 단위를 가지게 되었는지가 궁금했다. 1비트코인과 1이더리움은 어떻게 산정했지? 

채굴을 어느정도 하면 1코인을 가지게 되고 1코인의 가치는 어떻게 생각한거지? 이 기준을 세운것에 대해 별거 아닐지 모르겠지만 매우 놀랐다. 

얼마전에 1KG의 정의가 바뀐다는 말을 본적이 있다. 백금과 이리듐으로 만든 질량원기라는 것으로 1KG을 만든다고 한다. 

전세계의 모든 학자들이 모여서 모든 논리에 맞을 수 있는 단위를 산정하기 위해 고민했을 텐데 가상화폐의 가치는 도량형과는 차이가 있겠지만 어떻게 그 가치를 정의할 수 있었을까? 

기술과는 별개로 단위와 기준을 만들었다는 부분에서는 성공할지 실패할지는 모르겠지만 혁명가임은 분명하다.     

http://www.yonhapnews.co.kr/bulletin/2017/12/27/0200000000AKR20171227023400017.HTML?input=1195m

 

- 탈 금융권 탈 중앙화 가능? 

블록체인의 철학? 중 하나가 금융권과 같은 제3자에게 거래를 맞기지 않는 것이다. 

솔직히 현실상 불가능한 구조이지만 기술의 진보가 새로운 패러다임을 던질 수 있는 사건이다. 

다만 강의중에 의심적인 말이 있었다. 

기존에는 신뢰할 수 있는 거래에 대한 위임과 그에 대해서 비용을 지불했던 금융권의 서비스를 탈피함으로써 얻는 자유의 혜택으로 

금융서비스를 순수하게 개인대 개인 과거 고대시대 처럼 기관의 도움이 없이도 신뢰할 수 있고 믿을 수 있는 거래를 할 수 있다....  

라고 했던 부분은 솔직히 믿기 어려웠다. (마지막에 발표자도 문제를 제기한 부분)

역사적으로 대중이 똑똑해지면 자유를 얻거나 권력을 교체할 수 있었지만 또 다시 새로운 권력이 생기고 거기에 적응하면서 역사는 반복된 것으로 알고 있다. 

전체를 뺏긴 어렵겠지만 기존 금융권에서 이용하던 부분(예를 들면 공인인증서) 을 카카오 뱅크에서 블록체인 기반으로 제공하는 금융서비스를 통해 전 국민이 카톡으로 공인인증서 없이 은행업무를 보게 된다면 과연 완벽한 자유라고 할 수 있을까? 

이것은 단순히 하나의 기술이라기보다는 한 천재가 제시한 새로운 서비스 방식의 패러다임의 전환이지 않을까? 

암호화폐만 봤을때 관련된 기초 수학과 관련된 부분이나 이나 알고리즘에 대한 기술은 이미 끝이 났을 것이다.

어느 누가 Infra를 완성하고 자사의 플랫폼을 이용해 대중이 자연스럽게 거래를 할 수 있게 할까? 


아직 시장을 지배하는 주인이 없는 기술이라고 생각되는 점은 매우 SW스럽다는 것이다. 

클라우드 서비스가 막강한 HW의 진보와 해당 서비스를 이용할 SW 서비스의 양적 질적 발전이 동시에 나타났기 때문에 새로운 IT 공룡이 아니라 기존 IT 공룡들이 충분히 준비하면서 잠식이 가능했지만 블록체인은 아직 누가 승리자가 될 지 잘 모르겠다. 

아니면 오픈소스로서 누구나 이용할 수 있는 부분으로 Linux와 같이 완성된 기술로서만 남을지 새로운 서비스의 방향을 제시할 지는 아직 감이 잡히는게 없다. Windows(기존 금융권 + IT 공룡) vs Linux(다양한 자체 플랫폼 중요한건 오픈된 플랫폼) 의 예시가 맞을 지는 모르겠지만 블록체인 기반의 플랫폼 전환은 기존금융권을 탈피하려는 시장의 동의와 여러 이해관계자들의 시간과 비용을 필요로 한다고 생각하면서 매듭짓는다.

'My Reading > IT' 카테고리의 다른 글

2019 NDC 후기  (0) 2019.06.22

타이머 기능을 사용하게 되었다 꼭 타이머로 구현해야 하는 것은 아니지만 별도의 쓰레드로 동작하면서 특정 기능을 주기적으로 호출해야 하는 기능이 필요하게 되어 .Net에서 제공하는 타이머 기능을 조사했다 


목적 : 특정 작업을 주기적으로 실행 하기 위해 사용 


일단 동작하고 있는 프로세스 내부에서 기존의 작업과 별도로 동작해야 할 필요가 있는 경우 멀티 쓰레드 환경을 고려하게 된다 

두가지 조건을 만족해야 한다 

1. 다중 작업 처리 가능 

2. 특정 시간마다 이벤트 발생 


위 2가지를 고려하고 쓰레드 생성과 타이머 조사를 비교 했을 때 어느 것이 우위에 있는지 비교 분석을 하자면 

타이머의 장점 

 - Thread.Sleep 은 동작하는 프로세스에 인터럽트하는  강제로 프로세스를 멈추게 하는 성향이 있기 때문에 시스템 전체에 영향을 준다 (쓰레드의 단점) 

 - Thread를 만들어서 Sleep을 사용하지 않고 (Sleep을 사용하면 Timer 기능을 하는 Thread는 물론 시스템 전체가 멈춘다)

   Thread와 비교했을 때 반복(Interval) 간격을 옵션으로 간단하게 정할 수 있다 (2번 조건 만족)  

   시간 계산을 측정해서 구현할 수 있겠지만 Timer에서는 Interval을 설정만 하면 되기 때문에 사용하기 편리하다 (라이브러리 처럼 사용 가능) 

 - Timer는 Callback 개념으로 지정된 시간 후에 Callback을 하는 개념이라 상대적으로 부하가 적게 걸린다 ( 출처:http://nowonbun.tistory.com/139 )

   이 말은 정확한 증거는 아니지만 Thread에서는 Sleep()을 통해 다른 Thread로 옮겨가게 되지만 예를 들면 Sleep(10) 과 같이 작은 수치의 밀리세컨드를 지정하더라도 성능에 영향을 미치게 되지만 CallBack 함수로 호출되는 Timer의 경우는 상대적으로 부하가 적게 걸린다는 말로 보인다.  


타이머라는 것은 기본적으로 시간의 흐름을 연속적으로 측정하기 위함이기 때문에 굳이 Thread로 만들지 않더라도 .NET이 제공해주는 라이브러리 클래스를 사용하면 간단하고 편리하게 구현할 수 있다 (Thread Pool 관리도 자동으로 해준다는?? 부분이 있다)  


.NET 프레임워크에서 제공하는 타이머에는 3가지가 있다 

1. System.Windows.Forms.Timer 

2. System.Threading.Timer

3. System.Timers.Timer


MSDN + 검색한 내용의 간단한 설명이다 (출처: http://blog.daum.net/starkcb/117)


1) System.Windows.Forms.Timer

사용자가 정의한 간격마다 이벤트를 발생시키는 타이머를 구현합니다. 

이 타이머는 Windows Forms 응용 프로그램에서 사용할 수 있도록 최적화되었으며 창에서 사용해야 합니다


윈도우 폼 타이머라고 한다 윈도우 응용프로그램과 동일한 Thread에서 동작한다

즉, Timer는 UI Thread 상에서 동작한다 - 즉 Mutil Thread 환경이 아니라 단일 Thread 환경이다

반복주기를 설정하고 반복 주기마다 실행되는 이벤트를 등록한다


2) System.Threading.Timer


지정된 간격으로 메서드를 실행하는 메커니즘을 제공합니다


쓰레드 타이머라고 한다

UI Thread와 Work Thread로 나뉘어 진다 

UI Thread - 평소에는 유후 상태, 기다리다가 메시지 들어오면 메시지 루프에서 메시지 처리 (MFC가 기억난다...) 

Work Thread - background 작업, 메시지 루프는 사용하지 않는다 

멀티쓰레드로 두 쓰레드는 독립적으로 수행된다 

닷넷의 ThreadPool에서 관리한다 

이벤트 대신 Callback 매서드를 사용한다 

만약 반복 실행 작업이 UI Thread와 관련이 생기면 Cross Thread 문제가 발생한다 (Invoke, BeginInvoke를 통해 핸들링할 수 있다) 

메시지가 스레드에서 펌프되지 않을 경우에 유용

- 이 말은 Windows Form Timer의 경우 Message Loop에서 UI의 특정 이벤트에 반응하는 방식이 아니라 UI Thread와는 별개로 Background로 작업이 진행 될 때 즉 Work Thread로 사용될 때 유용하다는 말이다

  

3) System.Timers.Timer


응용 프로그램에 되풀이 이벤트를 생성합니다


서버타이머라고 한다 

Synchronizing Object 속성에 따라 달라진다 

Synchronizing Object 속성을 form 객체로 하면 UI Thread 상에서 동작 

Synchronizing Object 속성을 지정하지 않으면 Work Thread 상에서 동작 

Multi Thread 환경에서 Work Thread를 구현해서 사용 

시스템 시간(서버)을 사용해서 프로그램 리소스(시간)를 사용하는 System.Thrading.Timer 보다 정확

Thread 사이를 이동하면서 발생한 이벤트를 처리 가능 

주기마다 실행되는 이벤트를 등록하고 쓰레드 타이머와 마찬가지로 UI Thread를 핸들링 하기위해서는 Invoke, BeginInvoke를 이용해야 한다 

코드형태는 윈도우 폼 타이머와 비슷하다 


.NET의 타이머를 보다 보면 UI Thread와 Work Thread 간 크로싱 에러나 별도의 동작하는 Work Thread 얘기가 나오는데 간단히 생각하면 싱글 쓰레드인지 멀티 쓰레드인지 생각하면 된다 UI Thread에서만 동작하길 원하면 Windows.Forms.Timer를 사용하면 되고 멀티쓰레드 환경에서 독립적으로 동작하길 원한다면 System.Threading.Timer나 System.Timers.Timer 를 사용하면 된다 더 자세한 내용은 아래서 이어 가겠다 


두가지 측면에서 더 살펴보자면 

1. 사용법상의 차이점 

3가지 방법의 간단한 사용법을 쓰면 


1. System.Windows.Forms.Timer 사용법

- 객체 생성

System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();

- 반복 주기 및 작업 설정

timer.Interval = 1000; //주기 설정

timer.Tick += new EventHandler(timer_Tick); //주기마다 실행되는 이벤트 등록

void tmrWindowsFormsTimer_Tick(object sender, System.EventArgs e)
{
      //수행해야할 작업

}

- Timer 시작

timer.Enable = true 또는 timer.Start();

- Timer 중지

timer.Enable = false 또는 timer.Stop();

 

2. System.Threading.Timer 사용법

- 객체 생성

Timer 객체를 생성할 때, 반복적으로 실행하게 될 메서드를 콜백 메서드로 등록

System.Threading.Timer timer = new System.Threading.Timer(CallBack);

- 반복 주기 및 작업 설정

이 Timer 에는 Change 메서드가 있는데, 이 메서드는 dueTime과 period 를 입력받습니다

dueTime은 Timer 가 시작하기 전 대기(지연)시간이며 period는 반복 주기입니다
timer.Change(0, 1000);

그리고 반복 실행 작업이, 
윈도우 응용프로그램의 UI Thread와 연관된다면, Cross Thread 문제가 발생하기 때문에 Invoke나 BeginInvoke를

통해 핸들링 해야 합니다.

앞서, Timer 객세 생성시 등록한 콜백 메서드에서 BeginInvoke를 통해 UI 쓰레드를 핸들링 할 수 있습니다

 

delegate void TimerEventFiredDelegate();

void CallBack(Object state)
{
    BeginInvoke(new TimerEventFiredDelegate(Work));
}
        
private void Work()
{

     //수행해야할 작업(UI Thread 핸들링 가능)
}

 

- Timer 시작

위의 Change 메서드의 dueTime 이 0 이므로 그 즉시 시작된다. Start와 같은 별도의 시작 명령이 존재하지 않음

- Timer 중지
timer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);

dueTime와 period 를 무한대로 잡아서 Timer 가 실행되지 않도록 하는 것이 중지하는 것과 같습니다


3. System.Timers.Timer 사용법

- 객체 생성

System.Timers.Timer timer = new System.Timers.Timer();

 

- 반복 주기 및 작업 설정
timer.Interval = 1000;
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);  //주기마다 실행되는 이벤트 등록


이 Timer 역시 UI Thread를 핸들링 하기 위해서 Invoke 나 BeginInvoke를 이용해야 합니다
delegate void TimerEventFiredDelegate();
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    BeginInvoke(new TimerEventFiredDelegate(Work));            
}

private void Work()
{

     //수행해야할 작업(UI Thread 핸들링 가능)
}

 

- Timer 시작

timer.Enable = true 또는 timer.Start();

- Timer 중지

timer.Enable = false 또는 timer.Stop();


Windows.Forms.Timer 를 제외하고는 UI Thread에서 만들어진 컨트롤에 접근하려면 

Cross Thread 문제가 있으므로 마샬링?? 된 호출(Invoke / BeginInvoke)를 이용해야 하는 차이점이 있다고 한다??


2. 수행되는 Thread환경의 차이점 

먼저 UI Thread 라는 것의 환경에 대해 알아야 한다. 윈도우 응용프로그램 중 예를 들면 Button이나 ListView나 ComboBox 등 각종 컨트롤이 생성되고 핸들링 되는 것은 UI Thread 안에서 동작하게 된다 


이와 별도로 Work Thread라는 것이 있는데 기본(Default Thread) 이외에 개발자가 별도의 쓰레드를 생성해서 작업을 실행하면 이것을 Work Thread라고 한다. 또한 UI Thread 입장에서는 .NET의 Thread Pool에 의해 실행되는 쓰레드도 Work Thread로 볼 수 있다고 한다 

쓰레드가 다르면 쓰레드의 고유번호가 다르기 때문에 

System.Threading.Thread.CurrentThread.IsThreadPoolThread 속성은 현재 쓰레드의 고유 식별자 값을 가져온다고 한다 


1. System.Windows.Forms.Timer 의 쓰레드 환경 

- 기본 쓰레드의 고유 번호를 확인한다

윈도우응용프로그램 생성자나 기타 이벤트에서 아래 코드를 기입합니다

MessageBox.Show(System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());

 

- Timer 쓰레드의 고유번호를 확인한다

Timer 의 Tick 이벤트에서 다음의 코드를 기입합니다

void timer1_Tick(object sender, EventArgs e)
{
     MessageBox.Show(System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());

     //수행해야할 작업
}


결과적으로 두 쓰레드는 동일한 고유번호를 반환하게 된다고 한다 이런 이유에서 윈도우 응용프로그램의 기본 쓰레드인 UI Thread 안에서 Timre가 동작한다고 짐작할 수있다 즉 멀티 쓰레드 환경이 아닌 싱글 쓰레드라고 생각되는 점이다... 

그러면 궁금한점... 싱글 쓰레드면 왜 Windows.Forms.Timer를 쓰는 것인지?? 이해가 어렵다.. Timer는 기본 적으로 특정 작업에 특화되려면 Background에서 동작하는게 필수라고 생각했는데 왜 Single Thread로 만들었는지 의외였고 UI 단일 Thread에서는 Timer가 Message Loop에서 동작했다 아마도 UI에서만 Thread 변경없이 Message(화면 Event)가 들어오면 반응하도록 설계하지 않았을가 싶다. 


2. System.Threading.Timer의 쓰레드 환경

- 기본 쓰레드의 고유 번호를 확인한다

윈도우응용프로그램 생성자나 기타 이벤트에서 아래 코드를 기입합니다

MessageBox.Show(System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());

 

- Timer 쓰레드의 고유번호를 확인한다

CallBack 메서드에서 다음과 같이 코드를 기입합니다

void CallBack(Object state)
{
      MessageBox.Show(System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());

      BeginInvoke(new TimerEventFiredDelegate(Work));
}


이 경우는 서로 다른 쓰레드 번호를 반환한다 즉 UI Thread와 Work Thread가 분리되어 있다 

이 두 쓰레드는 독립적으로 수행되기 때문에 멀티 스레드의 환경을 가진다 앞의 Forms.Timer 객체와는 달리 Callback 매서드에서 시간이 오래 걸리는 작업을 수행해도 프로그램이 대기상태에 빠지지 않는다 

참고로 이 Timer는 닷넷의 Thread Pool 에서 관리한다 


3. System.Timers.Timer 의 쓰레드 환경 

위에서 한번 적었지만 이 Timer는 UI Thread에서 수행될 수도 있고 Work Thread에서 수행 될 수도 있다고 한다 Synchronizing Object 속성을 Form으로 하면 UI 이고 지정하지 않으면 Work 이다  


아래와 같이 SynchronizingObject 속성의 설정 여부에 따른 ManagedThreadid 값을 확인해 보기 바랍니다

timer.SynchronizingObject = this;

 

타이머 쓰레드의 고유번호를 알기 위해 Elapsed 이벤트에

MessageBox.Show(System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());

를 확인해 보세요


중요한 것은 Timer Thread를 어디에서 동작할 것인가 이다 그리고 Work Thread에서 UI Thread 전환 시 크로스 쓰레드 문제가 발생하기 때문에 Invoke와 같은 코드로 극복이 가능하나 Invoke는 강제 동기화 이기 때문에 시스템 저하를 가져올 수 있다 결국 UI Thread에서는 Forms.Thread를 사용해야 Invoke로 인한 성능저하가 없다는 것이다. 

그렇다면? 멀티 쓰레드로 동작하지 않는 것과 Invoke를 사용해서 강제 동기화를 하면서 다중 작업처리를 하는 것의 차이는 시스템이 복잡할 경우 테스트나 비교를 정확히 해봐야 알 것 같다 

 

2번 Threading.Timer와 Timers.Timer의 공통점은 멀티 쓰레드로 동작할 수 있다는 것이다 

그렇다면 차이점은 무엇일까? 

일단 Threading.Timer는 Work Thread에서만 동작이 가능하지만 Timers.Timer는 UI or Work 모두가 가능하다 

그리고 Therading.Timer는 프로그램 리소스 즉 프로세스 자체에 인터럽트가 걸리면 같이 멈추거나 느려지지만 Timers.Timer는 시스템 시간(OS??)에 영향을 받기 때문에 프로그램이 느려져도 TImer 스레드는 시간에 맞추어 실행이 된다 


하나의 예를 들어보자면 이 글작성 당시 듀랑고라는 넥슨 게임이 오픈 초기라 대기열에 따른 부하에 의해 게임 시작이 어렵다 즉 app 자체가 느려짐에 따라 다른 기능들도 모두 영향을 받는다면 타이머도 같이 느려져야 하는지 아니면 타이머는 정상적으로 체크를 해야하는지에 대한 고민이 생긴다. 

일단 나의 결론은 타이머 성격의 작업은 리얼타임의 일정한 시간에 이루어 져야 한다는 것이다. 만약 대기에 의해 서버를 늘리거나 외부 환경이 변경되었을 때 그것을 타이머로 체크한다면 app 자체의 시간이나 속도와는 상관없이 변경된 환경을 체크해야 할 것이다. 이런 경우라면 Threading.Timer가 아니라 Timers.Timer를 적용해서 작업자체에 대한 주기성을 지키는 것이 더 빨리 대처하는 타이머라고 생각된다. 


----------------------------------------------------------------------------------------------------------------- 참고 자료 (http://blog.daum.net/starkcb/117)

타 차이점 및 요약, 참조

아래 표는 msdn magazine에 소개된 세 Timer 의 차이점에 대한 표입니다

우리가 알아 본 내용 이외에도, 쓰레드 안정성(동기화 문제)에 대한 내용도 있습니다

 

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 

System.Windows.Forms

System.Timers

System.Threading

Timer event runs on what thread?

UI thread

UI or worker thread

Worker thread

Instances are thread safe?

No

Yes

No

Familiar/intuitive object model?

Yes

Yes

No

Requires Windows Forms?

Yes

No

No

Metronome-quality beat?

No

Yes*

Yes*

Timer event supports state object?

No

No

Yes

Initial timer event can be scheduled?

No

No

Yes

Class supports inheritance?

Yes

Yes

No

* Depending on the availability of system resources (for example, worker threads)



마지막으로 MSDN에 대한 내용도 같이 옮긴다 

서버 타이머, Windows 타이머 및 스레드 타이머

Visual Studio 및 .NET Framework에는 세 개의 타이머 컨트롤 즉, 도구 상자의 구성 요소 탭에서 볼 수 있는 서버 기반 타이머, 도구 상자의 Windows Forms 탭에서 볼 수 있는 표준 Windows 기반 타이머 및 프로그래밍 방식으로만 사용할 수 있는 스레드 타이머가 있습니다. 

Windows 기반 타이머는 Visual Basic 1.0 이상의 버전에 있으며 지금까지 크게 변경되지 않았습니다. 
이 타이머는 Windows Forms 응용 프로그램에서 사용하도록 최적화되어 있습니다
서버 기반 타이머는 일반 타이머를 서버 환경에서 최적으로 실행되도록 업데이트한 것입니다. 


스레드 타이머는 이벤트 대신 콜백 메서드를 사용하는 간단한 소형 타이머로서 스레드 풀 스레드에서 제공합니다.

Win32 아키텍처에는 UI 스레드와 작업자 스레드라는 두 종류의 스레드가 있습니다. 
UI 스레드는 대부분의 시간을 유휴 상태로 보내며 메시지 루프에 메시지가 도착할 때까지 기다립니다. 메시지가 도착하면 
이 메시지를 처리하고 다음 메시지가 도착할 때까지 기다립니다. 이에 비해 작업자 스레드는 백그라운드 처리를 수행하는 데 사용하며 메시지 루프를 사용하지 않습니다. 

Windows 타이머와 서버 기반 타이머는 모두 Interval 속성을 사용하여 실행됩니다. 
스레드 타이머의 간격은 Timer 생성자에서 설정됩니다. 



스레드에서 타이머를 다루는 방식을 보면 알 수 있듯이 각 타이머의 용도는 서로 다릅니다.

  • Windows 타이머는 UI 스레드가 프로세싱을 수행하는 데 사용하는 단일 스레드 환경을 위해 설계되었습니다. Windows 타이머의 정확도는 55밀리초로 제한되어 있습니다. 이 일반 타이머는 사용자 코드에서 사용할 수 있는 
    UI 메시지 펌프가 필요하며 항상 동일한 스레드에서 실행되거나 다른 스레드로 마샬링됩니다. 
    이 기능은 COM 구성 요소의 성능을 저하시킵니다. 

  • 서버 기반 타이머는 다중 스레드 환경에서 작업자 스레드와 함께 사용하도록 설계되었습니다. 두 스레드는 서로 다른 아키텍처를 사용하므로 서버 기반 타이머가 Windows 타이머보다 정확합니다. 
    서버 타이머는 스레드 사이를 이동하면서 발생한 이벤트를 처리할 수 있습니다. 

  • 스레드 타이머는 메시지가 스레드에서 펌프되지 않는 경우에 유용합니다. 
    예를 들어, Windows 기반 타이머는 운영 체제의 타이머 지원 기능에 의존하며 드에서 메시지를 펌프하지 않을 경우에는 타이머 관련 이벤트가 발생하지 않습니다. 이 경우에는 스레드 타이머가 보다 더 유용합니다.

Windows 타이머는 System.Windows.Forms 네임스페이스에, 서버 타이머는 System.Timers 네임스페이스에 그리고 스레드 타이머는 System.Threading 네임스페이스에 있습니다.


추가로 몇몇 자료들을 더 보면 Threading.Timer 보다 Timers.Timer가 더 Thread Safe 하다고 되어 있다 

그 이유는 SynchronizingObject 를 통해 Thread를 제어할 수 있는것이 더 safe 해서 인지 짐작만 된다 


추가로 더 조사한 내용을 올리면 아래 링크에서  

https://stackoverflow.com/questions/1416803/system-timers-timer-vs-system-threading-timer


CLR Via C#", Jeff Ritcher 는 그의 저서에서 System.Timers.Timer의 경우 비추천했다는 말이 나온다 UI와 연관되어 사용하는 것이라는 이유라던데 사무실에 있는 책같은데 한번 확인해 봐야겠다 그리고 추가적으로 .Net Core에서는 사라졌기 때문에 Work Thread로 사용하려면 결국 System.Threading.Timer를 사용해야 한다는 이유가 된다. 위의 Thread Safe 하다는 증거를 찾지 못한다면 System.Timers.Timer 의 장점은 사라져 보인다.    


추가로 .Net 타이머에 대해 비교한 내용이다 한번 읽어 보자 

https://web.archive.org/web/20150329101415/https://msdn.microsoft.com/en-us/magazine/cc164015.aspx


http://robertgreiner.com/2010/06/using-stopwatches-and-timers-in-net/



'Computer Language > C#|.Net' 카테고리의 다른 글

이스케이프 문자 처리 법  (0) 2018.01.06

별건 아니다 

이스케이프 문자를 처리하는 방법 중에 간단한 법이 있는데 간단히 말하면 ignore 시키는 것이다 


//  \\ : 백슬래시(\) 기초 하나를 표현 

// 한글입력기에서는 : \ 이지만 영문입력기에서는 슬래시(/)의 반대 

Console.WriteLine(" \\ : 백슬래시 표현 ");

      

// 백슬래시 다음에 나오는 문자는 이스케이프 문자로 본다.

// 그래서 두개를 붙여서 \를 표현한다 

Console.WriteLine(" C:\\Home\\MyRoom\\Default.cs");

      

// @를 붙이면 자동으로 이스케이프 문자를 무시한다 그래서 원래 쓰던 방식으로 써도 문제가 없다 

// 파이썬에서는 정규식을 쓸때 r을 붙여서 이스케이프를 무시한다 패턴에 /를 사용하는데 이스케이프 때문에 //를 매번 붙이면 복잡해진다

// r은 Row String이라는 규칙을 말한다. 

// 닷넷의 정규식에도 Ignore Escape 가 있다 

// 어쨌든 특정 문자 하나를 처리하기 위해 Escape On/Off 방식으로 처리한다는 점이 중요하다

Console.WriteLine(@"C:\Home\MyRoom\Default.cs");


      

// 문자열 앞에 @ 기호를 붙이면 문자열 자체로 본다.

// 그래서 아래와 같이 공백이 붙으면 공백도 문자의 일부로 보고 처리하니 아래와 같은 점은 주의하자

Console.WriteLine(

  @" 

       C:\Home\MyRoom\Default.cs

   ");


간단한거 하나 남기려 해도 쉽지않다... 블로그에 올리는 방식을 좀 고민해 봐야겠다  

초안만 작성된게 수십장인데.. ㅋㅋ 

어쨌든.. 결과는 아래와 같이 나온다 


'Computer Language > C#|.Net' 카테고리의 다른 글

.Net Timer Class 비교(3가지) 1  (0) 2018.01.29

+ Recent posts