(최초 작성일 - 2023.07.07)
먼저 기본 마크업과 레이아웃을 잡아주었습니다. 결과는 아래와 같습니다.
<p>
태그와 <q>
태그를 사용해서 카드의 content를 만들어주었습니다. 명언의 저자의 이름은 다른 폰트 스타일을 주기 위해 별도의 author
클래스를 주었습니다.
기본 마크업이 끝난 직후 모습
추가적인 스타일링은 핵심 기능이 완료되고 나서 조정할 예정입니다. 그러면 어떤 기능이 필요한지 나열해볼까요?
이 기능을 구현하기 위해서는
저는 외부 API 콜을 하여 명언 데이터를 버튼 클릭시마다 요청해 보겠습니다. 외부 API는 API-Ninjas의 Quotes
API를 사용해볼게요.
여러분들도 원하신다면 가입하시고, API키를 받아서 사용해보시기 바랍니다. API키는 잘 숨겨서 사용해야겠죠?
MDN - fetch API 문서를 참고하여 API에서 명언을 요청하는 비동기 함수를 작성했습니다. 헤더 부분에 API 키도 첨부하는 것 잊지 말아주세요!
async function getQuotes(url = '') {
try {
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': config.api_ninjas_key,
},
});
if (!response.ok) {
throw new Error('네트워크 오류');
}
return response.json();
} catch (error) {
console.error(error);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./style.css" />
<title>Random Quotes</title>
</head>
<body>
<div class="container">
<div class="card">
<div class="content">
<p class="quote"></p>
<span class="author"></span>
</div>
<button class="generate-btn">Generate Quote</button>
</div>
</div>
<script type="text/javascript" src="/apiKey.js"></script>
<script type="module" src="./main.js"></script>
</body>
</html>
주의: 이 방법은 배포 시에는 적용되기 어려운 방법입니다. 이에 관해서는 추가로 포스팅 하도록 하겠습니다.
깃허브에 내 API키가 노출이 되는 것은 보안적으로 굉장히 안 좋은 일입니다. 그렇기에, 별도의 apiKey.js
파일에 내 API 키를 객체로 저장해두고, script
태그에 추가하여 가져오는 식으로 우회했습니다.
apiKey.js
는 .gitIgnore
에 추가를 하였습니다.
//apiKey.js
const config = {
API_NINJAS_KEY: '[내가 발급받은 API Key]',
};
이로써 API 키는 깃허브에 노출되지 않을 것입니다. 하지만,이 방법은 레포지토리를 배포할 때는 적용될 수 없는 미봉책에 해당합니다. 왜냐하면 배포는 깃허브 레포에 있는 파일들을 기반하여 진행되기 때문에, 내 로컬에 있는 apiKey.js
파일을 찾을 수 없을 것이 뻔하기 때문입니다.
또한, 이렇게 코드로 우회한다고 해도, 브라우저의 Nework 헤더를 확인해보면 버젓이 내 API키를 확인할 수 있어서 찜찜하기도 합니다.
우측 하단에 API 키가 버젓이 노출되고 있는 모습입니다
프론트단에서는 근본적인 해결책이 존재하지 않는 것 같다는 생각이 들었습니다.
조사를 해보니,
정도가 있을 것으로 생각됩니다. 둘 다 프론트단이 아닌 서버단에서 환경변수로 API Key를 관리하는 방법이군요. 하지만 지금 당장은 배포하지 않을 예정이니 이정도만 하고 일단 쿨하게 ~ 넘어갑시다!
(node.js로 API 프록시 서버를 만들어보게 될 수도...? )
=> API 키를 프론트단에서 완전히 숨기기 위해, Netlify 환경변수와 Serverless function을 활용하여 진짜로 실행에 옮겨봤습니다. 정말 멍멍이 고생하면서 성공했어요 엉엉...Netlify 배포 후기글에서 확인하실 수 있습니다!
기능구현을 마친 JS 파일은 아래와 같습니다.
const quoteParagraph = document.querySelector('.quote');
const authorSpan = document.querySelector('.author');
const generateBtn = document.querySelector('.generate-btn');
async function getQuotes(url = '') {
try {
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': config.api_ninjas_key,
},
});
if (!response.ok) {
throw new Error('네트워크 오류');
}
return response.json();
} catch (error) {
console.error(error);
}
}
async function handleClick() {
const [{ author, quote }] = await getQuotes(
'https://api.api-ninjas.com/v1/quotes'
);
const quoteElement = document.createElement('q');
quoteElement.innerText = quote;
quoteParagraph.innerHTML = '';
quoteParagraph.appendChild(quoteElement);
authorSpan.innerText = '- ' + author;
}
generateBtn.addEventListener('click', handleClick);
오...잘 동작하는군요
배경은 radial-gradient
를 사용하였습니다. 처음 접하는 속성값이라
background: radial-gradient(ellipse at center, #06bdc1, #68469f);
https://developer.mozilla.org/en-US/docs/Glossary/
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
https://developer.mozilla.org/en-US/docs/Glossary/CORS
이상한 공백이 화면에 생겼습니다. 이 하얀 공백을 없애야, container div 가 화면을 꽉 채울텐데 말이죠.
* {
box-sizing: border-box;
}
.container {
display: flex;
justify-content: center;
align-items: center;
background: radial-gradient(ellipse at top, #e66465, transparent),
radial-gradient(ellipse at bottom, #4d9f0c, transparent);
}
바로 <body>
의 것이었습니다. 8px의 margin이 적용되어 있었습니다.
찾아보니, <body>
는 8px의 기본 margin이 적용되어 있다고 합니다.
등잔 밑이 어두웠어요...ㅠㅠ 그래서 <body>
의 margin과 padding을 0으로 설정해주어 container div가 화면 전체를 채우도록 스타일링할 수 있었습니다.
* {
box-sizing: border-box;
}
body {
padding: 0;
margin: 0;
}
.container {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background: radial-gradient(ellipse at top, #e66465, transparent),
radial-gradient(ellipse at bottom, #4d9f0c, transparent);
}
https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/radial-gradient