개발노트

Next - SNS 클론코딩 1, 2 본문

React/project

Next - SNS 클론코딩 1, 2

aloha2jh 2024. 4. 22. 22:42

 

목차

1. 기획서

2. 클론코딩 시작

3. API not yat

4. got API

5.  백엔드 관련


0 인트로

 

Next 14 버전

기존 pages Router -> app Router (layout기능) 로바뀜

페이지별 권한기능 

 

react 18 - 서버 컴포넌트?

넥스트 서버에서 리액트를 미리 렌더링해서  클라이언트한테 데이터 보내줄때 완성된 HTML 미리 보내주는것) HTML 로딩시간 단축

(넥스트 서버에 부담이 늘어남)

 

 

 


 

1 기획서


Next 프로젝트 만들기

화면 어떻게 만들지랑 주소체계파악하기

 

npx create-next-app

typescript , eslint , src-directory, app router O
aliasX

 

폴더구조

-넥스트서버에서 누구나 접근할수 있게 서빙해주는 폴더? 

-src/app구조인 이유?

public/타입스크립트 처리 용이

 

Layout.tsx 의 children 컴포넌트

src/app/layout.tsx 에 있는 children 컴포넌트 안에

pages.tsx가 들어감

 

로그인 유무에 따른 레이아웃 달라지는데 어떻게 처리할것인가?

=> 레이아웃을 두개 만든다

최상단 layout.tsx놔두고 레이아웃 만들고싶은 주소파일안에 layout.tsx만들면됨.

ex) /home은 다른 레이아웃적용하고싶다

1. /home 안에 layout.tsx(최상단레이아웃과 똑같은내용으로)  생성

그럼 최상단레이아웃 안에 layout이들어가고 그 안에 나머지 페이지가 들어가게됨!

 

브라우저 주소 app폴더에 반영하기

-url에 주소대로 app하위에 폴더구조대로 만들면됨.

-dynamic routes 바뀌는 이름은 대괄호로 폴더이름 만들어줄것 [username]

-주소창에 관여안하는 폴더 사용하기 ex 로그인 한 사용자의 url 경로(afterLogin)

 

링크태그 사용하기 - 'next/link'에서 가져오면 됨.

 

Layout 컴포넌트

param에  { children } 받고, 렌더에 {children} 써주기

 


Parallel Routes 

페러렐 라우츠  사용해서 모달 구현하기

1. @이름  으로 폴더 생성

2. 보여줄 페이지들이 같은 폴더안에 있어야 함.

3. 한화면에 두개의 페이지를 보여줄거기 때문에, 새로운 레이아웃을 만든다. layout.tsx

4. layout 컴포넌트에서 param으로 children, modal을 param으로 받고 둘다 렌더링 해줌

 

근데 이게 root 폴더경로와 일치하는 url 이 children이고 @modal 안에 경로와 일치하는게 modal로 들어가게되서,

ex) root/i/flow/login ( page ) <-  A

root/page (page) <- 여기보여주면서 모달을 띄워주고 싶었지만 A로 보여줄수밖에 없게됨.

root/@modal/i/flow/login (page) <- modal

 

+여기서도 page를 컴포넌트화 시켜서 보여주면 되지 않나.? 콜라보로 굳이 같이써야되나;

=> 만약 특정 페이지에서 한두개에서만 나오는 모달일경우 인터셉트 굳이 필요없음.

그러나 페이지 전체에서 나오는 모달일경우 인터셉팅필요!

일일히 Page 지정해주는게 불가넝 기본값 layout에 모달자리를 만드는게 효율적.

 

 

 

Intercepting Routes

주소가 다른데 뜰수있게 해줌 (.)i 

 

1. 레이아웃에 modal 추가

2. 인터셉 하고싶은 url경로랑 똑같은 폴더경로 만들고 - 젤 상위폴더에(.)점찍어주기!

 

ex) url 주소가 i/flow/login 요청이 들어왔을때,

@modal/(.)i/flow/login page <- 얘로 보여줌.

 

Link링크 타면 인터셉팅 페이지로 로드되지만,

주의) 

-새로고침하면 ->인터셉팅 안됨

-서버컴포넌트에서 리다이렉트 할때도 -> 인터셉팅으로 안됨.

 

리다이렉트 방법 2가지

replace와 redirect의 차이?

redirect는 서버 replace는 클라이언트

 

 

push 뒤로가기할때 리다이렉트요청하는 페이지로 이동이되서,

/ -> /login -> i/flow/login (만약login 리다이렉트걸면 무한반복걸림;;)

replace는대체되서 그전전페이지로

 

 

 

_private folder로 중복코드 관리

1. 중복 코드의 공통되는상위경로에 _이름 폴더만들기 (언더바쓰면 주소창에 안뜨는 private폴더 생성됨) 

2. 공통되는 page 를 컴포넌트로 만들기 

3. 두군데 이상에서 불러다 쓰기(불러다쓰는 쪽은 서버컴포넌트 여야 함!)

서버컴포넌트는 클라이언트컴포넌트 import 가능, 반대는 불가능.

 

@modal (.)  _common (beforeLogin)


Q. 만약 이메일 다음 클릭시 비밀번호 뜨게 어떻게 하지? -step 이란 값으로 저장~ 

강의랑 다르게 했음; 
인터셉팅 라우터 굳이 사용안해도 모달 기능 구현되서 메인 홈페이지를 컴포넌트화 시켰음. (이게 파일경로 들어가면 페이지 그대로 url이랑 매칭 되고 직관적이여서)인터셉팅 안쓰면 새로고침되도 똑같은페이지로드됨/리다이렉팅도 인터셉팅안써서 문제안생김.

 

Q. 루트 경로로 이동해도 안꺼지는데, next 공식문서에 => router.back() 

 

 

저장 ctrl+s 시에 자동정렬 관련

(원래 적용되던 vscode 잘쓰고 있었는데, 강의 next-create-app생성후 되던게 안되서 문제겪었음)

1. vscode preitter 설치

2. default 설정을 prettier

3. 프로젝트 안에 prettierrc폴더에 원하는 설정값 입력.

 

 


2 클론코딩


Active Link


넥스트 제공 훅인 useSelectedLayoutSegment사용해서 컴포넌트가 어떤 라우터에 있는지 알수 있음.

1. 클라이언트 컴포넌트로 만들기 use client

2. useSelectedLayoutSegment (or segments)사용해서 값 가져오기.

const segment = useSelectedLayoutSegment();

3. className 설정

훅쓰거나 이벤트리스너 있을땐 클라이언트 컴포넌트

 

+컴포넌트의 style url 경로 기본값은 public임

 

탭메뉴 구현

추천, 팔로우 버튼(탭) 누르는거에 따라서 다른 컴포넌트 불러오기

<Tab />컴포넌트 생성후 하위에 <Content/>컴포넌트에 다른 데이터 넘겨줌.

className={tab===0 ? "active":""}
onClick={onClickTabChange(0)}

tab==0?<Content data={dataRec} /> : <Content data={dataFol} />

 

ref값있을때만 클릭되게 하려면?

imageRef.current?.click(); 옵셔녈체이닝

 

dayjs 라이브러리

날짜 계산해서 몇초전, 21일전 출력해줌

 

게시글 클릭시는 post페이지로

유저 클릭시 user profile페이지로 이동하게

사진 클릭시는 사진페이지로

 

액션버튼 컴포넌트

버튼 클릭시 숫자 1 추가되게

기능 

1. 로드시
    1) 정보 숫자보여주기 2) 사용자가 눌렀는지 아이콘에표시(클래스연결)

2. 클릭시
    1)값 +1 되기 2)사용자가 눌렀는지 체크 토글

 

클릭시에 값 업데이트하는부분 헷갈렸는데 이렇게 하면 됬다.


 

 

Q. 제로초는 컴포넌트마다 css 쪼개서 컴포넌트당-파일2개씩관리하는데 이게 더 나은방안인가?

-나는 한파일에 관리하는게 편해서 지금 중점이 css관리방안 아니라 패쓰했는데 시간날때 생각해보기.

 

+ li 안에 Link next컴포넌트 넣었더니, 자식이 stopPropagation적용도 안됬음.

(시간관계상)그냥 마크업바꿨는데 우선순위 궁금하다.

Q.부모에 onClick 이벤트와 자식에 onClick이벤트 영역 겹칠때 리엑트는 어떻게 처리되지?

A) 부모->자식 (캡처링) 자식->부모(버블링) 이고 stopPropagation쓰라고 함.


 

게시하기 모달 - 페이지 어디서나 뜨는 모달 만들기


인터셉팅없이는 다른 페이지에서 호출이 불가.해서 페러럴+인터셉팅 사용했음!

 

특정페이지 에서만 공통되는 레이아웃에 적용된 컴포넌트 안보여주려면?

=> 해당 컴포넌트에서 segment일때, return null처리

 

 

-O 검색 페이지에서 검색필터 나오게 

사용자 옵션 두가지 (라디오버튼)

1) 모든 사용자 ㅇ 2) 내가팔로우 하는 사람들ㅇ

 

- O my-profile 페이지 퍼블
- O explore 페이지 퍼블 (강의에선 코드다시짜는데 이거 스타일적용만 바꿔도 되서 class로적용.)

- O back button 컴포넌트화 (my-profile / userSearchParams )

 

 

쿼리스트링값 받아서 보여주기

search?q="악의%20평범성"&src=trend_click&vertical=trends

<SearchForm q={searchParams.q} />

 

1. page에서 매개변수로 searchParams 를 받기(기본으로 들어있음)

2. 타입지정;{searchParams}: Props
type Props = {  searchParams :string}

3. searchParams.q값을 컴포넌트에 props로 넘겨주기

4. 받아서 placceholder에 보여줌.

 

링크이동하는 Tab 만들기


(디자인만 같을뿐 링크이동하지 않는 탭은 mark up도 달라져서, 이럴경우 새로 생성. LinkTab으로 만들었다.)

-querystring값을 param:props로 받아서, querystring 유지 하면서 뒤에 tab=trand 이렇게 tab값만 바꿔주게만들었음.

-Link태그 사용.

강의에서는 router로 이동하고 useSearchParams라는 훅사용했음

router.replace(`/search?q=`) // import {useRouter} from 'next/navigation'

useSearchParams는 props로 굳이 안넘겨도 되서 괜찮아 보임.

 

queryString 받아오기

1. {useSearchParams} from 'next/navigation';

2.searchParams = useSearchParams();
3.searchParams.get('q') //using the Get Method. 
should be a client component 'use client'


게시글 상세 페이지 status

서버컴포넌트에 이벤트리스너 붙여도 서버컴포넌트로 유지 하려면?

서버컴포넌트(Content)에서 이벤트리스너붙는 한줄만 클라이언트 컴포넌트로 만들어준다.
(슬롯방식인것 같다-자식이 껍데기만 되고 부모 html 값을 children으로 받아서 보여줌.)

<ContentItem> 
<div>{user.id}</div> //여기에 부모html값;
</ContentItem>

 

반대로. 부모가 클라이언트 컴포넌트, 자식이 서버컴포넌트일경우?

부모 컴포넌트에 children으로 넣어주기-children 이나 props로 서버컴포넌트 넘겨 받아 보여주기

(클라이언트가 서버컴포넌트 import하면 클라이언트로 바뀜;)

{children} //서버컴포넌트
<div></div> //부모 html

 

 

이벤트영역 겹칠때

onClickCapture={}
이벤트영역이 겹치는데, 바깥영역을 onClickCapture={}로 바꾸니 됬음 신기하구만..

이벤트 캡쳐링을 할수 있음.

 

 

컴포넌트 디자인 패턴 관련 고찰.

+ publising, markup, 컴포넌트나누는- 과정에선 더미데이터 수정 불가피.

=> data.js 에서 가져다 쓸것.

A. 하위는 간단하게 정보만 렌더링하도록(페이지에서만 호출)

-하위컴포넌트도 호출가능하게 하면 어디서 호출하는지 컴포넌트 일일히 까서 확인해야 함

-재활용성도 떨어짐

-만약 데이터 로드 순서가 영향을 미칠때 (다른컴포넌트로 상호적으로 데이터 바꿔야 할때)

ex) 탭클릭시 다른 버튼이름 로드할때, 탭과 버튼 상위에 있는 컴포넌트에서 데이터만 바꿔줬을때 알아서 로드 됨.

<-> B.

-상위에 데이터 호출이 너무 많아짐

-컴포넌트들이 자기 필요할때만 호출?

 

// 일단 껍데기만 만드는 과정에서는 하위컴포넌트에 데이터 붙어있는게 나음. OR 파일에서 가져와서 쓰기!!


photo modal 만들기

target : ContentItem의 photo영역

event : click

eventHandler : 모달 띄우기 ( left 사진+버튼 right 게시글+답글폼+답글 )

when & condition :즉시/  조건-afterlogin 페이지 전체에서 나오게 

 

modal url : aloha2jh/status/123/photo/1  `${userId}/status/${postId}/photo/1`

 

 

모달 퍼블완료 

(옮겼을때 자동으로 width사이즈에 맞게 들어가게 처음부터 퍼블하는 방안 없나? height도 마찬가지..)

퍼블리싱할때. div ul 이런거 사용하지 말것! 무조건 이름 지정해서 하기 (작은단위컴포넌트)

 

dummy Data

dummy 데이터를 따로 data.js 파일로 빼서 정리했다.

 

 

fakerjs


+ 버그가 있음 (게시하기랑 똑같이 만들었고 default 페이지도 만들어줬는데;)

버그 1) 페럴럴 children 페이지가 로드가 안됨 모달만뜸;

 

시스템 경고 해결하기

버그1) 페이지 로드될때마다 어느때부턴가 사진이 404 였다가 아니였다가 그럼.

key값 부여 후 해결됨.. 키값을 꼭 부여하자


message Page 만들기

퍼블 및 컴포넌트화 완료(data.js - json데이터로)

 


포스트 이미지 갯수에 따라 다른 레이아웃 적용해보기

0일때 early return 처리

1,2,3,4일때 감싸는 박스에 image.length 로 다른 클래스명 적용해서 , 클래스별로 다른 레이아웃style적용했음.

 

 

 

 

 

 

 

 

 

 

 

'React > project' 카테고리의 다른 글

Next - SNS 클론코딩 3  (0) 2024.05.13
next - getInitialProps  (0) 2020.08.27
nodemon  (0) 2020.08.27
redux 설치  (0) 2020.08.25
redux  (0) 2020.08.25