지난 포스팅에 XMLHttpRequest로 HTTP 통신을 정리했었다.
https://teddy8.github.io/2019/08/01/JS-xmlhttprequest/
이번 포스팅은 Fetch-api라는 Promise기반의 비동기로 처리하는 방법을 정리한다.
공식문서 https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Fetch API 예제</title>
</head>
<body>
<div id="user"></div>
<script>
const userEl = document.getElementById('user');
const reqPromise = fetch('https://naver.com', {
headers: { Accept: 'application/json' },
method: 'GET'
});
reqPromise
.then(res => {
if (res.status >= 200 && res.status < 300) {
return res.json();
} else {
return Promise.reject(new Error(`error ${res.status}`));
}
})
.then(data => { userEl.innerHTML = data })
.catch(error => alert(error));
</script>
</body>
</html>
XMLHttpRequest처럼 CORS가(지난번 포스팅) 발생할 수 있으며,
XMLHttpRequest처럼 와 비교했을 때, 가독성이 조금 더 증가 된 느낌이다.
XMLHttpRequest로 데이터를 전송하여 Request하고 결과값을 Response 받을 수 있다.
XMLHttpRequest 객체를 통해 비동기로 처리하는 방법을 정리한다.
비동기의 장점은 지난번 포스팅에서 설명했듯이
Response 받는 동안 다른작업을 바로 진행할 수 있다.
예제 소스코드
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>XMLHttpRequest 예제</title>
</head>
<body>
<div id="user"></div>
<script>
function httpGet(url, successCallback, errorCallback) {
const req = new XMLHttpRequest();
req.onload = () => {
if (req.status >= 200 && req.status < 300) {
successCallback(req.responseText);
} else {
errorCallback(new Error(req.statusText));
}
}
req.onerror = errorCallback;
req.open('GET', url);
req.setRequestHeader('Accept', 'application/json');
req.send();
}
const userEl = document.getElementById('user');
httpGet('https://www.naver.com/', data => {
userEl.innerHTML = data
}, error => alert(error));
</script>
</body>
</html>
위와 같이 사용할 수 있다.
하지만 해당소스는
CORS(Cross-Origin Resource Sharing) 에러가 발생한다.
최근 여러 도메인에 걸쳐서 구성되는 대규모 웹 프로젝트 및 REST API 등을 이용한
외부 호출이 많아지면서 해당 정책에 문제가 발생 하여 만들어진 정책이다.
웹 브라우저에서 자바스크립트의 XMLHttpRequest로 다른 웹페이지에 접근할 때는
동일한 출처(same origin)의 페이지만 접근 할 수 있다. (혹은 그쪽에서 허락해야 한다.)
출처 : 프로토콜 + 호스트명 + 포트
CORS 에러 발생 시, GET 방식으로 전달하더라도 OPTIONS로 전달하게 된다.
그 이유는 preflight request 라고 커스텀 헤더가 추가된 요청의 경우,
먼저 allow 헤더를 체크하기 위한 요청으로 options 메소드로 보내기 때문이다.
Access-Control-Allow-Headers 라는 응답 헤더에 서버에서 허용할 헤더값을 넣어서 주게 된다. 거기에 없는 헤더값을 클라이언트에서 요청하게 되면 CORS 정책에 의해 브라우저에서 요청을 날리지 않고 막아버리는 것이다.
즉, CORS 는 브라우저에서 요청을 날리지 않고 막는 것이다.
다만, 브라우저가 아닌 클라이언트에서 요청을 보내는 경우 응답을 받을 수 있다.
참고로 CORS에러를 우회하는 방법도 있지만 바람직한 방법은 아니므로 생략한다.
다음은 웹브라우저에서 데이터를 기억하고 싶을 때 쓰는 방법이다.
1. 로컬스토리지(Local Storage),
2. 세션스토리지(Session Storage),
3. 쿠키(Cookie)
이 방법들의 대한 차이를 간단히 정리한다.
웹 브라우저의 탭을 닫았다 켜도 유지된다.
자동로그인 여부나 설문조사 선택한 것 유지할 때 사용한다.
저장소의 구분은 (프로토콜 + 호스트 + 포트)로 한다. (ex: http://127.0.0.1:8080)
공식문서 https://developer.mozilla.org/en-US/docs/Web/API/Storage
웹 브라우저의 탭을 닫으면 제거 된다.
그렇기 때문에 잠깐 보관해야할 때 사용한다.
최대 4kb를 담을 수 있지만 서버와 지속적으로 통신해야하기 때문에
불필요한 데이터를 담으면 트래픽이 낭비될 수 있다.
그렇기 때문에 중요하지 않은 데이터는 최대한 로컬, 세션스토리지로 보관하면 좋다.
example.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>예제</title>
</head>
<body>
<script>
alert(location.href);
</script>
</body>
</html>
실행결과
http://127.0.0.1:5500/example.html
example.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>예제</title>
</head>
<body>
<script>
alert(location.hostname);
</script>
</body>
</html>
실행결과
127.0.0.1
example.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>예제</title>
</head>
<body>
<script>
alert(location.pathname);
</script>
</body>
</html>
실행결과
/example.html
example.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>예제</title>
</head>
<body>
<script>
alert(location.protocol);
</script>
</body>
</html>
실행결과
http:
(or https:)
example.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>예제</title>
</head>
<body>
<script>
location.href("https://naver.com");
</script>
</body>
</html>
location.assign으로도 가능하다
[1] location.search는
?a=12&b=34 와 같이
GET방식으로 넘긴 데이터값을 가져올 수 있다.
[2] 현재 URL의 모든 내용을 가져와서 replace를 통해 새로고침을 하는 식으로도 쓸 수 있다.
str = location.protocol + '//' + location.hostname + location.pathname + location.search + location.hash
location.replace(str);
https://teddy8.github.io/2019/07/15/ide-vscode-plugin/
위 포스팅에서 Prettier라는 vscode extension을 소개했었다.
알아두면 편리한 Prettier의 설치 및 사용법을 간단하게 알아본다.
왼쪽의 Extensions를 클릭하고
"Prettier" 검색 후 선택해서
install을 눌러 설치한다.
조금 더 편하게 사용하고 싶다면 간단한 설정이 필요하다.
(기본 단축키 Shift+Alt+F 에서 Ctrl+S로 사용할 수 있다)
왼쪽하단에 톱니바퀴를 누르고 Settings 클릭한다.
"prettier" 검색 후 Edit in settings.json을 누른다
settings.json 파일에
"editor.formatOnsave": true
위 코드를 추가한 후 저장해준다.
이제 코드 타이핑 후 Ctrl+S 를 누르면 자동으로 코드가 정렬되는 것을 확인할 수 있다
스크롤을 내려도 네비게이션이 항상 보이게 처리하는 방법 2가지를 소개한다
1. Javascript
2. CSS
example.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>DOM 네비게이션 예제</title>
<link rel="stylesheet" href="./scroll.css">
</head>
<body>
<section class="hero">
<h1>스크롤을 아래로 내려보세요.</h1>
</section>
<nav>
<a>자바스크립트 200제</a>
</nav>
<section class="articles">
</section>
<script>
const nav = document.querySelector('nav');
const navTopOffset = nav.offsetTop;
window.addEventListener('scroll', e => {
// nav를 상단에 고정. (브라우저 상단의 차이가 nav와 브라우저 상단의 차이보다 클 경우)
if (window.pageYOffset >= navTopOffset) {
nav.style.position = 'fixed';
nav.style.top = 0;
nav.style.left = 0;
nav.style.right = 0;
} else {
nav.style.position = '';
nav.style.top = '';
}
});
</script>
</body>
</html>
scroll.css
* { margin: 0; }
.hero {
height: 100px;
padding: 20px;
text-align: center;
background-color: #ccc;
}
nav {
background-color: black;
padding: 10px;
}
a {
text-decoration: none;
color: white;
}
.articles { height: 2000px; }
실행결과
스크롤을 내리면 원래 검정색 nav부분이 사라져야 하지만
브라우저 상단의 차이가 nav와 브라우저 상단의 차이보다 클 경우
nav요소를 상단에 위치하게 fixed 처리하여 고정된 모습을 볼 수 있다.
example.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>네비게이션 예제</title>
<link rel="stylesheet" href="./scroll.css" />
</head>
<body>
<div id="header">Header</div>
<nav id="nav">Navigation</nav>
<div id="content">Content</div>
</body>
</html>
scroll.css
#header,
#nav,
#content {
color: white;
text-decoration: none;
}
#header {
background: red;
height: 100px;
}
#nav {
background: cornflowerblue;
text-align: center;
padding: 40px 0px;
position: sticky;
top: 0;
}
#content {
background-color: green;
height: 1000vh;
}
실행결과
position을 sticky로 설정하고 top을 0으로 설정하면
마찬가지로 스크롤 고정을 구현할 수 있다.
(단 IE는 지원하지 않는다.)
데스크톱 브라우저에서 scroll 이벤트는 지속적으로 발생하지만
iPad나 아이폰은 사용자가 화면에서 손가락으로 스와이프하고 나서 떼는 순간 발생한다.
그럼 범용성을 고려한다면 위에서 소개한 2번째 방법으로 하는게 효율적인 것일까..
그랬을 경우 성능이슈는 없는 것일까.. 뭔가 이런 것들에 대한 감이 잘 오지 않는다
직접 해보는게 최고인데 나중에 해보장..ㅠ