본문 바로가기
국비학원/수업기록

국비 지원 개발자 과정_Day52

by 루팽 2023. 2. 10.

<step 4 비디오 재생하기>

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>클론코딩 - step4[비디오 재생하기]</title>
    <link rel="stylesheet" href="./youtube.css" />
    <link
      rel="shortcut icon"
      href="../../../images/youtube/logo.ico"
      type="image/x-icon"
    />
    <script defer src="./youtube.js"></script>
  </head>
  <body>
    <h3>유튜브 클론코딩 실습 4</h3>
    <header class="header">
      <div class="logo">
        <img src="../../../images/youtube/logo.png" alt="logo" />
        <h1 class="headerTitle">Youtube</h1>
      </div>
      <input
        class="input"
        type="search"
        name="keyword"
        id="keyword"
        placeholder="Search"
      />
      <button class="btnSearch">
        <img
          class="imgSearch"
          src="../../../images/youtube/search.png"
          alt="search"
        />
      </button>
    </header>
    <div id="root"></div>
  </body>
</html>

 

const keyword = document.querySelector("#keyword");

// input textfield에 입력한 후 엔터쳤을 때를 잡아내는 함수
keyword.addEventListener("keypress", (event) => {
  console.log("keypress => " + event.keyCode);
  // 사용자가 입력한 검색어를 찾는 함수 호출
  if (event.keyCode == 13) {
    handleSearch();
  }
});

// 사용자가 입력한 검색어 읽어오기
const handleSearch = () => {
  const user = document.querySelector("#keyword").value;
  console.log("사용자가 입력한 검색어 => " + user);
  search(user);
};

// video로 받아와서 구조분해할 수 있나? -> 리액트에선 가능, 바닐라에서는 불가
let videoItem;
const videoShow = (id, title, description, channelTitle) => {
  videoItem = `
  <section class = "detail">
  <iframe
    id="player"
    type="text/html"
    width="800"
    height="480"
    src="http://www.youtube.com/embed/${id}"
    frameborder="0"></iframe>
  <h2>${title}</h2>
  <h3>${channelTitle}</h3>
  <pre class = "description">${description}</pre>
  <div>
    <a href="./youtube.html">이전페이지</a>
    &nbsp;
    <a href="javascript:search('손흥민')">이전페이지2</a>
  </div>
  </section>
  `;
  document.querySelector("#root").innerHTML = videoItem;
};

// 사용자가 입력한 검색어로 조건 검색 구현하기
const search = (query) => {
  console.log("사용자가 입력한 btns 받음 => " + query);
  const ajax = new XMLHttpRequest();
  const videoList = [];
  const key = "";
  const SEARCH_URL = `https://youtube.googleapis.com/youtube/v3/search?part=snippet&maxResults=25&q=${query}&key=${key}`;
  // const SEARCH_URL = `http://192.168.10.47:5500/google/youtube/step4/sample.json`;
  // const SEARCH_URL = `http://192.168.10.71:5500/google/youtube/step4/sample.json`;

  ajax.open("GET", SEARCH_URL, false);
  ajax.send();

  const most = JSON.parse(ajax.response);
  const items = most.items;
  let items2;

  items2 = most.items.map((item) => ({
    ...item,
    id: item.id.videoId,
  }));

  console.log(items2);

  videoList.push(`<ul class = "videos">`);
  items2.map((video) => {
    // 자바스크립트에서는 파라미터로 값을 넘길 때 반드시 싱글쿼테이션' 또는 더블 쿼테이션"을 붙여야 값으로 인정된다
    // 만약 붙이지 않으면 XXX is not defined라고 뜸
    // 비디오 제목, 설명의 경우 특수문자(괄호 등) 배제하는 정규식 이용
    const reg = /[\{\}\[\]\/?.,;:|\)*~`!^\-_+<>@\#$%&\\\=\(\'\"]/gi;
    const title = video.snippet.title.replace(reg, "");
    const description = video.snippet.description.replace(reg, "");

    videoList.push(
      `<li class="container" onclick="videoShow('${video.id}','${title}','${description}','${video.snippet.channelTitle}')">`
    );
    videoList.push(`<div class="video">`);
    videoList.push(
      `<img class = "thumbnail" src='${video.snippet.thumbnails.medium.url}' />`
    );
    videoList.push(`<div">`);
    videoList.push(`<p class = "title">${video.snippet.title}</p>`);
    videoList.push(
      `<p class = "channelTitle">${video.snippet.channelTitle}</p>`
    );
    videoList.push(`</div">`);
    videoList.push(`</div">`);
    videoList.push(`</li">`);
  }); // end of map
  videoList.push(`</ul>`);

  document.querySelector("#root").innerHTML = videoList.join("");
}; // end of search

 

* {
  box-sizing: border-box;
  /* border: 1px solid red; */
}

.header {
  display: flex;
  height: 4rem;
  padding: 0.5rem 1rem;
  margin: 0 0.2rem;
  background-color: black;
}

.logo {
  display: flex;
  align-items: center;
  margin-right: 1em;
}

.headerTitle {
  color: white;
  margin: 0.2rem 0.5rem;
}

.input {
  flex-basis: 100%;
  font-size: 1.1rem;
  outline: 0;
  margin: 0rem 0.5rem;
}

.btnSearch {
  background-color: rgb(223, 50, 50);
  outline: 0;
}

.imgSearch {
  height: 100%;
  padding: 0.5em 0.2em;
}

.videos {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  list-style: none;
  padding-left: 0px;
  margin: 0;
  gap: 14px;
}

.container {
  width: 100%;
  padding: 0.2em;
}

.video {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  border: 1px solid lightgray;
  box-shadow: 3px 3px 5px 0px rgb(185, 185, 185);
  transition: transform 250ms ease-in;
  cursor: pointer;
}

.video:hover {
  transform: scale(1.02);
}

.thumbnail {
  width: 40%;
  height: 100%;
}

.title,
.channelTitle {
  margin: 10px;
  font-size: 0.8rem;
}

.channelTitle {
  font-size: 0.6rem;
}

.detail {
  padding: 1em;
}

.description {
  white-space: pre-wrap;
}

 

<JSP 사용, index 테이블 메인 바꾸기>

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	
<%
	String menu = request.getParameter("menu"); // info or login or board or google
	out.print(menu);
%>

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>패턴1</title>
<style>
a {
	text-decoration: none;
}
</style>
</head>
<body>
	<!-- 태그는 중첩해서 사용 가능함 -->
	<!-- 크기는 %로 주는 것이 좋다(가변적이니까) -->
	<table border="1" align="center" width="1000px">
		<tr>
			<td width="100%" height="50px">
				<!-- top 시작 -->
					<%@ include file="top.jsp"%>
				<!-- top 끝 -->
			</td>
		</tr>
		<tr>
			<td>
				<!-- body 시작 -->
				<table>
					<tr>
						<!-- 메뉴 시작 -->
						<td width="200px" height="400px">
							<%@ include file="menu.jsp"%>
						</td>
						<!-- 메뉴 끝 -->
						<!-- 메인 시작 -->
						<td width="800px" height="400px">
							<%
								if (menu == null) {
							%>
								<%@ include file="main.jsp"%>
							<%
								} else if ("info".equals(menu)) {
							%>
								<%@ include file="info.jsp"%>
							<%
								} else if ("login".equals(menu)) {
							%>
								<%@ include file="login.jsp"%>
								<%
								} else if ("board".equals(menu)) {
							%>
								<%@ include file="board.jsp"%>
								<%
								} else if ("google".equals(menu)) {
							%>
								<%@ include file="google.jsp"%>
							<%
								}
							%>
						</td>
						<!-- 메인 끝 -->
					</tr>
				</table>
				<!-- body 끝 -->
			</td>
		</tr>
		<tr>
			<td width="1000px" height="30px">
				<!-- bottom 시작 -->
					<%@ include file="bottom.jsp"%>
				<!-- bottom 끝 -->
			</td>
		</tr>
	</table>
</body>
</html>

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	
<table border="1" width="100%" height="100%" bordercolor="green">
	<tr>
		<td>top 영역</td>
	</tr>
</table>

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	
<table border="1" width="100%" height="100%" bordercolor="blue">
	<tr>
		<td valign="top">
			<table>
				<tr>
					<td><a href="./index.jsp?menu=info">소개</a></td>
				</tr>
				<tr>
					<td><a href="./index.jsp?menu=login">로그인</a></td>
				</tr>
				<tr>
					<td><a href="./index.jsp?menu=board">게시판</a></td>
				</tr>
				<tr>
					<td><a href="./index.jsp?menu=google">구글</a></td>
				</tr>
			</table>
		</td>
	</tr>
</table>

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	
<table border="1" width="100%" height="100%" bordercolor="yellow">
	<tr>
		<td>bottom 영역</td>
	</tr>
</table>

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	
<table border="1" width="100%" height="100%" bordercolor="red">
	<tr>
		<td>body 메인 영역</td>
	</tr>
</table>

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<table border="1" width="100%" height="100%" style="background-color:green">
	<tr>
		<td>info 영역</td>
	</tr>
</table>

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<table border="1" width="100%" height="100%" style="background-color:blue">
	<tr>
		<td>login 영역</td>
	</tr>
</table>

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<table border="1" width="100%" height="100%" style="background-color:red">
	<tr>
		<td>board 영역</td>
	</tr>
</table>

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<table border="1" width="100%" height="100%" style="background-color:yellow">
	<tr>
		<td>google 영역</td>
	</tr>
</table>

 

<뉴스 목록 - 전체 갱신>

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	
<%!
	int x = 1; // 전역변수 선언하기
	
	public String newsItem(String[] news) {
		StringBuilder sb = new StringBuilder();
		for(int i = 0; i < news.length; i++){
			if(i == (x - 1)){
			sb.append("<table width='500px' border='1px'>");
			sb.append("<tr><td>"+news[i]+"</td></tr>");
			sb.append("</table>");			
			} // end of if
		} // end of for
		String choice = sb.toString();
		return choice;
	} // end of newsItem
%>
	
<%
	// 스크립틀릿
	String news[] = {
		"젤렌스키 “전투기 지원을”…영·프·독 정상은 ‘확답’ 안 해",
		"유럽연합, 조만간 러시아 열번째 제재… 선전 매체 겨냥",
		"[속보] 튀르키예·시리아 강진 누적 사망자 2만명 넘어",
		"한국에서 왔니? 목에 걸어 中공항서 한국에 ‘보복조치’ 뒤끝",
		"우크라전 350일…하르키우 등 러시아 포격 증가"};

	String data = "";

	switch(x){
		case 1:
			data = newsItem(news);
			x++;
			break;
		case 2:
			data = newsItem(news);
			x++;
			break;
		case 3:
			data = newsItem(news);
			x++;
			break;
		case 4:
			data = newsItem(news);
			x++;
			break;
		case 5:
			data = newsItem(news);
			x = 1;
			break;
	} // end of switch
	
	// 기존에 읽어온 기사정보 지우기
	out.clear();
	out.print(data);
%>

 

< 뉴스 목록 - jquery 자동 갱신 처리>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
 
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
</head>
<body>
	<script type="text/javascript">
		// 호출하지 않아도 자동 실행
		// jquery(document) -> $로 바꿈 $(document)
		// window <- document <- ready(function(){실행문: 변수선언, if문, switch문, i+j}) 함수
		$(document).ready(() => {
			// 실행문이 오는 자리()
			start = () => {
				setInterval(autoReload, 2000); // 2초 대기(지연) 후 autoReload 호출
			}
			start();
		}) // end of ready - DOM을 다 읽었으면
	</script>
	<div id="d_news">뉴스 준비중 ...</div>
	<script>
		const autoReload = () => {
			console.log('autoReload 호출')
			// ajax함수는 jquery.min.js가 제공하는 API이다
			// ajax함수는 결국 XMLHttpRequest를 대신함
			// const ajax = new XMLHttpRequest();
			// ajax.open("GET", url, false)
			// ajax.send()
			/* 
				XMLHttpRequest (XHR) 객체는 서버와 상호작용할 때 사용함
				페이지의 새로고침 없이도 데이터를 가져올 수 있다(페이지의 일부를 업데이트 가능)
			*/
			$.ajax({
          type: "GET",
          url: "newsList.jsp",
          success: function (data) { // 성공했을 때
        	  // console.log(data);
        	  $("#d_news").html(data);
          },
          error: function(request, status, error){
        	  console.log("error")
        	  console.log("error" + request.status)
        	  console.log("error" + request.responseText)
          }
        });
		}
	</script>
</body>
</html>
<!--
	HTML(단방향, 변수선언이나 제어문 지원안됨, 이벤트 처리 불가)은 순차적으로 실행
	자바스크립트 코드의 위치에 따라서 document.querySelector(id or class or element)
	-> 항상 선언이 먼저여야함
	
	자바스크립트 위치
		1) head 안에 -> 전역변수, 함수 선언할 때(호출해야 실행됨)
			만약 이것을 지연하고 싶다면 defer 사용(Html, DOM Tree를 그릴 때까지 -> 그래야 querySelector 사용가능)
		2) body 안에 -> 호출하지 않아도 실행됨(단, 함수로 선언된 부분은 제외)
	
	자바스크립트로 화면을 그릴 수 있다
	document.write("<font color='red' size=18></font>")
	
	write는 어디다 쓰는 것인가? -> 브라우저
	
	Java는 브라우저에 쓸 수 없다!
	아래의 system은 로컬pc일뿐 브라우저 아님
	System.out.println("<b>굵은글씨</b>")
	
	아래의 out은 브라우저에 써준다(servlet이 제공하는 API)
	out.print();
	
	마임타입에 따라서 jsp라고 쓰고 html | json이라고 읽을수있음
	메인타입/서브타입
	image/png | jpe | gif
	text/html | css | javascript | module | babel
 -->

 

확장자가 아니라 mime타입에 따라 브라우저 출력 결정된다

타입이 json이어도 그냥 memberList 찍으면 json형식 x

<%@ page language="java" contentType="application/json; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.*, com.google.gson.Gson" %>

<%
	List<Map<String, Object>> memberList = new ArrayList<>();
	Map<String, Object> map = new HashMap<>();
	
	map.put("mem_id", "tomato");
	memberList.add(map);
	map = new HashMap<>();
	map.put("mem_id", "apple");
	memberList.add(map);
	map = new HashMap<>();
	map.put("mem_id", "banana");
	memberList.add(map);
	
	// 구글에서는 Gson.jar 라이브러리 지원
	Gson g = new Gson();
	// JSON포맷으로 출력하려면 아래와같이 해야함
	String temp = g.toJson(memberList);
	out.print(temp);
	// 아래와 같이 자료구조를 출력하면 JSON포맷이 아니다 -> 자바스크립트에서 읽을수가 없다(조회결과없음)
	out.print(memberList);
%>

 

<index 테이블 메인과 뉴스 목록 합치기>

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	
<%
	String menu = request.getParameter("menu"); // info or login or board or google
	out.print(menu);
%>

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
<title>패턴1</title>
<style>
a {
	text-decoration: none;
}
</style>
</head>
<body>
	<script defer type="text/javascript">
		$(document).ready(() => {
			start = () => {
				setInterval(autoReload, 2000); // 2초 대기(지연) 후 autoReload 호출
			}
			start();
		}) // end of ready - DOM을 다 읽었으면
	</script>
	<script>
		const autoReload = () => {
			console.log('autoReload 호출')
			$.ajax({
          type: "GET",
          url: "newsList.jsp",
          success: function (data) { // 성공했을 때
        	  console.log(data);
        	  $("#d_news").html(data);
          },
          error: function(request, status, error){
        	  console.log("error")
        	  console.log("error" + request.status)
        	  console.log("error" + request.responseText)
          }
        });
		}
	</script>

	<!-- 태그는 중첩해서 사용 가능함 -->
	<!-- 크기는 %로 주는 것이 좋다(가변적이니까) -->
	<table border="1" align="center" width="1000px">
		<tr>
			<td width="100%" height="50px">
				<!-- top 시작 -->
					<%@ include file="top.jsp"%>
				<!-- top 끝 -->
			</td>
		</tr>
		<tr>
			<td>
				<!-- body 시작 -->
				<table>
					<tr>
						<!-- 메뉴 시작 -->
						<td width="200px" height="400px">
							<%@ include file="menu.jsp"%>
						</td>
						<!-- 메뉴 끝 -->
						<!-- 메인 시작 -->
						<td width="800px" height="400px">
							<%
								if (menu == null) {
							%>
								<%@ include file="main.jsp"%>
							<%
								} else if ("info".equals(menu)) {
							%>
								<%@ include file="info.jsp"%>
							<%
								} else if ("login".equals(menu)) {
							%>
								<%@ include file="login.jsp"%>
								<%
								} else if ("board".equals(menu)) {
							%>
								<%@ include file="board.jsp"%>
								<%
								} else if ("google".equals(menu)) {
							%>
								<%@ include file="google.jsp"%>
							<%
								}
							%>
						</td>
						<!-- 메인 끝 -->
					</tr>
				</table>
				<!-- body 끝 -->
			</td>
		</tr>
		<tr>
			<td width="1000px" height="30px">
				<!-- bottom 시작 -->
					<%@ include file="bottom.jsp"%>
				<!-- bottom 끝 -->
			</td>
		</tr>
	</table>
</body>
</html>

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	
<table border="1" width="100%" height="100%" bordercolor="red">
	<tr>
		<td>
			<div id = "d_news">...</div>
		</td>
	</tr>
</table>

 

<bootstrap5 활용>

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Insert title here</title>
    <link rel="stylesheet" href="./step1.css" />
    <%@ include file = "../../common/bootstrapCommon.jsp" %>
  </head>
  <body>
    <!-- ==================== [[ Navbar start ]] ==================== -->
    <nav class="navbar navbar-expand-lg bg-light">
      <div class="container-fluid">
        <a class="navbar-brand" href="#">Navbar</a>
        <button
          class="navbar-toggler"
          type="button"
          data-bs-toggle="collapse"
          data-bs-target="#navbarSupportedContent"
          aria-controls="navbarSupportedContent"
          aria-expanded="false"
          aria-label="Toggle navigation"
        >
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
          <ul class="navbar-nav me-auto mb-2 mb-lg-0">
            <li class="nav-item">
              <a class="nav-link active" aria-current="page" href="#">Home</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Link</a>
            </li>
            <li class="nav-item dropdown">
              <a
                class="nav-link dropdown-toggle"
                href="#"
                role="button"
                data-bs-toggle="dropdown"
                aria-expanded="false"
              >
                Dropdown
              </a>
              <ul class="dropdown-menu">
                <li><a class="dropdown-item" href="#">Action</a></li>
                <li><a class="dropdown-item" href="#">Another action</a></li>
                <li><hr class="dropdown-divider" /></li>
                <li>
                  <a class="dropdown-item" href="#">Something else here</a>
                </li>
              </ul>
            </li>
            <li class="nav-item">
              <a class="nav-link disabled">Disabled</a>
            </li>
          </ul>
          <form class="d-flex" role="search">
            <input
              class="form-control me-2"
              type="search"
              placeholder="Search"
              aria-label="Search"
            />
            <button class="btn btn-outline-success" type="submit">
              Search
            </button>
          </form>
        </div>
      </div>
    </nav>
    <!-- ==================== [[ Navbar end ]] ==================== -->
    <!-- ==================== [[ Carousel start ]] ==================== -->
    <div
      id="carouselExampleCaptions"
      class="carousel slide"
      data-bs-ride="false"
    >
      <div class="carousel-indicators">
        <button
          type="button"
          data-bs-target="#carouselExampleCaptions"
          data-bs-slide-to="0"
          class="active"
          aria-current="true"
          aria-label="Slide 1"
        ></button>
        <button
          type="button"
          data-bs-target="#carouselExampleCaptions"
          data-bs-slide-to="1"
          aria-label="Slide 2"
        ></button>
        <button
          type="button"
          data-bs-target="#carouselExampleCaptions"
          data-bs-slide-to="2"
          aria-label="Slide 3"
        ></button>
      </div>
      <div class="carousel-inner">
        <div class="carousel-item active">
          <img
            src="../../images/sample/beach-daylight.jpg"
            class="d-block w-100"
            alt="..."
          />
          <div class="carousel-caption d-none d-md-block">
            <h5>First slide label</h5>
            <p>Some representative placeholder content for the first slide.</p>
          </div>
        </div>
        <div class="carousel-item">
          <img
            src="../../images/sample/camera_comp.jpg"
            class="d-block w-100"
            alt="..."
          />
          <div class="carousel-caption d-none d-md-block">
            <h5>Second slide label</h5>
            <p>Some representative placeholder content for the second slide.</p>
          </div>
        </div>
        <div class="carousel-item">
          <img
            src="../../images/sample/camping-goods.jpg"
            class="d-block w-100"
            alt="..."
          />
          <div class="carousel-caption d-none d-md-block">
            <h5>Third slide label</h5>
            <p>Some representative placeholder content for the third slide.</p>
          </div>
        </div>
      </div>
      <button
        class="carousel-control-prev"
        type="button"
        data-bs-target="#carouselExampleCaptions"
        data-bs-slide="prev"
      >
        <span class="carousel-control-prev-icon" aria-hidden="true"></span>
        <span class="visually-hidden">Previous</span>
      </button>
      <button
        class="carousel-control-next"
        type="button"
        data-bs-target="#carouselExampleCaptions"
        data-bs-slide="next"
      >
        <span class="carousel-control-next-icon" aria-hidden="true"></span>
        <span class="visually-hidden">Next</span>
      </button>
    </div>
    <!-- ==================== [[ Carousel end ]] ==================== -->
    <!-- ==================== [[ Card end ]] ==================== -->
    <div class="card-group">
	    <div class="card" style="width: 18rem;">
			  <img src="../../images/sample/도서-1.jpg" class="card-img-top" alt="...">
				  <div class="card-body">
				    <h5 class="card-title">Card title</h5>
				    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
				    <a href="#" class="btn btn-primary">Go somewhere</a>
				  </div>
			</div>
			<div class="card" style="width: 18rem;">
			  <img src="../../images/sample/도서-2.jpg" class="card-img-top" alt="...">
				  <div class="card-body">
				    <h5 class="card-title">Card title</h5>
				    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
				    <a href="#" class="btn btn-primary">Go somewhere</a>
				  </div>
			</div>
			<div class="card" style="width: 18rem;">
			  <img src="../../images/sample/도서-4.jpg" class="card-img-top" alt="...">
				  <div class="card-body">
				    <h5 class="card-title">Card title</h5>
				    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
				    <a href="#" class="btn btn-primary">Go somewhere</a>
				  </div>
			</div>
		</div>
    <!-- ==================== [[ Card end ]] ==================== -->
    <!-- ==================== [[ footer start ]] ==================== -->
    <nav class="navbar navbar-expand-sm bg-dark navbar-dark fixed-bottom">
		  <div class="container-fluid">
		    <span class="footer">자바캠프 Copyright &copy; 2023</span>
		  </div>
		</nav>
    <!-- ==================== [[ footer end ]] ==================== -->
  </body>
</html>

 

.card-group {
  display: inline-block;
  margin: 1.5rem;
  margin-bottom: 4rem;
}

.card-group.card {
  padding-right: 1rem;
}

.card-img-top {
  height: 100%;
}

.footer {
  display: flex;
  justify-content: center;
  color: white;
  font-size: 1rem;
}

댓글