Visual Studio 2013 에서 닷넷 구버전 디버깅 팁

Visual Studio 2013 에서는 디버깅하는데 편집하며 계속하기 하고 싶지만 v4.5.1 64비트만 된다는 오류가 나온다.
먼저 64비트 디버깅은 닷넷 4.5.1 부터만 되기 때문에 만약 IIS Express 를 64비트로 사용한다면 옵션 -> 환경 -> 웹 -> 64비트 IIS 사용 체크 해제해야 한다.

디버깅할 때 구버전에서도 편집하며 계속하기를 활성화 하려면 당연히 프로젝트 속성에 편집하며 계속하기 체크 해야 하고,
도구 -> 옵션 -> 디버깅 에서 “관리되는 호환성 모드 사용” 에 체크하면 된다.
이런데도 안된다면 프로젝트를 수동으로 편집해야 하는데, 디버깅할 프로젝트를 “프로젝트 언로드” 하고,
프로젝트명을 오른쪽 마우스에 편집한다. 그리고 맨 위에 있는 <PropertyGroup> 요소 안에 아무데나 아래 문구를 삽입한다.

<_ResolveReferenceDependencies>true</_ResolveReferenceDependencies>

그리고 프로젝트 다시 로드한다.
그러면 디버깅하면서 편집도 되고 편리할 것이다.

composite / 2015년 5월 14일 / Piss Development / 0 Comments

[.NET vs JAVA] 쓰레드 동기화

고급 언어의 가장 알다가도 모를 이슈가 바로 쓰레드 동기화이다.
둘 다 Thread unsafe 의 경우는 반드시 발생을 하며, 특히 대량 처리로 인해 꼬이는 경우에 대해서는 유용하게 사용한다.
그럼 이 둘이 사용하는 동기화의 차이는 무엇일까?

결론부터 말하자면 차이점 없다. 기능 똑같다. 단지 구문만 틀릴 뿐.
자바의 경우 메소드에 synchronized 키워드를 붙일 수 있다.

public synchronized void doSomething(){
    //...
}

하지만 그래봤자 메소드 내용을 아래와 같이 처리하는 꼴이 된다.

public void doSomething(){
    synchronized(this){
        //...
    }
}

닷넷은 메소드에 동기화 키워드를 제공하지 않으며 구문으로만 제공한다.

public void DoSomething()
{
    lock(this)
    {
        //...
    }
}

그리고 임의의 private 객체 하나 지정해서 이를 사용해서 부분적인 동기화 작업을 수행하는 케이스가 대부분이다.
문제는 자바의 경우 메소드 동기화는 클래스 동기화나 다름없는데도 이를 이용하는 경우가 많다는 것이다.
물론 클래스 모두 동기화를 걸어서 일관적으로 수행하는 작업이라면 오히려 편리하지만,
그런 경우가 흔치 않기 때문에 오히려 동기화 방식은 구문 방법을 추천하고 싶다.
그 이유는 간단하다. 유연하고, 명확하며, 동기화가 필요한 부분에만 적용되어 더 빠른 처리를 제공할 수 있다.
특히 닷넷과 자바를 오가는 등의 폴리글랏 개발자라면 메소드 동기화보다 동기화 구문을 사용하자.
마이그레이션하기 존나 편할 것이다.

composite / 2015년 5월 7일 / Piss Development / 0 Comments

Microsoft Edge? 한국에게는 ‘H'(엣찌)

H를 한국에서 보통 ‘에이치’라 읽지만 일본에서는 ‘엣찌’ 라고 읽는다.
그리고 이 엣찌의 또다른 뜻이 있는데, 사실 인터넷 신조어인 셈이지만
일본어 변태적을 뜻하는 ‘헨타이’ 의 로마자 Hentai에서 H의 일본어 발음의 로마자 Ecchi 이기도 하다.
주로 매체에서… 음… 음흠 흠흠. 일단 이정도 정보 가르쳐준 거라고 고마워 하라. 모르는 사람이었다면.

어쨌든, 한국에서는 아직도 크로스 플랫폼을 자위행위로 까내리는 새끼들이 있고, 기관, 기업들이 존재한다.
마침 이 기사가 있다. MS 새 브라우저가 웹 생태계에 던진 메시지
시리즈물 기사인데, 엄청나게 영양가 없는 기사다. 개인적으로. 특히 한국이 MS 엣지를 특히 주목해야 할 이유.

나도 HTML5 개발자고, CSS에 ECMA6 등 최신 표준을 추구하는 개발자인데도 불구하고 이 기사가 영양가 없는 기사라고 할 수밖에 없는 이유가…
대한민국의 IT 산업구조와 현실에 안맞는 법, 그리고 관피아… 설명하자니 그냥 내가 성경 쓰는게 더 나을 지도 모르겠다. 그정도로 길다.
그 중에 한국이 크로스 플랫폼을 거부하는 이유 중 몇가지가 있다면…

1. 배로 불어나는 구축비용

그렇다. 기관 소개 사이트를 구축할 때 IE만 생각하면 800만원이지만 크로스 플랫폼은 1500으로 불어난다.
그래서 크로스 플랫폼은 돈아까운 기관이나 기업들에겐 참 좆같지 아니할 수 없다.
근데 요즘도 그런 자세가 보인다면 노답. 옛날 향수에 젖어 10년전 가격으로 웹사이트 구축해달라는 거나 마찬가지다.
근데 크로스 플랫폼 할 거면서 IE 구축비용을 바란다면 그냥 나가 뒤지라고 말하고 싶다.
요즘도 100만원도 안되는 가격으로 네이버처럼 만들어 달라고 하는 무식쟁이들이 판을 치는데.
참 요즘 한국에서 무식한 새끼들도 사업할 수 있다는 게 노답이긴 하다.

2. 고도화 비용을 낭비

한국은 정말 멍청하지 아니할 수 없다. 말놀리기다 시발.
어쨌든, 한국은 사이트 재구축시 아예 갈아엎고 처음부터 구축한다.
근데 웃긴게 뭐냐면 개발환경은 이전 환경 그대로 쓴다는 거다.
예를 들어, 자바 1.4 쓴 웹 사이트를 재구축하는데 이전 환경에 맞추기 위해 1.4 그대로 쓴다는 거다.
그리고 디자인만 바뀐 결과물이 완성된다.
신규 구축 비용을 들이면서 서버 업글할 돈이 없는건지 그저 현업이 귀찮은건지 참 알다가도 모르겠다.
이게 진정한 비용 낭비다… 이럴거면 뭐하러 고도화를 하냐. 시발 그냥 리뉴얼 하지. 리뉴얼이 싸게 먹히는데.

3. 쥐어짜는 개발일정

아직도 10년전 웹 기술을 답습하는 불쌍한 개발자도 많고, 웹보다 엑스플랫폼 같은 응용 솔루션이 편하다고 우기는 개발자도 있다.
그들에게 단가는 여전히 올라가지 않고, 경력이 늘어나는대도 정체된 개발과 단가에 익숙해져 무신경해진 개발자들이 있다.
그들에겐 그런 빡빡한 개발일정에 익숙하다 보니 개발일정이 넉넉해지거나, 애자일이거나 하면 오히려 무능력해지는 개발자를 발견하게 된다.
어쨌든 간에 쥐어짜는 개발일정은 잠재적 오류를 볼 시간이 부족해지며, 구축 후에 조용하던 사이트가 갑자기 무너질 때 개발자 탓을 한다.
놀고 있다.

이 외에도 많은데, 지금도 이런 개발패턴에서 변하지도 않았는데 마소 엣지 브라우저가 나온 들 달라질 거? 없다.
굳이 있다면? 이런 시나리오가 나올 가능성 100%다. 이건 윈도우 8 때도 발생했던 일이다.

“저희 서비스는 마이크로소프트 엣지를 지원하지 않습니다. 반드시 인터넷 익스프로러에서만 이용할 수 있습니다.”

그리고 이런 공문 떨어지고 땜빵하면서 뻐길 것이다. 물론 결국은 무너지게 되어 있지만.
대한민국 정부부터 기업들은 그렇게 뻐겨 왔다.

그래도 한국의 선진 개발자들은 답을 찾을 것이다. 늘 그랬듯이.

composite / 2015년 5월 6일 / Piss Development / 0 Comments

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

지금 닷넷 하고 있지만 얼마 지나지 않은 자바 개발 시절 얘기다.
나는 자바스크립트의 비동기 패턴에 익숙했다.
그래서 가끔씩 이벤트 패턴을 사용하기도 한다. 웹인데도.
하지만 공통팀 개발자로부터 태클이 들어왔다.
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

2015년 4월 9일자 오픈소스 임베디드 DB 리스트

NoSQL Databases

여기서 닷넷이 지원되는 기준으로 나열한다. 자바 지원은 추후 나열해 보겠다.

DBreeze

Professional, open-source, NoSql (embedded Key / Value storage), transactional, ACID-compliant, multi-threaded, object database management system for .NET 3.5> XAMARIN MONO . Written in C# .
닷넷 100% 기반 NoSQL 임베디드 DB
Mono를 통하여 윈도우 외 운영체제 및 휴대장치에서도 지원, .NET 3.5 이상

RaptorDB

NoSql, JSON based, Document store database with compiled .net map functions and automatic hybrid bitmap indexing and LINQ query filters (now with standalone Server mode, Backup and Active Restore, Transactions, Server side queries, MonoDroid support, HQ-Branch Replication, working in Linux)

Task 클래스를 통한 비동기 처리 때문에 닷넷 4 이상 필요.
순수 닷넷 100% 기반 NoSQL 임베디드 DB.
Mono를 통하여 윈도우 외 운영체제 및 휴대장치에서도 지원.

필자는 NancyFx MVC에서 세션 저장할 때 이 라이브러리 사용.

EJDB

EJDB aims to be a fast MongoDB-like library which can be embedded into C/C++, .Net, NodeJS, Python, Lua, Java, Ruby, Go applications under terms of LGPL license.

node.js 개발자들에게 유명한 NoSQL Embedded DB. 물론 닷넷과 자바 등의 타 언어 (바인딩)도 지원한다.
Tokyo Cabinet 기반.
C언어로 만들었기 때문에 구축 전 운영환경 확인 필수 (32/64)
닷넷 4 이상 필요. 비주얼 스튜디오 2012 이상 추천.

BergDB

BergDB is a Java/.NET database designed to be simple and efficient. It was created for us developers who prefer to focus on our specific task, rather then spend time on database issues. BergDB has: simple key-value storage, ACID transactions, historic queries, efficient concurrency control, secondary indexes, fast append-only storage, replication, transparent object serialization and more. BergDB is an embedded, open-source, document-oriented, schemaless, NoSQL database.

자바 기반 라이브러리기 때문에 닷넷은 IKVM을 통해 제공하고 있음.

BinaryRage

BinaryRage – the ultra fast .NET key/value store
– BinaryRage is designed to be a lightweight ultra fast key/value store for .NET with no dependencies
– It’s production-ready – already in several large production-environments
– Supports complex objects out of the box (and lists of objects)
– 100% FREE and open (no paid pro version or anything lame like that)
– No configuration, no strange driver/connector, no server, no setup – simply reference the dll and start using it in less than a minute.
– Created it because I think there is a huge need for a very simple key/value store
– If you hate writing boilerplate code – you will love BinaryRage

닷넷에서 RaptorDB와 아마 쌍벽을 이룰 것으로 보고 있다.
RaptorDB와 마찬가지로 Production Ready 이기 때문에 안정적으로 쓸 수 있다.
얘 또한 닷넷 4 이상이 필요하다.

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

[.NET vs JAVA] Boxing VS Generic

닷넷은 2.0부터, 자바는 1.5부터 제네릭을 지원한다.
당연히 그 전까지는 박싱과 언박싱을 써왔다.
그리고 그때당시 개발자들은 이미 그런 방식에 익숙하기 때문에 제네릭을 안쓰기도 한다.
특히 자바개발자는 제네릭 개념이 꽤 늦게 들어왔기 때문에 제네릭 안쓰는 개발자가 더 많다.
심지어는 나처럼 제네릭 쓰지 말라는 이상한 소리를 들을 수도 있다.

자, 그렇다면 이 두 언어별 박싱과 제네릭의 특징을 알아보자.

.NET

닷넷은 닷넷 2.0부터 출연했는데, 시기적으로는 꽤 빨리 들어온 것이다.
어쨌든, 얘네들의 박싱과 언박싱은 C/C++의 단순한 업캐스팅 개념으로 만든 것이 아니다.
일단 닷넷에 있는 모든 객체는 object 클래스에 상속된다. 설령 struct로 정의한다 해도.
근데 이 structnullable이 불가능하다. 물론 Nullable<T>로 가능은 하지만.
얘네들의 박싱 개념을 C/C++로 표현하면 다음과 같다.

int num1 = 123;
object obj = num1;
int num1 = 123;
int *obj = new int;
(*obj) = num1;

즉, 전문적으로 말하자면 힙에 새로운 객체가 생성되면서 값이 복사되는 그런 개념이 되는 것이다.
그걸 Generic 이라는 개념을 도입했는데, 이 방식을 사용하면 Boxing과 Unboxing이 필요 없어진다.
ArrayList를 예로 들어보자.

ArrayList arr1 = new ArrayList();
ArrayList<string> arr2 = new ArrayList();

자. 일단 시니어 닷넷 개발자라면 HashTable 사용에 익숙할 것이다. 어쨌든, 얘네들은 동적 배열을 만드는데,
일정 개수만큼 (보통 16) 자리를 부여한다. 근데 제네릭이 없으니 뭐로 하겠나. 당연히 최상위 객체인 object 자리가 되는 것이다.
그러면 arr1.Add(num1); 을 넣으면 어떻게 되느냐. 싫어도 Boxing 해야 한다. 그럼 반대로 가져올때는? 당연히 강제 Unboxing 이다.
그에 반해 arr2 는 제네릭으로 타입이 명시되어 있다. 그리하여 닷넷 런타임은 일정 개수만큼 자리를 부여하되,
타입이 정해졌으니 object로 할 필요 없고 명시도니 string 자리를 부여한다.
그럼 거기다가 string 값만 넣으면 되니 Boxing 과 Unboxing 이 필요 있겠는가? 당연히 필요 없어지게 되는 것이다.
그래서 닷넷의 제네릭이 괜히 성능 얘기 나오는 게 아니고, 그걸 경험한 닷넷 개발자들은 제네릭에 익숙한 것이다.

Java

자바는 Auto Boxing 이란 개념이 있다. 닷넷 개발자는 생소할 텐데,
이 Autoboxing 개념은 자바 1.5에서 출발했다.
자바는 primitive type, Class, 그리고 null 이 있다.
자바 개발자들은 알 만한 사실이지만 primitive type 에 null 허용되는 건 당연히 아니다.
Auto boxing이 생기는 큰 이유는 바로 primitive type 와 Class 간 처리 때문이다.
숫자 타입으로는 primitive type 인 int 와, Class 인 Integer 가 있다.
이 둘이 오갈 때 당연히 메소드를 호출하는데,
int -> Integer = Integer.valueOf()
Integer -> int = (Integer).intValue()
이 둘을 명시적으로 Boxing 한다면 어떻게 될까? 먼저 primitive type 는 당연히 클래스가 된다.
Object도 클래스기 때문에 primitive type 를 직접 관리할 수 없기 때문이다.

int num1 = 123;
Object obj = num1;
//는 아래와 같다.
Object obj = Integer.valueOf(num1);

그렇다고 클래스라고 해서 그냥 넣는가? 안타깝게도 닷넷과 다를 바 없다.
자바나 닷넷이 Object 업캐스팅 개념이 없으니까.

자, 이제 제네릭으로 간다.
자바는 닷넷 제네릭과 달리 메모리에 관여하는 게 아니라 그저 심볼 역할만 하는 녀석이다.
그래서 ArrayListArrayList<T> 는 같은 클래스다.
닷넷은 ArrayListArrayList<T> 는 엄연히 다른 클래스로 취급하는 것과는 대조적이다.
이것은 당연히 하위 호환성 때문이다. 닷넷은 1.x과의 호환성을 포기하고 제네릭을 도입했으니 가능한 얘기다.

그래서 제네릭을 달아봐야 add() 로 넣을 때 박싱해버리고 get() 할때 언박싱한다.
제네릭 달아봐야 박싱 언박싱 그대로 해버리니… 그래서 닷넷과 달리 성능향상이 없다.
그저 컴파일 타임에서 타입 검증에 대한 강화 용도로 쓰이게 된다.

그래서 자바 개발자들은 제네릭 안써도 잘 한다. 굳이 필요가 없다고 느낄 정도다.
그래도 검증과 무결성 측면에서는 당연히 제네릭이 유리하다.
제네릭 쓴다고 성능 떨어지는것도 향상되는 것도 아니지만, 방어적 코딩이 나중에 장애나 유지보수에 어떻게 빛을 발하는지 겪어본 사람은 알 것이다.

결론

어쨌든 공통적으로 제네릭은 타입에 민감한 닷넷과 자바에게는 신의 한수인 것이다.
그러니 왠만하면 쓰자.

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

ES6 Generator 와 ES7 Generator의 차이점?

ES6 Generator

ES6의 Generator 는 Generator body가 .NET 3.5 의 Enumerable과 Java의 Iterator를 섞은 느낌.

function *foo(){
    for(var i=1;i< =10;i++){
        yield i;
    }
}

for (var v of foo()) {
    console.log(v);
}

그러나 일반적인 Iterator와는 달리 ES6의 Generator는 .next() 메소드 호출이 무제한 가능하다.
따라서 .next()를 통해 얻은 값에서 done:true 인 것으로 필터링 해야 한다.
만약 자바처럼 while(b = a.next()) 이런 식으로 반복문을 돌면 무한 반복이 된다.
왜냐면 a.next() 가 다 돌았다고 해도 계속 마지막 값을 전달하는 스펙 때문이다.
수정 : 모두 호출한 다음 next()를 호출하면 다음 yield 값을 불러오는데 없으면 value가 undefined 나온다. 물론 done:true 는 여전하다.

var a = foo(), b;
while(!(b = a.next()).done)
    console.log(b);

이런 측면에서 ES6 Generator는 기존 개발자들에게 Iterator 와는 다른 혼란이 올 수도 있다.
게다가 비동기를 쓰려면 인라인 함수도 Generator 구문을 사용해야 하며,
비동기 연동은 Promise 객체를 사용해야 하고, spawn 함수가 필요하다.
여러가지로 비동기 사용이 번거로워 계륵같은 구문이 아닐 수 없다.

spawn 함수 1
spawn 함수 2

사용 예제

//제목과 챕터별 내용을 외부 경로에서 비동기로 출력하는 예제
//getJSON 함수는 Promise 패턴을 사용한 Ajax 함수라고 가정한다.
function loadStory() {
  return spawn(function *() {
    try {
      let story = yield getJSON('story.json');
      addHtmlToPage(story.heading);
      for (let chapter of story.chapterURLs.map(getJSON)) {
        addHtmlToPage((yield chapter).html));
      }
      addTextToPage("All done");
    } catch (err) {
      addTextToPage("Argh, broken: " + err.message);
    }
    document.querySelector('.spinner').style.display = 'none';
  });
}

ES7 Generator

ES7의 Generator 는 .NET 4.5 의 await와 async 구문을 채용한 듯 한 느낌을 줄 것이다.
사실 사용법도 크게 다르진 않다. 게다가 비동기에 대한 배려가 잘 적용되어 있다.

//제목과 챕터별 내용을 외부 경로에서 비동기로 출력하는 예제
//getJSON 함수는 Promise 패턴을 사용한 Ajax 함수라고 가정한다.
async function loadStory() {
  try {
    let story = await getJSON('story.json');
    addHtmlToPage(story.heading);
    for (let chapter of story.chapterURLs.map(getJSON)) {
      addHtmlToPage((await chapter).html);
    }
    addTextToPage("All done");
  } catch (err) {
    addTextToPage("Argh, broken: " + err.message);
  }
  document.querySelector('.spinner').style.display = 'none';
}

ES6과 달리 spawn 함수가 필요없다. 하지만 비동기인 만큼 Promise 객체를 사용해야 한다는 사실은 변함없다.
하지만 번거로운 spawn 함수가 없는 데다가 코드가 상당히 간결해졌다. 그래서 ES6 스펙이 그냥 ES7로 넘어갔으면 하는 희망사항이 생기기도 한다.

사용법도 간단하다.

(async function() {
  await loadStory();
  console.log("Yey, story successfully loaded!");
}());

단지 실행시에도 Generator 구문을 써야 한다는 점만 빼면 간단하게 실행이 가능하다.

그럼 자바스크립트 개발자의 이해를 돕기 위해 .NET 4.5 에서 추가된 await/async 예제를 보도록 하자.
Async 및 Await를 사용한 비동기 프로그래밍

//msdn.microsoft.com 의 내용 길이를 가져오는 비동기 함수
async Task<int> AccessTheWebAsync()
{ 
    // HTTP 클라이언트 선언
    HttpClient client = new HttpClient();

    // GetStringAsync 함수는 mdsn.microsoft.com 의 HTML 내용을 비동기로 받아둔다.
    // Task 클래스는 JS의 Promise와 동일한 역할을 하며, (자바는 Future<t>) 일단 작업을 받아낸다.
    Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");

    // 일단 작업은 받아냈기 때문에 기다릴 필요 없이 해당 구문으로 넘어간다. 기타 할 것들.
    DoIndependentWork();

    // await를 사용하여 getStringTask 의 작업이 끝날 때까지 AccessTheWebAsync 메소드는 기다린다.
    // 만약 getStringTask 의 작업이 끝나면 urlContents 에 결과값을 전달한다.
    // 이게 끝날 때까지 다음 절차로 넘어갈 수 없다.
    string urlContents = await getStringTask;

    // 이제 위의 비동기 작업이 끝났으니 작업을 마무리할 시간.
    // 비동기 작업을 통해 받아온 urlContents 의 문자열 길이를 출력함으로서 작업을 마친다.
    return urlContents.Length;
}

여기서 공통점이 있다면 Promise 특성과 Generator의 성격을 안다면 알겠지만,
await 구문에 있는 메소드나 Promise 객체가 then 을 통하여 값을 전달할 때 까지는 다음 작업을 수행할 수 없다는 것이다.
ES6의 yield 과는 다르다. yield 구문은 그냥 쌩 값을 반복하듯이 내보내기 때문에 직접 핸들링 해야 한다는 차이점이 있다.
이 차이점을 이해했다면 ES7의 Generator 가 더 진보되고 편해졌다고 느껴질 것이다.

미안하다. 나도 다쓰고 이해시키는 것에 실패했다. 조만간 부가설명이나 글 수정을 통해 개선하겠다.
게다가 일도 바빠서 여기까지.

참고자료

The Basics Of ES6 Generators
ES7 async functions

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

자바와 닷넷의 문자열 연산자 차이

1. == 및 != 연산자

닷넷

닷넷은 == 연산자 오버로딩을 통하여 String.Equals 사용하여 값의 동일성을 비교.

자바

자바는 String이 닷넷과 같이 클래스이며 연산자 지원 안하는 특성상 레퍼런스 비교밖에 못하므로 동일한 값 비교 불가.
따라서 개발자가 직접 String.equals를 사용.

2. + 연산자

닷넷 :

string s = "asd" + b + "qwe";
//>> string s = string.Concat("asd", b, "qwe");

String.cs
.NET concat 원리

        [System.Security.SecuritySafeCritical]  // auto-generated
        public static String Concat(String str0, String str1) {
            //Contract 는 Test 및 유효성 검사를 위한 내부 클래스임.
            Contract.Ensures(Contract.Result<string>() != null);
            Contract.Ensures(Contract.Result</string><string>().Length ==
                (str0 == null ? 0 : str0.Length) +
                (str1 == null ? 0 : str1.Length));
            Contract.EndContractBlock();

            if (IsNullOrEmpty(str0)) {
                if (IsNullOrEmpty(str1)) {
                    return String.Empty;
                }
                return str1;
            }

            if (IsNullOrEmpty(str1)) {
                return str0;
            }

            int str0Length = str0.Length;
            //.NET 은 네이티브를 통해 포인터에다가 합칠 문자열 길이를 모두 합산하여 배열에 자리 부여
            String result = FastAllocateString(str0Length + str1.Length);
            //그리고 포인터에다가 순서대로 삽입
            FillStringChecked(result, 0,        str0);
            FillStringChecked(result, str0Length, str1);
            //그리하여 포인터 문자열 출력.
            return result;
        }

자바 :

String s = "asd" + b + "qwe";
//>> String s = new StringBuffer().append("asd").append(b).append("qwe").toString();

StringBuffer.java
자바는 문자열 증가 연산자 약속을 StringBuffer 클래스를 통해 합치며 원리는 닷넷과 차이가 있음.

닷넷과 자바의 문자열 합치기 차이점

닷넷 : 처음부터 합칠 모든 문자열의 길이만큼 자리를 포인터에 할당 후 삽입한 다음 포인터 결과값 출력.
자바 : StringBuffer 특성상 일정 자리를 부여 후 문자열 넣을 때마다 필요 시 일정량 증가 후 삽입한 다음 문자열 출력. (기본값은 +16)

닷넷과 자바의 문자열 합치기 공통점

반복문 등에서 문자열 추가시 닷넷은 StringBuilder, 자바는 StringBuffer를 쓰는 것이 성능상 이득.

여기까지.

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

닷넷에 있는 익명 타입은 왜 제네릭이냐?

닷넷 개발자로 귀환하고 첫 닷넷글이네.

5년전의 MSDN 글을 보고 5년 후에 쓴 내가 조금 처량해 보이지만…

여태까지 익명 클래스 사용하는 법이야 당연히 많지만, 왜인지 해소를 해준 글은 본 적이 없다.
MSDN 글이 내 궁금증을 해소해주는 유일한 곳이긴 하다. 물론 MS에서 만들었으니 MSDN 에 올라는거야 당연하긴 하지만.

어쨌든, 내가 4년전에 익명 타입을 알아내는 방법 글을 올렸었다.
와.. 이때동안 난 자바했네 시발.

어쨌든 여기서 특징이 있다면…

  • CompilerGenerated 특성이 적용됩니다.
  • 제네릭 타입입니다. 의외네요.
  • 클래스 이름에 “AnonymousType” 라는 문구가 포함됩니다.
  • 클래스 이름 머릿말에 C# 의 경우 “<>”, VB의 경우 VB$ 로 시작됩니다.
  • 클래스는 public 이 아닙니다.

이렇게 기재되어 있다. 뭐 다른 이유야 구분짓고, 게다가 어자피 지역 변수니 internal 클래스는 이해 한다.
근데 왜 제네릭일까? 그래서 위 MSDN 블로그에 갔다.

자. 익명 클래스 하나 만들었다고 치자.

var x = new { A = "hello", B = 123.456 };

그리고 이걸 빌드 후 리플렉션 툴로 까보면 해괴망측한 클래스 정의가 나온다.

.class '<>f__AnonymousType0`2'< '<A>j__TPar','<b>j__TPar'>

여기서 익명 클래스의 특징이 나오는데, 바로 속성 수만큼 제네릭 타입 개수가 나온다는 것이다.
예를 들어 속성이 2개면, 제네릭에 들어갈 타입도 2개란 소리다.
MSDN에서는 컴파일 후 사용자 친화적인 코드로 표현하면 아래와 같은 코드가 나온다고 한다.

[CompilerGenerated]
internal sealed class Anon0<ta , TB>
{
    private readonly TA a;
    private readonly TB b;
    public TA A { get { return this.a; } }
    public TB B { get { return this.b; } }    
    public Anon0(TA a, TB b)
    { this.a = a; this.b = b; }
    // 여기에 object의 Equals, GetHashCode 와 ToString 메소드 덮겠지.
}

sealed 키워드까지 붙었다. 물론 굳이 저 클래스를 상속할 이유가 있겠는가?
그렇다면 첫번째 코드의 익명 클래스로 선언했을 때 컴파일된 클래스 결과물은 이렇다.

자, 그렇다면 익명 클래스에서 자신이 사용한 클래스를 적용한다면?
보통은 당연히 public이라면 어자피 제네릭에 들어가니 상관은 없다.
그런데… 이런 경우가 있다.

public class B 
{
    protected class P {}
}

B 클래스 내에 P 클래스가 있다. 당연히 P 클래스는 B 클래스와 B를 상속한 클래스 내에서만 접근 가능하다.
그런데 그걸 익명 클래스를 통해 밖으로 끄집어내기 시작한다.

class D1 : B
{
    void M() { var x = new { P = new B.P() }; }
}

class D2 : B
{
    void M() { var x = new { P = new B.P() }; }
}

이렇게 하면 어떻게 생성되느냐. 아래와 같다.

class D1 : B
{
    [CompilerGenerated]
    ??? sealed class Anon0 { public P P { get { ... } } ... }
    void M() { var x = new { P = new B.P() }; }
}

뭐… 그러고 보니 P 클래스가 공개적 접근이 안되는데 B의 M 메소드로 공개하려 하니 골치가 아프지 않은가.
그래서 아예 접근 못하는 클래스를 복사해 익명 클래스로 재생성한 꼴이 된다.
이 부분에 대해선 필자도 좀 더 공부해봐야 겠다.

자. 일단 이렇게 나온다. 간단히 정리하자면 익명 클래스는 속성 타입들의 제네릭 클래스다.
그 이유는 맨 위 MSDN 링크에서 설명했듯이 “성능”이다. 단순히 성능이 빨르다고 했다면 제네릭이 쓸 필요가 없지만,
제네릭은 박싱/언박싱으로 인한 타입 검증 과정을 줄여줌으로써 성능상 이득을 내는 건 닷넷 개발자라면 알 것이다.
바로 이런 원리를 익명 클래스에서도 적용했다고 보면 된다. 납득 ㅇㅇ?

그럼 이만 물러나겠다. 뿅.

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

MariaDB의 미래? io.js의 미래? 누가 앞서갈까?

이번 포스팅부터는 더이상 워드프레스의 좆같은 비주얼 에디터를 안쓰고 Github flavor markdown 을 쓰도록 하겠다.

오늘 인터뷰했을 때 뜬금포로 갑자기 마리아디비 할 줄 아냐고 물어봤다. 오랜만에 들어보는군. 마리아디비.

내가 설마 안써봤을까봐는 개뿔 SI 하면 MSSQL과 오라클 둘뿐인데 가뜩이나 MySQL조차 중소기업 쓴다고 무시하는 판국에 왠 마리아디비?

뭐 어쨌든. 사실 오늘 인터뷰 때문에 생각나서 포스팅 날린다.

MariaDB

오라클이 오픈소스에 대해 대하는 꼬라지는 참으로 개발자들 사이에서도 유명하다. 그들에게 오픈소스는 오로지 소스만 오픈되어 있을 뿐
쓰려면 돈내라는 것이다. 설령 개인적이 용도라 해도 말이다.

MySQL 이 썬이 먹고 그 썬을 오라클이 먹으면서 오라클의 오픈소스 정책을 따라가기 시작했고, 그들의 DB솔루션 노하우를 적용하여(?)
엔터프라이즈에서도 쓸 수 있는 대신 존나게 비싼 솔루션을 출시했다.
물론 기존 MySQL 에서는 커뮤니티 에디션으로 계속 쓸 수는 있다.

하지만 MySQL 핵심 개발자들은 이런 오라클의 자세와 애매한 라이센스 적용에 반발하여 몇몇이 나가서 만들었는데
그게 바로 MariaDB다.

MariaDB는 MySQL을 기반으로 작성되었으며, GPLv2 오픈소스이다.
상업용으로 쓰기엔? 지장없다. 소스 바꿀 일이 없다면 말이다. 아마 대부분은 그렇게 소스 바꿀 일 없이 쓸 것이다.

MariaDB의 자세한 역사까지 기재하기엔 내 손 아프니까 위키백과 가서 봐라.

현재 나온 버전으로는 MySQL과 동일한 시스템, 동일한 쿼리구조, 동일한 데이터 구조를 가지고 있다.
출발이야 MySQL에 반발해 시작했으니.

하지만 그 마리아디비도 곧 다른 노선을 탈 것이라는데. 아직 예정이긴 하지만.

위키백과와 구글도 MariaDB로 전환을 발표했다고는 했다. 적용 했는지 안했는지 알 길은 없지만.
아마 쓰겠지. 특히 구글이 오라클 때문에 존나 골치아플텐데 말이다.

하지만 업계 반응은 그닥…

특히 한국은 특히 더…

여전히 MySQL 5.5 를 쓰는 업체들이 주류일 것이고, 마리아디비는 호환 가능하다 해도 다들 안쓰는데 굳이 뭐 눈치보면서 쓸 이유가 있겠냐고 생각할 것이다.

물론 돈 들여서 개발 시작하는데 처음보는 기술을 도입한다는 건 여러가지 불투명을 안고 간다니 이해는 한다.

그렇다고 해서 마리아디비가 MySQL보다 뛰어나다고 증명할 만한 자료 찾기도 어렵거니와 도입에 성공해도 누구한테 자랑해야 할 지 모를테고.

어찌보면 그 해답은 MariaDB가 MySQL 과 다른 노선을 탈 때 나올 것이다.

io.js

엊그제 같은 일일 것이다. node.js 개발자들은 더이상 차기 버전에 대해 불투명하고 불안한 미래를 암시하기 시작했다.

joyent 는 대체 뭐하고 있는 것이길래 차기 버전을 내세우지 않는 것일까?

그리고 그들은 node.js 개발에서 손을 떼고, 새로 출발하기 시작했다.

이름하여 io.js 이다. 이렇게 된 역사를 자세히 기술한 블로그 포스트가 있으니 참고하도록.

io.js 는 ECMAScript 6 하모니를 가장 빨리 도입한 선진적 자바스크립트 프레임워크로 거듭나는 길을 목적으로 가고 있다.

물론 1월 15일 모습을 드러냈지만 node.js 와 똑같이 생각하기엔 아직까지는 멀었나 보다.

그들이 공식적으로 node.js 와 같이 출발할 것이라는 발표와 달리 이리저리 예외가 떨어져 호환이 안되고 있다.

물론 그들도 안정된 버전을 내놓지는 않고 당연히 알파 버전을 내놓긴 했지만.

솔직히 말해서 내가 io.js 의 미래를 점치기에는 시기가 너무 빠른 듯 하다.

하지만 io.js 는 마리아디비와는 달리 node.js 와 같은 노선을 탄다니 케이스가 다른 경우가 되겠다.

그리고 과연 개발자 커뮤니티의 중심의 민주적인 자바스크립트 프레임워크가 될 것인지는 안정된 버전이 나올 때까지는 지켜볼 일이 되겠다.

그래서?

미래가 뭐냐고? 물론 나도 뭐라 단정지을 수도 없다. 불투명하다고 하고 싶지만 이 글을 끝내기엔 나 존나게 원망할 것이다.

그래. 마음대로 생각해라.

어자피 오라클이야 마음 고칠 생각은 눈꼽만큼도 안보이지만, 조이엔트는 이 분위기를 의식했는지 좀 더 열려는 모습을 보이고 있다.

마리아디비처럼 경쟁체제로 가거나, io.js 처럼 상생체제로 가거나. 이제 이 둘의 미래가 과연

기업형 개발자와 커뮤니티형 개발자에게 이 둘의 미래로 어떤 영향을 줄 지가 내가 짚어보는 키 포인트라고 생각하고 있다.

이미 주사위는 굴러졌다. 경쟁과 상생의 아이콘. 오픈소스의 경쟁체제로 간 마리아디비, 오픈소스의 상생체제로 간 io.js!

개발자라면 이 둘의 행보를 절대 놓치지 말고 끝까지 계속 지켜보아야 한다. 당신이 개발자라면.

당신이 오픈소스를 지향하던 폐쇄적을 지향하던 내 알 바 아니다. 이 둘의 행보가 개발자들에게 어떤 영향을 줄 지가 관건이다.

놓치면 지는거다.

아. 인터뷰 얘기 나왔다고 영향 가나 신경쓸 필요 없어. 그사람은 날 원하지 않아서 신경 쓸 필요가 없거든.
내가 뭐 대단한 인력이라고 자신하긴 아직 뭐하지만 그렇다고 내가 꿇리는 개발자는 아니거든.
선배 개발자들이 원치 않았던 망할 프론트엔드를 내가 여태까지 도맡아 했기 때문에!

composite / 2015년 2월 6일 / Piss Development / 2 Comments