반응형

http://vandbt.tistory.com/27 블로그에서 참조한 글입니다.^^

 

리파지터리 패턴은 그 복합성 때문에 완벽히 이해하고 적용할 수 있기까지 매우 어려운 패턴이라 생각됩니다. 여러번에 걸쳐 이 주제를 포스팅 하는 이유가 바로 그 때문입니다. 여러 문서를 학습하거나 구현에 적용할 때에는 관련된 해결해야 하는 문제들이 등장하게 되죠. 패턴이 잘못 사용되지 않도록 하기위해서는 그 패턴이 가지는 정확한 목적을 이해하는 것이 가장 우선시 되는 것이죠.


리파지터리 패턴은 그 역할과 구현이 명확한 개발언어로 스펙으로 정의 된것이 아닌, 일반언어(plain text)로 정의 되어 있음은 많은 개발자들이 정확한 의미를 파악하기 어려울 수 있습니다. MSDN 에 리파지터리 패턴에 잘 정의된 문서가 있어 [문맥] 과 [목표] 문단을 중심으로 번역 포스트 합니다.

이 문서는 리파지터리 구현시에 발생하는 [데이터 조회 로직]가 리파지터리에 들어가려는 현상이 있는데 이렇게 하는 것이 맞느냐 틀리느냐에 대한 근거 수집 차원에서 접근 했으며, 리파지터리의 세부 성격으로 보았을때 조회 로직 자체도 리파지터리로 부터 분리하는 것이 옳다라는 결론을 얻게 되었습니다. 이 결론이 틀리다 생각되시면 의견을 주시어 생각을 바로 잡을 수 있도록 도와 주시기 바랍니다.

Repository는 저장소 라는 용어로 데이터소스에 대한 관리(CRUD)를 어떻게 추상화 하느냐에 대한 패턴입니다.





문맥:

많은 어플리케이션에서 비즈니스 로직은 데이터베이스, 쉐어포인트, 웹서비스와 같은 데이터저장소의 데이터에 접근합니다. 직접접근은 다음과 같은 부작용을 초래할 수 있습니다.

중복된 코드
프로그래밍 에러가 발생할 높은 잠재성
비즈니스 데이터에 대한 오타
캐싱과 같은 데이터-관계 정책 중심화하기 어려움
외부 의존으로 부터 비즈니스 로직을 분리하기 어려움에 따른 테스트 불가능성


목표:

리파지터리 패턴을 사용하는 것은 다음의 목표를 하나 이상 달성합니다.

당신의 수 많은 코드를 테스트 자동화를 극대화하고, 유닛 테스트를 지원하기 위해 데이터 레이어로 부터 분리 시키기를 원한다.
당신은 여러 곳에서 데이터소스에 접근 하고 있으며, 중앙에서 관리되는 일관성 있는 접근 룰과 로직을 적용기를 원한다.
데이터 소스를 위한 캐싱 caching 전략을 중앙화 centralize 하기를 원한다.
데이터 또는 서비스 엑세스 로직으로 부터 비즈니스 로직을 분리함으로써 코드의 유지관리성 maintainability과 가독성 readability 을 향상 시키기를 원한다.
문제를 런타임이 아닌 컴파일 타임에 구분해 낼 수 있도록 비즈니스 엔터티를 강-타입 strongly typed 으로 사용하기를 원한다.
연결된 데이터와 작업하기를 원한다. 예를들어 필드를 계산하기를 원하거나 복합관계를 강제하거나 엔터티의 데이터 엘리먼트 사이의 비즈니스 룰과 작업하기를 원한다.
복잡한 비즈니스 로직을 단순화 시키기 위해 도메인 모델을 적용하기를 원한다.


솔루션:

비즈니스 로직이 모델에 대해서 동작하도록 함으로써 데이터를 조회하는 로직을 분리하기 위해 리파지터리를 사용한다. 비즈니스 로직은 데이터소스 레이어의 데이터 타입에 대해서 자연스러워야 하며, 데이터소스는 데이터베이스, 쉐어포인트 또는 웹서비스가 될 수 있습니다.

리파지터리는 어플리케이션에서 데이터 소스 레이어와 비즈니스 로직 레이어 사이를 중재 mediates 한다. 리파지터리는 데이터소스에 대해 데이터를 질의하고 데이터 소스와 비즈니스 엔터티 사이의 데이터를 매핑한다. 비즈니스 엔터티의 변경을 데이터 소스에 저장한다. 리파지터리는 데이터소스, 웹서비스에 의존적인 상호작용을 비즈니스 로직으로 부터 분리 시킨다. 데이터와 비즈니스 티어의 분리는 다음의 3가지 잇점을 얻게합니다.

1. 데이터로직 또는 웹서비스 접근 로직을 중앙화 한다.
2. 유닛 테스트를 위한 대안을 제공한다.
3. 어플리케이션 진화 될 수 있는 디자인을 채택할 수 있도록 유연한 아키텍처를 제공한다.

리파지터가 비즈니스 엔터티를 질의하는 두가지 방법이 있습니다. 클라이언트 비즈니스 로직에 대한 질의 오브젝트를 제출 하는 방법, 비즈니스 조건을 정의하는 메소드를 사용하는 방법. 후자의 경우 리파지터리는 클라이언트 행동에 대한 질의를 만듭니다. 리파지터리는 질의를 만족하는 엔터티 집합을 반환합니다. 다음의 다이어 그램은 클라이언트,데이터소스 사이에서 리파지터리의 상호작용을 보여줍니다.


리파지터리의 상호작용 다이어그램.




클라이언트는 지속화를 위해 변경되었거나 새로 생성된 엔터티를 리파지터리에 제출합니다. 더 복잡한 상황에서는 Unit of Work 패턴을 사용할 수도 있습니다. 이 패턴은 연관된 의존을 영속화하기 위해서 수행되어야 하는 여러개의 작업을 어떻게 캡슐화 할 수 있는지를 보여 줍니다. 캡슐화된 아이템은 변경/삭제 행위를 위해 리파지터리에 보내 집니다. 이 가이드는 Unit of Work 패턴의 예제를 포함하지 않습니다. 더 많은 정보를 얻길 원하시면 마틴 파울러의 웹사이트의 Unit of Work 페이지를 방문하세요.

리파지터리는 서로 다른 도메인에서 데이터와 작업 사이의 다리 bridge 입니다. 일반적인 경우는 데이터베이스 또는 쉐어포인트의 약-타입 의 데이터와 도메인의 강-타입 오브젝트에 매핑하는 것입니다. 한가지 예로 데이터베이스는 질의를 실행하기 위해 IDBCommand 오브젝트를 사용하고 IDataReader 오브젝트를 반환합니다. 리파지터리는 데이터소스에 대한 적절한 질의를 발행합니다. 그 결과를 외부로 노출된 비즈니스 엔터티에 매핑합니다. 리파지터리는 그 표현을 번역하기 위해 Data Mapper 패턴을 사용합니다. 리파지터리는 특정 기술에 대한 의존을 클라이언트로 부터 제거합니다. 예를 들어 클라이언트가 프로덕트 데이터를 조회하기 위해 리파지터리를 호출 한다면, 오로지 카탈로그 리파지터리의 인터페이스만을 사용하면 됩니다. 클라이언트는 프로덕트의 정보를 조회하기 위해 데이터베이스의 SQL로 질의 되는지 쉐어포인트의 CAMIL 이 사용되는지 알 필요가 없습니다. 이런 종류의 의존을 분리 시키는 것은 구현에 있어 유연함을 제공합니다.


구현상세:

쉐어포인트 를 예로 든 설명인데 번역 생략합니다. 코드를 이용한 구현 설명은 아니고 개념 설명입니다.

쉐어포인트 리파지터리의 상호작용 다이어 그램.




고려사항:


리파지터리 패턴은 코드의 추상화 정도를 증가시킵니다. 이는 이 패턴에 익숙하지 않은 개발자가 코드를 이해하는데 있어 더욱 어렵게 만들 수 있습니다. 이 패턴을 구현하는 것이 수많은 양의 코드 중복을 감소시키지만 관리해야 하는 클래스 수를 증가 시킵니다.

리파지터리는 서비스와 리스트에 접근하는 코드를 분리하는데 도움을 줍니다. 고립은 독립적인 서비스처럼 다루기 쉽게 만들어 줍니다. 하지만 전형적으로 리파지터리 그 자체를 테스트하는 것은 매우 어렵습니다.

멀티 스레드 환경에서 캐싱 데이터를 사용할 때 캐쉬 오브젝트에 대한 동기화도 고려해야 합니다. 종종 ASP.NET 캐쉬와 같은 일반적인 캐쉬는 스레드로 부터 안전하지만, 멀티 스레드 환경에서 작동 되는 오브젝트 그 차제에 대해 스레드로 부터 안전하도록 확인해야 합니다.

여러분이 고부하 시스템에서 데이터를 캐싱 한다면 성능 문제가 부가될 수 있습니다. 데이터소스에 대한 동기화 접근을 고려해 보세요. 이는 데이터에 대한 단일 요청만이 수행되도록 보장합니다.

### 끝.


참고

리파지터리 패턴 구현에는 마틴파울러의 데이터 매퍼 패턴 (Data Mapper pattern)이 함께 사용됩니다.
리파이터리 패턴 구현에는 마틴파울러의 질의객체 (Query Object) 라는 개념이 사용됩니다.
동적, 재사용가능, Single point decision 을 위해서는 명세서 패턴 (Specification pattern) 이 함께 사용됩니다.
질의의 개별 조건에는 Criteria 라는 개념이 사용됩니다.

 

반응형
반응형

.NET 웹 어플리케이션을 개발하는 도중 MySQL Server의 데이터와 연동을 해야하는 일이 필요했다.

우선 Nuget Package를 통해서 MySQL 관련 라이브러리 (MySql.Data.dll, MySql.Data.Entities, MySql.Web)를 설치를 했다.

그리고 web.config에서 MSSQL 접근 방식과 다를게 없이 connectionString설정을 하고 ProviderName를 MySql로 변경을

했다.

 

이래저래 비지니스 로직을 작성 하고 빌드 후 디버깅을 했더니~~~

시원하게 아래와 같이 오류를 뿜어 주신다.

mysql connector net no longer supports server versions prior to 5.0

처음에는 이게 뭔가 싶었다. MySQL Connector .NET을 최신 버전으로 다시 깔아보기도 하고 web.config 코드도 변경해보고

반나절을 삽질을 했지만 결과는 그대로......

 

다음날 모닝 커피를 하면 곰곰히 생각해보니 MySQL의 버전이 의심이 들었다.

역시나 "select version()"을 날려줬더니 4.0이란다...

타 팀의 서버라 "업그레이드 해주세요!! 작업하기 힘들어요" 하기도 그랬다.

MySQL Server를 설치하고 데이터 / 스키마등을 Export 하고 Import하고 여간 귀찮게 아닌다.

개발 환경이 VS2012인데 MySQL Connector .NET 하위 버전을 쓰기는 싫고 성공적으로 연동이 될꺼라는 보장도 없다.

Connector/Net version ADO.NET version supported .NET Framework version required MySQL Server version supported Currently supported
6.7 2.x+ 2.x+ for VS 2008, 4.x+ for VS 2010 / VS 2012, .NET RT for VS 2012 5.7, 5.6, 5.5, 5.1, 5.0 Yes
6.6 2.x+ 2.x+ for VS 2008, 4.x+ for VS 2010 / VS 2012 5.7, 5.6, 5.5, 5.1, 5.0 Yes
6.5 2.x+ 2.x+ for VS 2008, 4.x+ for VS 2010 5.7, 5.6, 5.5, 5.1, 5.0 No
6.4 2.x+ 2.x+, 4.x+ for VS 2010 5.6, 5.5, 5.1, 5.0 No
6.3 2.x+ 2.x+, 4.x+ for VS 2010 5.6, 5.5, 5.1, 5.0 No
6.2 2.x+ 2.x+ 5.6, 5.5, 5.1, 5.0, 4.1 No
6.1 2.x+ 2.x+ 5.6, 5.5, 5.1, 5.0, 4.1 No
6.0 2.x+ 2.x+ 5.5, 5.1, 5.0, 4.1 No
5.2 2.x+ 2.x+ 5.5, 5.1, 5.0, 4.1 No
5.1 2.x+ 2.x+ 5.5, 5.1, 5.0, 4.1, 4.0 No
5.0 2.x+ 2.x+ 5.0, 4.1, 4.0 No
1.0 1.x 1.x 5.0, 4.1, 4.0 No

출처 : http://dev.mysql.com/doc/refman/5.6/en/connector-net-versions.html

 

자자 MySQL Server 버전이 4.0이고

MySQL Connector .NET을 쓰면 오류를 뿜어내고 어떡하지 생각하다가

 

결국 ODBC를 쓰기로 결정했다.

 

http://dev.mysql.com/downloads/connector/odbc/ (최신버전)

http://dev.mysql.com/downloads/connector/odbc/3.51.html (ODBC ver3.51)

 

이곳에서 ODBC Connector ver 3.51을 설치(왜 최신버전이 아닌 하위버전이냐고?? MySQL Server 버전이 4.0이니깐.ㅜㅜ)하고

제어판의 ODBC Administrator에서 MySQL 서버를 시스템 DSN에 등록을 하고

web.config에서

<add name="mysql_conn" connectionString="DSN=MYSQL21;" providerName="System.Data.Odbc" />

이렇게 등록만 하면 비지니스 로직에서 개발하기 위한 준비는 끝이다.

참고로 ODBC를 사용하게 되면 .NET Entity Framework를 사용하지 못한다는 사실!!!! 두둥...

 

마지막으로 참고로 Window7 x64 환경에서 디버깅을 하게 되면 또 다른 런타임 오류가 나타날 것이다.ㅎㅎㅎ

그것은 바로 전 포스팅을 참고 하면 되겠다^^

 

 

 

반응형
반응형

.NET에서 MySQL 서버에 접근하기 위해서 MySQL ODBC를 설정하였다.

ODBC : MySQL ODBC 3.51 Driver 64bit 설치

MySQL 서버 버전이 4.0이기 때문에 ODBC를 사용하였다.ㅡㅡ;;

MySQL의 낮은 버전으로 인해 .NET Connector를 사용하지 못하니 Entity Framework도 쓰지 못한다.

 

로컬에서 테스트를 하는 도중 계속해서 아래와 같은 오류가 나타났다. (에휴,,,,)

"지정된 DSN은 드라이버와 응용 프로그램 간 아키텍처 불일치"

 

원인은

MySQL 서버의 환경이 x32이기 때문이다!!!!!!!! (아~~~ 뽝쳐!!)

 

해결방안은

Command 창에서 C:\Windows\SysWOW65>odbcad32.exe 를 실행하면

x32 ODBC데이터 원본 관리자가 나타난다.

일반적으로 관리도구를 통해 실행한 ODBC 설정이랑 다르다.

기본적으로 관리도구를 통해 사용하는 ODBC 대화창은 x64 환경인것 같다.

x32 ODBC 데이터 원본 관리자에서 해당 MySQL의 정보를 설정하면

정상적으로 연결 되는 것을 확인 할 수 있다.

 

반응형
반응형

각각의 웹 어플리케이션들의 machineKey를 동일하게 설정을 하게 되면 사이트 간의 웹 팜을 구성할 수 있다

한번의 로그인으로 생성된 세션 상태ID를 가지고 웹 팜 내에 구성되어있는 웹 어플리케이션에서 사용할 수 있다.

여기서는 machineKey를 자동으로 생성하는 코드를 공유하도록 하겠습니다.^^

 

- Generator_MachineKey.aspx

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Generator_MachineKey.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>제목 없음</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Button ID="btnGeneratorMachineKey" runat="server" Text="Machine Key 생성" OnClick="btnGeneratorMachineKey_Click" /> <br />
        <asp:Label ID="lblMachineKey" runat="server" Font-Size="12px"></asp:Label>
    </div>
    </form>
</body>
</html>

- Generator_MachineKey.aspx.cs

using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Security.Cryptography;
using System.Text;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    #region protected void btnGeneratorMachineKey_Click(object sender, EventArgs e) [Machine Key 생성 버튼 클릭]
    /// <summary>
    /// Machine Key 생성 버튼 클릭
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnGeneratorMachineKey_Click(object sender, EventArgs e)
    {
        StringBuilder machineKey = new StringBuilder();

        string key64byte = GetRandomKey(64);
        string key32byte = GetRandomKey(32);

        machineKey.Append("<machineKey");
        machineKey.Append(" validationKey=\"" + key64byte + "\"");
        machineKey.Append(" decryptionKey=\"" + key32byte + "\"");
        machineKey.Append(" validation=\"SHA1\" decryption=\"AES\"");
        machineKey.Append(" />\n");

        lblMachineKey.Text = machineKey.ToString().Replace("<", "&lt").Replace(">", "&gt");
    }
    #endregion

    #region public string GetRandomKey(int bytelength) [Machine Key 생성]
    /// <summary>
    /// Machine Key 생성
    /// </summary>
    /// <param name="bytelength"></param>
    /// <returns></returns>
    public string GetRandomKey(int bytelength)
    {
        byte[] buff = new byte[bytelength];
        RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
        rng.GetBytes(buff);

        StringBuilder sb = new StringBuilder(bytelength * 2);
        for (int i = 0; i < buff.Length; i++)
        {
            sb.Append(string.Format("{0:X2}", buff[i]));
        }

        return sb.ToString();
    }
    #endregion
}

 

 

반응형
반응형

jQuery Ajax를 통해서 input file에서 선택된 파일을 서버로 업로드 기능을 개발을 하였다.

하지만 영문이름으로 된 파일은 정상적으로 업로드가 되지만 정작 한글 파일 이름으로 된 파일은 서버 측 오류가

발생을 하였다.

 

로컬에서 디버깅을 하면 정상적이고 업로드가 되고 서버에 배포된 것을 가지고 하면 계속 파일 경로가 잘 못 되었다는

오류를 뱉어내고 있었다.

 

결국 클라이언트쪽 문제가 아닌 서버 문제라는 것을 인지 미친듯이 코드를 분석을 했다. (내가 작업한게 아니라 시간이..)

문제는 서버쪽 Charset 설정 문제!!!!

 

jQuery Ajax는 기본적으로 utf-8로 Content-Type 이 설정이 되어있다. 하지만 우리쪽 서버는 euc-kr로 처리~~

Web.config 파일에 아래 코드를 추가해서 클라이언트, 서버 모두 utf-8로 설정을 하니 정상적으로 동작한다

<system.web>

<globalization requestEncoding="utf-8" responseEncoding="utf-8" fileEncoding="utf-8" />

</system.web>

 

 

 

반응형
반응형

Visual Studio 2012에서 ASP.NET MVC4 프로젝트를 생성하는 도중에 아래와 같은 오류가 발생할 때가 있다.

"Error: this template attempted to load component assembly 'NuGet.VisualStudio.Interop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.".

이 현상은 Visual Studio 2012에서 Nuget 설치가 되어있지 않아서다.

해결 방법은 아래와 같은 순서로 진행하면 된다.

1. Visual Studio 2012를 실행 -> Tolls -> Extension & Updates

2. Online을 선택한다.

3. NuGetPackage Manager를 선택해서 Download를 클릭하면 Nuget Package가 설치된다.

 

 

설치가 되면 Visual Studio2012를 재시작한 후 프로젝트를 생성하면 오류 없이 정상적으로 동작하는 것을

확인할 수 있다.

 

반응형
반응형

Sandcastle은 비주얼 스튜디오를 통해 또한 컴파일러를 통해서 생성된 DLL과 코멘트 파일인 XML을 사용하여

Help File을 만들 수 있다.

예전의 프로젝트를 진행하면서 한번 생성을 해본 기억이 있으나, 무엇을 이용해서 만들었는지 기억이 나질 않아서

구글링을 미친 듯이 했었다.

그러는 도중 발견한 Sandcastle 프로그램!!

batch파일을 손쉽게 사용할 수 있도록 GUI 툴을 제공하는데 미리 생성된 DLL파일과 코멘트 파일인 XML 파일의 경로만

찾아서 지정해주면 자동으로 help 파일로 컴파일해준다. (오~~ 놀랍도다!!)

필요에 따라서 기능을 설정할 수 있다. 단점은 컴파일 시간이 조~~옴 길다

프로그램 다운 로드는 아래 주소를 통해서 받으면 된다.

http://shfb.codeplex.com/

다운로드를 받고 차례대로 프로그램을 설치하고 사용하면 된다.

설치가 완료되면 새로운 프로젝트를 생성하고 DLL, XML 경로만 잡아주고 컴파일 하면 된다.^^/

 

역시나 날로 쓰는 블로그!!

 

반응형
반응형

요렇게 하면 된다ㅎㅎ

1) Ensured .net 4.5 is installed.
2) Added <modules runAllManagedModulesForAllRequests="true"/> to my web.config
3) Ran %windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -ir in cmd
4) Checked that my app pool was set to Integrated Mode
5) Checked that it's set to use .net 4

 

 web.config에 아래 코드 추가

<system.webServer>
   
<modules runAllManagedModulesForAllRequests="true" />
    ...
</system.webServer>

반응형

+ Recent posts