[Thu Aug 31 21:58:33.018393 2023] [ssl:warn] [pid 19064:tid 444] AH01909: localhost:443:0 server certificate does NOT include an ID which matches the server name [Thu Aug 31 21:58:33.068371 2023] [ssl:warn] [pid 19064:tid 444] AH01909: localhost:443:0 server certificate does NOT include an ID which matches the server name [Thu Aug 31 21:58:33.086154 2023] [mpm_winnt:notice] [pid 19064:tid 444] AH00455: Apache/2.4.52 (Win64) OpenSSL/1.1.1m PHP/7.4.28 configured -- resuming normal operations [Thu Aug 31 21:58:33.086154 2023] [mpm_winnt:notice] [pid 19064:tid 444] AH00456: Apache Lounge VC15 Server built: Dec 23 2021 11:00:40 [Thu Aug 31 21:58:33.086154 2023] [core:notice] [pid 19064:tid 444] AH00094: Command line: 'D:\\jkSpace\\redmine\\redmine-4.2.4-0\\apache2\\bin\\httpd.exe -d D:/jkSpace/redmine/redmine-4.2.4-0/apache2 -f D:\\jkSpace\\redmine\\redmine-4.2.4-0\\apache2\\conf\\httpd.conf' [Thu Aug 31 21:58:33.091358 2023] [mpm_winnt:notice] [pid 19064:tid 444] AH00418: Parent: Created child process 17280
<!DOCTYPE html>
<html lang="KO">
<head>
<meta charset="UTF-8">
<title>computed</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
<div id="main">
<p>원본 문장 : "{{ sOriginalMessage }}"</p>
<p>대분자로 변환된 문장 : "{{ fnUpperCaseMsg }}"</p>
</div>
<script>
new Vue({
el:'#main',
// data는 머스태시 안에 넣을 값이 간달할 때 사용
data:{
sOriginalMessage: 'How are you?'
},
computed:{
// sOriginalMessage의 데이터를 모두 대문자로 변환
// 이때 데이터에 접근하기 위해 this 사용
fnUpperCaseMsg: function(){
return this.sOriginalMessage.toUpperCase();
}
}
})
</script>
</body>
</html>
* 머스태시 사용 : 문자열을 {{}} 로 감싸고 엘리먼트(P) 값 표시 - {{ sOriginalMessage }} : 문자열 변수 대체
- icons : 스플래시스크린에 표시할 아이콘 이미지 - 128dpi에 가까운 이미지를 화면에 표시 > src : 이미지 경로(절대/상대)
> sizes : 이미지 픽셀 크기
> type : 이미지 파일 유형
03-3 메인 화면 작성하기
* 010303 [DoIt!실습]index.html 파일 작성하기
- 0103/ex03_practice >index.html 파일 작성하기
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<!-- PWA 매니페스트 파일 연결, 상태 표시줄 색상을 흰색으로 변경 -->
<link rel="manifest" href="manifest.json">
<meta name="theme-color" content="#ffffff">
<!-- 모바일 기기 뷰포트, 브라우저 주소 표시줄의 파비콘 설정 -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- <meta name="viewport" content="width=device-width, user-scalabe=no"> -->
<link rel="shortcut icon" href="images/icons/favicon.ico">
<link rel="icon" type="image/png" sizes="16x16" href="images/icons/favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="images/icons/favicon-32x32.png">
<title>안녕하세요! PWA by JS</title>
<style>
html, body{
/* html, body 모두 높이를 100%로 고정시켜야 플렉스 박스 동작 */
heigth: 100%;
background-color: #F3A530;
color: #ffffff;
}
/* 화면에 출력될 div엘리먼트를 화면 가운데 배치하도록 설정 */
.container{
height: 100%; /* 높이를 100%로 고정 ㅇ*/
display: flex; /* 플렉스 박스로 배치 */
align-items: center; /* 상하 가운데 정렬 */
justify-content: center; /* 좌우 가운데 정렬 */
}
</style>
</head>
<body>
<div class="container">
<h1>안녕하세요!</h1>
<img src="/images/hello-pwa.png" alt=""/>
<p>by JK</p>
</div>
<!-- 서비스워커 등록 -->
<script>
if('serviceWorker' in navigator){
navigator.serviceWorker
.register('/service_worker.js')
.then(function () {
console.log("서비스워크가 등록됨!");
})
}
</script>
</body>
</html>
* 언어설정 : 설정하지 않으면 실행할 때마다 ‘디른 언어로 번역하시 겠습니 까?’라고 질문
- <html lang="ko">
* 뷰포트설정 - 모바일 브라우저로 PC 사이트 접속시 작게 보이는 현상 방지
- content의 어트리뷰트 값 설정
> width-=device-width : 몹바일 기기의 해상도로 너비값 자동 설정
> initial-scale=1 : 모바일 기기에서 확대하거나 축소 기능 허용
> user-scalable=no : 모바일 기기에서 확대하거나 축소 기능 제한
* 플렉스 박스 설정 : 화면에 표시할 글자와 이미지를 배치할 레이아웃 - 플렉스 박스(flex box) - 모바일 기기의 크기를 자동으로 고려한 최적의 레이아웃 표현 > html, body 높이를 100%로 고정 필요
* 화면 요소 배치
- 화면에 실제 출력되는 내용 : container 클래스를 선택자로 지정한 div 엘리먼
> div 엘리먼트를 화면 가운데 배치하도록 지정
* 서비스워커 등록 : if('serviceWorker' in navigator)...
- navigator.serviceworker에는 ServiceWorkerContainer라는 읽기 전용의 객체가 반환 > 이 객체 안에 있는 register() 메서드를 이용해
모바일 브라우저가 서비스 워커를 지원하는지 확인한 후
> 서비스 워커를 등록
- then() 메서드는 register() 메서드의 실행이 성공하면 실행
> register() 메서드가 실행되면 콘솔에 성공 메시지를 줄력
03-4 서비스 워커 만들고 실행하기
* 010304 [DoIt!실습]캐시를 관리하는 서비스 워커 만들기
- 0103/ex03_practice >캐시를 관리하는 서비스 워커 만들기
* 서비스워커
- 브라우저와분리되어 독립해서 실행 가능
- 캐시, 푸시 알림 , 웹 API와 연동 등 다양한 기능을 별도로 수행
> 실습대상 : 필요한 파일을 캐시하여 메모리에 저장
* service_worker.Js 파일 생성
// 캐시 제목과 캐시할 파일 선언
const sCacheName = 'hello-pwa'; // 캐시 제목 선언
const aFilesToCache = [ // 캐시할 파일 선언
'./', './index.html', './manifest.json', './images/hello-pwa.png'
];
// 서비스 워커 설치하고 캐시파일 저장
self.addEventListener('install', pEvent => {
console.log("서비스 워커 설치함!");
pEvent.waitUntil(
caches.open(sCacheName)
.then(pCache => {
console.log("파일을 캐시에 저장함!");
return pCache.addAll(aFilesToCache);
})
);
});
//고유 번호를 할당받은 서비스 워커 작동
self.addEventListener('activate', pEvent => {
console.log("서비스워커 동작 시작됨!");
});
// 데이터 요청을 받으면 네트워크 또는 캐시에서 찾아 반환
self.addEventListener('fetch', pEvent => {
pEvent.respondWith(
caches.match(pEvent.request)
.then(response => {
if(!response){
console.log("네트워크에서 데이터 요청!", pEvent.request);
return fetch(pEvent.request);
}
console.log("캐시에서 데이터 요청!", pEvent.request);
return response;
}).catch(err => console.log(err))
);
});
- 오프라인 동작을 위해 서비스워커가 캐시에 저장하
> 캐시 제목과 캐시할 파일 선언 : 캐시 제목은 서비스워커와 구분되도록 고유이름 사용
* 서비스 워커 설치 및 캐시 파일 저장 - install 이벤트
- 서비스 워커의 생애 주기
> [install -activate -fetch] 순서로 이벤트 발생
* install : PWA를 설치 - 서비스워커의 첫번째 생애주기
> 설치전 : installing
> 설치 후 대기 :installed
* 서비스 워커가 제대로 설치되면 pEvent에 포함된 waitUntil() 함수를이용해 비로소 캐시에 필요한 파일 저장 * 서비스 워커가준비될 때 캐시를 저장하는 것 : ‘프리 캐시(pre-cache)’ - waitUntil() 함수는 installing 상태에서 프리 캐시가 완료될 때까지 대기
- activate : 설치후 상태
* activate 이벤트 : 서비스 워커의 두 번째 생애 주기
- 서비스 워커 업데이트 : 서비스 워커가 고유한ID를 발급받아 브라우저에 성공적으로 등록되면 동작 > 웹 브라우저 의 개발자 도구에서 확인
* 서비스 워커 설치 후 - 업데이트 등의 이유로 캐시 제목 변경 : install 이벤트 처음부터 다시 발생
- 테스트할 때는 'Update on reload’ 체크 박스를 선텍 : 매번 캐시제목 변경 서비스워커등록 생략
> 새로 고침 : 기존 서비스 워커 ID 제거 -> 새로운 ID를 부여 : install 이벤트부터 새로 시작
* 앱 업데이트 시 서비스 워커 새로운 내용으로 교체 : activate 이벤트
- 활성중 : activating
- 활성후 : activated
* 서비스 워커의 내용 업데이트 : - 먼저 캐시 제목과 프리 캐시 파일 변경 : 새로운 서비스 워커ID로 새로운 캐시 내용이 설치 목적
- activating 상태에서 waitUntil() 함수를 사용해서 기존 캐시 제거 : 코드작성
* 오프라인 전환할 때 동작 - fetch 이벤트
- 서비스 워커의 마지막 생애 주기는 fetch 이벤트로부터 시작 > 이벤트가 발생 사례 : 브라우지 〈새로 고침〉 * 동작
- 온라인 상태 : 서버에서 조회
- 오프라인 상태 : 캐시에서 조
* 서비스 워커의 유무에 따른 fetch 이벤트 처리
- 1 : 온라인 - 서비스워커 없음
- 2 : 오프라인 - 서비스워커 있
* PWA 오프라인 동작 구조 : fetch 이 벤트 발생 후 (pEvent에 있는)respondWidth() 함수 활용
- respondWidth() 함수 : 결과값 준비 까지 네트워크 요청 일시 정지
> 캐시, 모바일 기기에 임시로 저장한 데이터로 처리
* service_worker.js
- 오프라인 처리 : PWA가 실행되면 캐시에서 가져올 데이터를 caches.match() 함수로 캐시 저장소에서 검색
> 발견된 캐시(response)를 반환하도록 코드를 작성
- 캐시를 발견하지 못하면 fetch(pEvent.request)를 통해 네트워크에 요청
* 실행 실습 후 서비스워커 삭제 : 다음실습 준
* 서비스 워커의 주요 이벤트 복습하기
- install : 서비스워커가 설치될 때 실행(앱설치) - 캐시파일 저장
- activate : 서비스워커 설치 후, 업데이트 역할 - 기존캐시 제거
- fetch : 서비스워커 설치 후 다음 실행 때 실제 작업할 내용 작성 - 브라우저 서버요청시 오프라인 상태면 캐시파일 조회