SimpleIsBest.NET

유경상의 닷넷 블로그

ASP.NET에서 공유 폴더 액세스 (V) : 최종

by 블로그쥔장 | 작성일자: 2005-12-15 오후 3:12:00
이 글은 오래된 전에 작성된 글입니다. 따라서 최신 버전의 기술에 알맞지 않거나 오류를 유발할 수 있습니다. 저자는 이 글에 대한 질문을 받지 않을 것입니다. 하지만 이 글이 리뉴얼 되면 이 글에 대한 질문을 하거나 토론을 할 수도 있습니다.

드디어 ASP.NET에서 공유 폴더를 액세스하는 방법에 대해 설명한 포스트 시리즈의 마지막입니다. -_-; 대부분 잘 아시는 내용임에도 불구하고 쓸데없이 글을 길게 쓴 느낌도 있지만... 그래도 한 번 정리한다는 의미에서...

시리즈 목차

Accessing Shared Folder in ASP.NET (V)

드뎌 마지막 이다. 지난 네 번째 포스트에서 ASP.NET 에서 공유 폴더를 액세스하기 위해서는 죽으나 사나 흉내내기(impersonation)이 필요하다는 것을 알았을 것이며, 이 흉내내기를 web.config 설정을 사용하느냐 아니면 직접 코딩을 사용하느냐의 선택을 하면 된다고 알았을 것이다. 사실 ASP.NET에서 공유 폴더를 액세스하는 방법이 오로지 이것 밖에 없을까?

그렇지는 않다. IIS 의 익명 사용자 계정을 바꾸는 방법도 있으며, Active Directory 환경이라면 파일 서버에서 컴퓨터 계정에 공유 폴더에 대한 권한을 주는 방법도 생각해 볼 수 있겠다. 다양한 방법 중에 마지막으로 소개할 방법은 네트워크 드라이브 연결에 대한 것이다.

Using Network Drive in ASP.NET

네트워크 드라이브는 공유 폴더를 로컬 컴퓨터의 드라이브로 매핑 하는 것을 말한다. 아주 간단하지 않은가? 사실 간단한 건 별로 없다. -_-; 사실 아주 많이, 아무런 생각 없이 사용하는 네트워크 드라이브란 것도 ASP.NET에서 쓸려고 하면 복잡도가 갑자기 증가해버리기 때문이다.

첫째로, 네트워크 드라이브는 사용자의 프로파일에 기록되는 내용이다. 뭔 말인고 하니, 현재 콘솔에 로그온 된 사용자가 TestUser 라고 하고 이 사용자가 net use 커맨드를 사용하거나 탐색기를 통해 네트워크 드라이브를 Z: 드라이브에 연결했다고 치자. 그럼 다른 사용자 TempUser가 터미널로 로그온 하면 네트워크 드라이브 Z: 가 보일까? 그렇다. 보이지 않는다. 왜냐면 연결된 네트워크 드라이브는 TestUser의 프로파일에만 기록된 설정이므로 TempUser 의 로그온 세션에는 해당 네트워크 드라이브가 보이지 않는다. 그렇다면 아무리 관리자가 네트워크 드라이브를 연결해 놓더라도 ASP.NET의 코드를 수행하는 계정이 다르다면 네트워크 드라이브가 보이지 않을 것이라는 얘기가 된다. 그래서... 말하고 싶은 것이 무엇인고 하면... 네트워크 드라이브를 설정에 의해서 연결하는 것은 대략 어렵다는 것이 되겠다. 즉, 관리자의 설정 행위에 의해 ASP.NET 어플리케이션이 네트워크 드라이브를 통해 공유 폴더를 액세스하는 것이 힘들다는 것이다.

둘째로, 일단 연결된 네트워크 드라이브는 프로파일에 기록되므로 명시적으로 연결한 네트워크 드라이브를 끊거나, 프로파일이 제거되도록 하지 않는 한 연결 정보가 계속 남아 있게 된다. 이는 심지어 프로세스가 종료한 후에도 계속 지속된다. 프로파일은 별도의 저장소에 기록되기 때문에 프로세스의 수행 여부와 무관하다. 대화형 사용자라면 로그 아웃을 하여 활성화된 프로파일을 제거할 수도 있다. 이것은 제약 사항이라기 보다는 편리한 사항인데, 매번 네트워크 드라이브를 연결할 필요 없이, 한번만 연결해도 된다는 얘기가 되겠다.

셋째로, 프로파일은 로그온 세션과 관련이 있다. 즉, 로그온 세션이 없다면 프로파일도 없다는 것이다. 대부분의 계정은 로그온 세션을 갖는다. 하지만 SYSTEM 계정과 LOCAL SERVICE 계정으로 작동하는 프로세스는 로그온 세션이 없다. 이는 곧 이 두 계정으로 작동하는 프로세스는 네트워크 드라이브 설정을 할 수 없다는 말과 상통 한다. ASP.NET에서 작업 프로세스가 SYSTEM 계정 혹은 LOCAL SERVICE 계정 하에서 작동한다면 네트워크 드라이브를 사용하여 공유 폴더를 액세스할 수 없다. 방법이 전혀 없진 않겠지만(필자도 아직 확인해 보진 못했다) 복잡한 다른 방법을 찾느니 지난 포스트의 흉내내기 기법이 더 쉬울 듯 하다.

Using Network Driver Programmatically

설정에 의해 쉽지 않다면, 코드로서 네트워크 드라이브를 연결해 버리면 되지 않을까? 그렇다. 오늘의 뽀인트는 코드를 사용하여 네트워크 드라이브를 연결해 버리면 된다는 것이다. 네트워크 드라이브는 일단 연결되면 그 설정이 프로파일에 남기 때문에 프로세스가 종료되더라도 설정은 여전히 남아 있다(로그오프에 의해 프로파일이 제거될 때까지). 또한 현재 쓰레드의 작업 계정과는 무관하다는 장점도 있다. 네트워크 드라이브를 연결하는 API는 연결에 사용할 사용자 계정 및 암호 등을 매개변수로 받기 때문이다. 즉, 로컬 계정과는 무관하게 파일 서버의 계정을 API 에 명시해 주면 되는 것이다. 로컬 계정과 무관하므로 파일 서버와 클라이언트에 동일한 계정을 만들고 암호를 일치시키는 삽질(?)을 하지 않아도 된다는 얘기와도 같다.

필자주) Windows XP/2000 의 IIS 5.x 은 aspnet_wp.exe 작업 프로세스가 IIS에 의해 종료되면 네트워크 드라이브 설정이 사라진다. 반면 IIS 6.0은 w3wp.exe 작업 프로세스가 종료하더라도 네트워크 드라이브 설정이 남아 있다. 왜 그러한가는 정확히 파악하지 못했지만 IIS 5.x 에서는 ASPNET 계정을 로그오프 시켜버리는 것이 아닌가 생각하고 있다. 아니면 말고... -_-;

그렇다면 닷넷에는 네트워크 드라이브를 위한 클래스가 있는가? 당근 없다. -_-; 하지만 우리에겐 조또 어렵지만 아쉬운 대로 쓸 수 있는 P/Invoke 란 것이 있지 않은가? 네트워크 드라이브에 관련된 API는 WNet API 이며 WNetUseConnection 등의 함수를 호출하면 네트워크 드라이브를 연결할 수 있다. 구체적인 WNet API와 P/Invoke 선언 그리고 관련 예제는 필자의 지난 포스트(네트워크 드라이브(공유 폴더) 작업하기)를 읽어 보면 될 것이므로 여기서 다시 이야기 하지 않겠다.

네트워크 드라이브는 일단 연결되면 명시적으로 네트워크 드라이브를 끊거나 로그 오프 하지 않는 한 설정이 계속 남아 있다고 했다. 따라서 매 네트워크 공유 폴더를 액세스 할 때 마다 네트워크 드라이브를 연결할 필요가 없다. 어플리케이션 시작 시점에서 한 번만 연결해도 충분하다(필자라면 Global.asax 에서 네트워크 드라이브를 연결하겠다). WNetUseConnection API 함수는 이미 연결된 네트워크 드라이브에 대해서는 리턴 값에 의해 친절히 이미 연결되었다고 알려주므로 이 반환 값에 의해 처리할 수 있을 것이다. 혹은 네트워크 드라이브에 대한 또 다른 필자의 포스트(네트워크 드라이브 목록 뽑기)에서 언급한 대로 WNet의 다른 API 들을 호출하여 이미 연결된 네트워크 드라이브 목록을 뽑아 볼 수도 있을 것이다. 구체적인 방법 및 예제 코드가 모두 포함되어 있으니 관심 있는 독자는 살펴보기 바란다.

Conclusion

전체를 대충 정리해 보자.

ASP.NET 어플리케이션에서 공유 폴더를 액세스하기 위해서는 파일 서버의 적절한 설정이 선행되어야 한다. 파일 서버는 공유 폴더에 클라이언트가 접근 가능한 계정으로 적절한 권한을 주어야 하며, 공유되는 파일 시스템 폴더 역시 해당 계정에 적절한 권한을 주어야 할 것이다. 파일 서버에서 쓸데 없이 파일 서버의 SYSTEM, NETWORK SERVICE, ASPNET, IUSR_XXX 계정에 대해 권한을 주는 것은 정말 삽질이 되겠다.

파일 서버 설정이 끝나면 ASP.NET 어플리케이션이 파일 서버에 접근할 수 있는 계정, 즉 파일 서버가 공유 폴더에 권한을 준 계정을 사용하기만 하면 된다. ASP.NET 어플리케이션이 사용하는 기본 계정들은 대부분 공유 폴더를 액세스하기 부적합하므로, web.config 의 <identity> 설정이나 "흉내내기" 코드를 사용하여 공유 폴더를 접근할 수 있는 계정을 쓰레드가 사용할 수 있도록 해야만 할 것이다.

끝... (왠지 마지막 결론이 졸라 짧은 느낌이 드는 건... 내가 너무 지쳐서 일게야...-_-; )


졸라 빡신 포스트 시리즈 였다. 5개의 글을 2주 만에 쓸려구 하니 몹시 힘들었다. 여기까지 모두 읽어본 독자라면 상당히 독한 인간으로 볼 수 있겠다. 아직도 읽고 있다니... -_-; 어찌되었건 시리즈를 모두 읽은 독자 제위들에게 심심한 감사를 드린다.



Comments (read-only)
#수고 많으셨어요. 유수석님. ^^ / 정성태 / 2005-12-15 오후 9:14:00
음... 저는 도저히 그런 글 못 쓰죠. ^^
#re: ASP.NET에서 공유 폴더 액세스 (V) : 최종 / 블로그쥔장 / 2005-12-15 오후 10:39:00
성태씨만 보면 감사할 따름입니다...
성태씨 같은 분이 제 호좁한 글을 읽어 주시는 것만도 감사한데...
이렇게 꼬박 꼬박 피드백 남겨주시고, 게다가 격려까지 해주시니 감사할 따름입니다...
#^^a 또 이러다 짜고치는 고스톱 되죠... ^^; / 정성태 / 2005-12-16 오전 9:10:00
에이... 왜캐 겸손하셔요... 제가 뭐 얼마나 대단하다고... 솔직히 유수석님에 비하면... "조족지혈" 이죠... ^^
게다가 제 블로그에 비해서... 너무 좋아서 뭐 좀 깍아내릴 게 없을 까 하고... 들락날락 하는 것 뿐입니다. 근데... 도대체가 헛점이 안 보이시넹. ^^ㅋ

유려한 블로그 디자인... 축적된 경험에서 나오는 훌륭한 수준의 글... 전문 DTP 편집가로부터 후원받고 있기라도 한 듯한 깔끔한 편집.

암튼... 제가 subscribe 하고 있는 국내 IT 블로그 중에는 유수석님 블로그가 단연 1위입니다요. ^^
#re: ASP.NET에서 공유 폴더 액세스 (V) : 최종 / 위시 / 2005-12-16 오전 9:10:00
정말~! 좋은글 감사드립니다. 글도 재미있게 잘쓰셔서
시간가는줄 모르고 읽었습니다 머리에 쏙쏙 들어오네요 ㅎㅎ
"상당히 자주찾는 즐겨찾기"에 추가 되셨음을 통보합니다 (.....)

앞으로도 부탁드립니다^^
#re: ASP.NET에서 공유 폴더 액세스 (V) : 최종 / 김형태 / 2006-04-04 오후 3:24:00
재미있게 또 쉽게 잘 봤습니다
저같은 초보에게 많은도움이 되었어요

감사^^
#re: ASP.NET에서 공유 폴더 액세스 (V) : 최종 / 정여진 / 2007-04-17 오전 12:17:00
글 잘 읽었습니다.
좋은 글 감사합니다.
#re: ASP.NET에서 공유 폴더 액세스 (V) : 최종 / 김병윤 / 2008-09-02 오전 11:32:00
독하게 읽었습니다. 감사합니다.
#re: ASP.NET에서 공유 폴더 액세스 (V) : 최종 / 김준호 / 2009-09-30 오후 3:35:00
글 정말 잘 읽었습니다.. VC2008로 네트워크 드라이브 어플리케이션을 만들어 보려구 하는데.. 네트워크 드라이브가 먼지 잘 몰라서
힘들었는데.. 감사 합니다.. 근데요..혹시 예제 파일좀 잇으시면 받을수 없을까요?.. 여기 저기 복사해서 해보는데 잘 안되서요 ;;
그리고 정말 궁금 한게 있는데요.. 네트워크 드라이브라는게 연결 할때 SSH서버와 관련이 있나요?
#re: ASP.NET에서 공유 폴더 액세스 (V) : 최종 / 김준호 / 2009-09-30 오후 3:36:00
혹시 보시면 이메일 이라도 부탁 드립니다...
k7942002@lycos.co.kr
#re: ASP.NET에서 공유 폴더 액세스 (V) : 최종 / 정형균 / 2010-03-16 오후 6:38:00
좋은글 잘 읽었습니다.
제가 웹사이트(Win2003, IIS 6.0)에서 파일서버의 한 폴더를 네트워크 드라이브(Z:)로 잡고 테스트를 했는데 드라이버가 잡히지 않아서 조언을 구하고자 글을 올립니다.
제가 시도한 방법은
1. 네트워크 드라이브를 잡는 batch 파일를 실행하는 방법 (Impersonation도 해 보았습니다.)
2. 유경상님의 알려주신 "WNetUseConnection" Win32 API를 이용하는 방법
으로 해 보았는데 잡히지 않았습니다.
이전에 1번 방법으로 잘 돌아갔었는데 IDC를 옮기면서 동작이 안되었습니다.

제 개발컴퓨터에서 실행하거나 서버에서 콘솔프로그램으로 실행을 하면 잘 동작이 됩니다.
( 제가 추측하건데 ASP.NET 계정의 권한문제 같기도 한데 그 부분에 대해서 어떻게 확인을 해야할 지 몰라서
발만 동동 구르고 있는 실정입니다.)

혹시 의심가는 부분이 있으시면 조언부탁드립니다.
#re: ASP.NET에서 공유 폴더 액세스 (V) : 최종 / 블로그쥔장 / 2010-03-17 오전 9:40:00
정형균//
네트워크 드라이브 이름(Z: 같은)은 각 계정의 프로필에 기록되는 정보입니다.
예를 들어 jack 이란 계정이 Z: 드라이브를 네트워크 폴더에 연결했다면 Z: 드라이브는
jack에게만 보이는 드라이브란 얘기지요. IIS 프로세스의 계정이 batch 파일을 수행하는 계정과
같지 않다면 IIS 프로세스에게는 Z: 드라이브는 존재하지 않습니다.
네트워크 드라이브를 잡는 계정과 IIS 계정이 일치하는지 확인하십시요.

권장되는 방법은 네트워크 드라이브 이름을 사용하는 것 보다 UNC 이름을 사용하는 것입니다.
예를 들어, Z:\Data 같은 이름보다는 \\FileServer\ShareName\Data 같은 이름을 사용하십시요.

도움이 되셨기를......
#re: ASP.NET에서 공유 폴더 액세스 (V) : 최종 / 정형균 / 2010-03-17 오전 11:56:00
아 유경상님이 말해주신 글을 보고 UNC 이름으로 하니까 성공했습니다.
감사합니다.

제가 해결했다고 좋아하고 있으니까 옆에 동료가 자기는 웹서버와 파일서버에 동일한 계정을 만들고
웹사이트에 가상디렉토리로 파일서버 공유폴더로 잡아놓고 해도 된다고 하더군요.

ㅡㅡ; 제가 생각하는 완전한 구조는 아니지만 진작 알려줬으면 좋았으려만...

어쨌거나 유경상님 덕분에 해결하게 되었습니다. 감사합니다.
좋은 하루 보내세요.