Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

input type="file"에서 찾아보기 버튼 바꾸기

웹에서 파일을 첨부하려면 <input type="file" />을 사용한다. 자동으로 찾아보기 버튼이 생기고 파일브라우징이 가능하다.

사용자 삽입 이미지


input type=file은 약간의 특징이 있다. 파일을 업로드하는 기능을 가진 특성때문에 다른 input타입과는 다르게 약간의 제약이 있다. 그건 스크립트를 이용해서 제어하는 것을 막고 있는 것인데 그것 때문에 다루기가 좀 쉽지 않다. 하지만 그것보다 문제되는게 저 "찾아보기..."버튼이다. 점점 디자인이 강조되고 있는 가운데 기본적으로 뜨는 찾아보기 버튼은 웹디자이너에게는 걸리적거리는 것 같다.

항상 디자인을 받을 때마다 찾아보기 버튼대신에 이미지버튼으로 된 디자인이 왔었는데 이번에 여러가지 테스트를 해보았다. 결론적으로 말하자면 찾아보기버튼은 바꿀수 없다.(적어도 내 지식 수준에서는...) 물론 이에대한 태클도 있을꺼라고 생각한다.



가장 쉽게 생각할 수 있는 것이 input type=file을 input type=text와 이미지버튼의 조합으로 대치하는 것이다.


<input type="text" size="30" id="txt" />
<img src="" onclick="document.getElementById('file').click();" />
<input type="file" size="30" id="file" style="display:none;" onchange="document.getElementById('txt').value=this.value;" />

위와같은 모양이다. 인풋파일은 보기에는 인풋텍스트와 버튼의 조합형태이기 때문에 앞에 인풋텍스트를 넣어놓고 그옆에 디자인된 이미지 버튼을 넣은 뒤에 인풋파일은 스타일을 주어서 보이지 않게 하는 것이다. 이미지 버튼을 onclick했을 때 인풋타입의 객체에 click()이벤트를 주는 구조이다. 파일선택하는 창도 아주 잘 뜬다. 인풋파일에 onchange이벤트를 주어서 파일선택해서 값이 들어갈때 인풋텍스트로 값을 복사해서 넣어서 찾아보기버튼을 이미지로 교체한 듯한 효과를 주는 것이다.

실제적으로 인터넷을 찾아보면 찾아보기 버튼 교체에 대한 위의 소스가 엄청 많다. 잘못된 정보의 대표적인 예라고 할 수가 있다. 서버쪽은 제대로 돌려보지도 않고 클라이언트쪽만 테스트 해보고 잘된다고 올려진 소스를 서로 계속 퍼나르고 있는 상황이다. ㅡ..ㅡ

인풋파일은 보안문제상 Read Only이기 때문에 스트립트로 값을 입력하는 것을 허용하지 않는다. 소스상으로는 아주 잘 돌아가는 거서럼 보이지만 막상 submit버튼을 누르면 전송이 되는 것이 아니라 인풋파일의 값이 clear되어 버린다. 스크립트로 실행한 것은 초기화 시켜버리고 다시한번 submit버튼을 눌러야 POST전송이 일어난다.

쉽게 말하면 이구조로는 절대 파일 업로드를 받을 수가 없다.



그래서 다른 방법을 찾기 시작했다.


<input type="text" size="30" id="txt" />
<span style="overflow:hidden; width:61; height:20; background-image:url(/images/button.gif);">
    <input  type='file' id="file" style="width:0; height:20; filter:alpha(opacity=0);" onchange='document.getElementById('txt').value=this.value;'>
</span> 

그래서 찾은 방법이 위의 방법이다. 방법은 앞에서 얘기했던것과 거의 비슷하다. 파일명을 보여줄 인풋텍스트를 하나 보여주고 그 뒤에 span을 둔다. span은 찾아보기 버튼을 대체해 주는 역할을 한다. 크기를 정해주고 배경색으로 버튼 이미지를 지정해 준다. 그리고 그 span안에 인풋파일을 넣어주는데 여기서 스타일로 width를 0px를 주고 alpha값으로 투명도를 0을 준 것이다.

이렇게 하면 인풋파일의 파일명이 나타나는 부분의 width가 0px가 되기 때문에 나타나지 않고 찾아보기 버튼의 크기는 조절할 수가 없기 때문에 앞에 넣은 인풋파일뒤에 바로 찾아보기 버튼이 위치한다. 하지만 투명도가 0이기 때문에 실제 위치하고 있기는 하지만 보이지가 않고 span의 배경인 버튼 이미지가 보이는 구조이다.

하지만 여기에 약간의 문제가 있다. 일단 여기서 중요한 역할인 투명도를 나타내는 alpha값은 IE에서만 유효한 스타일값이다. Firefox에서는 투명도를 -moz-opacity:0; 를 사용해야 하는데 이걸 사용해도 Firefox에서는 IE같은 효과가 나지 않는다. 배경으로 지정된 이미지버튼이 나오지 않는다. 머 이것만으로도 요즘같은 분위기에서는 의미가 없다고 본다. 그리고 눈에 보이는 버튼이 실제버튼이 아니고 실제버튼은 투명하게 있는 버튼이기 때문에 클릭을 하면 실제 버튼보다 작게 점선이 생겨서 보기에 별로이다. 또한 저 소스에서는 width가 61로 설정이 되어있는데 브라우저마다 다른지는 모르겠지만 IE7에서는 찾아보기 버튼이 103px이기 때문에 이미지버튼도 103에 맞추어 져야 크기에 맞출수 있을것 같다.

앞의 방법보다는 좀 낫긴 하지만 이 방법에도 확실히 문제가 있다.


하지만 이런 방식으로 실제 구현해서 사용하려고 하면 더 큰 문제에 부딪히게 된다. 인풋파일의 경우 파일을 선택했다가 올리기가 싫어지면 그냥 지워주면 되는데 여기서는 편법을 써서 인풋텍스트를 눈앞에 보여주었기 때문에 지워도 인풋텍스트만 지워질뿐 실제 인풋파일의 내용이 지워진것이 아니다. 결국은 아예 한번 선택하면 지우지 못하도록 막아주던가(이렇게 할수는 있지만 기존의 사용자경험을 깨버린다고 생각하기에 별로 하고싶지 않았다.) 인풋텍스트의 값을 지우면 인풋파일의 값도 지워줘야 한다. 

그럴려면 천상 스크립트로 값을 지워져야 하는데 보안문제 때문에 인풋파일은 스크립트가 값을 바꿔버리는 것을 허용하지 않는다. 다른거에 하던 식으로

document.getElementById("file").value = "";

는 아예 먹지도 않는다.  대신에...


document.getElementById("file").select();
//document.execCommand('Delete');   
document.selection.clear();

위와 같은 자바스크립트 코드를 이용하면 해당 인풋파일의 값을 지워줄 수 있다. 2번줄에 주석처리한 부분은 3번줄 대신 2번줄을 사용해도 된다. 둘줄 하나로 하면 된다. 물론 이 소스

(어찌된 일인지 글을 여기까지만 작성된채 공개됐다. 그럴리가 없는데 약간의 문제가 있었던듯.. 기억을 더듬어 글을 마무리 한다. 2008.7.17)
도 돌아가지 않는다. 위에 말한대로 보안문제 때문에 submit()할 때 문제가 생긴다.

인터넷을 찾아보다 보면 CSS를 이용해서 수십줄로 바꾸는 것도 있긴 한데 해보진 않았다. 버튼 하나 바꿀려고 여러문제는 가지게 되거나 아니면 수십줄의 코드를 넣는게 과연 의미가 있을까 하는 생각이 든다.

차라리 그 노력이면 요즘 게시판 등에서 많이 하는 추세대로 플래시 컴포넌트를 이용해서 바로바로 파일을 올릴수 있게 만드는 것이 훨씬 좋은 선택이라고 생각된다. 찾아보기 버튼은 왠만하면 그냥 쓰자.
2008/06/29 01:12 2008/06/29 01:12