외부 서비스를 이용해서 홈페이지를 만들었는데, 기본 템플릿으로 만들어진 사이트가 IE11 에서만 엄청 느리게 동작하는 현상이 있었다. 고민하다가 Edge 로 동작시키는 방법이 있지 않을까 하고 열심히 찾았다. 그러다 
stackoverflow.com/a/65258124 이런 글을 보았다.

주소에  microsoft-edge:google.com 이런 식으로 주소를 이동시키면 Edge 가 있는 경우 Edge 브라우저를 강제로 열 수가 있다. chrome 에서도 된다. 아래와 같은 팝업이 뜬다.

IE11 에서는 위와 같은 창이 없이 그대로 뜬다. 
IE11 일 때 edge 로 이동시키고 싶으면 아래와 같은 자바스크립트를 삽입하면 동작한다. 

<script>
if(navigator.userAgent.indexOf('MSIE')!==-1
|| navigator.appVersion.indexOf('Trident/') > -1){
    window.location.href = 'microsoft-edge:' + window.location.href;
}
</script>

IE11 일 때만 Edge 를 강제로 열어서 현재 주소로 이동시킨다. 다만 Edge 가 없는 환경일 때는 문제가 발생한다. 자바스크립트만으로는 Edge 브라우저가 있는지 없는지 알 수 없다. 그러나 IE11 사용자부터가 소수이고, windows 7은 이미 기술지원이 완료되었기 때문에 IE11 사용자의 컴퓨터 환경에 Edge 브라우저가 있다고 생각된다.  때문에 이렇게 사용하면 더 많은 사용자를 고려할 수 있을 거라 판단된다. 

예전에는 IE6 이 없어져야 한다고 생각했는데, 이제는 IE11 이다. IE11 때문에 개발하기 너무 힘들다. 

 회사 홈페이지 속도 개선을 하다보니 한계에 부딪혔다. DB 결과에 대해 cahce 을 적용하는 방법이 있긴 한데, 뭔가 전반적인 변경을 해야 한다. (이런것은 처음부터 고려하기가 참 어렵다. 속도개선이라는게 늦은 부분을 개선해야 하기 때문이다. 성급한 최적화는 개발 속도를 느리게 한다. ) 우선 빠르게 lighthouse (developers.google.com/web/tools/lighthouse?hl=ko) 점수를 개선할 방법을 찾다보니, 쉽게 적용할 수 있는 것을 많이 적용하고 있었다. 이젠 lighthouse 가 추천하는 것들 중 어려운 것만 남았다. 

 lighthouse 에서 추천하는 방법은 아니었지만 쉽게 속도 개선을 할 수 있는 방법을 생각해보니 HTTP/2 Server Push 를 적용하는 방법을 생각해 보았다.  HTTP/2 Server Push 란 웹접속시 리소스(이미지, 웹폰트, javascript, css 등등)을 같이 보내주는 방법이다. 일반적으로 브라우저가 HTML Document 요청되면 이 HTML 문서가 파싱되고 엘레멘트안에 이미지나 웹폰트 등등을 파악하고 다시 서버에 요청한다. 어차피 서버에 다시 요청될 것 서버에서 미리 보낸주는 방식으로 속도를 개선하겠다는 것이다. (물론 해당 리소스가 cache 되어 있는 경우, 불필요한 전송으로 트래픽 낭비이다. 이른 cookies 를 통해 개선할 수도 있다.)

Nginx 에서는 http2_push 를 통해서 이를 적용할 수 있다. (www.nginx.com/blog/nginx-1-13-9-http2-server-push/) 잘못하면 불필요게 트래픽을 낭비할 수 있어, 기본적으로 보내도 손해볼 것 같지 않을 매우 작은 사이즈의 이미지만을 첫 페이지에 적용했다. 

아래와 같이 적용할 수 있다. 

location = / {
        include uwsgi_params;
        uwsgi_pass .............
        ............
        http2_push /static/img/check.svg;
        http2_push /static/img/facebook.svg;
        http2_push /static/img/delete.svg;
        ............
    }

이렇게 설정할 경우 chrome dev tool 에서는 아래처럼 보이게 된다.

css 와 js 에도 적용이 가능하겠지만 이 경우 파일이 크다보니 이미 해당 파일의 cache 가 있는 경우 트래픽 낭비로 생각되었다. http2_push 를 적용한 파일들은 inline 으로 적용해도 상관없는 svg 파일이다. 

css 와 js 의 경우 cookies 에 버전번호에 대한 정보를 남겨두고 이 버전정보가 오래될 경우에만 HTTP/2 Server Push 하는 방법이 가장 효율적일 것 같다. 그런데 버전관리하는게 Nginx 와 통합되지 않으면 뭔가 수동으로 작업하는 것 같아 보여 배포하는데 불편할 것 같아서 그런 방식을 적용하지 못했다. 

 

 개인적으로 프로그램을 디버깅 할 때 로그보다는 break point 를 잡아서 확인 하는 것을 선호한다. 그래서 개발환경을 구축할 때 어떻게든 break point 로 디버깅 할 수 있는 환경을 구축하려고 노력한다. 그러나 이미 다른 사람들이 발견한 버그 특히 사용자가 버그에 대해서 잘 설명하지 못하는 경우에서는 꼭 로그 분석이 필요하다. 이 경우에서는 특정 값에 대해서 어떤 동작으로 반응한느지에 대한 문제인 경우가 많아서 어떠한 상태였고, 어떠한 상태로 데이터를 넣었는지 확인이 필요하다.

 Nginx 에서 로그 포멧에 대한 환경설정은 /etc/nginx/nginx.conf 내에서 세팅한다. 그리고 로그를 생성하는 코드는 /etc/nginx/sites-available 폴더내 파일에서 설정한다. 

참고 : stackoverflow.com/a/49701625 
log_format testlog '$remote_addr - $remote_user [$time_local] '
               '"$request" $status $bytes_sent '
               '"$http_referer" "$http_user_agent" "$request_body"';

여기서 가장 중요한 것은 $request_body 이다. 여기에 post 로 전달하는 key 와 value 가 key1=value1&key2=value2 형태로 전달된다. 

이 로그가 좋긴 하지만 경우에 따라서는 민감한 정보가 파일로 저장되는 문제가 있다. 로그인 하는 패스워드라든지 패스워드 변경시에 current_password 와 new_password 가 저장될 수 있다.  이 로그를 지워주는 방법이 있다. 
참고 : stackoverflow.com/a/45047352
map 이라는 directive를 이용하면 regular expression 을 이용할 수 있다. 그리고 nginx 가 1.11.0 이상이면 regular expression 을 이용해서 치환을 유연성있게 사용할 수 있다. 그래서 패스워드가 들어가는 부분을 **** 로 별표시로 변경 시킬 수 있다. 

map_hash_bucket_size 256;

map $request_body $req_body_pw1 {
    "~*(?<start>.*)(?<pw_name>password)=(?<pw_value>[^\&]*)(?<end>.*)"      $start&$pw_name=****$end;
    default        $request_body;
}
map $req_body_pw1 $req_body_pw2 {
	"~*(?<start>.*)(?<pw_name>current_password)=(?<pw_value>[^\&]*)(?<end>.*)"       $start&$pw_name=****$end;
	default        $req_body_pw1;
}
map $req_body_pw2 $req_body_pw3 {
	"~*(?<start>.*)(?<pw_name>new_password)=(?<pw_value>[^\&]*)(?<end>.*)"       $start&$pw_name=****$end;
	default        $req_body_pw2;
}
map $req_body_pw3 $req_body_pw4 {
	"~*(?<start>.*)(?<pw_name>confirm_password)=(?<pw_value>[^\&]*)(?<end>.*)"       $start&$pw_name=****$end;
	default        $req_body_pw3;
}


log_format  post_log '$remote_addr - $remote_user [$time_local]    "$request" '
	'$status $body_bytes_sent "$http_referer" '
	'"$http_user_agent" $request_time "$req_body_pw4" '

 

위에서 current_password 나 new_password 나 confirm_password 를 적절하게 변경해서 사용한다면 원하는 대로 masking 이 가능하다. 다만 이 형태가 다양하다면 $req_body_pw숫자 의 개수를 늘려줘야 한다.