코딩을 하다 보면 불편하지만 참고 넘어가는 경우가 있는데, 늘 바쁜 개발자가 차분히 환경을 개선할 만한 여유가 쉽게 나지 않는다. 비주얼 스튜디오를 쓰면서 필자를 아주 오랫동안 성가시게 했던것 중 하나가 바로 문서 탭(Document well)이다. 도대체 머저리 같은 MS 녀석들이 무슨 생각으로 탭 순서를 멋대로 헝클어 버리는지 이해할 수 없다. 그냥 최근 열람한 탭을 앞에 두는게 그들이 할 수 있는 최선인가보다. 얼마전 탭바를 스크롤할 수 있게 해준다는 설명을 읽고는 Productivity Power Tools 익스텐션을 설치했는데, 휠버튼으로 동작하는게 아니라 탭바의 양 끝에 쥐똥만한 버튼을 달아놓은게 전부였다. 댐잇... 


하지만, VS를 쓸 때 마다 늘 Xcode나 이클립스를 갈구하게 했던 불편한 점이 몇 개 해소됐다. 이 녀석은 탭을 사전순으로 소트해준다. 최근 열람한 탭을 제일 앞으로 가져와 탭바를 헝클어 버리는 염려가 없다. 그리고, 무려 스크롤 바에 오류를 빨강색으로 표시해준다! 수정된 라인은 노랑색, 커서는 흰색으로 표시해 준다. 수정된 파일 탭에 빨강 동그라미를 표시해주는건 뽀나스. 또, 들여쓰기에 탭과 스페이스가 섞인 코드를 열면 탭으로 통일시켜주는 버튼이 뜨거나, Ctrl+Click을 이용해 정의로 이동하게 해주고, 이클립스와 비슷하게 똑똑한 자동 괄호를 지원해 준다.


다시 본론으로. VS에서 코드를 열면 탭에 파일명이 표시되는데, 개발자에겐 이 탭바가 늘 비좁다. 아래의 그림에서는 6개의 코드를 열었지만 탭은 3개만 표시되며, 다른 코드로 오가는 동안 탭바는 무용지물이 된다. 앞서 언급한 익스텐션을 설치하면 탭바를 세로로 표시할 수도 있지만, 공간을 많이 낭비한다.


구글링으로 이런 방법을 알아냈다. 알고보니 VS의 기본 옵션에서 이 문제를 해결할 수 있었다. 도구 메뉴에서 '옵션...'을 누른다.


옵션창에서 '환경 - 탭 및 창' 섹션을 선택하고 '별도의 행에 고정된 탭 표시'에 체크를 하고 '확인'을 누른다.


필자가 그랬듯이 어쩌면 잠시 머뭇 할 수도 있다. 아무런 변화가 없기 때문. 이제 탭바에서 무슨 일이 있어도 자리를 사수하고 싶은 탭의 핀을 눌러 꽂아준다. 부왈라~! 이제 우리는 탭을 여러줄로 표시할 수 있다.

헐... 이제 봤더니 옵션과 상관없이 핀만 누르면 자동으로 멀티라인이 되어 위치를 사수한다 -_-; 옵션은 필요할 때 변경하면 될 듯.

그런데, 프로젝트를 처음 실행할 때 모든 핀이 뽑혀서 헝클어지는 버그가 있다. PPT의 커스텀 탭 기능이 문제인데, 옵션에서 끄고 VS를 재실행하면 해결된다.



이러한 환경으로 필자의 VS 개발 환경의 만족도가 크게 올랐지만, 이들과 시너지를 내는 화룡정점은 따로 있다. 바로 CodeMaid란 익스텐션인데, 필자가 주목한 기능은 Spade와 Cleanup, Reorganize이다.


Spade는 활성화된 코드의 개요를 보여주고 코드와 동기화된다.

즉, 변수나 델리게이트, 속성등을 region으로 감싸고 접어 놓으면, 개요에서도 접힌다. 그림처럼, 메소드 리스트를 시원하게 펼쳐놓고 왔다 갔다 할 수 있다. 개인적으로 미친듯이 갈구하던 기능으로, MS가 솔루션 익스플로러 + 멤버 목록 콤보박스를 멍청하게 구현해놓은 문제를 해결해준다. 하지만, 개요 업데이트 처리가 빠릿하지 않아 자주 저장을 하면 맥이 끊긴다. 파싱 속도를 미친듯이 높이고 스레드를 적절히 심어준다면 난 정말 사랑에 빠질것이다.

최근 클릭한 멤버 아이템들에 점진적으로 어두워지는 하이라이트를 해준다면 좋을텐데 아쉽다. VS10x Code Map v3는 하이라이트가 과하지만 편리하긴 하다. 하지만, 크기변경도 안되는 작은 폰트와 같이 이해할 수 없는 가독성 디자인과 점점 느려져 VS가 이상해지는 leak 때문에 쓰기 싫다. (게다가 30일간만 무료?다)


Cleanup은 코드를 깔끔하게 정리해준다.

코드를 우클릭해 실행할 수 있다. 불필요한 빈줄은 제거하고 필요한 빈줄은 삽입해서 보기 좋게 만들어 준다. #endregion 뒤에 리전 이름을 적어주거나 사용하지 않는 using문을 제거하고 사전순으로 정렬하며, 줄바꿈 없이 한줄로 길게된 코드을 보기 좋게 여러줄로 바꿔주기도 한다. 개발자의 코딩 습관에 맞게 세밀하게 규칙을 정할 수 있다.

옵션의 'Cleaning - Insert' 섹션에서 'Insert explicit access modifiers on'의 모든 항목을 꺼주면, 한정자가 생략된 모든 멤버에 'private'를 붙이느라 엄한 시간낭비를 하지 않는다. public과 protected 외에는 한정자를 붙이지 않은 필자의 1300라인 짜리 코드를 클린업 하는데 몇 분이 걸려, VS가 다운된 줄 알았다. 보통은 실행후 거의 바로 완료된다.


Reorganize는 코드 멤버의 순서를 재정렬해준다.

필자가 처음 코딩을 배워 1부터 무려 1000까지 합을 구하는 프로그램을 만들 당시만 해도 나중에 작성한 함수가 제일 끝에 있었다. 하지만 지금은 코딩하다 말고 알파벳을 중얼거리며 멤버를 이리 저리 옮기고 있는 자신의 모습을 자주 발견한다. 이들을 정리하지 않아 자신이 만든 코드를 분석하는데 한참 헤맨 경험은 여느 개발자에게나 있을것이다.

혹자는 이 기능에 환호할 수도 있겠다. 미리 정의된 규칙(수정가능)대로 코드 멤버의 순서를 재정렬해준다. 즉 델리게이트, 이벤트, 필드, 속성, 메소드 등으로 그룹 순서를 정리하고 각 그룹 내의 멤버들을 사전순으로 정렬한다. 그룹 순서는 편리하고 쉽게 변경할 수 있다.

이벤트 핸들러들을 코드 뒷쪽에 몰아넣는 등 별도로 구분하고 싶은 멤버들이 있다면 region으로 감싸 위치를 고정할 수도 있다. (물론, region 안의 멤버들 끼리 사전순 배열된다)


CodeMaid는 오픈소스이며 무료로 제공된다. 이 밖에도 많은 익스텐션들이 있으며, 마이크로소프트의 비주얼스튜디오 갤러리에서 살펴보거나, VS의 '도구 - 확장 및 업데이트...'를 눌러 다운로드할 수도 있다.


memo.

티스토리를 사용하면서 내용을 복사/붙여넣기할 때 마다 <span ...></span>들이 누더기처럼 붙는데 몹시 못마땅하다. Ctrl+Shift+V 를 누르면 raw text(서식이 제외된 텍스트)만 들어가긴 한지만, 엔터만 쳐도 이 누더기들은 불어나며 뽀나스로 붙어나는 &nbsp;와 쌍을 이루어  '뭔가 이상한' 부분이 생겨난다.

뭐, 그냥 간단하게 말하면 '이상한 것 같긴 한데 잘 안보인다'고 할 수 있다. 내가 싫어하는 부분은, '왜 잘안보이지만 이상해야되? 그냥 잘 되면 안되?'라는 생각 때문. '뭐 기술적으로 어쩌고 저째서 그렇게 된거야'라는 설명에 '아 그렇구나'하고 넘어가는건 참 싫다. 어려운것도 아니고 하찮은 수준의 기술만으로 해결되는건데 원 참... 개발자라 이런 생각을 하는지도.

정성들여 글을 쓰고 여러번 수정하고난 뒤에 남는 자국들 때문에, 결국 이놈의 HTML 보기에서 태그들을 지운다. 다른 블로그 서비스를 알아봐야겠다.

조금만 구글링 해보면 GetChildAtPoint와 PointToClient를 사용하라는 포스트가 널렸다. 조금 더 구글링 해보면 그것밖에 없다. 모두 그렇게 말한다. 그런데 그걸로 안된다 ㅋㅋ. 전자는 Visible이 false이거나 곂쳐진 경우를 무시하고 가장 뒤에 깔린 컨트롤을 반환하는 문제를, 후자는 Control.PointToClient가 이상한 값을 반환하는 문제를 가지고 있다. (Form의 메소드는 올바른 값을 반환한다. 왜 그런지 생각해볼 가치를 느끼지 못하고 있다.)


잘 동작하는 샘플을 찾지 못해 만들었다.


public static Control FindControlAtPoint(Control container, Point pos)
{
	Control child;
	foreach (Control c in container.Controls)
	{
		if (c.Visible && c.Bounds.Contains(pos))
		{
			child = FindControlAtPoint(c, new Point(pos.X - c.Left, pos.Y - c.Top));
			if (child == null) return c;
			else return child;
		}
	}
	return null;
}

public static Control FindControlAtCursor(Form form)
{
	Point pos = Cursor.Position;
	if (form.Bounds.Contains(pos))
		return FindControlAtPoint(form, form.PointToClient(Cursor.Position));
	return null;
}


스택 오버플로의 원문은 여기에.

It's not possible to create or open 'XNA Windows Game' project using Visual Studio 2012. As Microsoft publishes Windows 8 and Visual Studio 2012, XNA framework now only supports Windows Phone 8. If you like to create an 3D game using VS 2012, you must create Visual C++ project and use DirectX. However, there's a way to create or open XNA desktop application project.



1. Install Windows Phone SDK 8.0 first. And updates 'Games for Windows Marketplace Client', then install Windows Phone SDK 7.1. 7.1 versions can't be installed without the recent version of marketplace client on Windows 8.

If you already installed XNA Game Studio 4.0 on your PC, you can skip this step.


This blog describes how to install the 7.1 versions of SDK on Windows 8.



2. If you are planning to Install VS 2012, install it now and don't run it yet. If you already installed it, skip this step.



3. Run command prompt as administrator permission.



4. Execute the following line. This will copy VS 2010's XNA project templates into VS 2012 and will not overwrite the originals.


xcopy /s /d "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\XNA Game Studio 4.0\ProjectTemplates" "C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\Microsoft\XNA Game Studio 4.0\ProjectTemplates"


*If it prompts a question, type 'd' for directory.


5. Using the following command line, run IDE with setup mode so that VS recognizes the copied templates. Sometimes, this will take several minutes. Wait until new line is shown.

If you never ran VS 2012 since it has been installed, jump to the step 7.


"C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe" /setup



6. Close the command prompt.



7. Run VS 2012. Now you can create a new XNA game project or open a previous XNA projects. Don't panic with the "error like" warning message. You can continue by pressing 'OK' button.




Korean:


Visual Studio 2012에서 XNA 윈도우 게임 프로젝트를 만들거나 불러오는 방법


윈도우 8과 비주얼 스튜디오 2012를 내 놓으면서, 마이크로소프트는 XNA 프레임워크를 윈도우폰에서만 사용하도록 하려는 것 같다. 이제 새 버전의 개발환경에서는 윈도우폰 게임 프로젝트에서만 XNA 프레임워크를 사용할 수 있다. 하지만 방법은 있다. 다음과 같이 해보자.



1. Windows Phone SDK 8.0을 설치한다. 그리고 최신버전의 Games for Windows 마켓플레이스 클라이언트를 설치한 다음 Windows Phone SDK 7.1을 설치한다. 윈도우 8에서는 마켓플레이스를 업데이트하지 않으면 7.1이 설치되지 않는다. 이미 XNA Game Studio 4.0이 설치되어 있다면 이 과정을 건너뛸 수 있다.


2. 비주얼 스튜디오 2012를 설치할 계획이라면 지금 설치하고 실행하지 않는다.


3. 명령 프롬프트를 관리자 권한으로 실행한다.


4. 다음 명령줄을 실행한다. 이전 템플릿을 복사해오는 작업이며 새 비주얼 스튜디오에 없는 템플릿만 복사한다. 이전에 비주얼 스튜디오 2012를 설치한 후 한 번도 실행하지 않았다면 바로 7번으로 넘어간다.


xcopy /s /d "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\XNA Game Studio 4.0\ProjectTemplates" "C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\Microsoft\XNA Game Studio 4.0\ProjectTemplates"


*폴더인지 파일인지 묻는다면 올바른 위치에 SDK가 설치되어 있는지 확인할 것.


5. 다음 명령을 이용해 비주얼 스튜디오가 새로 추가된 템플릿을 인식할 수 있도록 설치모드로 실행한다. 빈 명령줄이 나타나면 작업이 완료된 것이다. 이따금씩 몇분이 걸리기도 한다.


"C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe" /setup


6. 명령 프롬프트를 닫는다.


7. 비주얼 스튜디오 2012를 실행한다. 이제 새 프로젝트 창의 XNA 섹션에서 윈도우용 프로젝트를 볼 수 있고 기존의 XNA 프로젝트를 불러올 수 있을 것이다.





...


이전에 개발한 XNA 프로젝트가 있는데, 제길슨 DirectX로 만들껄 하는 생각이 들었다. XNA를 데스크탑에서 영원히 숙청하려는건지 마소의 행보가 궁금하다. 역시나 삼차원의 세계에서는 네이티브의 퍼포먼스를 외면할 수 없다. 개뼉다구 같은 공짜 OS 만들어 뿌려 놓고 개발자들은 쓰지도 못하는 새 버전들만 줄창 만들어내는 헐 대박 쩔어 구글도 이제 와서 네이티브 모드를 구현하지 않는가.


"안드로이드 OS는 자바 스크립트로 개발되어 왔으며 젤리빈 부터 C로 일부 포팅하기 시작했다"


필자가 만든 소문이며 믿거나 말거나이지만, 아직까지 안드로이드 OS가 네이티브 코드로 개발되었다고 믿어지지 않으며 그지 발싸게 같은 플랫폼 편의성은 공포와 충격 그자체다. 더욱 놀라운 사실은, 자바개발만 해온 개발자들은 다른 개발환경을 접해보지 못해 안드로이드 플랫폼과 개발 프레임워크가 얼마나 불편한지 모른다.

VIsual Studio 2010을 사용하면서 약간 이상한 점을 발견했다. 런타임 오류가 발생했을 때 발생지점에서 중단되지 않고 try 구문인양 루틴을 빠져나가 버리는 현상이 그것인데, 이전 버전에서도 그랬는지는 모르겠다. 그런 현상이 발생하는 정확한 조건은 모르지만, 우선은 메뉴에서 '디버그 - 예외'를 눌러 예외 중단 설정을 변경할 수 있다. 메뉴에서 보이지 않는다면 'Ctrl+D, E'의 단축키로 대신할 수 있다. 아래의 샷은 Visual C# 2010 Express 버전의 모습이다.


적절한 항목에 'Throw됨' 체크를 하고 확인을 누르면, 신나게 디버깅할 수 있다. 다만, try 구문 내의 오류도 중단 대상이 되는 듯.

참고로 예외는 개발환경의 글로벌 설정이 아니라 프로젝트별 설정이다.

*예외 중단이 잘 동작 하지만 try { ... } 안에서도 중단되는 경우가 있다. 해외 사이트를 봐도 VS 2010의 새로운 예외 중단 동작 방식에 대해 혼란을 느낀다는 것을 알고 있는데, 아직은 확실한 조건을 이해하지 못했다.

*VS 2012에서 이 혼란이 완전히 사라졌다. 예외 설정을 변경하지 않아도 예외 발생지점을 잘 표시하며 그때 그때 무시할 수 있는 옵션도 제공한다.


Visual Studio 2010에서 폼에 툴스트립의 버튼을 클릭하고 속성창에서 Image 항목의 '...' 버튼을 눌렀더니 다음과 같은 오류 창이 떴다.

값은 null일 수 없습니다. 매개 변수 이름: docData (Value cannot be null. Parameter name: docData)

 
좋은 싫든 확인버튼만을 눌러야 하는데 구글링을 해보니 주로 VS의 베타버전에 대한 포럼에서 이같은 주제가 발견되었으며, 5분간 추적한 결과 뾰족한 해결책을 제시한 곳이 없었다. 필자의 경우, 새 XNA 프로젝트를 생성하여 System.WIndows.Forms 참조와 윈폼을 추가한 후, 폼 디자이너에서 툴스트립의 버튼에 Image 속성 옆에 있는 '...' 버튼을 눌렀을 때 이와 같은 오류창을 보게 되었다. 원인은 ...

"프로젝트에 리소스 파일이 없어서 (Add a 'Resource.resx' file into your project.)"

... 였다.

솔루션 탐색기에서 프로젝트 루트를 우클릭, '추가-새 항목'을 누른 후 'Resource.resx'란 이름(다른 이름도 무관한 듯)으로 리소스 파일을 추가하고, 폼디자이너에서 다시 시도하면 오류창이 사라졌음을 알 수 있게 될 것이다.


Spring Framework 또는 Tiles를 사용해 뷰 컨트롤러를 구현할 때, 서블릿의 request handler는 ModelAndView 개체를 리턴한다. 단순 메시지 박스를 출력 또는 첨부파일 다운로드 구현에 대한 레퍼런스를 검색해보면 국내외를 막론하고 복잡하거나 거추장스러운 방법으로 구현되어 있어 가장 적은 코딩으로 구현하는 방법을 소개한다.
 
아래의 코드로 메서드를 구현한 다음 서블릿에서 호출하면 된다. 작성된 코드는 혐오스럽고 섬뜩하며 불필요한 리다이렉션이나 팝업을 생성하지 않는다.

 
파일 다운로드 구현:
String sv_name = request.getParameter("ServerFilename");
String dw_name = request.getParameter("DownFilename");
 
View view = new AbstractView() {
	@Override
	protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception
	{
		response.setContentType("application/octet-stream");
		response.setHeader("Content-Transfer-Encoding", "binary");
		response.setHeader("Content-Disposition", "attachment;fileName=\"" + dw_name + "\";");
		OutputStream outs = response.getOutputStream();
		File file = new File(sv_name);
		response.setContentLength((int)file.length());
		FileInputStream ins = new FileInputStream(file);
 
		try
		{
			/* copy stream data */
		}
		catch (java.io.IOException e)
		{
			response.setContentLength(0);
			System.out.println("File not found.");
			e.printStackTrace();
		}
		outs.flush();
	}
};
  
ModelAndView mv = new ModelAndView(view);

페이지 생성:
// 메시지박스를 출력하고 스크립트를 실행하는 ModelAndView 객체를 리턴한다.
public static ModelAndView getMessageView(final String msg, final String script) {
	View view = new AbstractView() {
		@Override
		protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {
			response.setContentType("text/html; charset=EUC-KR");
			response.setCharacterEncoding("EUC-KR");
			ServletOutputStream outs = response.getOutputStream();
			outs.println("");
			outs.flush();
		}
	};

	return new ModelAndView(view);
}

*스크랩이나 복사는 자유롭게 하세요. 하지만, 일부를 수정하더라도 '복사 + 붙여넣기'를 하여 포스팅했다면 적어도 출처는 링크해 주어야지요! 공개된 내용이라면 아주 조그맣게 출처만 명기하세요. 어려운 일이 아닐 뿐 더러 매너있어 보입니다.


CLR에서 단일 스레드로 함수 수행시 오랫동안 응답이 없을 경우 데드락으로 예외처리를 하게 되어 런타임이 중단되며 VS에서 아래와 같은 메시지가 출력된다.


The CLR has been unable to transition from COM context 0x118b008 to COM context 0x118b178 for 60 seconds. The thread that owns the destination contex
ContextSwitchDeadlock was detected
Message: The CLR has been unable to transition from COM context 0x118b008 to COM context 0x118b178 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations.

구조적인 코드변경을 하지 않고 해결할 수 있는 방법이 있다. 프로젝트가 로드된 상태에서 디버그 메뉴의 '예외(Ctrl+D, E)'를눌러 아래와 같이 'ContextSwitchDeadlock' 항목의 'Thrown' 체크를 해제한다.

 
 *출처: http://dotnetdud.blogspot.com/2009/01/clr-has-been-unable-to-transition-from.html