'분류 전체보기'에 해당되는 글 189건

  1. 2008.11.30 NoM 1.3 업데이트와 두 번째 셀프 인터뷰 2
  2. 2008.11.21 변경 이벤트를 지원하는 WPF 종속성 속성 생성 코드 조각
  3. 2008.11.19 Event Stuff Generator의 비주얼 스튜디오 코드 조각 버전
  4. 2008.11.17 당신이 내게 우주를 가져다 주었어. 2
  5. 2008.11.11 솜이슬이 PC사랑 11월호에 소개되었습니다.
  6. 2008.11.10 다운그레이드, 그리고 설치 파일을 이용한 설치 5
  7. 2008.11.02 SNS Soft의 소프트웨어들
  8. 2008.10.30 이벤트 코드 생성기 1.1 업데이트
  9. 2008.10.28 MS가 발표한 무료 Winform / ASP.NET 차트 4
  10. 2008.10.26 MPML (Midnight Peach Macro Language)

NoM 1.3 업데이트와 두 번째 셀프 인터뷰

NoM 2008. 11. 30. 01:34

안녕하세요 김과장님, 그 동안 잘 지내셨나요?

네 덕분에.

놈이 업그레이드를 했다지요?

네. 찔끔 찔끔 조금씩 업그레이드를 하다, 이번에는 제법 큰 폭으로 업그레이드를 했습니다.

그런데 업그레이드를 왜 하나요? 원하는 사람이 있긴 한가 보죠. 혹시 아직도 그냥 자기 만족만 하고 계신 건 아닌가요?

그러게요. 놀랍게도 놈 1.0 버전에 대한 반응이 제법 괜찮았습니다. 댓글도 30개가 넘게 달렸구요.

알바..

절대 아니거든요.

나도 댓글들 주욱 봤는데, 대부분 인터뷰가 웃긴다는 말만 있지 프로그램에 대한 좋은 반응은 별로 없던데요.

여전히 예리하시군요.

그래서 개발은 접고 혹시 인터뷰로만 계속 가시려는 것 아닌가요?

뭔가 건덕지가 있어야 인터뷰라도 할 거 아닙니까.

아 그래서 업그레이드를 계속 하시는군요.

그렇다고 볼 수 있죠.

그런데 이번 업데이트가 1.3인데, 1.1 때랑 1.2때는 인터뷰를 하자고 안하시데요.

제가 좀 바빴습니다. 설마 제가 놈의 업데이트를 항상 모니터링 하고 있다고 생각하시는 건 아니겠지요?

아 그런 것 아니었나요?

인터뷰 계속 하기가 살짝 망설여 지네요.

그건 그렇고, 이전 버전들에 대한 피드백은 많이 받으셨나요?

인터뷰 웃긴다는 내용도 포함시켜도 됩니까?

당근 아니죠.  알바성 글도 빼고요.

음, 역시 그렇군요...

그래도 고맙게도 몇몇 분께서 피드백을 주셔서 큰 도움이 되었습니다.

주로 버그나 에러에 관한 내용일 것 같은데, 가장 많이 받은 컴플레인이 무엇이었습니까?

주로 설치가 안된다는 이야기였지, 버그나 에러에 대한 이야기는 없었습니다. 즉 상당히 안정적인 프로그램이라고 평가를 해주셨다고 할 수 있겠습니다.

아 물론 그렇겠죠. 설치도 못해봤는데 어떻게 버그를 발견했겠습니까.

원래 매사를 그렇게 부정적으로 보십니까?

아 됐고, 설치는 왠 안되는 겁니까?

대부분 놈 자체 보다는 닷넷 프레임웍 3.5 SP1의 설치가 안되는 경우가 많았습니다. 아시다시피 놈은 닷넷 프레임웍 3.5 SP1이 설치되어 있어야 실행할 수 있는 프로그램이거든요.

그럼 닷넷 프레임웍 3.5 SP1이 설치 안되는 이유는 무엇일까요?

야릇한 사이트에 즐겨 가시기 때문이죠. 또는 각종 바이러스나 스파이 웨어 혹은 설치된 프로그램들 간의 충돌이 원인일 수 있습니다.

야릇한 사이트는 김과장님 이야기인 것 같고요, 아 갑자기 지난 번 인터뷰 내용이 생각 났는데, 종종 노트북을 들고 화장실에 가신다고 하셨잖아요. 화장실에서 주로 어떤 사이트에 접속하시는지가 갑자기 좀 궁금해지네요.

어허...

그러니까 바이러스나 스파이 웨어 혹은 프로그램 간의 충돌이 주 원인이라는 말씀이시군요.

그렇지요.

결국 놈이 설치 안되는 건 김과장님의 잘못이 아니라 사용자의 컴이 지저분해서 그렇다는 말씀인가요?

뭐 꼭 그렇다기 보다는... 좀 그렇죠. MS 오피스나 아래 한글도 좀 지저분한 컴에서는 잘 설치가 안되는 경우가 있지 않습니까? 닷넷 프레임웍의 경우에도 비슷하게 볼 수 있습니다.

그래서 배 째라는 식으로 아무런 조치도 안 취하고 있습니까?

그렇지는 않고요. 이번 업데이트에서는 나름 배포 문제를 좀 풀어보려고 했습니다.

말만 하지 마시고, 구체적으로 어떤 노력을 하셨는지를 말씀 해 보시죠. 말씀 하실 수 있나요?

이전 버전에서는 닷넷 프레임웍 3.5 SP1와 별도로 배포해야 하는 컴퍼넌트 두 개를 더 사용하고 있었는데요. 이번에는 그 둘을 빼버렸습니다.

그럼 이제 100% 설치가 잘 되는 건가요?

세상에 100%란 게 어디 있습니까. 하지만 윈도우를 새로 깔고 설치하면 아마 100% 가까이 될 겁니다.

윈도우를 새로 깐다고요? 인터뷰를 읽는 분들이 "썅"이라고 하시지 않을까요?

역시 좀 그렇지요? 그럼 그 말은 편집 해주세요.

알겠습니다.

꼭 편집해 주세요.

네 꼭 편집하겠습니다.

1.3 버전의 새로운 기능들에 대한 소개를 좀 해주시죠.

먼저 UI를 정리했습니다. 제가 보기에는 좀 더 직관적으로 변경된 것 같습니다.

그리고 스킨을 두 개 더 추가했습니다.

아 스킨은 좀 그만 합시다. 스킨 기능 쓰는 사람 아무도 없는 것 알죠?

알죠.

그런데 왜 스킨에 그렇게 집착하니까?

왜냐면 뭔가 개발을 많이 한 것처럼 보이니까요.

그런데 사실은 김과장님이 하는 일은 아무 것도 없다면서요. 듣기로는 놈이 사용하는 써드 파티 컨트롤 라이브러리에서 스킨과 관련한 모든 기능을 다 제공한다더데.

맞아요. 이번에 스킨 추가하면서 코드를 변경한 것은, "Pumpkin" 과 "Dark Side"라고 문자열 두개 추가한 것 밖에 없습니다.

결국 하는 일 없이 뭔가 날로 먹을 수 있을 것 같아 스킨을 계속 추가하는 게 맞습니다.

설마 이게 1.3 버전의 업데이트 내역 전부는 아니겠지요?

맞는데요.

진짜로 인터뷰 하려고 업데이트는 생색만 내는 것이 맞나 보군요.

아 한 가지 더, 아직 시험 중인 기능이긴 하지만 자동 캡쳐 기능이 추가되었어요.

또 무슨 쓸 데 없는 기능을 집어넣으려고 하시나요?

이번에는 진짜 유용한 기능이에요. 물론 잘 동작하면.

어떤 기능입니까? 들어나 봅시다.

자동 캡쳐를 키고 링크를 클릭하면, 새로 열린 페이지를 자동으로 캡쳐하는 기능입니다. 매번 캡쳐 버튼을 누르는 수고를 들어줄 수 있지요.

예를 들어서 한겨레 21에서 아래 세 기사를 캡쳐하려고 한다고 합시다.

자동 캡쳐를 체크한 후 각 링크를 한 번씩 누르기만 하면 세 페이지가 캡쳐가 됩니다. 정말 편리하지 않습니까?

글쎄요. 사용해봐야 알겠네요. 게다가 제대로 동작이 안될지도 모르고요.

사용해보시고 피드백 부탁드립니다.

더 소개할 기능이 있나요?

뭐 오늘은 이 정도.

인터뷰 밑천이 다 떨어졌나 보군요.

또 업데이트 하면 다시 인터뷰 할 수 있나요?

그렇긴 한데, 찌질하게 업데이트 한 거면 좀 자제해 주시면 고맙구요.

네 알겠습니다.

인터뷰에 응해 주셔서 감사합니다.

노 프라블럼 입니다.

참, 새 버전 설치는 어떻게 합니까?

이전과 동일합니다. 이미 설치하신 분은 놈을 실행하면 자동으로 업데이트가 되고요. 처음 설치하시는 분은 http://snssoft.net/Nom/publish.htm 에서 설치하시면 됩니다.

이미 설치는 하였는데 자동 업데이트가 안되면, 프로그램 추가/삭제에서 이전 버전을 삭제하시고 다실 설치하시면 됩니다.

네 고맙습니다.

네 고맙습니다.

:

변경 이벤트를 지원하는 WPF 종속성 속성 생성 코드 조각

Dev Tools/이벤트 코드 생성기 2008. 11. 21. 09:25


요즈음 WPF 공부를 성실하게 하다 보니 앞으로 종속성 속성을 빈번하게 만들 것 같다는 예감이 듭니다.

그래서 VS2005(2008)의 코드 조각 기능을 사용하여 반복적인 타이핑을 줄일 수 있는 코드 조각을 만들어 보았습니다.

사용 방법은 다음과 같습니다.

도구 -> 코드 조각 관리자를 실행합니다.

가져오기 버턴을 눌러 새로운 코드 조각을 가져옵니다.

첨부된 Dependency Property.snippet를 불러옵니다.

마침을 누르면 코드 조각이 추가됩니다.

추가된 코드 조각의 정보는 다음과 같습니다.

image

이 코드 조각을 사용하는 예를 볼까요?

종속성 속성을 가질 클래스를 추가합니다. 이름은 SecretButton으로 하겠습니다.

image

일반 버튼을 확장하여 비밀 텍스트를 추가로 가질 수 있는 버튼입니다.

비밀을 저장할 Secret 종속성 속성을 추가하겠습니다.

클래스 내부에서 dp라고 입력하고 탭키를 누릅니다.

image

(위 이미지에 생성된 코드의 일부입니다.)

현재 커서는 속성 이름을 변경하는 곳에 위치하고 있습니다. 속성 이름인 Secret를 입력하고 탭 키를 누릅니다.

이제 커서는 속성의 형식을 변경하는 곳에 있게 됩니다. 이번에는 string 라고 입력하고 탭 키를 누릅니다.

이번에는 속성의 기본값을 입력합니다. 여기서는 ""라고 입력합니다.

값을 편집하는 중에 기존 값을 변경하지 않으려면 그냥 탭 키만 누릅니다. 또한 엔터 키를 누르면 편집이 끝납니다.

 

위 예에서 생성된 전체 코드는 다음과 같습니다.

#region Secret dependency property things
/// <summary>
/// Identifies the Secret dependency property.
/// </summary>
public static readonly DependencyProperty SecretProperty =
    DependencyProperty.Register(
        "Secret", typeof(string), typeof(SecretButton),
        new FrameworkPropertyMetadata("", OnSecretChanged, OnSecretCoerced));

/// <summary>
/// Gets or sets the Secret assigned to the control.
/// </summary>
[Description("Gets or sets the Secret assigned to the control.")]
[DefaultValue("")]
public string Secret
{
    get { return (string)GetValue(SecretProperty); }
    set { SetValue(SecretProperty, value); }
}

private static object OnSecretCoerced(DependencyObject element, object value)
{
    string newValue = (string)value;
    SecretButton control = (SecretButton)element;

    //TODO : 여기에 커스텀 로직을 입력.

    return newValue;
}

private static void OnSecretChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
    SecretButton control = (SecretButton)obj;

    RoutedPropertyChangedEventArgs<string> e = new RoutedPropertyChangedEventArgs<string>(
        (string)args.OldValue, (string)args.NewValue, SecretChangedEvent);
    control.OnSecretChanged(e);
}

#region 라우팅된 SecretChanged 이벤트. UIElement를 상속하는 클래스만 유효
/// <summary>
/// Identifies the SecretChanged routed event.
/// </summary>
public static readonly RoutedEvent SecretChangedEvent = EventManager.RegisterRoutedEvent(
    "SecretChanged", RoutingStrategy.Bubble,
    typeof(RoutedPropertyChangedEventHandler<string>), typeof(SecretButton));

/// <summary>
/// Occurs when the Secret property changes.
/// </summary>
public event RoutedPropertyChangedEventHandler<string> SecretChanged
{
    add { AddHandler(SecretChangedEvent, value); }
    remove { RemoveHandler(SecretChangedEvent, value); }
}

/// <summary>
/// Raises the SecretChanged event.
/// </summary>
/// <param name="args">Arguments associated with the ValueChanged event.</param>
protected virtual void OnSecretChanged(RoutedPropertyChangedEventArgs<string> args)
{
    RaiseEvent(args);
}
#endregion
#endregion

:

Event Stuff Generator의 비주얼 스튜디오 코드 조각 버전

Dev Tools/이벤트 코드 생성기 2008. 11. 19. 13:33



Event Stuff Generator와 동일한 일을 하는 비주얼 스튜디오용 코드 조각을 만들어 보았습니다.

이제는 이벤트 코드 조각을 만들기 위해 따로 Event Stuff Generator 툴을 실행할 필요 없이 비주얼 스튜디오에서 바로 코드 조각을 생성할 수 있게 되었습니다.

(코드 조각을 설치하고 사용하는 방법은 이전 포스트인 변경 이벤트를 지원하는 WPF 종속성 속성 생성 코드 조각를 참고하시기 바랍니다.)


첨부파일에는 Event Stuff C# 2.0 (0).snippet 부터 Event Stuff C# 2.0 (5).snippet 까지 6개, 그리고 Event Stuff C# 3.0 (0).snippet 부터 Event Stuff C# 3.0 (5).snippet 까지 6개의 snippet 파일이 있습니다.

각각 C#의 버전과 생성할 이벤트 매개 변수 클래스의 필드 수에 대응합니다.

예를 들어 AgeChanged 이벤트가 AgeChangedEventArgs 이벤트 매개 변수 클래스와 연결되어 있고, AgeChangedEventArgs가 int oldAge, int newAge 라는 두 개의 필드를 가지고 있다면 Event Stuff C# 2.0 (2).snippet 혹은 Event Stuff C# 3.0 (0).snippet을 사용하면 됩니다.

(필드 수가 여섯 개 이상인 경우는 지원하지는 않지만 소스를 수정하여 직접 만들어 쓰는 방법이 있습니다.)


단축키는 C# 2.0용 코드일 경우에는 ev20 ~ ev25, C# 3.0의 경우에는 ev30 ~ ev35 까지 총 12개를 지정해두었습니다.


필드의 갯수에 따라 거의 동일한 코드 조각을 6개씩 만들어야 하는 것이 비효율적이긴 하지만, 비주얼 스큐디오의 코드 조각에는 필드의 갯수에 따라 반복하는 함수를 지원하지 않기 때문에 어쩔 수가 없는 것 같습니다. (C#의 경우 겨우 3개의 함수만 지원합니다.)

혹시 다른 방법을 아시면 알려 주시면 감사하겠습니다.


또 한 가지 툴을 사용할 때 보다 불편한 점은 매개 변수 클래스의 필드 수가 많아지면 입력이 다소 불편함 감이 있습니다.

예를 들어 코드 조각에서는 oldAge와 OldAge를 각각 입력하여야 하기 때문에 툴에 비해 타이핑 수가 거의 두 배 정도 많습니다.

그래도 각각 일장일단이 있으니 툴이나 코드 조각 중 편리한 것을 사용하시면 되겠습니다.

기술 지원은 양 쪽 다 지원하도록 하겠습니다.

:

당신이 내게 우주를 가져다 주었어.

기록 2008. 11. 17. 23:51

당신이 오기 전 까지는 나는 그냥 코드에 미친 일 중독자였었어.

부를 사람도, 불러줄 사람도 없는 외딴 방에서 웅크리고만 있었지.

그런 내게 당신이 우주를 가져다 주었어.

 

내게 와줘서,

그리고 수현이와 같이 와줘서,

정말 고마워.

- 아내에게 보내는 결혼 3주년 메시지

:

솜이슬이 PC사랑 11월호에 소개되었습니다.

솜이슬 2008. 11. 11. 00:31

어떤 사용자 분이 알려주셔서 알게 되었는데, 월간 PC 사랑 11월 호에 솜이슬에 대한 기사가 실렸다고 합니다.

어떻게 된 영문인지 찾아보니, "영어 공부도 PC로 하자"는 기사에서 몇 가지 소프트웨어들을 소개하면서 솜이슬도 약간 소개가 되었습니다.

솜이슬이 알려줘서 기분이 좋긴 하지만 약간의 미묘한 문제들을 고민해야 하는 상황이 되기도 하였습니다.

솜이슬을 사용하시는 분들의 이해를 구할 따름입니다.

:

다운그레이드, 그리고 설치 파일을 이용한 설치

솜이슬 2008. 11. 10. 23:39

몇 가지 미묘한 문제 때문에 솜이슬의 일부 기능이 잠정적으로 중지되었습니다.

중지된 기능의 전체 목록은 다음과 같습니다.

  • 로그인
  • 계장 등록
  • 비밀번호 변경
  • 비밀번호 재발급
  • 서버에서 불러오기
  • 서버에 저장하기
  • 패키지에서 추가

보시다시피 모두 서버를 필요로 하는 기능입니다.

서버가 준비되는대로 복원하도록 하겠습니다.


아울러 배포 방식에도 변화가 생겼습니다.

이제부터는 Click Once 배포 대신 설치 파일을 통해 배포가 이루어지게 됩니다.

하지만 자동 업데이터가 새로이 내장되어 업데이트는 항상 자동으로 수행됩니다.


이전 버전을 사용하고 있는 분들은 프로그램 추가/제거에서 기존 버전을 삭제하고 새로운 버전을 설치하시기 바랍니다.

새로운 버전을 설치하지 않으면 오류가 발생하여 정상적인 사용이 어렵습니다.


물론 이전 버전을 삭제하고 새로운 버전을 설치하더라도 이전에 사용하던 데이터 파일은 계속 사용할 수 있습니다.


설치 방법은 다음과 같습니다.

1. 닷넷 프레임웍 3.5 서비스 팩1을 설치합니다. 아래 파일을 실행하면 닷넷 프레임웍을 자동으로 설치합니다.


2. 솜이슬 설치 파일을 실행합니다.

:

SNS Soft의 소프트웨어들

秀作 2008. 11. 2. 01:01

언젠가 자세히 말씀드릴 기회가 있으면 좋겠습니다만, 프로그래머로서 저는 오랫동안 어떤 회사를 꿈꿔왔습니다.

프로그래머로서의 창조 본능을 최대한으로 발휘할 수 있는 회사, 만들고 싶은 것을 만들고 싶은대로 만들 수 있는 회사, 그래서 일과 놀이와 직업과 생계와 자아실현을 서로 구별할 필요가 없는 회사, 실현 가능성을 떠나서 오랫동안 제가 매혹되어온 회사의 모습입니다.

현재로서는 ISV(독립 소프트웨어 벤더) 형태가 제가 열망하는 회사의 모습에 가장 가깝지 않나 싶습니다.

SNS Soft는 그런 생각으로 만들어진 야매 회사입니다. 물론 상법 상의 절차를 거치지 않았으니 회사라고 불러서는 안되겠지요.

언젠가 때가 무르익으면 진짜 회사가 되기를 기대할 따름입니다.

 

이번 포스트에서는 현재까지 발표된 SNS Soft의 소프트웨어들에 대한 정리를 하고자 합니다.

 

솜이슬 : 프리미엄 영어 단어장

설치

기술 지원

 

Midnight Peach : LINQ to SQL에 기반한 범용 코드 생성기

설치

기술 지원

 

Event Stuff Generator : C# 이벤트 코드 조각 생성기

설치

기술 지원

 

Code Formatter : 기술 문서 작성을 위한 코드

설치

기술 지원

 

NoM : 웹 페이지를 TXT로 일괄 저장하는 툴

설치

기술 지원

:

이벤트 코드 생성기 1.1 업데이트

Dev Tools/이벤트 코드 생성기 2008. 10. 30. 11:08

이벤트 코드 생성기의 버전이 1.1로 업데이트 되었습니다.

이전 버전을 이미 설치하신 분들은 자동 업데이트가 될 것이며, 새로 설치하실 분들은 아래 링크를 클릭하시면 됩니다.

http://snssoft.net/devtools.eventstuffgenerator/publish.htm

 

사용방법은 다음과 같습니다.

image

1. 생성할 이벤트의 이름을 입력합니다.

 

2. 이벤트 매개변수 클래스의 필드의 형과 이름을 입력합니다.

필드가 여러 개 라면 엔터키를 눌러 줄을 구분합니다.

T data

와 같이 제네릭 필드도 사용할 수 있습니다.

 

3. 템플릿을 선택합니다.

기본적으로 C# 2.0과 C# 3.0용의 템플릿이 제공됩니다. (이 두 템플릿의 차이는 C# 3.0에서는 자동 구현 속성을 사용하는 것 밖에 없습니다.)

Custom 1 ~ Custom 5 템플릿은 사용자가 자유롭게 편집하여 사용할 용도로 제공되는 템플릿입니다.

 

4 ~ 5. 생성 버튼을 클릭하면 코드 텍스트 상자(5번 부분)에 생성된 코드가 표시됩니다.

 

6. 코드 복사 버튼을 누르면 생성된 코드가 클립보드로 복사됩니다.

 

추가로 만약 기본 제공되는 템플릿을 수정하여야 한다면 아래 방법처럼 하실 수 있습니다.

a. Custom 1 ~ Custom 5 템플릿 중 한 가지를 선택하고 템플릿을 적절히 구성합니다. 이때 사용되는 템플릿에서 사용되는 매크로에 대한 설명은 매크로 패널(8번 부분)을 참조합니다.

b. 템플릿 저장 버튼을 눌러 수정된 템플릿을 저장하면, 다음 실행 시 저장된 템플릿이 나타납니다.

:

MS가 발표한 무료 Winform / ASP.NET 차트

미분류 2008. 10. 28. 00:31

소개

David Hayden 의 블로그를 읽다가 MS가 발표한 무료 Winform / ASP.NET 차트가 있음을 알게 되었습니다.

지난 9월 8일에 출시되었는데 이제야 알게 되었네요.

image

충분히 살펴보지는 못했지만, (제가 아는 한 에서는) 써드 파티 차트 컨트롤의 최고봉이라고 할 Chart-FX에는 미치지 못하지만, Infragistics나 DevExpress 사의 차트 컨트롤과는 대등한 수준인 것 같습니다.

즉, 상용 수준의 차트 컨트롤을 무료로 사용할 수 있다는 의미가 되겠습니다.

 

컨트롤은 Microsoft .NET Framework 3.5용 Microsoft Chart Controls에서 다운 받을 수 있습니다. 혹 영문 버전을 설치하였다면 Microsoft .NET Framework 3.5용 Microsoft Chart Controls 언어 팩에서 한국어 언어 팩을 추가로 설치할 수 있습니다.

그리고 차트 컨트롤을 비주얼 스튜디오와 통합하는 Microsoft Chart Controls Add-on for Microsoft Visual Studio 2008는 여기에서 다운 받을 수 있습니다. 필수는 아니지만 문서샘플도 다운 받으실 것을 추천합니다.

 

헬로우 월드

그냥 소개만 하고 마치면 아쉬우니까, (상징적인 의미로서의) '헬로우 월드'라도 한 번 찍어보겠습니다.

 

1. 위 링크를 모두 다운 받아 설치한 후 비주얼 스튜디오에서 새 윈폼 응용프로그램을 만듭니다.

2. 윈폼 디자이너가 열린 상태에서 도구 상자를 보면 새로 추가된 차트 컨트롤이 데이터 카테고리아 안에 아래 그림과 같이 보입니다.

image

3. 차트 컨트롤을 윈폼 디자이너로 끌어옵니다.

image

4. 이제 차트의 데이터 소스를 지정하여야 합니다. 물론 예상하시다시피 데이터베이스 테이블이나, XML, 엔터티 컬렉션 등을 모두 데이터 소스로 지정할 수 있지만, 여기서는 간단하게 엔터티의 컬렉션을 사용하도록 하겠습니다.

5. 여러 학생의 국어 영어 수학 점수에 대한 차트를 그리는 상황이라고 가정하겠습니다. 각 학생의 점수를 표현하는 Score 클래스를 프로젝트에 추가합니다.

image

6. 먼저 빌드를 한 번 해준 후, 차트 컨트롤의 속성에서 데이터 소스를 선택한 후 아래 그림과 같이 프로젝트에 새 데이터 소스를 추가합니다.

image 

7. 데이터 소스 타입에서 객체를 선택하고, 위에서 만든 Score 클래스를 선택합니다.

image

image

8. 차트 컨트롤의 Series 속성을 선택하여 시리즈 컬렉션 편집기를 엽니다.

image

9. Name은 '국어', XValueMember는 'Name', YValueMember는 'Korean'으로 설정합니다.

이는 가로 축으로는 응시자의 이름이 나오고 세로 축으로 국어 점수를 표시하겠다는 의미입니다.

image

10. 시리즈를 두 개 더 추가한 후 Name과 YValueMember 값을 각각 아래 그림과 같이 설정합니다. 가로 축은 응시자의 이름이므로 세 시리즈 모두 'Name'이 됩니다.

image

image

11. 영어의 차트 타입은 Bubble로, 수학의 차트 타입은 Spline으로 설정합니다.

image

12. Form1 클래스의 코드 비사이드 파일에 아래와 같은 코드를 추가합니다.

Score 객체의 리스트를 만들어 이를 차트의 데이터 소스로 지정하는 일을 하고 있습니다.

 image

여담이지만, Form 클래스의 Shown 이벤트에 이벤트 핸들러를 추가하지 않고, 바로 OnShown 메서드를 재정의하는 것을 유심히 보시기 바랍니다. 이는 이벤트 핸들러를 추가하는 방식에 비해서 몇 가지 이점을 가지고 있습니다. 이에 대해서는 졸고 C# 코딩 연습 - 대리자와 이벤트에서 자세히 다루고 있습니다.

13. 실행을 하면 아래와 같은 차트를 보실 수 있습니다.

image

 

정리

개발자로서 어려운 선택을 해야 하는 경우가 종종 있습니다.

'유연한 확장이 가능하고 비용이 들지 않는 오픈 소스 기반의 라이브러리를 선택하느냐, 품질이 보장되고 친절한 매뉴얼과 기술 지원이 제공되는 상용 제품을 구매하느냐'도 그런 선택의 하나인 것 같습니다.

물론 프로젝트의 상황과 개발자의 가치관이나 취향 등에 따라 결국 취사선택될 문제이긴 하나, 이 차트 컨트롤의 경우에는 고민스러운 선택을 하지 않아도 될 것 같습니다.

'참 고마운 사람들'이라고 손뼉을 치며 좋아하면서도, 가슴 한 쪽이 서늘해지는 기분이 듭니다.

이 차트 컨트롤과 비슷하거나 못한 상용 제품을 파는 개발사는 그럼 어떻게 될까요?

그들이 쓰러지고 나면 그 다음에는 또 누가 쓰러질까요? 혹시 나?

:

MPML (Midnight Peach Macro Language)

Midnight Peach 2008. 10. 26. 13:44

[주의]
이 글은 MP의 현재 버전 (3.X)에 맞지 않습니다.

단순 참고용으로만 활용하십시오

MP의 템플릿은 고유한 문법을 가지고 있습니다.

이 문법으로 기술된 언어를 Midnight Peach Macro Language, 줄여서 MPML 라고 합니다.

이번 포스트에서는 이 MPML의 문법에 대해서 살펴보도록 하겠습니다.

 

이전 포스트인 MP의 구성에서 말씀드렸듯이, MP는 패키지 DBML에 정의되어 있는 엔터티 클래스를 원본으로 하여 (패키지에 포함된) 템플릿을 치환하는 방식으로 코드를 생성합니다.

이때 템플릿에는 엔터티의 클래스를 어떻게 치환하여야 하는지에 대한 정보가 기술되어 있습니다. 이 정보가 일정한 규칙(문법)을 따라야만 치환이 정상적으로 이루어집니다.

바로 이 규칙(문법)을 정의해 놓은 것이 MPML입니다.

 

만일 사용자가 MP에 내장된 Default 패키지를 수정하여 사용하여야 한다면, 패키지에 포함된 템플릿을 수정하여야 합니다.

템플릿을 수정하기 위해서는 MPML의 문법에 대해서 알 필요가 있습니다.

결과적으로 MPML을 알아야 하는 이유는 패키지를 커스터마이즈 하여 사용자의 필요에 맞는 코드를 생성하기 위해서라고 하겠습니다.

 

MPML은 매크로를 정의하는 (언어라고 부르기도 힘들 정도록) 대단히 단순한 언어입니다. 따라서 문법도 무척 간략합니다.

먼저 MPML의  EBNF는 다음과 같습니다.

(참고로 EBNF, 즉 확장된 바커스-노어 폼은 언어의 사양을 정의하는 메타 언어입니다. EBNF에 대한 설명은 이 포스트의 범위를 벗어나므로 위키피디아의 항목 등을 참고하시기 바랍니다.)

 

template = {database | table loop | table | column loop | comment | variable | character} ;

database = "<#D " , "CamelName" | "PascalName" | "DataContext" , " D#>" ;

table loop = "<#A " , table loop type , ":", {loop seperator} , ":", {character | table} , " A#>" ;

table loop type = "AL" | "TB" | "VW" ;

loop seperator = "[N]" | "[T]" | character ;

table = "<#T " , "CamelName" | "PascalName" | "DbName" | "Schema" | "BeginCommentIfView" | "EndCommentIfView" , " T#>" ;

column loop = "<#O " , column loop type , ":" , {loop seperator} , ":", {character | column} , " O#>" ;

column =  "<#C " , "CamelName" | "PascalName" | "DbName" | "Type" | "DbType" | "BeginCommentIfReadOnly" | "EndCommentIfReadOnly",  " C#>" ;

column loop type = "AL" | "PK" | "NP" | "IN" | "NI" | "RO" | "NR" | "NU" | "NN";

variable = "<#V ", {character}, " V#>";

comment = "<#- ", {character}, " -#>";

character = [a-z] | [A-Z] | [0-9] | white space ;

 

위  EBNF에 대해서 실제 템플릿 코드와 함께 하나씩 살펴봅시다.

 

1. template = {database | table loop | table | column loop | variable | comment | character} ;

EBNF의 정의에 의하면 이 라인은, '템플릿은 database, table loop, table, column loop, variable, comment, character 요소의 반복으로 이루어져 있다'는 의미가 되겠습니다. 따라서 위 EBNF의 두 번째 라인부터는 각 요소들에 대한 정의가 이어집니다.

 

2. database = "<#D " , "CamelName" | "PascalName" | "DataContext" , " D#>" ;

database요소에 대한 정의입니다. "|" 는 "또는"의 의미이므로,  database는 "<#D "로 시작하고, "CamelName" 이나 "PascalName" 이나 "DataContext"가 이어지고, " D#>"로 끝난다는 말이 되겠네요.

그리고 이때 "CamelName" 이나 "PascalName" 이나 "DataContext"는 각각 데이터베이스의 소문자 이름, 대문자 이름, DataContext 클래스 이름으로 치환되도록 미리 정해진 속성입니다.

 

예를 들어 아래와 같은 템플릿을 만나면,

internal static <#D DataContext D#> CreateDataContext()
{
    return CreateDataContext(false, true);
}

MP는 <#D DataContext D#>를 이렇게 해석합니다.

'<#D 로 시작하고 D#>로 끝나니 이것은 (DBML) 데이터베이스에 대한 매크로이구나. 또한 DataContext 라고 했으니 이 부분을 DBML에 정의되어 있는 데이터베이스의 DataContext 객체 이름으로 치환해야겠구나'

따라서 다음과 같은 코드가 생성됩니다. (DBML의 DataContext가 MemopadDataContext라고 가정합니다.)

internal static MemopadDataContext CreateDataContext()
{

    return CreateDataContext(false, true);
}

 

database요소의 가능한 값은 다음과 같습니다.

매크로 설명 (샘플 프로젝트의 경우)
PascalName 대문자로 시작하는 이름 <#D PascalName D#> ==> Memopad
CamelName 소문자로 시작하는 이름 <#D CamelName D#> ==> memopad
DataContext DataContext의 형식 이름 <#D DataContext D#> ==> MemopadDataContext

 

3. table loop = "<#A " , table loop type , ":", {loop seperator} , ":", {character | table} , " A#>" ;

table loop 요소는 조건에 해당하는 엔터티(테이블 혹은 뷰)를 반복하며 코드를 생성하는 요소입니다.

"<#A"와 "#A>" 태그로 시작하고 끝나는데, 태그의 내부는 ":" 으로 구분된 세 부분으로 이루어져 있습니다.

이는 각각 반복할 엔터티의 종류, 각 반복 시의 구분자, 반복 내용인데, EBNF 문법에서 알 수 있듯이, 첫번째 부분은 한 번만 나오는 반면에 두번째와 세번째 부분은 0회 이상 반복될 수 있습니다.

 

4. table loop type = "AL" | "TB" | "VW" ;

table loop type 요소는 반복할 엔터티의 종류를 지정합니다.

각 매크로의 의미는 다음과 같습니다.

매크로 설명 (샘플 프로젝트의 경우)
AL 모든 엔터티

<#A AL:: A#> ==>

Contact, Member, Memo, Reading, ReadingView를 반복

TB 테이블인 엔터티만

<#A TB:: A#> ==>

Contact, Member, Memo, Reading를 반복

VW 뷰인 엔터티만

<#A VW:: A#> ==>

ReadingView를 반복

 

5. loop seperator = "[N]" | "[T]" | character ;

엔터티(테이블 혹은 뷰)와 엔터티의 속성(컬럼)이 반복될 때 각 반복 사이에 삽입될 문자열을 지정합니다. 반복 사이이기 때문에 마지막 반복 후에는 문자열이 삽입되지 않습니다.

가능한 값의 목록은 다음과 같습니다.

매크로 설명 (샘플 프로젝트의 경우)
[N] 줄바꿈(\r\n)을 반복 사이에 삽입합니다.

<#A TB:[N]:<#T PascalName T#> A#> ==>

Contact

Member

Memo

Reading

[T] 탭(\t)을 반복 사이에 삽입합니다.

<#A TB:[T]:<#T PascalName T#> A#> ==>

Contact    Member    Memo    Reading

character 사용자가 지정한 문자열을 반복 사이에 삽입합니다. 아래 character 요소를 참조하십시오.

<#A TB:, :<#T PascalName T#> A#> ==>

Contact, Member, Memo, Reading

 

6. table = "<#T " , "PascalName" | "CamelName" | "DbName" | "Schema" | "BeginCommentIfView" | "EndCommentIfView" , " T#>" ;

table 요소는 엔터티의 여러가지 속성에 대한 매크로를 가지고 있습니다.

각 매크로의 의미는 다음과 같습니다.

매크로 설명 (샘플 프로젝트의 Contact 테이블의 경우)
PascalName 엔터티의 대문자로 시작하는 이름 <#T PascalName T#> ==> Contact
CamelName 엔터티의 소문자로 시작하는 이름 <#T CamelName T#> ==> contact
DbName SQL 서버 테이블(뷰)의 이름
SQL 서버 테이블(뷰)의 이름과 엔터티의 이름은 다를 수 있습니다.
<#T DbName T#> ==> Contact
(테이블과 엔터티의 이름이 동일)
Schema SQL 서버 테이블(뷰)의 스키마.
일반적으로는 "dbo"이며, SQL 서버 2005 이상에서만 지원.
<#T Schema T#> ==> dbo
BeginCommentIfView 엔터티가 뷰인 경우 "/*"를 반환 <#T BeginCommentIfView T#> ==>
(Contact는 테이블이기 때문에 아무 것도 생성되지 않음)
<#T BeginCommentIfView T#> ==> /*
(엔터티가 Contact가 아니라 ReadingView인 경우)
EndCommentIfView 엔터티가 뷰인 경우 "*/"를 반환 <#T EndCommentIfView T#> ==>
(Contact는 테이블이기 때문에 아무 것도 생성되지 않음)
<#T EndCommentIfView T#> ==> */
(엔터티가 Contact가 아니라 ReadingView인 경우)

 

여기까지의 요소들이 합쳐진 템플릿의 예를 볼까요?

<#A AL:[N]:
public static <#T PascalName T#>Manager <#T CamelName T#> { get; private set; }
A#>

1)모든(AL) 엔터티에 대해 2)각 반복에 있어 줄바꿈문자([N])를 구분자로 하여 3)"public static <#T PascalName T#>Manager <#T PascalName T#> { get; private set; }"라는 문자열을 반복하라는 의미가 됩니다.

또한, 반복되는 "public static <#T PascalName T#>Manager <#T CamelName T#> { get; private set; }" 문자열에 있어서도 "<#T PascalName T#>"와 "<#T CamelName T#>"를 각각 엔터티의 파스칼 이름과 카멜 이름으로 치환을 하게 됩니다.

결과적으로 이 템플릿에 샘플 프로젝트의 DBML을 대입하면 아래와 같은 코드가 생성됩니다.

public static ContactManager contact { get; private set; }
public static MemberManager member { get; private set; }
public static MemoManager memo { get; private set; }
public static ReadingManager reading { get; private set; }
public static ReadingViewManager readingView { get; private set; }

 

7. column loop = "<#O " , column loop type , ":" , {loop seperator} , ":", {character | column} , " O#>" ;

column loop 요소는 table loop 요소가 엔터티에 대한 반복을 나타내는 것 처럼 엔터티의 속성에 대한 반복을 나타냅니다.

table loop 요소와 마찬가지로 ":" 으로 구분된 세 부분으로 이루어져 있는데, 역시 반복할 엔터티 속성의 종류, 각 반복 시의 구분자, 반복 내용에 해당됩니다.

이 중 반복 시의 구분자는 table loop와 동일하며, 반복 내용은 table 대신 column 요소가 사용된다는 점만 제외하면 동일합니다.

 

8. column loop type = "AL" | "PK" | "NP" | "IN" | "NI" | "RO" | "NR" | "NU" | "NN";

column loop type 요소는 반복할 엔터티 속성의 종류를 지정하는 것입니다.

각 매크로의 의미는 다음과 같습니다.

매크로 설명
AL ALl. 모든 컬럼  
PK Primary Key. 기본키인 컬럼  
NP Not Primary key. 기본키가 아닌 컬럼  
IN INcremental. 자동증가 컬럼  
NI Not Incremental. 자동증가가 아닌 컬럼  
RO Read Only. 읽기 전용 컬럼  
NR Not Read only. 읽기 전용이 아닌 컬럼  
NU NUllable. 널을 허용하는 컬럼  
NN Not Nullable. 널을 허용하지 않는 컬럼  

 

9. column =  "<#C " , "PascalName" | "CamelName" | "DbName" | "Type" | "DbType" | "BeginCommentIfReadOnly" | "EndCommentIfReadOnly",  " C#>" ;

엔터티의 속성에 대한 정보를 나타내는 요소입니다.

매크로 설명 (샘플 프로젝트의 Contact.Name 컬럼의 경우)
PascalName 엔터티 속성의 대문자로 시작하는 이름 <#C PascalName C#> ==> Name
CamelName 엔터티 속성의 소문자로 시작하는 이름 <#C CamelName C#> ==> name
DbName SQL 서버 테이블(뷰)의 컬럼 이름
SQL 서버 테이블(뷰)의 컬럼 이름과 엔터티의 속성 이름은 다를 수 있습니다.
<#C DbName C#> ==> Name
(테이블의 컬럼과 엔터티의 속성 이름이 동일)
Type 엔터티 속성의 C# 형식 <#C Type C#> ==> string
DbType SQL 서버 테이블(뷰) 컬럼의 형식 <#C DbType C#> ==> nvarchar(50)
BeginCommentIfReadOnly 읽기 전용 컬럼인 경우 "/*"를 반환 <#C BeginCommentIfReadOnly C#> ==>
(Contact.Name은 읽기 전용 컬럼이 아니기 때문에 아무 것도 생성되지 않음)
EndCommentIfReadOnly 읽기 전용 컬럼인 경우 "*/"를 반환 <#C EndCommentIfReadOnly C#> ==>
(Contact.Name은 읽기 전용 컬럼이 아니기 때문에 아무 것도 생성되지 않음)

 

10. variable = "<#V ", {character}, " V#>";

variable 요소는 런타임에 사용자가 입력한 값으로 치환되는 매크로 입니다.

즉 위의 모든 요소는 DBML 파일에 정의된 엔터티에 의해 치환이 되는 반면에, variable 요소는 사용자가 지정한 값에 의해 치환이 됩니다.

따라서 variable요소에는 미리 정해진 매크로가 없습니다.

사용자가 런타임에 입력하여야 할 변수의 이름은 패키지 마다 상이한데, 이는 패키지 정의 파일(pds)의 <Variable> 요소에 정의되게 됩니다.

 

예를 들어 기본 패키지인 Default의 경우 패키지 정의 파일에는 아래와 같은 코드가 있습니다.

<Variable>
  <Name>Namespace</Name>
  <Value>Memopad.Biz</Value>
  <Description>생성될 코드의 네임스페이스</Description>
</Variable>
<Variable>
  <Name>ConnectionString</Name>
  <Value>ConfigurationManager.ConnectionStrings[0].ConnectionString</Value>
  <Description>연결 문자열</Description>
</Variable>
<Variable>
  <Name>CollectionType</Name>
  <Value>List</Value>
  <Description>Get이 반환할 제네릭 컬렉션 형식. Add(T item) 메서드를 가지고 있어야 함.</Description>
</Variable>

이는 UI 상으로는 아래 그림과 같이 표시됩니다.

빨간 줄은 사용자가 입력하여야 할 변수의 이름이고, 파란 줄은 실제 입력하는 값입니다.

위 그림과 같이 Namespace 라는 변수에 Memopad.Biz 라는 값을 입력하였다면,

템플릿에서 <#V Namespace V#> 라는 매크로는 Memopad.Biz로 치환되는 것입니다.

 

10. comment = "<#- ", {character}, " -#>";

comment 요소는 코드의 생성과는 상관 없이 템플릿에 주석을 달기 위해 사용하는 요소입니다.

반복하지만 comment 요소는 코드로 치환되지 않습니다. 단지 템플릿 내의 주석을 달기 위한 용도로만 사용됩니다.

 

11. character = [a-z] | [A-Z] | [0-9] | white space ;

MPML의 정의에 의하면 character 요소는 '영어 대소문자, 숫자, 화이트 스페이스의 0번 이상 반복' 으로 정의되어 있긴 하지만, 그냥 일반적인 문자열로 생각하셔도 무방합니다.

EBNF의 규칙에 의하면 누구나 알 수 있을 만큼 명백한 요소에 대해서는 정의를 생략할 수 있습니다. MPML의 정의에 있어서도 white space 라는 요소는 생략되어 있습니다.

: