아티클

FireFox Browser Hidden 속성 값 유지 문제

2014-09-16 09:54:16

 

 개발자분들이 개발 업무를 수행하며 어렵다고 여기는 부분 중 한 가지가 크로스 브라우징 문제입니다. 크로스 브라우징과 관련해서는 수많은 이슈들이 존재하기 때문에 모두 언급하는 것은 불가능합니다. 하지만 제가 오늘 말씀드릴 내용은 개인적으로 개발 업무를 수행하며 겪었던 특이한 케이스 중 한 가지이며, 나름대로 해결한 방법을 나누고 또한 더 나은 해결 방법이 있다면 공유해 보았으면 합니다. 

 

개발자분들은 History Back이라는 용어에 관하여 대부분 아실 겁니다. 하지만 일반 사용자분들도 모두 사용하고 있는 기능인데요, 저희가 웹 서핑을 하며 흔히 사용하게 되는 "뒤로가기" 기능을 말합니다. 가령, 제가 특정 페이지에서 어떤 항목을 입력하고 있던 상황에서 실수로 다른 페이지로 이동하는 버튼을 눌려 페이지를 이동하였다면, 이전에 썼던 내용들을 기억하지 못할 수도 있고 처음부터 다시 작성해야 되는 난감한 상황에 직면하게 됩니다. 다행히도 대부분의 웹 브라우저들은 이런 상황을 예방하기 위해, History Back 기능을 제공하고 있습니다. 웹 브라우저 캐시에 전 페이지들에 대한 정보를 저장해 두고, "뒤로가기" 동작을 수행하였을 때는 이전 작업 상황 그대로를 보여 주게 됩니다. 하지만 때에 따라 주민번호나 비밀번호와 같이 개인적인 정보들에 대해서는 불편하더라도 매번 입력하도록 처리해야 하는 필요성이 생깁니다. 이 때 활용할 수 있는 기능이  AutoComplete 인데요 AutoComplete의 목적은 한번 입력했던 정보를 브라우저가 기억하고 있다가 사용자가 타이핑 하는 순간에 그와 유사한 리스트 목록을 보여 주도록 하여 사용자 편의성을 제공합니다.

 

현재 AutoComplete 기능은  IE, FireFox, Opera, Chrome, Safari 모든 주요 브라우저에서 지원 되고 있으며, 사용자가 특정 필드에 입력하기 시작하면, 브라우저는 초기 입력 값에 기초하여, 필드에 기입하는 옵션을 표시하게 됩니다. 지원 되는 HTML 엘리먼트는 <input> types: text, search, url, tel, email, password, datepickers, range, and color 이며 HTML5의 신규 스펙으로 나와 있습니다. 좀 더 자세한 내용은 WRSchools를 참조하시면 됩니다.

 

어느 정도 AutoComplete 개념에 대한 이해가 되셨다면 간단한 예제를 동작을 살펴보도록 하겠습니다.

 

< 예제 코드 FireFox Browser : Text 입력 값 전송 및 전송된 값을 출력 >

- 하나의 Form에 4개의 Input text 와 1개의 button이 있고 Script를 통해 Submit 합니다.

( 종종 개발자분들이 사용하는 방식인 javaScript를 통해 action을 재 정의하고 날리고 History Back을 하였을 때 Chrome, IE, FireFox가 다른 현상을 보이게 됩니다. Script 동작에 대한 브라우저별 차이는 이번 주제를 벗어나므로 차후 컨텐츠에서 새롭게 다루도록 하겠습니다.)

 

- 위의 코드를 실행하면 4개의 "텍스트 입력 창"이 생기고 1개의 "전송 버튼"이 생깁니다. 각각의 텍스트 입력 창에 1, 2, 3, 4를 입력하고 전송 버튼을 눌려 전송된 값을 출력 합니다. 다음으로 History Back(뒤로가기) 키를 누르면 각각의 "텍스트 입력 창"에 입력했던 1, 2, 3, 4가 그대로 유지되어 있음을 알 수 있습니다.
지극히 정상적인 결과이며 웹 표준을 잘 준수하고 있습니다.

만약, 특정 "텍스트 입력 창"에 입력하는 정보가 개인정보 및 보안이슈로 매번 새롭게 입력되길 원한다면 앞서 설명드렸던 autocomplete를 활용할 수 있습니다.
autocomplete="off" 라는 속성을 추가하게 되면, 자동완성 기능의 상실뿐 아니라 History Back 동작에서도 텍스트 값을 초기화 시킵니다.

< 예제 코드 FireFox Browser : autocomplete 속성 추가(default on) >

지금까지 살펴 본 내용을 간단히 요약해 보면 History Back 동작 수행 시 기본적으로 입력 값이 남아 있습니다. 만약에 값을 남아 있지 않도록 하고 싶다면 autocomplete를 꺼주시면 됩니다.

아마 지금쯤 글을 읽어 보시며 "그래서 뭐가 문제라는 거지 ?" 라고 의문을 가질 수 있을 것 같습니다. 지금까지의 예제는 가시적으로 보여 드리기 input type text를 사용하여 입력된 값을 유지하거나, 지우는 방식을 보여 드렸습니다. 하지만 실제로 문제가 되었던 부분은 Hidden 속성이었습니다. Hidden 속성은 개발자분들이 자주 사용하는 input 속성으로 가시적으로 보일 필요 없이, 이후 페이지에 사용될 파라미터의 전달 혹은 검색 조건 적용 등과 같이 다음 페이지에 넘겨줘야 할 데이터 정보를 가지고 있는 속성입니다. 바로 앞의 Input type text와 같은 경우, History Back 이후 데이터 값이 남아 있는 경우 특정 값을 넘겨주고 싶지 않다면 "텍스트 입력 창"에서 지워 버리면 그만 이지만 Input type hidden과 같은 경우는 말 그대로 숨겨진 값이므로 사용자가 수정할 수 있는 데이터 값이 아닙니다.
이해하기가 어려울 수 있으니 "백문이 불여일견" 코드예제와 STEP BY STEP으로 문제 상황을 재현해 보겠습니다.

< 예제 코드 FireFox Browser : Hidden 속성 값 유지 문제 >
하나의 Form에 2개의 Hidden 속성과 2개의 Button이 존재하며 각각의 버튼은 하나의 Form을 공유하며 각각의 hidden 속성에 1, 2의 값을 적용한 뒤 전송하게 됩니다. 동작을 살펴보도록 하겠습니다.
STEP 1 : "전송1 버튼"을 눌러 Hidden 1의 값을 전송합니다.
STEP 2 : 1의 값이 정상적으로 넘어 왔습니다. OK!
STEP 3 : History Back을 통해 첫 페이지로 돌아 온 뒤 "전송 2 버튼"을 눌러 Hidden 2의 값을 전송합니다.
STEP 4 : 2의 값이 정상적으로 넘어 왔습니다. OK! 
Huk!!! 저는 2의 값을 적용해서 전송하였지 이전에 전송했던 1의 값을 원하지는 않았습니다. 

보시는 바와 같이 저는 각각의 버튼을 눌렸을 때 해당되는 하나의 값이 전송되기를 기대했지만 하나의 폼을 공유 함에 따라 이전 데이터 값이 남아 있게 되는 잘못된 결과를 받게 되었습니다. 실제 코드는 더욱 복잡하기 때문에 수많은 파라미터 값 중 한 두 개의 값이 남아있었다는 것을 눈치채기가 어려울 수 도 있겠죠... ㅡㅜ

그럼 무엇이 문제 였으며, 나름대로의 해결책을 알려 드리도록 하겠습니다.
무엇이 문제였을까요?
저희가 Back End 객체 지향 개발을 할 때, 개발을 추구해야 하는 방향성에 대하여 SOLID 원칙이라는 것이 있습니다. 그중 S에 해당하는 단일 책임의 원칙(Single Responsiblility Principle)이라는 항목이 있는데요. 말 그대로 하나의 Class는 하나의 책임을 가져야 한다는 것입니다.  개인적으로 이번 문제의 Case에서도 이와 유사한 개념으로 생각해 볼 수 있을 것 같습니다. 제가 예제로 보여 드렸던 코드에서는 하나의 Form 내부에서 두 개의 페이지 이동 버튼을 두고 Hidden 속성 또한 공유하고 있습니다. History Back의 동작을 살펴보기 앞서 책임이 분리되지 못했던 것입니다.

해결 방법은 무엇일까요 ? 

가장 좋은 해결 방법은
1. 책임의 분리
가장 좋은 해결 방법은 "무엇이 문제였을까요?"를 보시면 개발자분들이라면 대부분 예상하셨겠지만 근본 문제를 해결하는 것입니다. 책임을 분리하는 것이죠. 하나의 폼에 하나의 버튼과 관련 Hidden 속성을 제공하여 한 가지 동작을 하도록 구성하는 것입니다.
다음과 같이 Form을 두개로 분리하고 두 개의 동작을 구분하도록 구현하는 것입니다. 그리고 차후 컨텐츠에서 말씀드리겠지만 form.action의 값을 스크립트에서 재정의 하는 것은 좋은 방법이 아닙니다(Browser 별 동작 차이가 있음). 되도록이면 Form 엘리먼트 자체에 Action을 걸어 주는 것이 좋습니다.

2. 스크립트 단에서 재정의
말씀드린 것처럼 첫 번째 방법이 가장 좋은 방법이지만, 개발자들은 항상 시간의 압박이 있죠. 그리고 이미 로직 자체가 복잡해져서 함부로 변경했을 때 사이드이펙트가 발생할 수 있습니다. 그렇다면 특정 행동에 대하여, 스크립트 상에서 hidden 속성을 초기화 시켜 주고 필요한 데이터 정보만을 넣어 주면 됩니다.

3. AutoComplete 활용
좋은 방법은 아니지만 앞서 말씀드렸던 Autocomplete를 활용할 수 있습니다. autocomplete='off'는 input type text에서 history back 동작 시 기존에 작성했던 정보를 지웁니다. 하지만 이를 hidden 속성에서도 동일하게 동작 시킬 수 없는 이유는 autocomplete spec에서 hidden 속성은 지원하지 않기 때문입니다. 그럼 어떤 방법이 있을까요? input text를 사용하고 css를 통해 blind 처리를 해버리면 hidden과 비슷한 개념으로 사용할 수 있습니다.

결론적으로, 저는 코드의 초기 설계부터 1번과 같이 역할의 분리를 명확히 하는 것이 최우선이고 부득이할 경우 2번과 같이 재정의를 하시는 것이 맞다고 생각됩니다.
그리고 3번은 방법은 이런 방법으로도 가능하겠구나 정도만 아시면 될 듯합니다. 

첫 입사 이후 올리는 포스팅이라 주저리 주저리 말이 많았던 것 같습니다. 그리고 이 방법이 정답이라고 말씀드릴 수 도 없을 것 같습니다. 서론에서 말씀드렸던 것 처럼 더 좋은 방법이 있다면 알려 주시고, 유익한 정보들을 공유할 수 있는 널리가 될 수 있기를 기대합니다
감사합니다.
댓글 0
댓글을 작성하려면 해주세요.