해당 포스트는 사실 제작년에 알았던 이슈이고..
작년에 팀분들과 이야기 하다가 정리했던 이슈인데 작성만 해놨다가 이제야 올리게 된다. ( 반성..)

그래도 나름 신기했던 동작이였고, 나중에 누군가에게는 도움이 될것 같아서 정리해둔다.

보통 HTML5 에서는 checked, selected, disabled, readonly 등의 attribute 를 사용할때 아래와 같이 쓰게 된다.

 <input type="checkbox" checked> <!-- 이렇게 쓰는걸 선호함 -->
 <input type="checkbox" checked="checked">

위에서 checked attribute 만 선언 하는것은

아래의 코드는 기본적으로 HTML5 에서 동일하게 취급되기 때문이다.

 <input type="checkbox" checked>
 <input type="checkbox" checked="">
 <input type="checkbox" checked="checked">

이 이유는 checked attribute 는 boolean attribute 이기 때문이기도 한데 추가하자면 XHTML에서는 checked=”checked” 가 유효하지만 HTML5에서는 같은 결과를 내기 때문에 checked 하나만 쓰게 된다.
프로젝트를 할때 checked=”checked” 로 퍼블리싱 되어 오는 경우도 있지만. 같은 팀에서 협업할때 checked 형태를 더 선호하고 convention도 이렇게 되어있어서 나는 개인적으로 checked 하나만 사용하는것을 좋아한다.

그렇다면 input 이 checked 되었을 경우에 css 적으로 효과를 준다면 어떤 선택자를 쓰게될까?
해당 선택자는 다음과 같다.

input:checekd{

}

여기 까지 보자면 뭐가 문제가 있나? 생각 되지만.  문제는 IE8 같은 오래된 브라우저에서 발생한다.

바로 :checked 선택자가 동작하지 않는다. 그렇다면 이 경우 fallback 을 하기 위해서  [checked] 선택자를 사용하는 방법이 있다.

input[checked]{
// 
}

이렇게 되면 IE8 이하의 브라우저에서도 해당 이슈를 해결 할 수 있다.

다만 이런 방법이 또다른 오류를 발생하게 하는데 주로 jQuery로 이 checked 속성을 이용해서 작업할때 발생하게 된다.

예를들어 아래의 코드가 문제가 된다는 것이다.

//[checked] 선택자 안먹음. 
//:checked는동작
var isChecked; 
// isChecked 는 true 또는 false
// 주로 요소들끼리 이벤트가 연결되어있는 경우 사용  
if ( isChecked ){
  $( "input" ).prop( "checked", true ); // checked 적용 
} else {
  $( "input" ).prop( "checked", false ); // checked 해제 
};

 

보통 jQuery로 DOM 조작을 하는경우 2가지 method 를 많이 쓰게 되는데 이 2개의 메소드는$().prop()$().attr() 이다. ( + $().removeAttr() 도 )

prop과 attr 가 혼용되기도 하고 실제로 많은 개발자들이 헷갈려 하기도 한다.

부연 설명을 하자면.  jQuery 1.6 이하의 버전에서는 attr 로 이 prop의 역할도 일부 수행하고 있었기 때문에 주로 개발자들이 헷갈려했고 이 이슈는 1.6 이후의 버전부터 해당 역할이 분리되었으며 jQuery 공식 사이트에서도 해당 이슈에 대해 설명하고 있다. http://api.jquery.com/prop/

그렇기 때문에 대부분 jQuery를 자주 쓰는 개발자 또는 prop과 attr 의 차이를 잘 아는 사람일수록 attr 보다 input 의 checked property를 제어할때는 prop을 사용한다.  다시 말하면 checked 와 같은  property를 조작 하려면 prop 메소드를 쓰는게 맞다. ( js 로 dom의 checked 효과를 제어 하려면. )

 

다만 위의 [checked]와 같이 IE8 대응 코드가 들어가게 된다면 prop 메소드는 제대로 된 checked 효과를 주지 못한다.

그렇기 때문에 이 경우에는 attr() 메소드를 사용해야 하고 attr( “checked”, “checked” ) 메소드를 사용했기 때문에 해당 효과를 제거 하고 싶다면 removeAttr( “checked” )를 사용해야 한다.

즉 위 코드는 아래와 같이 수정되어야 한다.

//[checked] 선택자 안먹음. 
//:checked는동작
var isChecked; 
// isChecked 는 true 또는 false
// 주로 요소들끼리 이벤트가 연결되어있는 경우 사용  
if ( isChecked ){
  $( "input" ).attr( "checked", "checked" ); // checked 적용 
} else {
  $( "input" ).removeAttr( "checked" ); // checked 해제 
};

정리하자면 2가지가 핵심이다.

1. input 의 propery를 컨트롤 하려면 prop() 메소드가 맞다. (jQuery 기준)
2. 단 해당 input 요소가 checked 되었을때 특정 효과를 주는 스타일링이 있다면 (css) 
그리고 해당 서비스가 IE8 이라면!  호환성을 위해 [checked]선택자와 removeAttr() , attr() 을 사용하자 

물론  IE8 때문에 매번 prop대신 attr을 사용하기 싫다면 prop으로 기본 처리를 하고 IE 8이하인 경우에만 removeAttr(), attr() 로 fallback 하게 짜도 된다.

( 선택자는 [checked] ,:checked 둘다 사용해서 css 를 사용해야 한다. IE8 이하만 따로 CSS 를 만들어 관리하는 방법도 있다. )

 

금년도에 프로젝트를 하면서 가장 역사적(?) 인 사건을 하나 꼽으라면.. (angualr,gulp,등등이 있지만..)

IE8 을 대상 브라우저에서 제외 시키기로 결정했다는 점이다.

사실 이 부분은 기존의 프로젝트가 탄생했을때부터 문제가 되었던 부분이며 해당 프로젝트는. IE7 을 지원했고,
IE7 에서 너무 극악으로 성능이 떨어져 어쩔수 없이 (+ 사용자도 없고..) 제외 했지만. IE8 도 만만치 않은 놈이라. 생각보다 너무 많은 고생을 했다.

제외에 대한 근거로는

  1. 사용자가 거의 없음
  2. 성능이 원하는 만큼 안나옴
  3. 개발 리소스가 너무 많이 들어감

이였지만. 한마디로 요약하자면 “IE8에 들어가는 리소스를 다른데 투입하면 완성도를 더 높힐수 있다” 였다.

이러한 근거로 기획팀을 설득했고. 접속자중에 실 사용자가 없다는게 파악되면서 결국에는 IE8을 대상 브라우저에서 제외시키기로 하였다.

결론적으로는 IE8을 제외 하면서 angular.js 도 사용가능하게 되었고. jQuery도 일부 버전 업데이트 가능하게 되었고 얻은게 더 많은것 같다.

다만.. 그동안 IE8 에서 고생했던 부분을 블로그에 짤막히(?) 정리해보고자 한다. 대략적으로 생각나는 이슈는 아래와 같다.

  1. 셀렉터 이슈
    1. pseudo 셀렉터가 잘 먹지 않으며
    2. 멀티 셀렉터도 잘 먹지 않는다.
    3. 즉.. 믿고 쓸수 있는건 id, class
    4. 이건 나중에 정리하자
  2. base64이슈 
    1. base64로 인코딩 된 이미지의 용량 제한이 발생
  3. Hover 이벤트 동작 안함
    1. $().is(“:hover”) 가 IE 78 에서는 동작안함
    2. 정리 예정
  4. change 이벤트 오류 (IE7에서 발생 )
    1. IE7에서는 change 이벤트가 정상동작안함
    2. jQuery에서는 click 이벤트로 fallback
    3. 이것에 대한 side effect 정리.
  5. property와 attribute 의 차이  $().prop을 써야하나?  $().attr()을 써야하나?
    1. 이건 jQuery 공식문서에도 나와있는데 다시 정리 필요
    2. 여기 해당 이슈에 대해 일부 정리 http://blog.kazikai.net/?p=111
  6. localStorage 이슈
    1. localStorage가 지원되지 않아. $.jStorage 를 사용했는데 여기에도 조심해야 할 이슈 있음
  7. window.opener 이슈
    1. window opener 로 창을 열고 데이터를 전달할때
    2. JSON형태의 데이터는 동작을 보장하지 못함
    3. IE 7,8,9, 심지어 10 에서도 자주 나타남
    4. 결국 데이터 전달할때는 JSON.stringify()로 .. 문자열로 변환해야함
    5. 관련 포스팅은 IE8과 9에서 발생하는 javascript memory leak 이슈

이제는 IE8 이하 브라우저를 대상으로 개발하는 경우가  없겠지만.. 나중을 위해 리마인드.( 다시 볼일 없기를..)

모바일 사파리 , 즉 아이폰의 웹브라우저에서 input요소를 이용해 UI를 개발하다보면 가끔가다 input 안에 shadow가 보인다던지. 양옆에 border가 생긴다던지 하는 의도치 않은 화면이 보이는 문제가 있다.

이건 브라우저 버그라기보다는 webkit-appearance 가 동작하기 때문이다. ( 아이폰이 단말에 맞춰서 강조 또는 ui적으로 보여줌 )

이걸 해결하기 위해서는 css 에 아래 코드 한줄이면 끝난다.

input {
-webkit-appearance: none;
}

해당 css 는 모바일 사파리 즉 아이폰에서만 발생하므로, 안드로이드 브라우저에서는 발생하지 않는다.