저번에 배웠던 jQuery를 이어서 공부하자.
저번 글에서 실습했던 '나만의 추억 앨범'에서 추억 저장하기 버튼을 누르면 박스가 켜졌다 꺼졌다를 반복할 수 있는 만들어보자.
이처럼 두 가지 상태 사이를 전환하는 동작을 우리는 '토글(toggle)' 이라고 한다.
즉 어떤 속성이나 상태를 켜거나 끄는 동작.
<script>
function openclose() {
$('#postingbox').toggle();
}
</script>
직관적으로 알기 쉽게 openclose 라는 함수를 만들고 $('#...')을 통해 지정해주고, 뒤에 .toggle()을 붙임으로서 우리는 postingbox를 토글한다는 걸 알 수 있다.
여기서 openclose()는 우리가 추억 저장하기 버튼을 누를 때 마다 실행해야하기 때문에 추억 저정하기 버튼에 onclick = "openclose()"를 해준다.
그러면 우리는 추억 저장하기 버튼을 누를 때 마다 포스팅 박스가 켜졌다 꺼졌다 하는 토글 동작을 볼 수 있다.
이어서 우리는 포스팅 박스를 토글을 이용해 동작 전환을 하면 반대로 포스팅 박스를 기록하기 누르면 카드가 추가 생성되도록 만들어보자.
이번엔 저번에 실습했던 스파르타플릭스를 이용할 것 인데
저 포스팅 박스에 데이터를 넣고 기록하기를 누르면 새로운 카드가 생성되도록 할 것이다.
또한 앞에서 했던 토글 기능도 추가적으로 넣어줄 것이다. (영화기록하기 버튼을 누르면 토글 되도록)
function makeCard() {
let image = $('#image').val();
let title = $('#title').val();
let comment = $('#comment').val();
let star = $('#star').val();
let temp_html = `
<div class="col">
<div class="card">
<img src="${image}"
class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">${title}</h5>
<p class="card-text">${star}</p>
<p class="card-text">${comment}</p>
</div>
</div>
</div>`;
$('#card').append(temp_html);
}
자 여기서 .val()은 값을 주는 것인데 코드를 보며 이해하면 우리는 $('#...')의 값을 let ... 의 각 변수들에 값을 주는 것이다.
temp_html 안에 우리가 전에 적었던 카드 하나의 div를 다 복사하여 그대로 붙여주고 각 클래스의 내용을 ${...}으로 변경해주면 우리가 .val()로 주었던 값을 그대로 적용시킬 수 있다.
이때 star는 저번 코드 그대로 이용하면 숫자로 나올 수 있는데.
<select class="form-select" id="star">
<option selected>별점 선택</option>
<option value="⭐">⭐</option>
<option value="⭐⭐">⭐⭐</option>
<option value="⭐⭐⭐">⭐⭐⭐</option>
<option value="⭐⭐⭐⭐">⭐⭐⭐⭐</option>
<option value="⭐⭐⭐⭐⭐">⭐⭐⭐⭐⭐</option>
</select>
숫자 부분에 '별'을 넣어주면 숫자가 아닌 별로 값이 저장되는 것을 볼 수 있다.
마지막으로 makeCard() 함수는 당연히 기록하기 버튼의 onclick으로 넣어줘야하고, 카드는 원래 카드가 있던 div에 추가되야 하기 때문에 카드가 모였던 div에 id 를 새로주고 append를 사용하여 추가해준다.
이렇게 추가되는 것을 알 수 있다.
혹시 나도 나중에 까먹을 수 있기 때문에 완성코드도 올려놓아야겠다..ㅎㅎ
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>스파르타플릭스</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Gowun+Dodum&display=swap');
* {
font-family: "Gowun Dodum", sans-serif;
}
.main {
background-color: green;
color: white;
background-image: url('https://occ-0-1123-1217.1.nflxso.net/dnm/api/v6/6AYY37jfdO6hpXcMjf9Yu5cnmO0/AAAABeIfo7VL_VDyKnljV66IkR-4XLb6xpZqhpLSo3JUtbivnEW4s60PD27muH1mdaANM_8rGpgbm6L2oDgA_iELHZLZ2IQjG5lvp5d2.jpg?r=e6e.jpg');
background-position: center;
background-size: cover;
}
body {
background-color: black;
}
.mycards {
width: 1200px;
margin: 20px auto 20px auto;
}
.mypostingbox {
width: 500px;
margin: 20px auto 20px auto;
border: 1px solid white;
padding: 20px;
border-radius: 5px;
}
.form-floating>input {
background-color: transparent;
color: white;
}
.form-floating>label {
color: white;
}
.input-group>label {
background-color: transparent;
color: white;
}
.mypostingbox>button {
width: 100%;
}
</style>
<script>
function openclose() {
$('#postingbox').toggle();
}
function makeCard() {
let image = $('#image').val();
let title = $('#title').val();
let comment = $('#comment').val();
let star = $('#star').val();
let temp_html = `
<div class="col">
<div class="card">
<img src="${image}"
class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">${title}</h5>
<p class="card-text">${star}</p>
<p class="card-text">${comment}</p>
</div>
</div>
</div>`;
$('#card').append(temp_html);
}
</script>
</head>
<body>
<header class="p-3 text-bg-dark">
<div class="container">
<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
<a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-white text-decoration-none">
<svg class="bi me-2" width="40" height="32" role="img" aria-label="Bootstrap">
<use xlink:href="#bootstrap"></use>
</svg>
</a>
<ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0">
<li><a href="#" class="nav-link px-2 text-danger">spartaflix</a></li>
<li><a href="#" class="nav-link px-2 text-white">홈</a></li>
<li><a href="#" class="nav-link px-2 text-white">시리즈</a></li>
<li><a href="#" class="nav-link px-2 text-white">영화</a></li>
<li><a href="#" class="nav-link px-2 text-white">내가 찜한 콘텐츠</a></li>
</ul>
<form class="col-12 col-lg-auto mb-3 mb-lg-0 me-lg-3" role="search">
<input type="search" class="form-control form-control-dark text-bg-dark" placeholder="Search..."
aria-label="Search">
</form>
<div class="text-end">
<button type="button" class="btn btn-outline-light me-2">Login</button>
<button type="button" class="btn btn-danger">Sign-up</button>
</div>
</div>
</div>
</header>
<div class="main">
<div class="p-5 mb-4 bg-body-tertiary rounded-3">
<div class="container-fluid py-5">
<h1 class="display-5 fw-bold">킹덤</h1>
<p class="col-md-8 fs-4">병든 왕을 둘러싸고 흉흉한 소문이 떠돈다. 어둠에 뒤덮인 조선, 기이한 역병에 신음하는 산하. 정체 모를 악에 맞서 백성을 구원할 희망은 오직
세자뿐이다.</p>
<button onclick="openclose()" type="button" class="btn btn-outline-light">영화 기록하기</button>
<button type="button" class="btn btn-outline-light">상세정보</button>
</div>
</div>
</div>
<div class="mypostingbox" id="postingbox">
<div class="form-floating mb-3">
<input type="email" class="form-control" id="image" placeholder="영화 이미지 주소">
<label for="floatingInput">영화 이미지 주소</label>
</div>
<div class="form-floating mb-3">
<input type="email" class="form-control" id="title" placeholder="영화 제목">
<label for="floatingInput">영화 제목</label>
</div>
<div class="input-group mb-3">
<label class="input-group-text" for="inputGroupSelect01">별점</label>
<select class="form-select" id="star">
<option selected>별점선택</option>
<option value="⭐">⭐</option>
<option value="⭐⭐">⭐⭐</option>
<option value="⭐⭐⭐">⭐⭐⭐</option>
<option value="⭐⭐⭐⭐">⭐⭐⭐⭐</option>
<option value="⭐⭐⭐⭐⭐">⭐⭐⭐⭐⭐</option>
</select>
</div>
<div class="form-floating mb-3">
<input type="email" class="form-control" id="comment" placeholder="추천 이유">
<label for="floatingInput">추천 이유</label>
</div>
<button onclick="makeCard()" type="button" class="btn btn-danger">기록하기</button>
</div>
</div>
<div class="mycards">
<div id="card" class="row row-cols-1 row-cols-md-4 g-4">
<div class="col">
<div class="card">
<img src="https://movie-phinf.pstatic.net/20210728_221/1627440327667GyoYj_JPEG/movie_image.jpg"
class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">영화 제목</h5>
<p class="card-text">⭐⭐⭐</p>
<p class="card-text">영화 코멘트</p>
</div>
</div>
</div>
<div class="col">
<div class="card">
<img src="https://movie-phinf.pstatic.net/20210728_221/1627440327667GyoYj_JPEG/movie_image.jpg"
class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">영화 제목</h5>
<p class="card-text">⭐⭐⭐</p>
<p class="card-text">영화 코멘트</p>
</div>
</div>
</div>
<div class="col">
<div class="card">
<img src="https://movie-phinf.pstatic.net/20210728_221/1627440327667GyoYj_JPEG/movie_image.jpg"
class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">영화 제목</h5>
<p class="card-text">⭐⭐⭐</p>
<p class="card-text">영화 코멘트</p>
</div>
</div>
</div>
<div class="col">
<div class="card">
<img src="https://movie-phinf.pstatic.net/20210728_221/1627440327667GyoYj_JPEG/movie_image.jpg"
class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">영화 제목</h5>
<p class="card-text">⭐⭐⭐</p>
<p class="card-text">영화 코멘트</p>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
클라이언트 - 서버 개념 이해하기
- [서버→클라이언트] : JSON은 Key:Value로 이루어져 있습니다. 자료형 Dictionary와 아주 유사
- [클라이언트→서버]
- GET → 통상적으로! 데이터 조회(Read)를 요청할 때 EX) 영화 목록 조회.
- POST → 통상적으로! 데이터 생성(Create), 변경(Update), 삭제(Delete) 요청 할 때 EX) 회원 가입, 회원 탈퇴, 비밀번호 수정
Fetch 시작하기
Fetch란? JavaScript에서 서버로 네트워크 요청을 보내고 응답을 받을 수 있도록 해주는 매서드.
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Fetch 시작하기</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
function hey() {
let url = 'http://spartacodingclub.shop/sparta_api/seoulair';
fetch(url).then(res => res.json()).then(data => {
console.log(data['RealtimeCityAir']['row'][0])
})
}
</script>
</head>
<body>
<button onclick="hey()">fetch 연습!</button>
</body>
</html>
연습 코드인데 hey() 함수 부분을 보면 fetch(url). ... 으로 코드가 적혀있는 것을 볼 수 있다.
여기서 url은 너무 길기 때문에 위에서 미리 let url의 변수에 url을 적어준 것이고, console을 제외한 나머지 부분은 기본 뼈태 형태라 외우지말고 그저 필요할 때 전에 썼던 코드에서 복사해서 가져와 사용하기만 하자.
일단 url을 타고 들어가면 마치 딕셔너리와 리스트가 나오는 것을 볼 수 있고 우리는 거기서 데이터를 가져올 수 있다.
data['RealtimeCityAir']['row'][0]
RealtimeCityAir 딕셔너리 안에 row 딕셔너리 중에 0번째 데이터를 가져오라는 뜻이다.
이것을 우리는 콘솔창에서 볼 수 있는 것이고 ,이때 함수 hey는 버튼을 눌렀을 때 작동하도록 되어있는 것을 보아하니 버튼을 누르면 우리가 가져오려고 했던 데이터가 결과로 나타나는 것을 확인할 수 있다.
연습 코드를 통해 더욱 fetch에 대해 알아보자.
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Fetch 시작하기</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
function hey() {
let url = 'http://spartacodingclub.shop/sparta_api/seoulair';
fetch(url).then(res => res.json()).then(data => {
let rows = data['RealtimeCityAir']['row'];
rows.forEach(a => {
let gu_name = a['MSRSTE_NM'];
let gu_mise = a['IDEX_MVL'];
console.log(gu_name, gu_mise);
});
})
}
</script>
</head>
<body>
<button onclick="hey()">fetch 연습!</button>
</body>
</html>
뭔가 매우 많이 추가된 것 같지만 우리가 기존에 쓰던 문법들이 그저 추가된 것 뿐이다.
당연히 먼저 hey()가 어디 있는지 부터 확인하면 fetch 연습! 이라는 버튼을 누르면 작동되게 되어있는 것을 알 수 있고 url은 길기 때문에 let url 이라는 변수명에 저장해주었다.
fetch의 기본 뼈대에서 rows라는 새로운 변수명을 선언해주고 rows 변수에 데이터 RealtimeCityAir 딕셔너리의 row 데이터들을 저정하는 것을 볼 수 있고 우리는 반복문(forEach)를 통해 row 안에 있는 특정 데이터만 가져오려는 것을 볼 수 있다.
각각 새로운 변수로 선언하여 원하는 데이터명을 넣어주고 console.log를 통해 결과를 보면
fetch 연습! 버튼을 누르자 콘솔창에 없던 데이터들이 생성 되는 것을 볼 수 있고
이때 버튼을 계속 누르면 데이터가 반복적으로 추가되는 것을 알 수 있다.
하지만 우리는 버튼이 눌릴 때 마다 똑같은 데이터가 추가되는 것은 불편하고 콘솔창에 데이터가 뜨는 것도 불편하기에 브라우저에 나타나게 하면서 버튼을 계속 눌러도 똑같은 데이터가 추가되지 않고 조건문을 이용해서 글자의 색도 바꿔보자.
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>미세먼지 API로Fetch 연습하고 가기!</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<style type="text/css">
div.question-box {
margin: 10px 0 20px 0;
}
.bad {
color: red;
}
</style>
<script>
function q1() {
let url = 'http://spartacodingclub.shop/sparta_api/seoulair';
$('#names-q1').empty();
fetch(url).then(res => res.json()).then(data => {
let rows = data['RealtimeCityAir']['row'];
rows.forEach(a => {
let gu_name = a['MSRSTE_NM'];
let gu_mise = a['IDEX_MVL'];
let temp_html = ``;
if (gu_mise > 40) {
temp_html = `<li class="bad">${gu_name} : ${gu_mise}</li>`;
} else {
temp_html = `<li>${gu_name} : ${gu_mise}</li>`;
}
$('#names-q1').append(temp_html);
});
})
}
</script>
</head>
<body>
<h1>Fetch 연습하자!</h1>
<hr />
<div class="question-box">
<h2>1. 서울시 OpenAPI(실시간 미세먼지 상태)를 이용하기</h2>
<p>모든 구의 미세먼지를 표기해주세요</p>
<p>업데이트 버튼을 누를 때마다 지웠다 새로 씌여져야 합니다.</p>
<button onclick="q1()">업데이트</button>
<ul id="names-q1">
</ul>
</div>
</body>
</html>
자 항상 함수가 어느 곳을 가는 지 먼저 파악하자.
q1() 함수는 onclick인 것을 확인했고, 우리가 앞에서 했던 코드와 크게 다르지 않은데
추가된 것은 let temp_html 변수인데 id = "names-q1" 중 한문장을 복사하여, temp_html 변수에 넣어준다.
이때 우리는 여러개의 실시간 데이터를 저장하여 반복적으로 보여주는 것이기 때문에 고정된 데이터가 아닌 변수로 바뀌주어야 한다.
let temp_html = `<li>${gu_name} : ${gu_mise}</li>`;
이 코드는 저번 글에서도 비슷한 구조를 많이 봤을 것이다.
${...}을 통해 내가 넣고자 하는 데이터를 넣어주고, 마지막으로 append를 이용하여 namse-q1에 새로운 데이터들을 넣어준다.
그리고 우리는 버튼을 계속 눌러도 똑같은 데이터가 반복적으로 나오면 안되기에 empty를 이용해서 fetch가 시작되기 전에 데이터를 비워줄 것이다.
또한 조건문을 넣어 40 초과면 빨간색 글자로 바꿔줄 것인데.
let temp_html = ``;
if (gu_mise > 40) {
temp_html = `<li class="bad">${gu_name} : ${gu_mise}</li>`;
} else {
temp_html = `<li>${gu_name} : ${gu_mise}</li>`;
}
이렇게만 짤라서 보면 코드를 어렵지 않게 이해하고 해석할 수 있다.
우리가 원하는 조건에 부합하면 그 문장은 빨간색으로 나오게 하는 코드이다.
<li></li>에 클래스 명을 주어서 그 클래스를 빨간색 글자로 <style>...</style>에서 디자인해주고 조건에 충족되지 않으면 클래스명을 빼주기만 하면 원래 글자색으로 나올 것이다.
우리가 원하는 결과가 나온 모습이다.
마지막으로 스타르타플릭스에 오늘 기온을 추가하고 마무리하겠다.
원래 기존의 스파르타 플릭스에서 아주 조금만 추가 및 수정만 하면 되기에 완성 코드는 넣지 않겠다.
<ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0">
<li><a href="#" class="nav-link px-2 text-danger">spartaflix</a></li>
<li><a href="#" class="nav-link px-2 text-white">홈</a></li>
<li><a href="#" class="nav-link px-2 text-white">시리즈</a></li>
<li><a href="#" class="nav-link px-2 text-white">영화</a></li>
<li><a href="#" class="nav-link px-2 text-white">내가 찜한 콘텐츠</a></li>
<li><a href="#" class="nav-link px-2 text-white">현재기온: <span id="msg"></span>도</a></li>
</ul>
헤더 부분에 내가 찜한 콘텐츠를 복사하여 똑같은 것을 하나 더 만들어주고 내용만 수정해주겠다.
여기서 <span></span>을 볼 수 있는데 id를 따로 주기 위해 사용했다고 생각해도 무방하다.
$(document).ready(function () {
let url = "http://spartacodingclub.shop/sparta_api/weather/seoul";
fetch(url).then(res => res.json()).then(data => {
let temp = data['temp'];
$('#msg').text(temp);
})
})
여기가 중요한데!
document ready를 처음 볼 것이다.
document ready? 문서가 준비되면 매개변수로 넣은 콜백 함수를 실행하라는 의미
쉽게 말하면 우리가 브라우저 창을 새로고침 할 때 마다 자동으로 실행된다.
즉 안에 fetch 는 오늘 하루종일 다뤄왔기에 큰 어려움 없이 해석이 가능하고 그저 이 fetch를 새로고침 할 때 마다 작동시키는 것이다.
이것은 <script> 맨 처음 넣어주고 코드를 실행하면 결과를 얻을 수 있다.
header 부분에 현재 기온이 추가된 모습을 볼 수 있다.
(날씨가 풀렸지만. 아직도 난 덥다..ㅠ)
'TIL > Web(frontend)' 카테고리의 다른 글
TIL 2024-09-10 (Web - 5주차 Firebase) (2) | 2024.09.10 |
---|---|
TIL 2024-09-09 (Web - 4주차 Firebase) (0) | 2024.09.09 |
TIL 2024-09-06 (Web - 3주차 HomeWork) (4) | 2024.09.06 |
TIL 2024-09-04 (Web - 2주차) (8) | 2024.09.04 |
TIL 2024-09-03 (Web - 1주차) (1) | 2024.09.03 |