이 글은 소박한 오픈형 워드프레스 팀블로그 "업데이트 후 종료"에 먼저 올린 것입니다.
혹시 개발 얘기는 아니지만 사소하게 나누고 지나가고 싶은 얘기가 있나요? udnxt.com을 업데이트 후 종료하세요!
폼을 입력하는 사용자는 딱 두 가지에만 관심이 있다.
그밖에는 사용자가 그 어떤 것에도 관심이 없다는 사실을 기억할 필요가 있다. post_title
이 required
값인지 내가 이모지를 입력할 수 있는지 없는지 내가 유효한 우편번호를 입력했는지 어떤지 사용자는 알지도 못하고 관심도 없다. 중요하니까 한 번 더 말한다. 사용자는 폼을 입력할 때 기술적인 부분은 전혀 관심 갖지 않는다!!!
이 사실을 순순히 받아들이는 것이 생산성에 도움이 된다. 나도 “아니 왜 사람들은 내가 기껏 다 도움말 부분에 써놓은 걸 안 읽고 지들 멋대로 행동해 놓고서 나한테만 지랄이야” 했는데, 어느 날인가 생각을 바꿔서 “그래 내가 여기서 경고를 쓰고 안내를 쓰고 백날 해봐야 어차피 뻑날 건 또 뻑난다” 하고 현실을 받아들이자 일이 좀더 편해졌다.
기왕 들이닥칠 사용자 불편이라면 좀더 편안한 마음으로 처리하거나 심지어는 예측하고 선대응하고 싶지 않은가? 그래서 “휴먼 에러와의 싸움” 시리즈를 준비했다. 내가 그간 (그리고 지금) 웹애플리케이션 개발 작업을 하다가 “아 맞아 이런 거 있었지” 했던 부분들을 까먹지 않으려고 만든 치트시트이므로, 필요하다 싶은 부분은 체크하시고, 관심 없으면 밑의 ‘추천’만 누르고 지나가시기 바란다.
문자열의 sanitizing은 웹개발 영역에서 (특히 한국 웹이라면) 한 번씩은 만져보는 똥이다. 웬만한 인젝션 공격 방어는 대다수 웹프레임워크가 해주고 있으니 여기서는 인코딩이 걸릴 만한 것들을 짚어보자.
(그 전에 한 가지만: 설마 아직도 EUC-KR
에 미련을 못 버리고 UTF-8
을 안 쓰고 있는 건 아니겠지?)
(원래 지금 인터넷 세상은 당연히 UTF-8
을 써야 하지만 특히) 사용자가 이모지를 입력할 것 같은 필드는 무조건 UTF-8
로 값을 넘겨야 하고, 그걸 저장하는 칼럼은 utf8mb4_*
형식의 콜레이션을 줘야 한다. 처음부터 새로 만드는 거라면 그냥 이렇게 하면 되는데 문제는 과거 레거시가 존재할 때다. 이때는 세 가지 선택이 있다.
utf8
에서 utf8mb4
로 올리는 것은 별문제 없음.네이버 블로그에게 길들여진 한국인들은 편집기에 관해 다음과 같은 믿음이 있다.
em
태그를 쓰라고? 그게 뭔데?h1
, h2
태그란 게 있어? 몰라 내 알 바 아님. 제목이 필요하다면 36pt
짜리 굵은 글씨를 만들면 될 뿐이야.당신은 이 믿음과 싸우고 싶은가? 위지윅 에디터는 이 질문을 놓고 고르면 된다.
span style=”어쩌구”
를 떡칠해도 괜찮다면) 네이버 Smart Editor를 써주자. 이 편집기가 문제를 일으킬 때는 사람들은 당신에게 따지지 않고 그냥 꾹 참을 것이다.몇 번을 강조해도 지나치지 않은 게 기본값이다. 가급적 프론트에서 미리 만들어 제공하도록 하고, 못해도 DB 저장 직전에는 뭔가 만들어야 한다.
지역 기반 커뮤니티를 만들 때 그 지역의 주소가 입력될 것이라고 기대되는 경우가 있다. 이때 사람들은 절대 전체 주소를 넣지 않고 상세주소부터만 적는다. 물론 우편번호 입력기를 이용해서 주소를 받는다면 상관 없겠지만 예컨대 단순 문자열을 구글이 처리 가능한 주소로 바꾸려면 반드시 적당한 전체 주소 변환을 해줘야 한다.
비슷하게, ‘인원수’를 입력할 때가 있다. ‘아동’의 수는 0
이 될 수 있을지 몰라도 설마 ‘성인’의 인원수까지 0
일 리는 없으므로, 인원수를 입력받는 폼은 처음 뜰 때부터 아예 기본값을 그 최소값인 1
로 갖고 있는 편이 좋다.
내 경험에 사람들은 폼 중간쯤의 큰 입력칸(=textarea
)과 최하단의 파란 버튼(=submit
) 사이에 무엇이 있어도 절대 알아채지 못한다. 따라서 여기 위치한 입력칸들은 사용자가 빈 입력을 넣는 실수를 반드시 저지른다고 보아야 한다. 이런 입력칸들에 대한 기본값/폼검증 처리를 특히 더 유념해야 하는 이유다.
input type
을 “email”
이나 “number”
, “url”
로 주면 이런 건 대부분의 모던 브라우저들이 알아서 format validation을 해 준다. 하지만 날짜와 같이 특정 포맷이 필요한데 아직 공식 지원은 없는 타입들은 어떨까? 뾰족한 수가 없다.
날짜(+시간) 입력은 헛짓거리 하지 말고 순순히 외부 라이브러리의 도움을 받도록 하자.
date type
의 input
에 대한 입력 UI를 제공한다. 하지만 어떤 브라우저는 그렇지 않다. 다소 불편하고 bulky해 보이더라도, 어느 브라우저에서나 똑같은 모양으로 뿌려지는 일시 선택 UI를 제공하는 편이 불평 불만을 훨씬 줄여준다.strtotime()
등)해서 어떻게 때려맞추면 될 것도 같지만 이것은 본질적으로 취약하고 부족하다. 예컨대 사용자가 datetime
포맷을 따라야 하는 칸에 date
만 입력했다면 이것은 무슨 의미인가? 사용자가 실수로 ‘2018-02-29’
를 입력했을 때 이 함수가 떨굴 exception
을 사용자에게 뭐라고 알려줘야 할 것인가? “당신은 올해가 윤년이 아니었다는 걸 몰랐나 봅니다?”검증이 언제 이루어져야 하는가의 문제는 실무 웹개발자들을 외롭게 하는 주제 중 하나다. 나로서는 현재 대원칙 하나만을 체득한 상태인데, 최소한 그 결과를 너무 늦게 알려주지는 말아야 한다는 것이다. 예컨대 비밀번호가 유효하지 않을 경우 그 사실은 가입 버튼을 누르기 전에 통지되어야 한다. 사람들은 폼을 제출하는 순간 비밀번호 필드의 값을 까먹기 때문이다.
2000년대까지만 해도 모든 폼은 제출된 순간에만 뭔가를 할 수 있었으므로, 그 시대의 프레임워크들은 폼 검증 후 원래 제출값을 그대로 다시 돌려주기 위해 플래시 데이터라는 궁여지책을 만들어냈다. 이것이야말로 안 쓸 수 있다면 쓰지 말아야 할 대표적인 코딩 역사의 유산 중 하나다. 왜냐하면 이게 사용자 입장에서는 폼 작성이 끝난 줄 알았는데 안 끝났다고 우기는 생트집이거든.
기술적으로도 이 직관이 맞는 게, 플래시 데이터를 이용해 폼을 다시 뿌리는 작업은 엄밀히 말하자면 어딘가로 이동을 한 것이기 때문이다. 사용자는 분명 빈 화면을 보면서 “앗 이게 어딘가로 이동하고 있구나 = 폼 작성이 드디어 끝났구나” 하는 기대를 품는데 그 끝에 나오는 내용이 아까 그 폼 그대로라면, 이건 사용자의 기대를 저버리는 일이며 순 헛걸음에 불과하게 된다.
그런 의미에서, 폼이 맥락적으로 아예 다른 페이지로 넘어가야만 하는 (신규 가입과 같은) 경우가 아니라면, 특정 필드를 검증하든 폼 전체를 제출하든 가급적 AJAX를 사용하자. 심지어 폼 제출 자체를 처리할 때도 AJAX는 기존 입력값을 따로 어떻게 할 필요가 없는 반면 전통적인 액션 방식은 각종 세션 지랄 끝에 그 값을 살려서 다시 넘겨야 하는데, 일부러 그렇게 복잡하게 살 이유가 있을까.
서브밋 이벤트가 문제가 된다고? 놀랍게도 문제가 된다.
input type=button
↑ 이런 게 있다고 하면, 이걸 누르면 무슨 일이 일어날까? 이론상 아무 일도 일어나지 말아야 한다. 근데 어떤 브라우저들은… 저 버튼을… 누가 시키지도 않았는데… submit
버튼으로 사용한다!!! 왜? 왜?? 모르겠다. 아마 브라우저 개발자들도 엉망진창으로 만들어진 입력폼과 사람들의 불평불만에 넌더리가 났나 보지. 어쩔 수 없다. So they got laundry about it and we gotta deal with it.
아무 처리도 되어 있지 않은 제목 input
과 본문 textarea
가 있다고 치자. 사용자가 그 input
을 눌러 입력을 하고 엔터를 치면 무슨 일이 일어날까? 폼 전송이 되어 버린다! 휴대폰 키보드에서는 이 경우 아예 엔터키 표시가 “전송”이라고 뜰 것이다!
물론 그건 당신 잘못이 아니고 이건 너무나 부조리한 일이다. 하지만 우리는 사용자와 싸울 이유가 전혀 없으므로, 각종 필드에 required=”required”
속성을 주고 13
번 키가 눌렸을 때의 처리를 넣고 폼전송시 e.preventDefault()
를 호출하는 등의 안전 울타리를 쳐주는 것이 더 나은 선택이라 할 것이다.
너무 빨리 전송되어도 문제가 된다고? 놀랍게도 문제가 된다. 정확히는, 사용자에게 한 번 뭔가를 물어보고(컨펌받고) 지나가야 하는 종류의 폼이 존재하기 때문에 그런 폼에 대해서 그 단계를 생략하면 문제가 된다. 물론 모든 폼입력에 대해서 컨펌 프롬프트를 띄우는 것은 옳지 않다. 하지만 때로는, 기획자도 디자이너도 사용자도 누구도 필요하지 않을 거라고 생각하는, 그러나 인류에 대한 믿음 부족 때문에라도 분명히 필요할 게 뻔한 컨펌이 존재한다는 사실을, 개발자들은 잊으면 안 된다.
사용자들의 인터넷이 너무너무 느려서 요청-응답 통신 자체가 중간에 실패할 수 있다는 여지를 항상 두어야 한다. 이 주제 하나만 가지고도 이 시리즈 한 편을 더 쓸 수 있을 정도다. 여기서는 폼에 관해서만 논하자면…
제목 그대로다. 사람들이 공들여서 오랜 시간 동안 쓸 것 같은 textarea
는 무조건 임시 저장 루틴을 구현해 놓도록 하자. 이 구현은 복잡하게 하자면 한없이 복잡해지기는 하지만, 폼 전송간 불의의 데이터 손실 상황을 불필요하게 처벌하지 않으려면 임시 보관 개념 내지 보관함 개념을 고려할 필요가 있다. 예를 들자면 자기 로그인 세션이 만료되는 줄도 모르고 뭔가를 쓴 다음 제출을 하는 경우…가 어디 있냐고? 믿기 힘들겠지만 누군가의 현실이다!!!
제 2탄은 파일을 다룰 생각이다. 생성, 수정, 업로드/다운로드 등 대환장 주제가 한둘이 아니다. ㅋㅋ
좋은 포스트 감사합니다 :)
그리고 또 벨로그에 오신 것을 환영합니다!!
훌륭한 필력을 갖고 계신 것 같아요!
2탄도 기대 됩니다.