diff --git a/README.md b/README.md
index d91ad02..65e97ab 100644
--- a/README.md
+++ b/README.md
@@ -21,9 +21,7 @@ https://getbootstrap.com/docs/4.3/examples/album/
## 구현 화면
-(이곳에 구현한 이미지를 이곳에 첨부해주세요. 아래는 예시 이미지입니다.)
-
-
+
## 구현 조건
@@ -32,7 +30,24 @@ https://getbootstrap.com/docs/4.3/examples/album/
2. 상단에 `Header`는 스크롤하여도 화면에 고정되어 보이도록 합니다.
## 컴포넌트 계층 구조
+! 이 페이지의 구조와 대략적인 기능을 참고, 이름과 테마는 제가 새롭게 정하였습니다.
+! 페이지 이름은 "Pocket
+
+
+💥assets : img1 ~ img5
+Photo.jsx에서 불러와서 사용할 이미지 저장.
+
+
+💥components : Header.jsx, PhotoCard.jsx
+
+Header.jsx - 상단 고정되는 로고, 메뉴를 포함한 바. header_container 안에 크게 header_left, header_menu 요소들을 넣어서 설계, flex를 이용하여 각각 왼쪽, 오른쪽으로 붙게 정렬. hover를 이용하여 menu 안의 home과 contact를 누르면 언더바가 생기게 동적인 기능을 넣음.
+
+PhotoCard.jsx - Photo 페이지의 사진 카드 틀. 사진인 image, 제목인 title, 설명인 description을 변수 설정함. 사진, 제목, 설명을 적을 곳을 설정하고 view (자세히 보기), edit (수정하기) 버튼을 추가함. 여기에도 hover 효과를 추가하여 마우스를 가져다대면 부드럽게 잠시 커지게 됨. 세로로 정렬하여 순서대로 사진, 제목, 설명 순으로 카드의 형태 지정.
+
+
+💥pages : Home.jsx, Photo.jsx
+
+Home.jsx - 사용자가 페이지에 접속하였을 때 가장 먼저 보게 되는 화면. (헤더 밑에 위치) 먼저 useEffect, 라우터 기능을 사용하여 콘솔에 페이지에 접속한 것을 보내게 함. 간단한 환영 인사, 설명이 뜨고 밑에 "회원가입 / 로그인" 버튼과 "자세히 알아보기" 버튼을 삽입. 각각 누르게 되면 화면 위에 "~~ 화면으로 이동합니다." 라는 메시지가 뜨도록 함. 또한 hover 효과를 삽입하여 동적 효과 부여.
-주된 컴포넌트인 헤더, 푸터, 포토카드(사진과 글이 있는 것), 버튼에 대해 어떤 계층으로 설계했는지 이곳에 작성해주세요. 그리고 자식 컴포넌트 들에 대해서 어떤 의도를 갖고 설계했는지(ex 정렬하기 위해서, border를 주기 위해서 등) 부담없이 간단하게 적으면 됩니다. (아래는 예시입니다.)
+Photo.jsx - 먼저, components에 있는 PhotoCard 파일과 assets에 있는 사진들을 불러옴. 사진 카드에 들어갈 이미지, 제목, 설명을 적은 배열. map을 이용하여 photolist 배열에 적은 항목들을 PhotoCard 컴포넌트로 만들어 props 로 사진, 제목, 설명을 전달하여 여러 개의 사진 카드가 만들어지게 됨. 배열은 flex를 이용하여 가로로 가운데 정렬하게 설정.
-
diff --git a/package-lock.json b/package-lock.json
index 889b4b6..4954267 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,7 +9,8 @@
"version": "0.0.0",
"dependencies": {
"react": "^19.1.0",
- "react-dom": "^19.1.0"
+ "react-dom": "^19.1.0",
+ "react-router-dom": "^7.6.2"
},
"devDependencies": {
"@eslint/js": "^9.25.0",
@@ -1599,6 +1600,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/cookie": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
+ "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -2470,6 +2480,44 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-router": {
+ "version": "7.6.2",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.6.2.tgz",
+ "integrity": "sha512-U7Nv3y+bMimgWjhlT5CRdzHPu2/KVmqPwKUCChW8en5P3znxUqwlYFlbmyj8Rgp1SF6zs5X4+77kBVknkg6a0w==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie": "^1.0.1",
+ "set-cookie-parser": "^2.6.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "7.6.2",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.6.2.tgz",
+ "integrity": "sha512-Q8zb6VlTbdYKK5JJBLQEN06oTUa/RAbG/oQS1auK1I0TbJOXktqm+QENEVJU6QvWynlXPRBXI3fiOQcSEA78rA==",
+ "license": "MIT",
+ "dependencies": {
+ "react-router": "7.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ }
+ },
"node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@@ -2543,6 +2591,12 @@
"semver": "bin/semver.js"
}
},
+ "node_modules/set-cookie-parser": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
+ "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
+ "license": "MIT"
+ },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
diff --git a/package.json b/package.json
index 31c454b..d6fb807 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,8 @@
},
"dependencies": {
"react": "^19.1.0",
- "react-dom": "^19.1.0"
+ "react-dom": "^19.1.0",
+ "react-router-dom": "^7.6.2"
},
"devDependencies": {
"@eslint/js": "^9.25.0",
diff --git a/src/App.jsx b/src/App.jsx
index 7716cdf..cdc02a0 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,8 +1,15 @@
+import React from "react";
+import Header from "./components/Header";
+import Home from "./pages/Home";
+import Photo from "./pages/Photo";
+
function App() {
return (
<>
- 화이팅!
+
+
+
>
)
}
diff --git a/src/assets/img1.jpg b/src/assets/img1.jpg
new file mode 100644
index 0000000..98cc960
Binary files /dev/null and b/src/assets/img1.jpg differ
diff --git a/src/assets/img2.jpg b/src/assets/img2.jpg
new file mode 100644
index 0000000..c8ba35b
Binary files /dev/null and b/src/assets/img2.jpg differ
diff --git a/src/assets/img3.jpg b/src/assets/img3.jpg
new file mode 100644
index 0000000..5627097
Binary files /dev/null and b/src/assets/img3.jpg differ
diff --git a/src/assets/img4.jpg b/src/assets/img4.jpg
new file mode 100644
index 0000000..d67e005
Binary files /dev/null and b/src/assets/img4.jpg differ
diff --git a/src/assets/img5.jpg b/src/assets/img5.jpg
new file mode 100644
index 0000000..9bceabc
Binary files /dev/null and b/src/assets/img5.jpg differ
diff --git a/src/components/Header.css b/src/components/Header.css
new file mode 100644
index 0000000..a991db2
--- /dev/null
+++ b/src/components/Header.css
@@ -0,0 +1,47 @@
+.header {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ background-color: #56abff;
+ color: white;
+ padding: 16px 0;
+ z-index: 1000;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
+}
+
+.header_container {
+ margin: 0 auto;
+ padding: 0 24px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.header_left {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding-left: 30px;
+ font-size: 0.7rem;
+ font-weight: bold;
+ white-space: nowrap;
+}
+
+.header_menu {
+ list-style: none;
+ display: flex;
+ gap: 24px;
+ margin: 0;
+ padding-right: 30px;
+}
+
+.header_menu li a {
+ color: white;
+ text-decoration: none;
+ font-weight: 500;
+}
+
+.header_menu li a:hover {
+ text-decoration: underline;
+}
\ No newline at end of file
diff --git a/src/components/Header.jsx b/src/components/Header.jsx
new file mode 100644
index 0000000..3d852c5
--- /dev/null
+++ b/src/components/Header.jsx
@@ -0,0 +1,20 @@
+import React from "react";
+import "./Header.css";
+
+function Header() {
+ return (
+
+ );
+}
+
+export default Header;
diff --git a/src/components/PhotoCard.css b/src/components/PhotoCard.css
new file mode 100644
index 0000000..f263d93
--- /dev/null
+++ b/src/components/PhotoCard.css
@@ -0,0 +1,60 @@
+.photo-card {
+ width: 400px;
+ height: auto;
+ border: 1px solid #ddd;
+ border-radius: 8px;
+ background: #fff;
+ overflow: hidden;
+ margin: 16px;
+ display: flex;
+ flex-direction: column;
+}
+
+.photo-card:hover {
+ transition: transform 0.3s ease;
+ transform: scale(1.03);
+}
+
+.photo-img {
+ width: 180px;
+ height: 180px;
+ object-fit: cover;
+ display: block;
+ margin: 0 auto;
+}
+
+.photo-card h2 {
+ margin: 10px;
+ font-size: 20px;
+ text-align : center;
+ color: #333;
+}
+
+.photo-card p {
+ margin: 10px;
+ font-size: 14px;
+ text-align : center;
+ color: #333;
+}
+
+.photo-action {
+ display: flex;
+ justify-content: center;
+ gap: 8px;
+ margin: 10px 0 16px;
+}
+
+.photo-action button {
+ padding: 6px 12px;
+ font-size: 13px;
+ background-color: #f0f0f0;
+ border: 1px solid #bbb;
+ border-radius: 4px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+.photo-action button:hover {
+ background-color: #e0e0e0;
+ transform: scale(1.05);
+}
diff --git a/src/components/PhotoCard.jsx b/src/components/PhotoCard.jsx
new file mode 100644
index 0000000..53cfba2
--- /dev/null
+++ b/src/components/PhotoCard.jsx
@@ -0,0 +1,19 @@
+import React from "react";
+import "./PhotoCard.css";
+
+function PhotoCard({image, title, description}){
+ return(
+
+

+
{title}
+
{description}
+
+
+
+
+
+ )
+
+}
+
+export default PhotoCard
\ No newline at end of file
diff --git a/src/pages/Home.css b/src/pages/Home.css
new file mode 100644
index 0000000..49c95b2
--- /dev/null
+++ b/src/pages/Home.css
@@ -0,0 +1,54 @@
+.intro {
+ text-align: center;
+ padding: 100px 20px;
+ max-width: 800px;
+ margin: 0 auto;
+}
+
+.intro h1 {
+ font-size: 2.5rem;
+ margin-bottom: 20px;
+}
+
+.intro p {
+ font-size: 1.1rem;
+ color: #555;
+ margin-bottom: 40px;
+}
+
+.buttons {
+ display: flex;
+ justify-content: center;
+ gap: 20px;
+}
+
+
+.btn1 {
+ font-size: 1rem;
+ padding: 12px 24px;
+ border: none;
+ border-radius: 6px;
+ cursor: pointer;
+ background-color: #007bff;
+ color: white;
+}
+
+.btn2 {
+ font-size: 1rem;
+ padding: 12px 24px;
+ border: none;
+ border-radius: 6px;
+ cursor: pointer;
+ background-color: #6c757d;
+ color: white;
+}
+
+.btn1:hover {
+ transition: transform 0.3s ease;
+ transform: scale(1.1);
+}
+
+.btn2:hover {
+ transition: transform 0.3s ease;
+ transform: scale(1.1);
+}
\ No newline at end of file
diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx
new file mode 100644
index 0000000..3f9565b
--- /dev/null
+++ b/src/pages/Home.jsx
@@ -0,0 +1,34 @@
+import React, { useEffect } from "react";
+import "./Home.css";
+
+function Home(){
+ useEffect(() => {
+ console.log("Home 페이지에 접속했습니다.");
+ }, []);
+
+ const handleJoinClick = () => {
+ alert("회원가입 / 로그인 화면으로 이동합니다.");
+ };
+
+ const handleEtcClick = () => {
+ alert("자세히 알아보기 화면으로 이동합니다.");
+ };
+
+
+ return(
+
+ Welcome to Pocket Album!
+
+ 포켓앨범에 오신 것을 환영합니다! 이곳은 여러분의 소중한 추억을 혼자만의 공간에 < br />
+ 가볍게 스크랩할 수 있는 서비스를 제공합니다. 간단한 회원가입을 통하여 저희 서비스를
+ 즐겨주세요!
+
+
+
+
+
+
+ );
+}
+
+export default Home;
\ No newline at end of file
diff --git a/src/pages/Photo.css b/src/pages/Photo.css
new file mode 100644
index 0000000..98ccfdb
--- /dev/null
+++ b/src/pages/Photo.css
@@ -0,0 +1,6 @@
+.photo-grid {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ padding: 32px;
+}
diff --git a/src/pages/Photo.jsx b/src/pages/Photo.jsx
new file mode 100644
index 0000000..26cef01
--- /dev/null
+++ b/src/pages/Photo.jsx
@@ -0,0 +1,29 @@
+import React from "react";
+import PhotoCard from "../components/PhotoCard";
+import img1 from "../assets/img1.jpg";
+import img2 from "../assets/img2.jpg";
+import img3 from "../assets/img3.jpg";
+import img4 from "../assets/img4.jpg";
+import img5 from "../assets/img5.jpg";
+import "./Photo.css";
+
+function Photo() {
+ const photolist = [
+ { image: img1, title : "오사카1", description: "일본은 라멘이 맛잇더라고요" },
+ { image: img2, title : "오사카2", description: "유니버셜스튜디오도 재밋엇어요" },
+ { image: img3, title : "시드니", description: "여기는 고급 일본 여행같은 느낌이래요 꼭 가보고 싶습니다" },
+ { image: img4, title : "뉴욕", description: "무조건... 타임 스퀘어 앞에서 새해 맞이하는 게 버킷리스트 1번" },
+ { image: img5, title : "텍사스", description: "카우걸 체험 해보고 싶음" },
+ ];
+
+ return(
+
+ {photolist.map((item, idx) => (
+
+ ))}
+
+ );
+};
+
+
+export default Photo;
\ No newline at end of file