
📗목차
Carousel이 무엇인지 예시 하나를 보이겠다.
이렇게 슬라이드 형태로 계속해서 넘겨 볼 수 있는 것을 말한다.
지난 시간 useNavigate를 사용한 페이지 이동(4)에서 생성했던 Album 컴포넌트에다가 위와 같은 형태로 포토북을 만들 생각이다.
먼저 Carousel 라이브러리를 설치해보자.
npm i react-material-ui-carousel
그런 다음 아래의 코드를 Album 컴포넌트에 import 해주자.
import Carousel from "react-material-ui-carousel";
그러면 이제 Album 컴포넌트에 Carousel의 기본 틀을 넣어 보자.
import React from 'react';
import Carousel from "react-material-ui-carousel";
const Album = () => {
return (
<div>
<Carousel
autoPlay={false}
>
(...) // 이미지 데이터 생략
</Carousel>
</div>
);
};
export default Album;
이미지 데이터를 넣기 전에 Carousel 내부를 디자인해볼 것이다.
포토북 형태로 디자인을 만들고 싶어서 인터넷에 포토북을 제작하는 사이트를 찾아보았다.
이런 이미지를 발견했다.
저 모양대로 Carousel을 디자인 하여 스크린을 넘기는 형태로 만들 수 있겠구나 싶었다.
우선 왼쪽 페이지와 오른쪽 페이지 두 갈래로 나눠서 디자인 해야한다.
<Carousel
className="crsl"
autoPlay={false}
>
<div className="albumBox">
<div className="leftBox">
</div>
<div className="rightBox">
</div>
</div>
</Carousel>
이렇게 leftBox와 rightBox로 나눈다.
Album.css 파일을 새로 생성하자.
Album 컴포넌트에 스타일 적용은 다 Album.css에 할 것이다.
현재 Album 컴포넌트의 배경은 LoginBox 컴포넌트의 배경 이미지와 같다.
위의 포토북처럼 Album 컴포넌트의 배경을 흰색으로 바꿔준 다음에 leftBox와 rightBox를 디자인할 것이다.
자, 이렇게 흰 배경으로 설정해줬으면 이제 leftBox와 rightBox 디자인을 해보자.
여기서 중요한 건 box-shadow이다.
이 그림자 기능으로 leftBox와 rightBox 사이의의 경계선을 그려줄 수 있다.
그리고 leftBox와 rightBox의 모서리의 그림자까지 설정해주면!!
얼핏보면 그냥 넘기는 책 같다.
이렇게 포토북을 만들었으면 다음은 Carousel에 적용할 이미지가 필요하다.
pulblic 폴더에 images 폴더를 하나 생성하자.
그리고 그 안의 cats, graduation, myFace, food 폴더를 생성해주자.
public>images>cats
public>images>graduation
public>images>myFace
public>images>food
각 폴더에 이미지들을 넣어준 다음 이미지 관련 데이티 파일을 하나 만들어 보겠다.
data.js
const imageData = [ { id: 1, title: "고양이", urlLeft: [ "images/cat/cat.jpg", "images/cat/cat_box.jpg", ], urlRight: [ "images/cat/cat_sleep.jpg", "images/cat/cat_stand.jpg", ], txt: [ "울 집 귀여운 고양이입니당.", "이름은 호박이😻" ], }, { id: 2, title: "졸업식", urlLeft: [ "images/졸업식/졸업사진1.jpg", "images/졸업식/졸업사진4.jpg", ], urlRight: [ "images/졸업식/졸업사진2.jpg", "images/졸업식/졸업사진3.jpg", ], txt: [ "2023년 8월 31일🎉", "졸업식 날 찍은 사진입니다." ], }, { id: 3, title: "셀카", urlLeft: [ "images/myFace/셀카1.jpg", "images/myFace/셀카2.jpg", ], urlRight: [ "images/myFace/셀카3.jpg", "images/myFace/셀카4.jpg", "images/myFace/셀카6.jpg", ], txt: [ "내 얼굴🤗", "^ㅇ^" ], }, { id: 4, title: "내가 먹은 음식", urlLeft: [ "images/food/음식1.jpg", "images/food/음식2.jpg", "images/food/음식7.jpg", ], urlRight: [ "images/food/음식5.jpg", "images/food/음식4.jpg", "images/food/음식3.jpg", "images/food/음식6.jpg", ], txt: [ "맛있겠다. 다시 보자.🍰" ], }, ]; export default imageData;
위에서 data.js 파일을 사용하기 위해서 아래와 같이 import 해주자.
import React from 'react';
import Carousel from "react-material-ui-carousel";
import '../style/Album.css';
import imageData from "./data";
const Album = () => {
return (
<div>
<Carousel
className="crsl"
autoPlay={false}
>
(...) // 이미지 데이터 생략
</Carousel>
</div>
);
};
export default Album;
이제 data.js 파일에서 선언한 imageData 변수를 Album 컴포넌트에 사용할 수 있게 됐다.
imageData 변수를 사용하여 이미지를 적용해보자.
import React from 'react';
import Carousel from "react-material-ui-carousel";
import '../style/Album.css';
import imageData from "./data";
const Album = () => {
return (
<div>
<Carousel
className="crsl"
autoPlay={false}
>
{imageData.map(content => (
<div key={content.id} className="albumBox">
<div className="leftBox">
<h3>{content.title} 앨범집</h3>
{content.urlLeft.map((url, urlIndex) => (
<img key={urlIndex} src={url} width={165} alt="이미지" />
))}
{content.txt.map((txt, txtIndex) => (
<span className="contents" key={txtIndex}>{txt}</span>
))}
</div>
<div className="rightBox">
<h3>추억을 열어 보세요.</h3>
{content.urlRight.map((url, urlIndex) => (
<img key={urlIndex} src={url} width={165} alt="이미지" />
))}
<button className="entrance">펼쳐보기</button>
</div>
</div>
))}
</Carousel>
</div>
);
};
export default Album;
Album.css 파일에서 다른 태그들의 CSS까지 적용하게 되면 다음 아래와 같이 나타난다.

포토북이 꽤나 다채로워졌다
이제 상단에 다크 모드 아이콘과 로그아웃 버튼을 만들어 보겠다.
다크 모드 아이콘을 클릭하면 화면이 검은색으로 바뀌는 기능을 만들어 보겠다.
이 기능은 useState가 필요하다.
다크 모드
const [darkMode, setDarkMode] = useState(false); const onClick = () => setDarkMode(prev => !prev)
이 코드를 Ablum 컴포넌트에 적용해보겠다.
import React, { useState } from "react";
import Carousel from "react-material-ui-carousel";
import '../style/Album.css';
import imageData from "./data";
const Album = () => {
const [darkMode, setDarkMode] = useState(false);
const onClick = () => setDarkMode(prev => !prev)
return (
<div className={darkMode === true ? "dark" : "light"}>
<img
src={darkMode === true ? "images/light.png" : "images/dark.png"}
className="icon"
width="40"
onClick={onClick}
alt="Icon"
/>
<Carousel
className="crsl"
autoPlay={false}
>
{imageData.map(content => (
<div key={content.id} className="albumBox">
<div className="leftBox">
<h3>{content.title} 앨범집</h3>
{content.urlLeft.map((url, urlIndex) => (
<img key={urlIndex} src={url} width={165} alt="이미지" />
))}
{content.txt.map((txt, txtIndex) => (
<span className="contents" key={txtIndex}>{txt}</span>
))}
</div>
<div className="rightBox">
<h3>추억을 열어 보세요.</h3>
{content.urlRight.map((url, urlIndex) => (
<img key={urlIndex} src={url} width={165} alt="이미지" />
))}
<button className="entrance">펼쳐보기</button>
</div>
</div>
))}
</Carousel>
</div>
);
};
export default Album;
위의 코드에서 return 바로 아래를 보면 darkMode 클래스를 가진 div 태그가 보일 것이다.
이 div 태그는 전체 코드를 감싼 상위 태그이다. 즉, Album 페이지 전체를 차지하는 거나 다름 없다.
다시 한번 살펴보자.
다크 모드
<div className={darkMode === true ? "dark" : "light"}> <img src={darkMode === true ? "images/light.png" : "images/dark.png"} className="icon" width="40" onClick={onClick} alt="Icon" /> <Carousel> (...) // 생략 </Carousel> </div>
삼항 연산자를 사용한 걸 볼 수 있다.
darkMode가 true일 때 클래스명을 "dark"로 해놓고, false일 때 "light"로 해놓았다.
dark클래스와 light 클래스를 각각 CSS 파일에 스타일링을 해줄 것이다.
그렇게 되면 Album 페이지 전체가 darkMode 상태에 따라 색상이 바뀌게 될 것이다.
그 다음 img 태그도 darkMode 상태에 따라 이미지 경로가 달라지는 것을 확인할 수 있다.
즉, darkMode가 true일 때 ☀️이런 햇님 아이콘으로 보이고,
darkMode가 false일 때 🌜이런 달님 아이콘이 보이는 것이다.
바로 이렇게 말이다.
맨 왼쪽 상단의 아이콘을 클릭하게 되면?
화면이 검은색으로 바뀌었다.
✌️성공이다.
2023. 12. 16 글 수정
현재 Album 페이지
라이트 모드
다크 모드
로그아웃을 구현하기 위해서 useNavigate를 사용해야 된다.
import { useNavigate } from 'react-router-dom';
위의 코드를 Album 컴포넌트에 import 해주고,
const navigate = useNavigate();
const handleLogout = useCallback(() => navigate('/'), [])
이 두 줄 코드를 Album 컴포넌틑에 적용해보자.
import React, { useState } from "react";
import { useNavigate } from 'react-router-dom';
import Carousel from "react-material-ui-carousel";
import '../style/Album.css';
import imageData from "./data";
const Album = () => {
const [darkMode, setDarkMode] = useState(false);
const navigate = useNavigate();
const onClick = () => setDarkMode(prev => !prev)
const handleLogout = useCallback(() => navigate('/'), [])
return (
<div className={darkMode === true ? "dark" : "light"}>
<img
src={darkMode === true ? "images/light.png" : "images/dark.png"}
className="icon"
width="40"
onClick={onClick}
alt="Icon"
/>
<button className='exit' onClick={handleLogout}>로그아웃</button>
<Carousel>
(...) // 생략
</Carousel>
</div>
);
};
export default Album;
button까지 만들고 onClick 이벤트를 설정해준다.

로그아웃 버튼까지 구현을 다 했다.
import React, { useState, useCallback } from "react";
import { useNavigate } from 'react-router-dom';
import Carousel from "react-material-ui-carousel";
import '../style/Album.css';
import imageData from "./data";
const Album = () => {
const [darkMode, setDarkMode] = useState(false);
const navigate = useNavigate();
const onClick = () => setDarkMode(prev => !prev)
const handleLogout = useCallback(() => navigate('/'), [])
return (
<div className={darkMode === true ? "dark" : "light"}>
<img
src={darkMode === true ? "images/light.png" : "images/dark.png"}
className="icon"
width="40"
onClick={onClick}
alt="Icon"
/>
<button className='exit' onClick={handleLogout}>로그아웃</button>
<Carousel
className="crsl"
autoPlay={false}
>
{imageData.map(content => (
<div key={content.id} className="albumBox">
<div className="leftBox">
<h3>{content.title} 앨범집</h3>
{content.urlLeft.map((url, urlIndex) => (
<img key={urlIndex} src={url} width={165} alt="이미지" />
))}
{content.txt.map((txt, txtIndex) => (
<span className="contents" key={txtIndex}>{txt}</span>
))}
</div>
<div className="rightBox">
<h3>추억을 열어 보세요.</h3>
{content.urlRight.map((url, urlIndex) => (
<img key={urlIndex} src={url} width={165} alt="이미지" />
))}
<button className="entrance">펼쳐보기</button>
</div>
</div>
))}
</Carousel>
</div>
);
};
export default Album;
다음 포스팅은 이미지 관련 데이터 관리를 위한 서버를 구현할 것이다!
지금까지는 이미지 관련 데이터를 프론트에서 불러왔지만 이제 서버에서 불러오도록 할 것이다. 😉