C# 7.0의 새로운 기능

이번 .NET Core 출시 이례로 C# ~6.0 기반의 모든 것들을 이제 .NET Core에 집중할 예정이라고 한다.
그리고, Roslyn 컴파일러 덕분에 C# 6.0 문법이 C# 5.0 인 닷넷 환경에서도 지원할 수 있도록 어셈블리를 제공하고 있으니,
아마 구버전 문법 환경에서도 사용할 수 있도록 지원되지 않을까 예측을 할려다 말았다. 굳이…

자, 본문으로 들어가서, 차기 닷넷코어에 탑재될 C# 7.0 언어의 새로운 기능을 Araboza.

Tuple

자바에서 걍 값만 쳐넣는 클래스를 POJO라고 한다. 그리고 닷넷에서는 POCO라고 한다.
대충 이런 식이다.

class PropertyBag
{
    public int Id {get; set;}
    public string Name {get; set;}
}
var myObj = new PropertyBag { Id = 1, Name = "test};

C# 3.0부터 지원해서 여러분들도 자주 써왔을 것이다.
닷넷에서는 이런 놈들을 지칭하는 용어가 튜플이다.

out 인자

잘 쓰지는 않지만 out 인자를 통해 메소드에서 여러 인자를 받아낼 수 있다.

public void GetLatLng(string address, out double lat, out double lng) { ... }

double lat, lng;
GetLatLng(myValues, out lat, out lng);
Console.WriteLine($"Lat: {lat}, Long: {lng}"); 

하지만 가장 큰 문제점이 있다면 바로 async 메소드에 쓸 수가 없다는 것.
그리고 코딩하기 참 불편하다. 패턴 참 개같아 보인다.

Tuple<> 클래스

C# 3.0부터 Tuple 이라는 클래스가 생겼는데, POCO 만들기 귀찮을 때 유용하기도 하다.

public Tuple<int, int> GetLatLng(string address) { ... }

var latLng = GetLatLng("some address");
Console.WriteLine($"Lat: {latLng.Item1}, Long: {latLng.Item2}");

근데… 알다시피 프로퍼티 이름 참… 맘대로 못짓는다. 어쩔 수 없다. 제공 클래스의 한계니까.

POCO

가장 많이 쓰는 패턴이다. Value Object 답게 읽거나 쓸 수 있다.

struct LatLng{ public double Lat; public double Lng;}
public LatLng GetLatLng(string address) { ... }

var ll= GetLatLng("some address");
Console.WriteLine($"Lat: {ll.Lat}, Long: {ll.Lng}"); 

근데 코딩 길이 참 길다. 원래 그렇지 뭐.

Tuple 반환 타입

자, 이제 C# 7.0의 튜플 형식에 주목해보자.
먼저, 2개 이상의 원하는 이름으로 반환 타입을 만들 수 있다.

public (string FirstName, string LastName) GetNames(string! fullName) //형식 뒤에 느낌표가 뭔지는 다음에 설명.
{
  string[] names = fullName.Split(" ", 2);
  return (names[0], names[1]);
}

var name = GetNames("john doe"); 
Console.WriteLine($"Name: {name.FirstName} {name.LastName}");

자, 이렇게 하면 out 변수와 같은 효과를 내면서, 심지어 async 메소드에 대응이 가능하다고 한다. 오예.
원리야 Tuple에 네 변수를 대입하는 방식이니 편하게 써주자.

당연히 인라인도 가능하다.

var ll = new (double lat, double lng) { lat = 0, lng = 0 };

이렇게 하면 li 변수에 당신이 정한 tuple 멤버를 속성으로 사용하여 다룰 수 있다.

레코드 형식

별 거 없다. POCO 클래스 작성하기 간결해지는 효과가 있다. 예를 들면,

class MyPoint
{
    int _x;
    int _y;
    int _z;
    MyPoint(int x, int y, int z){
        this._x = x;
        this._y = y;
        this._z = z;
    }
    public int X {get{ return this._x;}}
    public int Y {get{ return this._y;}}
    public int Z {get{ return this._z;}}
}

C# 7.0부터 아래처럼 짜면 위와 비슷한 클래스가 만들어진다.

class Point(int X, int Y, int Z);

이 때, 알아야 할 점이 있다.

  • 레코드 형식도 상속 “된다”.
  • 레코드 형식은 IEquatable<> 인터페이스에 상속된다. 이 덕분에 같거나 틀린 연산자로 비교 시 레퍼런스 비교가 아닌 멤버 값 비교를 통해 비교가 가능하다.
  • ToString() 메소드는 자동으로 오버라이드 되어 레코드 각 멤버와 값을 나열하게 된다.

패턴 매칭

C# 7.0부터 나온 재밌는 기능이다. 이 기능 때문에 switch 문이 재밌어질 것이다.
먼저 예제를 보자.

class Geometry();
class Triangle(int Width, int Height, int Base) : Geometry;
class Rectangle(int Width, int Height) : Geometry;
class Square(int width) : Geometry;

Geometry g = new Square(5);
switch (g)
{
    case Triangle(int Width, int Height, int Base):
        WriteLine($"{Width} {Height} {Base}");
        break;
    case Rectangle(int Width, int Height):
        WriteLine($"{Width} {Height}");
        break;
    case Square(int Width):
        WriteLine($"{Width}");
        break;
    default:
        WriteLine("<other>");
        break;
}

간단히 얘기하자면, 첫번째로 얘기한 튜플 형식의 산출물인 셈인데,
switch 문을 통해 각 상속 된 클래스와 멤버가 맞는지 비교하여 해당될 때 문을 실행할 수 있다.
예를 들면, 사용자가 있고, 사용자가 개인 사용자, 단체 사용자가 있다고 할 때,
switch 문으로 개인 사용자와 단체 사용자에 따라 다른 형식으로 문을 작성한다고 보면 될 것이다.

Non-nullable 참조 형식

참조 형식은 class로 시작하는 것들이다. 자바야 내장 값 형식 말고 죄다 참조이니 뭐.
어쨌든, 참조 형식은 기본적으로 null 이 가능하다. 이제 불가능하도록 설정할 수 있다.
이런 형식을 제안한 사람이 있는데 이 링크로 들어가면 성지순례할 수 있다.무려 5년 전에 제안한 기능이다.

값(struct) 형식은 기본적으로 null 을 가질 수 없다. 반드시 기본값을 가지게 되어 있다.
하지만 Nullable<> 형식이 생겨 값 형식 뒤에 ? 만 붙이면 null을 가질 수 있다.

int a = 1; // 일반 값 형식
int? b = null; //null을 가질 수 잇는 값 형식

이 문법 덕에 DB나 타언어 연동 시 유연하게 대응이 가능할 것이다.
여기서 주의할 점은 null을 가질 수 있을 뿐 절대 참조 형식이 아니라는 점.

자, 이번엔 참조 형식이다. 참조 형식 중 대표적인 string 형식이 있는데,
non-null 처리 하려면 별도의 처리를 해야 한다. 하지만 이제 아래처럼 하면 된다.

string a = null;
string! b = null;

형식 뒤에 느낌표(!)를 붙이면 null이 불가능한 참조 변수를 만들 수 있다.
목적은 컴파일 타임에서 null이 불가능한 참조 변수를 만드는 데 목적이 있기 때문에
위처럼 코딩하면 컴파일 오류가 난다. 당연히 null 이 아닌 값이나 초기화를 해 줘야 한다.
string 뿐만 아니라 당신이 사용하는 클래스에도 당연히 적용 가능하다.

제네릭도 적용 가능하다.

//이렇게 하면 Dictionary 형식만 non-nullable.
Dictionary<string, List<MyClass>>! myDict;

//이런 식으로 원하는 형식 뒤에 non-nullable 참조를 정의할 수 있다.
Dictionary<string!, List<MyClass!>!>! myDict;

//제네릭과 제네렉 하위 모든 형식에 non-nullable 참조를 원할 경우 형식과 제네릭 사이에 ! 붙이면 된다.
Dictionary!<string, List<MyClass>> myDict;

지역 함수

클래스 멤버인 메소드와는 달리 블록 내에 잠깐 처리하고자 할 경우 사용하는 방법이 나같은 경우 람다식이다. 그렇게 가능하다.
하지만 이런 형식도 한계가 있는데,

  • 제네릭 사용 불가
  • refout 사용 불가능
  • 가변 인자 사용 불가

이를 간결하게 대비할 수 있는 지역 함수 기능을 제공한다.
람다식에서 못한 한계를 여기서 해결할 수 있다.

public int Calculate(int someInput)
{
    int Factorial(int i)
    {
        if (i <= 1)
            return 1;
        return i * Factorial(i - 1);
    }
    var input = someInput + ... // Other calcs

    return Factorial(input);
}

Factorial 이란 함수는 Calculate 메소드 문 내에서만 사용할 수 있다는 특징이 있다.
그 외에는 메소드처럼 정의하고 사용하면 된다.

불멸 형식(Immutable Types)

C#이나 자바나 대표적인 불멸 형식은 string 이다.
불멸 형식은 아래와 같은 장점이 있다.

  • 스레드로부터 안전하다.
  • 코드의 목적이 명확하다.
  • 병렬 처리가 쉽다.
  • 참조가 캐쉬되지 않으며 바뀌지도 않는다.

자, 사용법을 알아보자.
일반적인 POCO 클래스이다.

public class Point
{
    public Point(int x, int y)
    {
        x = x;
        Y = y;
    }

    public int X { get; }
    public int Y { get; }
}

초기화 시 좌표값을 받고 써먹는 클래스이다.
하지만 누군가 setter 넣고 중간에 값을 바꿔치기 하면 원치 않는 결과가 나올 텐데,
class 앞에 immutable 키워드만 넣으면 만사 OK.

public immutable class Point
{
    public Point(int x, int y)
    {
        x = x;
        Y = y;
    }

    public int X { get; }
    public int Y { get; }
}

이렇게 하면, string 처럼 중간에 값이 변조될 가능성이 없어지기 때문에, 인스턴스를 사용하는 동안 참조를 보장받을 수 있다.
즉, 메소드가 중간에 변조할 수 없다는 뜻이다. 처음부터 끝까지 초기화한 형식 그대로 갖다 쓸 수 있다는 것.
게다가 이런 형식에 대비해 유용한 문법이 생겼는데, 기존 인스턴스로부터 값을 바꿔 새 인스턴스로 만들 수 있는 문법이 생겼다.

var a = new Point(2, 5);
var b = a with {X = 1}; // {X = 1, Y = 5}

존나좋군.

언제 이런 문법으로 코딩 가능?

.NET 로드맵에 의하면, 올해 가을에 1.1이 나오는데, 안타깝게도 아직은 이 스펙을 못쓴다. 하지만 아직 이게 다가 아니라고 한다.
이 스펙을 사용할 수 있는 시기가 MSDN에 의하면, 차기 비주얼 스튜디오부터 이 스펙을 사용 가능하다고 알려져 있다. 문제는 비주얼 스튜디오가 언제 나올 지 모른다. 내년에 나오겠지 뭐.
Github Roslyn work list of features 에 소개된 기능 외에 고려하고 있는 기능을 볼 수 있으며, 심지어 참여도 가능하니,
관심이 있으면 주저 말고 영어로 의견을 내놓으면 된다.

근데… 자바는 아직도 1.x인데 2.x 버전이 지구 멸망하기 전까지 나올런지 모르겠다.
여담으로, WCF는 닷넷 코어에 채용이 됐지만, WPF는 계획이 없다고 한다. 그걸 기다리느니 차라리 Electron에 닷넷 붙이는 게 크로스 플랫폼에 효율적일 듯 하다. 아님 자마린으로 모바일 개발 하던가.

참고자료

미안. 죄다 영어다. 한글 자료는 아무리 찾아봐도 없더라. 이 글을 쓴 이유이기도 하다.

C# 7: New Features
New features in C# 7, part 2
Essential .NET – Designing C# 7

composite / 2016년 7월 19일 / Piss Development / 1 Comment

.NET Core RC2 to RTM 마이그레이션

존나 쉽다. 걍 날 따라해라. 공통사항이다.

project.json 파일 아래 부분 수정

{ //...
    "Microsoft.NETCore.App": "1.0.0"
}

위 부분을 아래처럼 수정.

{ //...
    "Microsoft.NETCore.App": {
        "version": "1.0.0",
        "type": "platform"
    },
}

(만약 위처럼 안써있는 사용자 한정.)

그리고 다시 project.json 에서 모든 패키지 버전을 1.0.0-rc2-final 에서 1.0.0 로 수정.
대상: Microsoft.AspNetCore.*Microsoft.Extensions.* 여튼 저런 식으로 써있는 패키지 다.

비주얼 스튜디오 2015 사용자라면 닥치고 아래 절차에 따르면 된다.

  • Update 3 로 업데이트.
  • Tools Preview 2 설치. (뻘짓만 안하면 이전버전 언인스톨 안해도 됨)
  • .NET Core RC2 프로젝트 연다.
  • 프로젝트 컨텍스트 메뉴에서 Nuget 패키지 관리… 클릭.
  • 업데이트 탭 클릭.
  • 닥치고 모두 체크하고 업데이트 버튼 클릭.
  • 안심하고 화장실 갔다와.

끗. 이제 dotnet run 치고 ENTER 치면 언제 한듯 안한듯 깔끔하게 앱이 실행될 것이다.

composite / 2016년 6월 28일 / Piss Development / 0 Comments

.NET Core RC2 Tools preview 1 Offline Installer

전에 비주얼 스튜디오 도구를 RC1에서 R2로 올리는 삽질기를 올렸었다.
그리고 RC2는 치사하게 오프라인 설치 파일을 제공하지 않는 것도 알려줬었다.

하지만 오프라인 설치하도록 하는 방법은 있다. 다행히도.
출처는 여기니 영어 좀 알면 정확한 사용법을 익히도록 한다.
아님 걍 날 따라해.

준비물

일반 사용자(또는 귀차니어)
* 비주얼 스튜디오 업데이트 2 (Express 제외한 모든 에디션)
* DotNetCore.1.0.0.RC2-VS2015Tools.Preview1.exe

고급 사용자
* 7집이나 반디집 등 CAB 파일 보거나 풀 수 있는 압축 프로그램 아무거나.

일반 사용자

  1. 받으라는 준비물을 받았으면 적당한 폴더에 옮긴다. 아님 말고.
  2. 설치 파일이 있는 폴더에 packages 폴더를 만든다.
  3. 설치 파일 목록이 든 텍스트 파일을 받아 packages 폴더에 놓는다.
  4. 목록을 urls.txt 등 편한 파일로 저장한다.
  5. packages 폴더에 powershell Get-Content urls.txt | ForEach-Object {Invoke-WebRequest $_ -OutFile $(Split-Path $_ -Leaf)} 스크립트 실행.
  6. 다 받았으면 압축하여 배포하던 공유하던 니맘대로 한다. 참고로 전체 크기는 거의 500MB에 육박한다.

고급 사용자

일반 사용자 2번까지 한 다음 아래 절차를 따른다.

  1. 압축 프로그램으로 설치 파일을 연다.
  2. 0이라는 파일이 있는데 실제 다운로드 설치파일 목록이 있는 XML 파일이다. 그걸 연다.
  3. 아무 에디터 열고 “찾기” 한 다음 정규식 체크하고 DownloadUrl="(.*?)" 입력한다. (Subline Text나 Atom 추천)
  4. 모두 선택 후 거기 나온 모든 URL을 추출한다. (선택하지 말고 다 받아야 한다. 한개라도 빠지면 온라인으로 받으려 나댈 것이다.)
  5. URL 목록을 만들었으면 일반 사용자 4번부터 따르면 된다.

이렇게 하고 압축하여 인터넷이 막힌 환경에서도 ASP.NET Core RC2 개발환경을 설치할 수는 있다.
근데… 문제는 ASP.NET Core 개발하려면 아직 인터넷 없이는 힘들긴 하지만,
나처럼 설치 더럽게 안되는 환경에서는 더없이 좋은 환경이 될 것이다.

아, 사족으로 나는 이것도 실패에서 결국 Github Issue 올렸다. 시발.

2016-06-24 업데이트:
Issue 원인은 DRM으로 인한 리소스 접근 실패. 문서보안이 화근이었다.
결국 포기. 다른컴 테스트해보니 존나게 잘 깔림. 시발 안해.

composite / 2016년 6월 23일 / Piss Development / 0 Comments

또다른 오픈소스 IDE: Consulo IDE

흐음… 한국에 자바 IDE 쌍벽은 아무래도 Eclipse 와 IntelliJ 일 것이다.
Netbeans 도 있긴 하지만 쓰는 사람이 드물어서…

어쨌든 간에, JetBrains 에서 .NET IDE 만든다고 한 지 2주.
근데 댓글에서 심상치 않은 IDE를 발견했다.

이름하여 Consulo IDE 이다.

Consulo는 IntelliJ IDEA Community Edition의 쉘 전신인 IDEA IDE 베이스로 만들어진 오픈소스 IDE이다.
현재 안드 공식 개발 툴인 IntelliJ IDEA 기반의 쉘 UI 프레임워크가 오픈했다라…
엉? IntelliJ에 썼던 UI가 오픈소스라고?

정말 있다. 오픈소스로. IntelliJ Community Edition

그렇다. 커뮤니티 에디션에 한해서 오픈소스로 공개하긴 했다.
게다가 Apache 2.0 라이선스다. 상업적으로 써도 문제는 물론 없다.
아니었으면 상업적으로 안드로이드 개발은 물건너 갔을테니.

어쨌든, 다시 Consulo로 돌아가자.

Consulo는 현재 C#, Javascript, Java 등을 지원하며, 모든 언어를 지원하는 하나의 IDE로 통일하겠다는 목표를 가지고 있다.
안타깝게도 안정된 버전이 아니라서 실무에 쓰기는 조금 어렵지만,
유니티 개발자들이 이 IDE를 주목하고 있다.
왜냐?
모노IDE가 좆같거든.

인텔리 기반이라 인텔리 플러그인을 지원 하기는 한다. 조금 손을 봐줘야 한다고 한다.
마이그레이션 과정을 거치는데, 아무래도 라이선스 이슈 때문이다.
불편하더라도 인텔리제이와는 분리해야 써야 하는 이유이기도 하다.

Add a plugin

JetBrains 에서 Project Rider 로 C# IDE를 꾀하고 있고.
아마 유니티 개발에서 하나의 변수로 떠오를 가능성이 큰 상황이다.
어자피 모노와 닷넷은 API가 틀리지 언어 구조와 스펙까지 틀린 건 아니니
지켜봐야 할 내용이고,

거기에 오픈소스로 강공을 펼칠 Consulo IDE에도 주목할 필요가 있다.

IDE 전쟁이 시작되는 것이다. 우오.

composite / 2016년 1월 28일 / Piss Development / 0 Comments

JetBrains 가 이젠 닷넷 IDE도 만든다!

어젯밤에 잠시 사색에 빠졌다.

ASP.NET 5가 이제 크로스 플랫폼일 테고…
핵심 코어인 .NET Core가 크로스 플랫폼이라면…
분명 JetBrains 에서는 이를 놓치지 않을 것이다…

그리고 다음날 내 예언(?)을 페북에 올리려 했는데…

http://i.imgur.com/6LABroy

http://i.imgur.com/3w4S7zG

그렇다. 진짜 JetBrain이 단단히 미쳤다.
그렇다면 블로그 원문 링크로 가도록 하겠다.

프로젝트 명은 Rider 이고 아직 정확한 제품명은 없다.

일단 특이한 점은 C#만 지원한다. VB나 F는 언급이 없었다. 근데 만들런지도 불투명 하니 신경 끄자.

Rider Search Everywhere popup

Rider editing

Rider new project templates

뭐… IDEA 제품 패턴이 어디 가겠는가? C# 에 Resharper 기능이 가미된 C# IDE라고 보면 된다고 한다.
게다가 크로스 플랫폼 지원한다니 말 다했지. 맥과 리눅스에도 돌아가는 IDE라면 매료될 것이다.

EAP(Early Access Program) 에 제한적 신청을 내주 오픈한다고 한다. 만약 실시간으로 받고 싶으면 @JetBrainsRider 트위터를 팔로우하면 된다.
라이선스야 뭐 IntelliJ 공통일 테고 Jetbrains Toolbox 에 포함된다고 한다. 이제 가격만 공개되면 된다.

그럼… 나는 이만.

composite / 2016년 1월 14일 / Piss Development / 0 Comments

Javascript 파이프라인

어찌보면 나도 간과한 일일 수도 있다.
Javascript 로 열심히 삽질하다 보면 역시 콜백 늪에 안빠져본 자스 개발자는 없을 것이다.
이런 콜백 지옥을 빠져나가기 위해 여러 패턴이 도입되었고, 그 중 대표적인 게 Promise 패턴, Generator, 그리고 async/await 이다.

마침 Play.node() 라는 컨퍼런스가 이미 진행했었고, 공개된 발표자료 중 바로 한눈에 들어온 세션이 있었는데,
그게 바로 Session 3. Pipe: 콜백지옥의 또 다른 거짓 선지자 였다.

그리고 콜백 지옥을 빠져나갈 수 있다는 여러 선지자들, 그리고 세션 발표자가 이를 개선하기 위해 만든 또다른 선지자를 소개하는 시간이었다.
필자는 여기에 참여하지 못해 이 세션의 처음과 끝이 어땠는지는 잘 모르겠지만, 자스 개발자들은 뭔가 너무 차별화된 형식으로 접근하려는 시각이 눈에 띄었다.

그렇다. 너무 차별화되어 다르게 보일 수 있지만 결국 똑같은 패턴.

그게 바로 작업 흐름 관리이다. 영어로 Task flow management.
이를 관리하기 위해 보통 제공되어 사용하는 패턴이 바로 Pipeline pattern 이다.
작업 단위 간 통신을 위해 꼬리를 물고 무는 패턴.

자바스크립트는 싱글 쓰레드다. 그렇기 때문에 얻을 수 있는 이점이 있지만 이를 위해 잃은 많은 것들이 있다.
얻을 수 있는 이점이 바로 비동기 이다. 자스는 비동기에 능하다. 어떤 작업 흐름을 미꾸라지처럼 빠져 나가는 재주를 지녔다.

다른 언어에서도 이런 미꾸라지같이 작업 흐름을 마칠 수 있는 이점을 수용하려 하고 있었고, 이렇게 생겨난 것이
자바의 Future<T> 와 닷넷의 Task<T> 이다. 그리고 닷넷 4.5 에는 asyncawait 문법으로 비동기 작업 흐름 관리에 종지부를 찍을 것 같았다.
자스에서도 이런 종지부를 받아들여 ES7에 들어올 예정이긴 하지만… 언제 들어올지는 아직 모른다. 그렇기에 기대에 부응하지 못하고 오늘도 자스는 작업 흐름을 관리하고 있다.

동시성과 비동시성을 합쳐서 여러 케이스로 작업 흐름을 관리하는 업무는 의외로 많다.
하지만 많은 개발자들은 이를 동기적으로 처리하려고 한다. 왜냐, 그게 편하고 순서있고 보기도 편하기 때문에.

하지만 위 소개된 세션을 통해 이런 자스의 고충을 이해할 수밖에 없는 이유가 있다. 아니. 이해해야 할 수밖에 없다.
바로 자스는 아까 말했듯 싱글 스레드이다. 아까 말했듯이 자스는 어찌보면 너무 많은 것을 잃은 것만 같다.
쓰레드를 여러 개 사용할 수 있는 자바나 닷넷 등이 아니다 보니 쓰레드 단위로 Pipeline 을 갖는다는 것은 매우 어려운 일이다.
그래서 위 세션처럼 비동기 방식의 장점을 살려 바로 이벤트를 통해 작업 흐름을 관리하는 파이프라인을 구현한 것이다.
여기서 가장 핵심 공통점은 바로 작업 간 데이터를 주고받아야 한다. 그리고 이 때문에 구현한 것이다.
자스는 작업 흐름 관리를 위해 콜백 간에 데이터를 주고받아야 하는 일이 많다. 그렇다 보니 전통적인 방법으로는 콜백 지옥이 발생하는 것이다.

그렇다. 자스도 결국 파이프라인 패턴 써야 한다. 작업끼리 물고 물고 늘어진다. 이건 어느 언어나 업무 흐름에 피할 수 없는 숙명인 것이다.
자스는 작업을 관리하는 방식이 다를 뿐, 결국 작업은 파이프라인인 것이다. 어쩌면 동시에 해야 할 수 있고, 그리고 동시에 모두 끝나야 대기탔던 작업 해야 하고.

WE ARE THE HELLO WORLD.

참고자료

Play.node() 발표자료 http://d2.naver.com/news/2602887
자바 : 파이프 스트림과 쓰레드간 데이터 교환 http://javacan.tistory.com/entry/72
닷넷 : C# 쓰레드 이야기: 11. 이벤트(Event) http://www.hanbit.co.kr/network/view.html?bi_id=360

콜백지옥의 또 다른 거짓 선지자 관련 또다른 참고자료

Node.js Flow (part 1) – Callback Hell vs. Async vs. Highland http://blog.vullum.io/javascript-flow-callback-hell-vs-async-vs-highland/
Node.js Flow (part 2) – Fibers and Generators http://blog.vullum.io/nodejs-javascript-flow-fibers-generators/
yortus/asyncawait – Callback heaven for Node.js with async/await https://github.com/yortus/asyncawait

composite / 2016년 1월 6일 / Piss Development / 0 Comments

[C#] Assembly Attribute

자바 어노테이션에 없는 아주 강력한 기능이 있는데, 닷넷에 있는 어셈블리 단위 특성 기능이다.
닷넷 개발자가 어셈블리 특성을 자주 만지는 경우가 바로 프로그램 정보에 쓰이는 아래 코드다.

[assembly: AssemblyTitle("HelloWorldProgram")]
[assembly: AssemblyDescription("The Hello World Program")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("My company")]
//...

사실 이들 특성은 프로젝트/Properties/AssemplyInfo.cs 에 있는데, 프로젝트 속성으로 손쉽게 수정할 수 있다.
나도 사실 아무렇지도 않게 봤지만, 이제서야 이녀석의 진면모를 알게 되었다.
어셈블리 단위의 특성이 왜 위력적인지 예제를 통해 알아본다.

어셈블리 단위 특성은 아래와 같은 용도로 사용할 수 있다.

  • 프로그램의 플러그인
  • 프레임워크 확장

그렇다. 주로 확장 편의성에 유용한 기능이다.

그렇다면 나만의 커스텀 어셈블리 특성을 만들고 적용할 수 있을까?
당연하다.

2개의 프로젝트를 만들어보자. 하나는 콘솔 응용 프로그램, 하나는 클래스 라이브러리.

먼저 응용 프로그램에 특성을 정의해 보자.

[AttributeUsage(AttributeTargets.Assembly)]
public class MyCustomAttribute : Attribute {
    public MyCustomAttribute() : this(string.Empty) {}
    public MyCustomAttribute(string txt) { Mytext = txt; }
    public string Mytext { get; private set; }
}

그다음 클래스 라이브러리에 아무 CS 파일에 넣어 클래스 및 네임스페이스 바깥 아무 곳에나 아래 특성을 추가한다.
물론 그 클래스 라이브러리는 응용 프로그램 프로젝트를 참조해야 겠지.

[assembly: MyCustom("Hello World!")]

어셈블리 단위 특성이기 때문에 아무 곳에나 특성을 추가할 수 있으나, 반드시 앞에 assembly: 넣어야 에셈블리 특성이 적용된다.

다시 응용 프로그램으로 돌아가서, 타 라이브러리에 접근하여 특성에 접근해 보자.

public static void Main(string[] args)
{
    Assembly asembly = Assembly.LoadFrom("어셈블리경로");
    var attributes = assembly
    .GetCustomAttributes(typeof(MyCustomAttribute), false)
    .Cast<MyCustomAttribute>().select(my => {
        Console.WriteLine("타 어셈블리 특성 : {0}", my.Mytext);
        return my;
    });
}

끗. 별거없다. 테스트는 안해봤다. 조만간 테스트 후 업데이트 하겠다.
예제만 별거 아닌것처럼 보이지만, 플러그인 베이스 개발에는 이만한 메타데이터 저장소가 없다.
많이 쓸 일은 없다. 그건 현실이다. 하지만 아는만큼 힘이 될 것이다. 특히 확장성에.

진짜 끗.

composite / 2015년 11월 24일 / Piss Development / 0 Comments

ASP.NET 5 RC1 요약

Visual Studio 2015 (Update 1) 개선점

설치 방법 (공통, 윈도우 기준)

새 프로젝트로 ASP.NET 프로젝트를 선택하고 만들면, 아래 그림과 같이 Get ASP.NET 5 RC가 생긴다.

Before

클릭하면 설치된다고 한다.

(역자 주 : 댓글 보고에 따르면, 0x80091007 - The hash value is incorrect 이런 식의 메시지로 만약 설치가 안되는 사용자가 있다고 한다. 이 경우, 베타 버전의 DNVM 및 Visual Studio Tools 를 모두 제거한 다음 최신 ASP.NET 5 설치 방법 페이지에 가서 Download 라고 써있는 필요한 것들을 다시 받거나 Command line 방법으로 다시 설치하면 된다.)

설치 후, ASP.NET 5 Template에 3가지 템플릿이 뜨면 성공이다.

After

맥과 리눅스는 Command line tool로 설치하면 되며, 설치가 안될 경우 또한 지우고 다시 설치하면 된다.

Bootstrap Snippet

Visual Studio도 이제 IntelliJ IDEA 처럼 확장 추천 기능이 생긴 모양이다. 페이지를 만들어 bootstrap을 쓰게 된다면
아래 화면처럼 추천 확장하는 노란 탭이 뜨면서 클릭하면, Bootstrap snippets 확장을 설치할 수 있다.

Extenstion

그럼 도구 상자에 Bootstrap 도구가 생길 것이다.

Tools

New Bower Package Manager UI

여태까지는 제이쿼리 같은 자바스크립트 프레임웤 등을 Nuget으로 설치할 수 있었다. 근데 관리가 너무 비효율적이라 원성도 잦았다. 흐음.. 아무래도 자바진영의 WebJar도 좀 그럴텐데…
어쨌든, ASP.NET 5 프로젝트에서 아예 프론트엔드 패키지 관리를 Bower로 사용하기 시작했다.

Bower

오른쪽 마우스 클릭으로 백엔드는 기존처럼 Nuget, 프론트엔드를 Bower로 패키지 관리를 할 수 있게 된다.
크로스 플랫폼 및 다환경간 접근 차원에서는 괜찮은 정책이다.

UI

그것도 모자라 Visual Studio 에서는 프론트엔드 패키지에 대해서 이제는 Nuget으로 설치했다면 Bower로 설치하라고 안내까지 뜬다.

nuget

MVC 스캐폴딩

이제 ASP.NET 5 에서도 ASP.NET MVC 5 처럼 스캐폴딩 항목 추가 기능이 생겼다.

Scaffold

근데 필자는 ASP.NET MVC보다는 NancyFX를 더 많이 써온 터라 이 부분에 대해서는 지식이 부족한 점 양해 바란다.
이 기능으로 컨트롤러와 뷰 또는 API 컨트롤러를 한번에 생성 가능하다는 이점이 있다고 한다.

솔루션 탐색기 정리작업

Explorer

이제 project.json 같은 고급 설정 파일을 가렸다. 솔루션 탐색기에서 안보일 뿐 실제로는 당연히 존재한다. 프로젝트 관리를 용이하게 하기 위해서인 듯 하다.
그리고 hosting.ini 파일 대신 hosting.json 으로 교체했다. 내용은 hosting.ini와 비슷하며, 없어도 돌아가는데 지장 없다. 이 경우 자체 웹 서버 가동 시 포트는 5000번이 할당될 것이다.

프레임워크 및 런타임 개선사항

Static Void Main

콘솔 프로그램 실행하는 메인 메소드를 아래와 같이 바꿨다.

public static void Main(string[] args) => WebApplication.Run(args);

C# 6.0 문법으로. 대부분 할 게 없으니까. 물론 내용이 좀 들어가야 한다면 그땐 종전 방식대로 사용하면 되지만.

Cross-platform SQL Client

이제 MSSQL 클라이언트 라이브러리를 크로스 플랫폼으로 밟고 있다.
아직 여러 건의 레코드셋 기능을 지원하지 않는다는 단점이 있지만, 이는 곧 해결될 것이라고 한다.
이제 윈도우를 비롯해 맥과 리눅스까지 LocalDB가 지원된다는 것이다.

SQLClient

아직 베타이지만, 아래 연결 문자열을 등록하면 된다.

"ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=aspnet5-MyCoolWebsite;Trusted_Connection=True;MultipleActiveResultSets=false"

몇몇 플랫폼에서 System.Net.Security 패키지가 정상적으로 설치되지 않는 문제점이 있을 수 있다고 한다. 이 경우 명시적으로 System.Net.Security 패키지를 추가하면 해결은 가능하다.

Default webroot folder

베타 버전까지는 project.json 에서 명시적으로 webroot 폴더를 지정했고, 없으면 더이상 돌아갈 이유가 없었다.
하지만, 이제부터 굳이 지정을 안해도 기본값으로 프로젝트 내 webroot 폴더를 가리키도록 하였으며, 이 폴더 조차 없을 경우 프로젝트 폴더를 가리키되, 정적 파일로 제공하는 방식으로 바뀌었다.

Strong Named Framework Libraries

윈도우는 파일명에 대소문자 구분을 안하지만, 유닉스 기반은 대부분 파일명 등에 대소문자를 구분한다. 그래서 닷넷 환경에서 크로스 플랫폼을 위해서 대소문자를 구분할 수 있는 강력한 이름 정책이 당연히 필요했고, 이를 적용했다. 패키지 명도 당연히. 윈도우 GAC 내 어셈블리도 모조리 대소문자 구분하도록 강력한 이름으로 지정하도록 하며, 만약 커스텀 GAC이 있다면 강력한 이름으로 적용해야 한다.

새로운 .NET 플랫폼 표준 소개

새로운 크로스 플랫폼 닷넷 환경이 ASP.NET 5만 맞춰져 섭섭해 보였던 개발자들도 있을 것이다. 하지만 이미 뒤에서 닷넷 개발환경 표준을 만들고 적용하고 있다.
여태까지 닷넷 개발환경은 Visual Studio 기준에서 만들여졌다고 봐도 무방할 정도로 닷넷 개발 환경이 툴에 너무 의존적이었다.
오해입니다. 오해! 닷넷 개발환경 표준을 참고하라.
각 플랫폼 및 닷넷 버전별로 버전을 표시하고 이를 관리하는 표준을 지원하여, Visual Studio 뿐만 아니라 다른 텍스트 에디터나 IDE 등의 개발 환경에서도 닷넷 개발이 편리해지도록 꾀하고 있다.

이 표준은 ASP.NET 5 RTM이 나오면 그 때 확정이 된다고 한다.

현재 ASP.NET 5 프로젝트를 만들면 dotnet5.4 라는 프로파일이 정의되는데, 이는 .NET 4.6, .NET Core 5,Mono 에 호환되는 프로파일이라 보면 된다.

기타 변경사항

Github Issues를 통해 여태까지 바뀌거나 수정, 개선한 사항들을 확인할 수 있다.

(필자는 NancyFX를 써와 Glimplise를 안써와서 이 부분은 따로 다루고 여기서는 다루지 않는다.)

요약정리

이제 RC를 통해 닷넷에 대해 크로스 플랫폼 개발환경을 적용하며, MS에서 지원하는 정식 개발환경으로 거듭고 있다.

  • live.asp.net 에서 커뮤니티 질문과 업데이트 소식 등을 실시간 또는 이전에 방송했던 소식을 받아볼 수 있다. 라즈베리에 닷넷도 돌렸다.
  • get.asp.net 항상 최신을 유지하라. 안되는 환경 붙들어 매는것보단 낫다.
  • docs.asp.net 에서 ASP.NET 문서 작성에 누구나 참여할 수 있다. 당연히 번역도 가능하다. 페북에 어느분이 번역해주신다는데 당연 환영!

이제 거의 완료되었다. 내년 봄까지 긴 시간이 남았다고 하지만 금방 지나갈 것이다. 이제 당신이 더 다양해진 ASP.NET 환경으로 개발할 앱은 무엇이 있을까?

composite / 2015년 11월 19일 / 미분류 / 1 Comment

[C#] 명쾌한 abstract 메소드와 virtual 메소드 차이점

왠지 모르게 다들 어렵게 설명한다.
데브피아만 가도 “abstract는 없으면 인스턴스 생성 안되고 virtual 은 없어도 인스턴스 생성된다…”
한국 종특인 돌려말하기인지 모르겠지만, 초보들에게는 더럽게 이해 안되는 답변이다.
심지어 그런거 모르냐, 책을 읽어라, 알게된다. 이지랄까지 하고 있으니…
선배 개발자들 맞는지 의문 투성이다 정말. 먹고살기 빠듯한 건 아는데 그렇게 가르쳐주기 귀찮았냐 하는 생각이 든다.
내가 후배 개발자를 위해 간단명료하게 설명한다.

자. 네가 얻은 새로운 집에 시멘트만 있는 방 내부를 꾸미게 됐어.
이게 abstract class 다.

벽지는 붙여야지? 안그럼 방이냐? 폐가지.
그리고 장판 깔아야지 안그럼 맨발로 방 못들어가잖아.
그래서 벽지와 장판 붙이는 기능을 가진 메소드를 abstract로 선언한다.

좋아. 벽지는 일단 붙였어. 그럼 벽지에 데코를 붙이는 생각도 했을거야.
예를 들면, 벽에 뭐 매달거나, 야광 스티커를 붙이거나 할거야.
근데 이건 안해도 지장 없잖아.
그래서 벽지 데코를 붙이는 메소드를 virtual로 선언한다.

이해했지?

public abstract class 추상인테리어{
    public abstract 벽지 벽지칠하기();
    public abstract 장판 장판붙이기();
    public virtual 데코레이션 데코붙이기(){
        return null; // 기본 데코 안붙일거다.
    }
}

public sealed class 철수인테리어 : 추상인테리어{
    public override 벽지 벽지칠하기(){
        var 벽지칠 = new 벽지();
        var 벽지색 = 벽지색깔.파란색;
        //벽지 칠하는 프로세스 구현
        return 벽지칠;
    }
    public override 장판 장판붙이기(){
        var 장판깔기 = new 장판(장판.흔한거);
        //장판 까는 프로세스 구현
        return 장판깔기;
    }
}

public class 영희인테리어 : 추상인테리어{
    public override 벽지 벽지칠하기(){
        var 벽지칠 = new 벽지();
        var 벽지색 = 벽지색깔.분홍색;
        벽지칠.패턴 = 벽지패턴.꽃무늬;
        //벽지 칠하는 프로세스 구현
        return 벽지칠;
    }
    public override 장판 장판붙이기(){
        var 장판깔기 = new 장판(장판.예쁜거);
        //장판 까는 프로세스 구현
        return 장판깔기;
    }
    public override 데코레이션 데코붙이기(){
        var 데코 = new 데코레이션();
        데코.종류 = 스티커.야광(색깔.초록색);
        //데코 붙이는 프로세스 구현
        return 데코.다붙였다();
    }
}

존나 흔한 이름으로 클래스 붙였다.
끗.

composite / 2015년 8월 21일 / Piss Development / 1 Comment

자바 개발자들은 왜 비동기를 싫어하는 걸까?

지금 닷넷 하고 있지만 얼마 지나지 않은 자바 개발 시절 얘기다.
나는 자바스크립트의 비동기 패턴에 익숙했다.
그래서 가끔씩 이벤트 패턴을 사용하기도 한다. 웹인데도.
하지만 공통팀 개발자로부터 태클이 들어왔다.
Anonymous Class 사용을 하지 말라는 거다. 유지관리가 어렵다는 이유에서였다.
나는 어이가 없어서 따졌고, 프로그램도 문제없이 돌아가는데 대체 왜냐고 물어봤다.
결국 최종적인 답변은 듣지 못했으나, 한가지 단서를 발견했다.
원래 자바는 익명 클래스를 만들면 해당 클래스에 $숫자 가 추가된 파일을 생성한다.
아마 그가 걸고 넘어지려는게 그 파일이 아닌가 생각했다.
왜냐면 그 달러 파일 안넘기면 당연히 런타임 오류가 나서 프로그램이 동작하지 않으니까.
개발환경에서 멀쩡히 돌아가는게 가운영서버에서 안돌아가는 케이스 되시겠다.
Jenkins 쓰지만 운영 배포는 따로 관리를 통해 수동으로 배포하고 운영한다.
결국 얼마 지나지 않아 나는 익명 클래스 빼고 길고 긴 Procedural style 로 코딩할 수밖에 없었다.
야근했다. 그날. ㅅㅂ.

자바 SI 하면서 정말 힘들었다. 튀는 개발은 받아주지 않는다. 당연하겠지만.
게다가 정부부터 전자정부 강제로 쓰게 만드는데 뭐 그건 좋다 이거야.
하지만 확장성이 부족하고 (어려움) 틀 안에서만 개발해야 한다.
이래놓고서 대량 트랜잭션을 바란다. 미치겠다.
물론 불가능한 건 아니다. 단지 빡셀 뿐이다.

자바는 원체 동기와 비동기 유연하게 돌릴 수 있다. Quartz를 통한 스케줄링을 사용할 수 있다.
특히 웹에서 그 진가를 발휘하지만 역시 GC와 메모리 문제로 따로 돌리는 경우가 대부분이다.
닷넷의 경우 이벤트 지원이 확실하기 때문에 비동기 프로세스를 자바보다 더 간결하게 구성할 수 있다.
그러나 ASP.NET의 경우에도 웹 앱에 스케줄링 걸면 뻑나가기 때문에 따로 빼거나 COM+ 돌린다.
여기서 웹상에서는 자바가 ASP.NET 보다는 스케줄링 작업이 잘 되긴 하지만 둘다 결과적으로 메모리 관리는 쉣이다.
둘 다 웹에서 비동기 스케줄링 걸 수는 있지만 메모리 관리 측면에서는 올바르지 않은 방법이다.
하지만 비동기만 쓴다면 나쁜 선택도 아니다. 사실 관점지향개발(AOP)도 비동기의 한 부류이기 때문이다.
이벤트 돌리니까 말이지. 하지만 그렇게 생각 안하나보다. 게다가 AOP조차도 잘 안쓴다.
비동기 개발에 능한 자바 개발자는 이벤트를 효율적으로 운영하는 방법을 찾는 데에 열중했고,
그 과정에서 발견한 프레임워크가 바로 Akka 이다.

하지만 SI 출신 개발자들은 이런 방식의 코딩을 능멸하는 것 같다.
여전히 많은 개발자는 Procedural style 의 코딩을 즐긴다. 객체지향? 그건 클래스에나 통하는 거고.

당연히 전통적 방식에 익숙한 자바 개발자들이 아는 범위 내에서 문제 없이 코딩해야겠는데 어쩌겠는가.
절차지향이 아무래도 보기에는 좋으니까. 무조건 순서대로 처리하니까 말이다.
게다가 가능하면 절차대로 수행하는 게 프로젝트 면에서 안전빵이라 생각하고 있을 것이다.

하지만 요즘은 달라졌다. 코어 수는 늘어났고, 더 많은 작업을 더 짧은 시간에 해내기를 요구한다.
게다가 코어 수가 늘어난 것도 엄청 오래됐다. 전통적인 싱글 코어에 맞춘 프레임워크는 멀티코어를 자동으로 해결해주지 않는다.
그 어떤 언어라도 마찬가지다. 더 많은 작업을 더 빨리 작업하려면 개발자가 생각하고 잡아주고 코딩해야 한다.
그런 측면에서 Procedural style 코딩은 이에 한계가 있다.
자바와 닷넷이 아무리 멀티코어를 지원한다 해도, Procedural style 코딩은 결국 하나의 쓰레드만 쓰는 꼴이니까.
프레임워크가 알아서 필요하면 쓰레드 잡고 간다고 편안하게 생각한다면 그건 개발자의 자질이 글러먹었다.

그런 측면에서 병렬 처리는 많은 작업을 짧게 해내는 데 유용한 기능을 제공한다.
자바 닷넷 둘 다 제공하거나, 부족할 경우 채워주기도 한다.
하지만 아무리 커다란 프로젝트라도 여전히 이를 만족하는 개발은 없다. 본적도 없고.
공공데이터 시스템 빼고는. (이는 병렬처리 안하면 뻑나가는 구조임)
특히 금융권 개발은 이를 잘 반영 안하고 있다. 대부분 DB 프로시저에 익숙한 탓이기도 하다.
그리고 이를 개선할 생각도 없고 개선하려 해봤자 눈먼 돈만 나가고 결국 실패하고.

이 병렬 처리를 하려면 개발자가 갖춰야 할 기본 자세가 바로 비동기이다.
왜냐면, 병렬 처리는 동시에 이루어지기 때문에,
Procedural style 로는 동시에 누가 먼저, 나중에 시작 후 끝나는지 캐치할 방법이 없기 때문인 데다가,
Procedural style 은 싱글 프로세스이기 때문에 애초부터 접근할 방법이 없다.

비동기의 장점은 꽤 많다. 물론 비동기도 Procedural style 에 비해 단점도 있다.
특히 비동기는 작업 중간중간을 캐치할 수 있다는 크나큰 장점이 있다.
예를 들면, 1분 이상 걸리는 무거운 쿼리를 요청한다고 가정해보자.
Procedural style 로 하려면 이 쿼리를 마냥 기다려야 다음 작업을 진행할 수 있다. 과정보다는 결과가 우선시되는 작업이다.
하지만 비동기로 하면 이 무거운 쿼리가 성능에 어떤 영향을 미치는지, 이에 실패하면 어떨지 등 여러 경우를 캐치할 수 있다.
이는 결과와 과정을 둘 다 캐치해낼 수 있는 작업인 것이다.
그걸 잘 반영한 자바 프레임워크가 바로 Akka 이다.
하지만 그거 쓰는 자바 개발자들이 얼마나 있을까. 특히 SI 말이다.

Akka 가 이젠 닷넷 개발자도 배려해 주었다. 이런 비즈니스 요구를 잘 반영한 Akka를 말이다.
아. 생각해 보다 닷넷 개발자도 자바 개발자와 다를 거 없다. 둘 다 절차적 스타일에 따른다.

나는 이 글을 쓰는데 비동기를 강조하고 Procedural style 을 까내리려 하는 것은 절대 아니다.
Procedural style 은 당연히 피할 수 없는 코딩 구조이다.
하지만 나는 필요시 비동기 스타일을 권유하고자 글을 쓰는 것이다.
굳이 대안을 작성하자면, 비동기 개발 좀 하라고. 끝.

SI가 정말 한국 개발의 발전을 저해시키고 동결시키긴 했다. 나도 이런 답답한 개발에 지겨우긴 했다.
하지만 그렇다고 나를 받아주는 곳도 없다. SI에서는 튀고, 그렇다고 선진개발자에게 SI경력은 Procedural style 중점의 개발자로 낙인찍히니.
나는 이렇게 본의아니게 어정쩡한 개발자가 되버렸다.
뭐. 아무렴 어때. 이제부터 중요한 것은, 내가 직접 보여주는 수밖에.

어떤 패턴을 쓰던 나는 존중한다. 하지만 그 패턴만 고집하는 행위는 옳지 않다.
그런 사고방식이 전에 자바 개발했을 때 개발자의 사기를 떨어뜨렸다.
그래서 나는 어떻게 개발하던 존중해달라고 하고 싶어서
이런 뻘글 썼다.

아. 한가지 첨언하자면 Akka는 스칼라로 만들어졌지만 자바로 개발 가능하니 스칼라 태클 걸지 않도록.
자세한 소개는 Akka 로 한국어 웹 검색만 해도 좌르륵 나온다.

composite / 2015년 4월 10일 / Piss Development / 0 Comments