bootstrap 4 에서 modal 창이 떠 있을 때 javascript 로 clipboard 에 text 를 복사려 하려고 했는데, 잘 동작하지 않았다.
일반적으로 clipboard 에 text 를 복사하는 동작은 보통 아래 처럼 구현한다.

function copyToClipboard(val) {
	var t = document.createElement("textarea");
	document.body.appendChild(t);
	t.value = val;
	t.select();
	document.execCommand('copy');
	document.body.removeChild(t);
}

 

body 에 textarea 를 추가하고, 거기에 copy 하고 싶은 text 를 집어 넣는다. 그리고 그 textarea 를 선택해서 copy 명령어를 보낸다. copy 가 끝나면 불필요한 textarea 를 삭제한다. 이 코드는 ios safari 에서도 잘 동작한다. 

어째든 이렇게 코드를 구현했는데, bootstrap modal 창이 떠 있을 때 이상하게 동작하지 않았다. (물론 원인도 한 참 후에 알게 되었다. ). 결국 찾아보니 stackoverflow 에 답이 있었다. 
 https://stackoverflow.com/a/48147679/6652082

$.fn.modal.Constructor.prototype._enforceFocus = function() {};

이렇게 처리 하면 된다. 

파이썬 flask 웹 프레임워크 버전을 2.0 대로 업데이트 하는 테스트를 진행하였다. 기존에는 request.is_xhr 이라고 해서 ajax 로 전달되는 것인지 아니면 http 에서 페이지 이동으로 들어온 것인지 구분해주는 코드가 있었다.( XHR 은 javascript 의 XMLHttpRequest 를 의미 한다.) flask 가 버전업 되면서 flask 에서 사용하는 werkzeug 버전도 업그레이드 되면서 더 이상 request.is_xhr 가 지원되지 않는다. 그래서 그 이유를 확인하다가  HTTP 헤더 중 X-Requested-With 헤더를 알게 되었다. (X- 가 붙은 헤더는 표준이 아니라는 의미라고 한다. )

 Javascript 를 이용한 네트워크 요청과 HTML 에서의 여러 method(get, post) 를 이용해서 접속하는 경우를 구별하는 원리를 몰랐는데, 관습적으로 Javascript 를 이용할 때  X-Requested-With 헤더값을 XMLHttpRequest 로 해서 전달하는 것으로 보인다.  jquery 의 ajax 구문을 이용할 때는 이 헤더가 기본적으로 설정되는 것 같다. 요즘 많이 사용하는 axios 같은 라이브러리의 경우 axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 와 같이 수동으로 넣어(https://github.com/axios/axios/issues/1322#issuecomment-449626391 ) 주는 식으로 적용하는 것 같다. (X-Requested-With 가 관습적으로 넣은 것이라 request.is_xhr 가 사라지는 것으로 추정한다. )

 기존 flask 에서는 이 헤더가 XMLHttpRequest 값으로 오면 request.is_xhr 가 true 로 전달되는 것 같다. 어째든 이제는 헤더값을 직접 확인 해야 할 것 같다.  request.headers.get('X-Requested-With') == 'XMLHttpRequest' 일 때 ajax 이라고 생각해야 될 것 같다. 

https://developers.google.com/calendar/api/guides/create-events#python
구글 캘린더 API 에서 일정(Event)를 생성할 때 start, end 를 datetime 이 아니라 date로 생성할 수 있다. 이 때 end 의 date 는 포함되는 날짜가 아니다. 파이썬의 range 함수처럼 생각하면 된다. range(1, 5) 의 의미는 1, 2, 3, 4 까지이다. 
만일 2021-01-13일만 지정하고 싶다면 아래와 같이 end 를 다음날로 지정해야 한다. 

{.......,   "start": {"date":"2021-01-13"}, "end": {"date":"2021-01-14"}, ......}


만약 start, end 를 같은 date 로 지정할 경우 구글 캘린더 웹 사이트에서는 잘 보이는데, 구글 캘린더 앱(안드로이드)에서는 일정이 보이지 않는 문제가 있다.  

이것을 몰라서 오늘 너무 많은 시간을 소모했다.