반응형
oneted page 원티드 페이지 만들기 도전!!
파일구조를 파악하고 파이어베이스 까지 가자
파일구조 |
|
@media | @media 미디어타입 and (조건) { /* 조건에 맞는 스타일 */ } |
테일윈드버전명령어 npm list tailwindcss |
|
<Link>태그이후 import import Link from 'next/link'; // 이 부분을 추가하세요. |
1 |
카드 컴포넌트 |
1 |
Next.js SSG 와 리액트 SPA의 차이 |
1 |
사이드 패딩값 |
1 |
테일윈드 div로 틈 패딩값 주는 코드 | 틈패딩 값 div 태그로 만들기
1 출력 : padding: 10px; |
리턴 삼항연산자 조건&& |
|
<>와 </> (즉, Fragment) |
|
사이트 뒤에 동적 로그만들기 ./src/pages/wd/[id].tsx |
https://www.wanted.co.kr/wdlist/518?country=kr&job_sort=job.latest_order&years=0&locations=all 사이트 뒤에 동적 로그만들기 - **(필수) 매 기업마다 Dynamic Routing 설정하기** : 더미 회사 JSON - 더미 회사 JSON 을 만들어서 API 가 아닌 단순 Import 를 통해 정보를 find / filter 조회 - 예) http://localhost:3000/wd/10238 접근 시 10238 ID 더미 기업 JSON 정보 사용
1 |
사이트 뒤에 동적 로그만들기 ./src/pages/wd/[id].tsx Next.js의 특징 userRouter 훅을 사용할려면 URL 파라미터 값을 적어야된다. |
Next.js의 동적 라우팅을 사용하려면 해당 페이지의 파일명을 [변수명].tsx 형식으로 작성해야 합니다. 예를 들어, /wd/1, /wd/2, ... 등으로 접근할 수 있는 페이지를 만들려면 파일 이름을 [id].tsx로 해야 합니다. 그리고 해당 페이지에서는 Next.js의 useRouter 훅을 이용하여 URL 파라미터 값을 가져올 수 있습니다.
1 |
1 |
|
firebase 명령어 |
1 |
유투브사이트(참고사이트) | https://www.youtube.com/watch?v=uikATllLdRc 파이어베이스 연결강의 |
파이어베이스1 |
1 |
파이어베이스2 |
1 |
19:00 | |
파이어베이스 add |
1 |
파이어베이스 3 |
1 |
파이어베이스4 useEffect |
1 |
나의 토큰 |
|
1 |
|
image%B1.PNG에서 2F를 사용한이유는? | image%2FB1.PNG에서 %2F는 URL 인코딩에서 사용되는 특수 문자입니다. 즉, image%2FB1.PNG는 실제로 image/B1.PNG를 의미합니다. 파이어베이스 스토리지의 URL에서 파일 경로 부분이 이런 방식으로 인코딩되어 표시됩니다. |
위의 규칙은 로그인한 모든 사용자에게 파일에 대한 읽기/쓰기 권한을 부여합니다. |
|
만약 인증하지 않은 모든 사용자에게 파일에 대한 읽기 권한을 부여하려면 |
|
파일경로의 이해도 |
|
npm install swr |
|
오류 내용 |
1 |
오류 내용 2 |
|
|
인수 유형 문제 |
으로 바꿈 |
리액트 인라인 스타일코드 로 Hight 60px 맞춰서 탑섹션 고정하기 |
제가 제공한 코드 는 인라인 스타일을 사용한 React JSX 문법입니다.</div style={{height: '60px'}} >
1 |
@min - max를 적용한 .class name globalcss 만들는 방법 |
|
왼쪽 오른쪽 위 아래 패딩값 |
|
상하좌우 패딩 조건 | padding-top: 10px; padding-right :15px ; padding-bottom :20px ; padding-left :25px ; |
라우터 사용법 순서 | |
npm install react-router-dom | |
BottomCardinsider.tsx |
|
파일구조: pages wd [id].tsx BottomCard.tsx |
|
BottomCard.tsx | import React, { useEffect, useState } from 'react'; import { getStorage, ref, getDownloadURL } from "firebase/storage"; import Link from 'next/link'; const BottomCard = () => { const [companies, setCompanies] = useState([]); useEffect(() => { const fetchLogos = async () => { const storage = getStorage(); const companiesData = [ { id:1, name:"오너클랜", logoUrl:"image/B1.PNG", // 액세스 토큰 제거 description:"고급 개발자(typescript, nodejs, MySQL)", location: "서울", location2: "한국" } , ]; for (let company of companiesData) { const gsReference = ref(storage, company.logoUrl); company.logoUrl = await getDownloadURL(gsReference); } setCompanies(companiesData); }; fetchLogos(); }, []); return ( <div className="BottomCard"> <h3>적극 채용 중인 회사</h3> <ul className="company-list" style={{display:'flex', flexWrap:'wrap', padding:'0'}}> {companies.map(company => ( <> <li key={company.id} className="company-card" style={{width:'23%', listStyleType:'none', margin:'1%'}}> <Link href={`/wd/${company.id}`}> <img src={company.logoUrl} alt={`${company.name} logo`} /> <div style={{height: '10px'}} /> <div className="BottomCardHead">{company.description}</div> <h4>{company.name}</h4> <span className="addressDot">{company.location}</span> <span className="addressDot">.</span> <span className="addressDot">{company.location2}</span> <span>{company.reward}</span> </Link> </li> </> ))} </ul> </div> ); }; export default BottomCard; |
[id].tsx | import { useRouter } from 'next/router'; import BottomCardinsider from '../../components/BottomCardinsider'; export default function Company() { const router = useRouter(); const { id } = router.query; return <BottomCardinsider id={id} />; } |
이해 | <OnerClan/> 컴포넌트가 렌더링되는 위치는 코드에서 정의된 순서에 따릅니다. 현재 코드에서 <OnerClan/> 컴포넌트는 두 번 호출되고 있습니다. 첫 번째 호출은 {company && <ComponentToRender company={company} />} 부분에서 이루어지며, 여기서 ComponentToRender는 components[id]를 통해 결정됩니다. 만약 URL의 id가 1이라면, ComponentToRender는 OnerClan이 되고, 따라서 <OnerClan company={company} />가 렌더링됩니다. 두 번째 호출은 코드 하단의 <Tag/><OnerClan/> 부분에서 이루어집니다. 이 부분은 조건문 없이 항상 <OnerClan/>를 렌더링합니다. 따라서 만약 URL의 id가 1일 경우, <OnerClan/> 컴포넌트가 두 번 렌더링되므로 페이지 상단과 하단에 각각 나타나게 됩니다. 만약 하단에 있는 <OnerClan/> 컴포넌트를 제거하려면 해당 줄을 주석 처리하거나 삭제하면 됩니다: jsx <div> <Tag/> {/*<OnerClan/>*/} </div> 또한 동적으로 선택된 컴포넌트(ComponentToRender)와 이미지 및 기타 정보 사이에 공간을 추가하려면 적절한 스타일(예: 마진)을 적용하거나 추가적인 HTML 요소(예: 개행(<br />) 등)를 사용할 수 있습니다. |
이해2 | import React from 'react'; import { useRouter } from 'next/router'; import TopSection from "./TopSection"; import ImageComponent from './ImageComponent'; import Tag from './Tag'; import OnerClan from "../pages/OnerClan"; // import Nulldy from '../pages/Nulldy'; // 예시: 만약 Nulldy라는 컴포넌트가 있다면 import Sidefixpage from "./Sidefixpage"; // 가능한 모든 JobDetailX 컴포넌트를 포함하는 객체 const components = { 1: OnerClan, // 2: Nulldy, // 예시: 만약 id가 2인 회사의 상세 페이지로 Nulldy라는 컴포넌트를 사용하려면 }; const JobDetail = ({company}) => { const router = useRouter(); const { id } = router.query; // URL에서 id 값을 추출 // id에 해당하는 컴포넌트 선택 const ComponentToRender = components[id]; return ( <div className="Hirecom" style={{padding: '0px 80px 50px 80px'}}> {/* 패딩: 위 80px, 오른쪽 80px, 아래 50px, 왼쪽 20px */} <TopSection/> <div style={{height: '60px'}} /> <div style={{display: 'flex'}}> <Sidefixpage style={{width:'340px'}}/> </div> <div> {/* ComponentToRender 가 존재할 경우만 렌더링 */} {company && ComponentToRender && <ComponentToRender company={company} />} {/* 기타 내용... */} </div> </div> ); }; export default JobDetail; |
회사의 추가에 대한 개념 | 만약 각각의 회사에 대해 별도의 컴포넌트(OnerClan, Nulldy, 등)를 가지고 있고, 이러한 컴포넌트들이 각기 다른 레이아웃과 스타일을 가지고 있다면, URL에서 추출한 id에 따라 해당 컴포넌트를 동적으로 렌더링하려면 아래와 같은 방식을 사용해야 합니다: jsx import OnerClan from "../pages/OnerClan"; import Nulldy from '../pages/Nulldy'; const components = { 1: OnerClan, 2: Nulldy, }; const JobDetail = ({company}) => { const router = useRouter(); const { id } = router.query; const ComponentToRender = components[id]; return ( <div className="Hirecom"> {/* ... */} {company && ComponentToRender && <ComponentToRender company={company} />} {/* ... */} </div> ); }; 위의 코드는 URL의 id 값에 따라 다른 컴포넌트를 렌더링합니다. 즉, /wd/1 URL은 OnerClan 컴포넌트를, /wd/2 URL은 Nulldy 컴포넌트를 보여줍니다. 새로운 회사가 추가될 때마다 해당 회사의 상세 정보 페이지용 새로운 컴포넌트를 생성하고 이를 components 객체에 추가해야 합니다. 그러나 대부분의 경우, 모든 회사가 공유하는 공통된 레이아웃과 스타일을 가진 단일 JobDetail 컴포넌트가 있고, 그 안에서 동적으로 변경되는 부분만 데이터(회사 정보)로 처리합니다. 이 경우에는 각각의 회사 데이터만 다르게 전달하면 되므로 새로운 페이지나 별도의 파일을 만들 필요가 없습니다. |
회사의 추가 기본틀 | const JobDetail = ({company}) => { // ... 기타 코드 return ( <div className="Hirecom" style={{padding: '0px 80px 50px 80px'}}> {/* 패딩: 위 80px, 오른쪽 80px, 아래 50px, 왼쪽 20px */} <TopSection/> {/* ... 기타 코드 */} <div> {company && ( <> <ImageComponent imageName={company.logoUrl}/> <h3>{company.description}</h3> <p>{company.name}</p> {/* ... 기타 정보 */} </> )} </div> </div> ); }; |
제목1
규칙에서 allow read: if true; 부분은 모든 사용자가 모든 문서를 읽을 수 있음을 나타내고, allow write: if request.auth != null; 부분은 인증된 사용자만 모든 문서를 쓸 수 있음을 나타냅니다. Firebase Storage 규칙: Firebase Storage는 개발자가 파일(예: 이미지, 비디오 등)을 업로드하고 다운로드할 수 있는 클라우드 기반 스토리지 서비스입니다. 이러한 파일에 대한 접근을 제어하기 위해 사용되는 것이 바로 Firebase Storage 규칙입니다. |
|
규칙에서 allow read; 부분은 모든 사용자가 모든 파일을 읽을 수 있음을 나타내고, allow write: if request.auth != null; 부분은 인증된 사용자만 모든 파일에 쓸 수 있음(즉, 업로드 및 삭제 가능)를 나타냅니다. 결국 두 코드 조각은 각기 다른 서비스(Cloud Firestore와 Firebase Storage)에 대해 어떤 유형의 요청(read/write 등)이 허용될 것인지를 결정하는 보안 설정입니다. |
|
firebase 스토리 이미지파일을 가져와서 로드하는 코드 |
1 |
.Tag 코드 |
1 |
Top section hight60px; 높이설정하는방법 |
1 |
.jobdetailboder 상 하 좌 우 페이지 css 적용하는방법 |
1 |
동작의 원리 | 1. BottomCard.tsx 2. BottomCardinsider.tsx 3. JobDetail.tsx |
구글 인증하는방법 Authentication 새 제공업체 추가 구글 이메일 등록 사이트 Google Cloud Console에 접속한다. API API 및 서비스 |
1 구글 인증하는방법 ※ 구글 api 사용자 인증 정보 API 키 Browser key (auto created by Firebase) 2023. 9. 16. 없음 OAuth 2.0 클라이언트 ID Web client (auto created by Google Service) 2023. 9. 23. 웹 애플리케이션 서비스 계정 fir-oneted@appspot.gserviceaccount.com App Engine default service account firebase-adminsdk-dkhwn@fir-oneted.iam.gserviceaccount.comfirebase-adminsdk 1 |
탑메뉴 css |
1 |
.Topfilter1{ margin-bottom: 25px; padding-top: 10px; width: 100%; padding-bottom: 10px; } .Topfilter2 { position: fixed; left: 0; right: 0; top: 0; border-bottom: 1px solid #36f; background-color: #fff; z-index: 2; padding-top :20px; padding-bottom :25px !important; } |
탑 필터를 주므로서 탑은 고정된 상태에서 탑상단은 고정되고 밑에 채용정보의 글의 내용과는 겹치지않고 자연스럽게 보여집니다. - z-index:2; : z-index 값을 '2'로 설정하여 다른 겹치는요 소보다 위에 위치하도록 합니다(z-index 값이 클수록 위). -padding-top and -bottom with !important keyword to ensure these styles take precedence over other potentially conflicting styles 1 |
양옆 패딩값 조절하는 div |
|
모달창에 대한 이해 |
const [modalVisible, setModalVisible] = useState(false); const handleOpenModal = () => { setModalVisible(true); }; const handleCloseModal = () => { setModalVisible(false); }; onClick={handleOpenModal} 으로 작동하게된다. 1 |
모달창 왼쪽 오른쪽 이동 및 모달창 전체크기 만드는 코드 |
1 |
모달창 다른곳 누르면 닫히게 하는 코드 |
1 |
햄버거 모달창 코드 |
1 |
스타일 컴포넌트 설치 명령어 | npm install --save styled-components |
반응형
'컴퓨터공부 > ASAC 웹풀스택' 카테고리의 다른 글
Next.js 공부 정리 (1) (0) | 2023.09.25 |
---|---|
git 사용법 정리 (0) | 2023.09.19 |
ASAC 웹 풀스택 리액트 복습 (0) | 2023.09.11 |
Next.js 기본세팅 (0) | 2023.09.08 |
댓글