자바스크립트에서 많이 사용하고 있는 Date 객체의 경우에는 toISOString 이라는 메소드를 지원한다.

평소에는 해당 메소드를 쓸일이 없지만 Date 함수를 통해 만들어진 Date 객체의 경우에는 yyyymmdd
형태가 아니기 때문에 간혹 보다보면 아래와 같은 코드로 사용하는 경우가 많다.

let currentDate = new Date();
let currentDay = currentDate.toISOString().substr( 0, 10 );
// currentDate == 'YYYY-MM-DD' 와 포맷으로 리턴

실제로 Date 객체를 계산하거나 전달할때 상당히 유용한 방법이라 대부분 많이 사용하고  있다.
(심지어 오픈소스에서도..) 다만 이 메소드가 생각보다 치명적인 오류가 될 수있다.

즉 사용할때 조심해야 할 부분이 있다.
우선 현재 날짜를 다음과 같이 2월 1일로 수정하자 시간은 오전 2~3시 정도로 잡으면 된다.

스크린샷 2017-02-01 오전 2.42.23

그 다음 브라우저 콘솔을 열어서 위 스크립트를 쳐보자

결과가 어떻게 나오는가?

예상했던 결과는 ‘2017-02-01′ 일 것이다.
( 2017은 연도에 따라 변경될 수 있겠지만 2월 1일이므로 2월1일로 예상했을 것이다. )

하지만 이 결과는 2017-01-31 로 나오게 된다. (?)

스크린샷 2017-02-01 오전 2.43.11

그래서 다시 currentDate 를 쳐보면
currentDate는 Wed Feb 01 2017 03:16:07 GMT+0900 (KST) 와 같이 정상적으로 2월 1일이 리턴되는데
정확한 날짜가 currentDate객체에 저장되었는데도 결과값이 다르게 나온다.

그렇다면 이 2개의 결과가 다른 이유는 무엇일까?

이 이유는 Date 객체의 toISOString 메소드는  ISO 포맷의 문자열로 반환하는데
이때 ISO 포맷은 타임존으로 UTC 타임존의 zero offset을  사용하게 되면서 발생하게 된다. 

즉 우리가 사용하는 타임존이 아닌 UTC 타임존으로 나오게 되고 날짜가 다르게 표현될 수도 있다.
우리 나라 시간은 해당 시간의 UTC+09:00 기준으로 나오기 때문에 9시간을 더해야 맞다.

조금 더 헷갈리면 아래의 코드를 쳐보면 알 수 있다.

currentDate.toUTCString();

스크린샷 2017-02-01 오전 2.43.17

역시 1월 31일로 나오게 된다.  여기에 9시간을 더하면 다음날 3시16분이 되므로 위에 currentDate 에 저장된 값과 일치 하게 된다.

오픈 소스들에서 문제가 안된이유는 아마도 오픈소스 소유자들의 국가들은 UTC 타임존이 zero offset이라 이슈가 되지 않아서 그럴 것 이고
결론적으로 toISOString() 은 UTC 타임존 zero offset을 사용하지 않는 국가에서 사용할때는 문제가 되므로 함부로 사용하면 안된다. 

 

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

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

보통 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 이하 브라우저를 대상으로 개발하는 경우가  없겠지만.. 나중을 위해 리마인드.( 다시 볼일 없기를..)

화면 개발시에 iframe은 계륵 같은 존재라고 생각한다.

css 를 분리하고 유지/보수 를 따로 할수 있으므로. ( 또한 배포도..)
서비스에는 상당히 유용하지만.  실제 서비스에 활용했을때는 생각보다 이슈가 많이 발생한다.

이 이슈도 개발인 서비스에서 부득이하게 iframe을 사용했을때 발생했던 문제이다.

일단 대부분의 iframe 주소는 정적으로 사용되게 되는데

< iframe src="{{주소}}" > </ifame>

이 주소가 API 형식으로 특정 데이터를 받아와서 삽입 되었을때 문제가 발생하였다.

대략적인 흐름은 다음과 같다.

  1. 부모창 Loading
  2. 부모창 api 호출
  3. api 결과값에 있는 주소로 iframe 의 src 변경 ( $(“iframe”).attr(“src”, “주소”); )
  4. iframe도 로딩

이러한 흐름을 갖고 있는 화면을 만들었는데. 이상하게 간헐적으로..
해당 페이지에서 뒤로가기 버튼을 눌렀을때. 부모창의 이전 페이지로 가야 하는데 iframe 의 창이 부모창의 모습이 나와있는 형태로 보이는 이슈가 발생했다. 즉 아래 화면처럼 ..


사실 저 이슈는 개발 PC에서는 거의 발생하지 않았고 성능이 느린 윈도우 PC 에서 주로 발생하여서, 개인적으로는 브라우저 버그 또는 특정 플랫폼 버그( 윈도우…) 라고 생각하고 해결할 생각이 없었다.

하지만 시간이 남아 처음부터 다시 생각했고 문제의 원인을 찾았다.

문제는 # 이라는 값 때문이였는데. iframe 의 src 값은 비어있기 때문에 초기 값은 “” 즉 null 값이 들어갈수 밖에 없었고. 이게 웹 유효성 검사에서. 지적당해서 해당 값에 의미없는  값인 “#” 이 들어가게 되었다.  이게 api를 통해 iframe 주소 값을 받아오게 되면

$( "iframe" ).attr( "src", "" );

란 javascript로 변경 되었는데. 이게 타이밍 이슈가 있는 로직이였다.

설명을 다시 하자면.  # 은 자기자신 즉 현재 부모창을 가르키는 역할을 하는데 iframe 에 값이 없는것이 아니라. 현재 부모창을 다시 한번 로드하는 형태이다.

대부분의 api 는 빠르게 요청되어서.
1. api로 주소 받아온다음
2. iframe 다시 로드
되는데. 일부 느린 PC에서는 1번 부분보다 자식창의 현재 # 값의 로딩이 더 빠른경우가 발생했다.

그 이후에 2번이 로딩 되니 당연히 iframe의 주소 히스토리는
1)# , 2)새롭게 로드된 화면  순서일수 밖에 없으며 뒤로가기를 누르고나 history.back(), history.go(-1)을 하게 되면 1) 번 #으로 돌아갈수밖에 없다. ( 그래서 위에 화면처럼 나온다. )

이제 문제를 확인했으니. 해당 이슈를 회피하거나. 근본적인 이슈를 제거 해야 한다.
HTML에 src에 값이 들어가있지 않으면.. 특정 QA를 통과할수가 없으므로. #은 무조건 사용해야 하는 상황이기 때문에 javascript로 처리해야 하는데…

그래서 아래 코드를 바꿔 보기로  했다.

$("iframe").attr("src","새로운주소");

아예 iframe  자식 화면의 브라우저 히스토리를 갱신해버리면 # 값으로 뒤로 갈 이유가 없을것이라고 판단 위 코드를  다음과 같이 변경 했는데 결과적으로 문제가 해결되었다.

$("iframe").get(0).contentWindow.location.replace("새로운주소");

위 코드는 iframe 의 히스토리를 날려버리기때문에 뒤로가기했을때 전혀 문제가 발생하지 않는다.

별거 아닌 코드인것 같지만. 생각보다 이슈 찾고 고민하느냐고 삽질을 많이했다. 특히 위 이슈는 재현이 안되므로..

정리하면.

1. 동적으로 iframe 주소가 로딩되는경우
2. $().attr() 방식보다는
3. DOM기본 함수의 location.replace를 사용하자.

 

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

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

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

input {
-webkit-appearance: none;
}

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

금년도 들어서 가장 해결하기 어려웠고.. 왜 그렇게 동작하는지 이해가 안갔던 이슈다.

상황은 다음과 같다.
1.parent.html 에서 child.html 을 오픈 함
2.child.html 은 특정 동작을 취하면 parent.html에 저장된 window.setAction()호출
3.window.setAction( jSonData ) 와 같이 인자로 오브젝트 데이터를 전달하게 된다.
4.전달된 데이터는 전역 변수( 해당 스코프 안에서 ) parent.html 에서 저장하고 있다가. 특정 동작이 실행되면 ajax로 백엔드에 전달

언뜻보면 간단한 흐름을 가진 구조다. 하지만. 3번과 4번에서 IE8&9에서 문제가 발생한다. 즉 jsonData가 전달 당시에는 제대로 전달이 되는것 같지만, ( 디버그로 확인해보면 전달 당시에는 정상적인 값이 출력된다. ) 사용하려고 하면 null 도 아닌 null같은 쓰레기 값이 들어가 있어서 그 동작은 정상적으로 수행되지 않는다.

문제를 좀 객관화 하자면 IE 8&9에서는 부모페이지와 자식 페이지 상의 전역함수로 호출할경우 파라미터에 복잡한 JSON형태의 데이터가 들어가면 해당 데이터를 직접 저장하는게 아닌. 데이터가 생성되었을때 기준으로 shallow copy를 해오는것 같다. ( 이부분이 맞는지는 사실 정확히 모르겠다.. 자료를 찾아봐도 없다. )

이상황에서 자식창이 종료가 되면 shallow copy된 데이터도 같이 날아가버리는 현상이 발생한다.

문제에서 사용했던 data는 아래와 같다.

"data":[{
  "key1":"value",
  "key2":"value",
  "keyList":[{
    "key3":"value",
    "key4":"value"
   }],
  "key5":"value"
  },
  {
  "key1":"value",
  "key2":"value",
  "keyList":[{
    "key3":"value",
    "key4":"value"
  }],
  "key5":"value"
 }];

아무런 문제가 없는 일반적으로 사용하는 이중 배열 형태의 데이터다. 단지 data[0].keyList 가 한번더 배열인형태로 좀 복잡할 수가 있지만 (?) 트리 형태의 구조를 표현할때는 저렇게 구조를 잡는게 맞다.

당연히 해당 데이터는 circular-reference 로 만들어진 것도 아니였다. 그래서 해당 문제를 해결 하기 위해 일단 문제를 단순화 했다.

위의 과정중에
3. window.setAction( jSonData ) 와 같이 인자로 오브젝트 데이터를 전달하게 된다.
jsonData 부분에 위에 명시했던 데이터를 객체 형식으로 저장해서 과정4번 과정까지 진행해봤다. ( 즉 아래와 같이..)

var jsonData =[{  "key1":"value",
  "key2":"value",
  "keyList":[{
    "key3":"value",
    "key4":"value"
   }],
  "key5":"value"
  },
  {
  "key1":"value",
  "key2":"value",
  "keyList":[{
    "key3":"value",
    "key4":"value"
  }],
  "key5":"value"
 }];
window.setAction( jSonData );

정말로 신기한건 위와 같이 하면 문제가 해결 된다는 것이다.

하지만 실제로 웹서비스에서 저런 정적인 데이터는 불가능하므로, 다시 변수로 저장을 시도해봤다. 4번의 페이지에서 전달받았을 당시에는 IE8에서 디버깅을 해보면 문제없이 전달이 되므로.. 해당 변수 데이터를 클로저로 저장도 해보고. localStorage 에 저장도해보는 작업을 해본다.

하지만 결론은 모두 다 null도 아닌 쓰레기 값(?) 이 저장되며 여전히 4번 순서에서 오류가 났다..

그러다가 4번의 전달받은 데이터를 JSON.stringify( jsonData)로 해서 스트링으로 저장도 시도 해봤지만. 해당 데이터를 JSON.parse( )로 다시 JSON으로 만들때 circular reference 오류가 발생했다.
( circular reference가 나는 이유는.. 해당 데이터가 정상적이지 않기 때문에..)

정말 이리저리 삽질을 진행하다가 결국에는 문제를 해결했다.
아래는 해결한 방법이다.

var jsonData =[{  "key1":"value",
  "key2":"value",
  "keyList":[{
    "key3":"value",
    "key4":"value"
   }],
  "key5":"value"
  },
  {
  "key1":"value",
  "key2":"value",
  "keyList":[{
    "key3":"value",
    "key4":"value"
  }],
  "key5":"value"
 }];
jsonData = JSON.stringify( jsonData );
window.setAction( jSonData );

즉 자식 페이지에서 부모 페이지로 전달할때 JSON.stringify()로  스트링화 해서 전달한후 다시 JSON.parse() 해서 사용했더니 정보도 저장이 잘되었고 4번순서의 ajax 요청에도 정상적으로 활용할 수 있었다.

* 참고로 JSON관련 라이브러리는 jquery-json 을 사용했습니다. ( 그래서 문제없이 IE에서 JSON라이브러리를 사용가능)

뭔가 해결은 냈지만.. 원인을 정확하게 파악을 못해서 여전히 찝찝하다.

그 이후에 여러가지 방법으로 찾아봤는데.
https://support.microsoft.com/en-us/kb/2711084
위와 같은 내용이 존재한다. 요약하자면

IE 8에서는 윈도우창을 열었다 닫을때 참조하는 순환참조형태의 배열이 있다면 메모리 누수현상이 발생함” 이다.

물론 내가 만든 저 배열의 순환참조는 없었지만. IE 8에서 메모리 누수 현상이 있기때문에 내가 만든 패턴도 저 이슈에 걸렸다고 생각이되는데. 정확한 이해가 되지 않는데 다시 말하자면 나는 순환참조 배열이 아니다..

결국 의문점이 더 해소가 되지 않아서 더 찾아봤다. IE 에서 메모리 누수현상은 꾸준히 지적되어왔으니 내가 겪은 이슈도 분명히 있을것이라 생각하면서..
여러 검색 끝에 아래와 같이 결과물이 나왔다. (  MSDN..)

https://msdn.microsoft.com/en-us/library/bb250448(v=vs.85).aspx
해당 글에는 공식적으로 메모리 누수 패턴에 대해 설명하고 있다.

1.Circular References : 순환참조
2.Closures: 클로져
3.Cross-Page Leaks: 크로스 페이지 누수
4.Pseudo-Leaks : 슈도 누수(?)

드디어 찾았다. 3번째 크로스 페이지 누수다.

원문은 다음과 같다.

Cross-page leaks are often very small leaks of internal book-keeping objects as you move from site to site.

즉 사이트에서 사이트간의 이동 할때 내부적으로 저장된 객체해서 메모리 누수가 종종 발생한다고 한다.  이것을 스트링으로 저장하고 활용했기때문에 해결 가능했던 것이고 IE 8&9에서는 해당 이슈가 지적되며 개발자가 이런 객체로 저장하고 활용하는것을 어느정도 방어적으로 코드를 작성해야 한다고 나와있다.

많이 돌아와서.. 결국 이슈를 해결하고 원인도 알았다. ( 사실 이 포스팅을 준비하면서 더 찾아보다가여기까지 결론에 왔다.. 원래는 “~~해서 해결했다. 그래도 모르겠다. ” 였는데..)

한줄로 요약하자

IE 8&9 에서 사이트간 이동할때 객체형태의 데이터를 전달할때는 신중해야한다. (메모리누수 현상 발생할수도 있음 )

추가 : 포스팅 하고 해당 페이지의 3번째 이슈에 대한 상세 설명을 보면 DOM과 객체간의 이슈를 중점적으로 다루고 있다. 다만 내  이슈의 경우에는 자식창이 종료되면서 자식창이 가지고 있던 객체가 가비지 콜렉터에 의해 지워지면서 발생하는 이슈인것 같다.

이놈의 IE8 은 제발 없어져야 (.. ) 할 브라우저이다.

웹개발시에 이미지가  base64 encode되어서 들어가는 경우도 사실상 존재하긴한다.

(물론.. 절대경로 형태로 특정 이미지를 load하는게 더 좋은 방법이다. )

금년도 진행했던 프로젝트에서 텍스트 에디터로 summernote 라는 오픈소스를 사용했는데. ( http://summernote.org/  ) 다른 텍스트 에디터에 비해 최신 브라우저 지원이 잘되어있으며, bower  와 같은 도구도 지원하고 ui도 필요한것만 있어서 아주 유용하게 사용했다. (라이센스도 MIT이고.)

다만 이미지 업로드를 붙히는 과정에서. 여력이 안되서. 초기버전에는 summernote에서 지원하는 base64 encode 방식으로 이미지 삽입 기능을 사용했는데.

해당 기능을 사용하면 아래와 같이 HTML에 삽입이 된다.

<img style=”width: 275px;” src=”data:image/jpeg;base64,/9j/…..M0gH//2Q==” data-filename=”3.jpg”>

물론 간단한 이미지를 올리고 표시하는 경우에는 별도의 이미지 업로드 서버가 없이 사용할 수 있어, 상당히 유용한데.

문제는 이 데이터가 증가하면 DB가 감당하기도 어렵고, 조회 할때 너무 많은 데이터를 불러와서 API형태의 웹페이지에서는 그렇게 좋은 방법 같지는 않다.

게다가 여기서 문제가 발생했다.

QA를 통해 IE8에서 해당 이미지가 안보인다고 이슈라이징이 되었는데..

문제는 내 개발 PC 는 IE10이고. 개발자도구로 IE8로 렌더링/브라우저 모드를 변경해도 해당 이슈는 재현되지 않았다.

그래서 여러방면으로 찾아본 결과 아래의 글을 찾기에 이른다.

http://stackoverflow.com/questions/10159500/internet-explorer-and-base64-image-display

즉 IE8 에서는 32KB이상의 base64 encode 이미지를 지원 하지 않는 다는 것이다.

base64이미지를 사용하려면 32KB보다 낮은 이미지를 사용해야 하는데 사실상 안전성을 위해 사용하지 않는 편이 더 좋은것 같다. (급할땐 어쩔수 없지만..)

이후에 해당 기능은 별도의 이미지 서버에 올려서 URL을 리턴받는 방식으로 개발 교체 되었고, 지금은 문제가 발생하지 않는다..(하지만 이미이전에 만들어놓은 데이터가 속을 썪이고.. 있다.. )

만약 base64 인코딩된 이미지로 HTML에 삽입해서 페이지를 개발했는데 IE8에서 이슈가 발생한다면 빨리 이미지업로드 서버구축후 ( 아니면 오픈된 다른것을 사용하던가. ) 해당기능은 교체해야 할 것이다.