선생님의 설명 덕분에 클라이언트 컴포넌트에서도 Server Action을 활용하는 방법을 알게 되었습니다. 하지만 몇가지 의문이 있는 상태입니다. ㅜㅜ Server Action이라는 것이 클라이언트 컴포넌트에서 직접 DB에 접근하거나 별도의 브라우저에서 요청하지 않더라도 서버에 요청을 보내서 Prerendering 하는 방식이 맞을까요? 그러면 보안 상의 장점도 가질 수 있고, 속도에도 개선이 생기는게 맞을까요? 클라이언트 컴포넌트에서 Server Action을 사용하게 된다면 기존의 Server Action의 장점이 없어지는 것 같은데 사용하는 이유가 단순히 강의에서의 설명을 위함이신지 아니면 별도의 장점이 있으셔서 강의에 넣으실 계획을 하신 건지 궁금해서 질문남깁니다!
제가 이해한 것이 맞는지 확인차 질문 남기게 되었습니다! MSW의 경우, service worker가 브라우저의 요청을 뺏어서 browser.ts로 요청을 전달하는 게 맞을까요? 그렇다면 http.ts같은 경우는 서버 컴포넌트에서 서버로 요청을 보낼 때는 next 서버에서 요청을 보내고 난뒤의 데이터를 가지고 서버에서 미리 렌더링하기 때문에 이 요청을 mocking하기 위해 만들어두신 개념이 맞을까요?
안녕하세요! 강의 중간에 generateMetadata 를 사용하는 부분에서 왜 서버 api로 분리를 했는지에 대해 의문이 생겨서 질문드립니다. generateMetadata 에 사용할 getSinglePost 함수는 원래 아래와 같은 코드로 작성되어있었습니다. 여기서 generateMetadata 를 구현하실때, 기존의 getSinglePost 를 사용하시지 않고, getSinglePostServer 를 사용하셨는데 혹시 왜 이렇게 서버 API로 분리를 하셨는지 알 수 있을 까요? 처음에는 generateMetadata 는 서버 환경에서 진행이 되기 때문에 서버에서 돌아가는 api를 작성해야 한다 그렇기 때문에 credentials: 'include 를 사용하는 부분이 있다면 이는 클라이언트 환경에서만 적용이 되는 것이므로 headers: { Cookie: cookies().toString() } 를 사용해야 한다 라고 저는 이해를 했었기 때문에 getSinglePost 대신 getSinglePostServer 로 분리를 하신거라고 생각했습니다. 근데 기존의 getSinglePost 는 애초에 인증 여부가 필요한 부분이 아니어서 credentials: 'include 는 없었는데 왜 강의에서 getSinglePostServer 로 따로 분리하시고 headers: { Cookie: cookies().toString() } 를 추가로 적용하셨는지 궁금합니다!
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예 [질문 내용] 강의에서(12:00부분) 참조값만 복사하고 인스턴스를 복사하는 것이 아니라는데, 결국 같은 인스턴스를 접근하게 되잖아요 그러면 위 뜻이 인스턴스가 동일해지는 것은 맞지만, 참조값을 복사하는 것이지 인스턴스를 복사하는 것이 아니라서 잘못 인지하지 말라는 뜻인가요? 아니면 인스턴스가 달라서 참조값만 복사한 것이기에 인스턴스를 복사하는 것이 아니라는 뜻인가요? Data dataA = new Data(); // 1.Data인스턴스 생성후 dataA에 참조값 넣음 dataA.value = 10; Data dataB = dataA; // 2.dataA 참조값을 복사하고 대입함 System.out.println("dataA.value = " + dataA.value); // 10 System.out.println("dataB.value = " + dataB.value); // 10 // 3.dataB는 dataA의 인스턴스에 동일하게 접근하게됨
서버 컴포넌트가 프론트 서버에서 미리 렌더링되는 것으로 알고 있었습니다. 이것이 맞을까요?? 클라이언트 컴포넌트랑 서버 컴포넌트의 렌더링 방식을 찾아봤음에도 여전히 헷갈리는데 시간적 여유가 되신다면 쉽게 알려주실 수 있을까요?? 클라이언트 컴포넌트 사이에 서버 컴포넌트를 넣으면 렌더링 동작이 어떻게 수행되는지 궁금합니다. 강좌에서는 PostArticle이라는 클라이언트 컴포넌트의 자식으로 서버컴포넌트를 넣는데, 공식문서에서는 클라이언트 컴포넌트가 DOM Tree의 끝에 오도록 하는 것을 권장하는 것으로 알고 있었는데 제가 잘못 알고 있던 것이었을까요??
안녕하세요. 온라인강의 수강하는 학생입니다. 주중엔 짬짬이 강의만, 코딩학습은 주말만.. 학습 진도가 늦지만. 장기간 걸쳐. 열심히 해 보겠습니다.ㅎ 회원가입 과제 아래와 같이 해 보았습니다. (1) vector 부분을 어떻게 적용해야 하나요? figma에서 제공하는 svg소스를 복사,붙여 넣기만 했는데... (2) ellipse 부분을 어떻게 적용해야 하나요? checkbox나 radio 부분에 svg 소스 활용방법이 궁금합니다. (3) 과제에 대한 멘토님의 소스를 보고싶은데 , 제가 못 찾는 것인지 멘토님 소스 보는 방법을 가르쳐 주셨으면 합니다. 멘토님의 의견 감사합니다.
안녕하세요~ 양질의 강의 잘 수강중입니다. https://github.com/mswjs/msw/issues/1801 종종 발생하는 이슈 같은데 (제로초님 코멘트도 있네요!) 저도 제로초님 코드 그대로 따라해보았지만 해당 이슈가 계속 발생하네요ㅠㅠ어떤 문제 때문인지 감이 잘 잡히지 않는데 MSW를 다운그레이드 하는 방법 밖에 없을까요? 조언 부탁드립니다ㅠ
안녕하세요! React로 NodeBird SNS 만들기 섹션4 팔로우/언팔로우 강의를 끝까지 수강한 수강생입니다! 항상 강의 잘 보고 있습니다! 제로초님 감사합니다! 김블루 계정으로 핑크공주 계정을 팔로우 했을 때 팔로잉, 팔로워 사용자의 이름과 금지 표시 아이콘이 목록 화면에 보이지 않습니다! (아이콘이 들어가는 위치에 다른 아이콘을 넣었을 때도 아이콘이 표시되지 않았습니다!) 리덕스와 네트워크 탭을 확인했을 때 팔로워, 팔로잉 목록 불러오기는 성공했습니다. vsCode 터미널, 콘솔, 리덕스, 네트워크 항목에도 에러가 없으며 앤트 디자인 아이콘 버전도 아이콘에 맞게 수정하고, item도 추가했지만 해결되지 않았습니다! 구글 검색 및 제로초님 강의와 트위터 클론 깃허브를 확인 후에도 원인을 알 수 없어 질문 글 올립니다! [김블루 계정의 팔로잉 목록] [핑크공주 계정의 팔로워 목록] FollowList.js // Ant Design 아이콘 불러오기 import { StopOutlined } from '@ant-design/icons'; ... return ( <List style={{ marginBottom: '20px' }} /* 격자 모양 */ grid={{ gutter: 4, xs: 2, md: 3 }} /* 목록 크기 */ size="small" /* 팔로잉 목록, 팔로워 목록 헤더 */ header={<div>{header}</div>} /* 더보기 버튼 */ loadMore={ <div style={{ textAlign: 'center', margin: '10px 0px' }}> <Button>더 보기</Button> </div> } /* 팔로잉 목록, 팔로워 목록 전체 테두리 */ bordered /* 목록용 데이터소스 : 팔로잉 목록, 팔로워 목록 더미데이터 배열 전달 */ dataSource={data} renderItem={(item) => { <List.Item style={{ marginTop: '20px' }}> <Card actions={[<StopOutlined key="stop" onClick={onCancel(item.id)} />]}> <Card.Meta description={item.nickname} /> </Card> </List.Item> }} />/* List 닫음 */ ); };
백엔드소스 받아 로컬에 서버 가동시켰고, 레디스 서버도 켜두었고 강사님이 올려주신 클라이언트 ch4소스에서 실행시켜, 회원가입 도중 에러가 발생합니다. postresql 디비에는 정상적으로 회원정보가 등록되긴 하였습니다만, 프론트에서 아래와 같은 에러가 있는데요 원인이 무엇일까요? Error: CredentialsSignin at signIn (webpack-internal:///(action-browser)/./node_modules/next-auth/lib/actions.js:62:22) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async $$ACTION_0 (webpack-internal:///(action-browser)/./src/app/(beforeLogin)/_lib/signup.ts:53:9) at async /Users/yhj/Desktop/yhj_projects/next-app-router-z-master/ch4/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:38:489 at async tX (/Users/yhj/Desktop/yhj_projects/next-app-router-z-master/ch4/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:37:5313) at async rl (/Users/yhj/Desktop/yhj_projects/next-app-router-z-master/ch4/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:38:23339) at async doRender (/Users/yhj/Desktop/yhj_projects/next-app-router-z-master/ch4/node_modules/next/dist/server/base-server.js:1406:30) at async cacheEntry.responseCache.get.routeKind (/Users/yhj/Desktop/yhj_projects/next-app-router-z-master/ch4/node_modules/next/dist/server/base-server.js:1567:28) at async DevServer.renderToResponseWithComponentsImpl (/Users/yhj/Desktop/yhj_projects/next-app-router-z-master/ch4/node_modules/next/dist/server/base-server.js:1475:28) at async DevServer.renderPageComponent (/Users/yhj/Desktop/yhj_projects/next-app-router-z-master/ch4/node_modules/next/dist/server/base-server.js:1852:24) at async DevServer.renderToResponseImpl (/Users/yhj/Desktop/yhj_projects/next-app-router-z-master/ch4/node_modules/next/dist/server/base-server.js:1890:32) at async DevServer.pipeImpl (/Users/yhj/Desktop/yhj_projects/next-app-router-z-master/ch4/node_modules/next/dist/server/base-server.js:902:25) at async NextNodeServer.handleCatchallRenderRequest (/Users/yhj/Desktop/yhj_projects/next-app-router-z-master/ch4/node_modules/next/dist/server/next-server.js:266:17) at async DevServer.handleRequestImpl (/Users/yhj/Desktop/yhj_projects/next-app-router-z-master/ch4/node_modules/next/dist/server/base-server.js:798:17)
[제로초 강좌 질문 필독 사항입니다] 질문에는 여러분에게 도움이 되는 질문과 도움이 되지 않는 질문이 있습니다. 도움이 되는 질문을 하는 방법을 알려드립니다. https://www.youtube.com/watch?v=PUKOWrOuC0c 0. 숫자 0부터 시작한 이유는 1보다 더 중요한 것이기 때문입니다. 에러가 났을 때 해결을 하는 게 중요한 게 아닙니다. 왜 여러분은 해결을 못 하고 저는 해결을 하는지, 어디서 힌트를 얻은 것이고 어떻게 해결한 건지 그걸 알아가셔야 합니다. 그렇지 못한 질문은 무의미한 질문입니다. 1. 에러 메시지를 올리기 전에 반드시 스스로 번역을 해야 합니다. 번역기 요즘 잘 되어 있습니다. 에러 메시지가 에러 해결 단서의 90%를 차지합니다. 한글로 번역만 해도 대부분 풀립니다. 그냥 에러메시지를 올리고(심지어 안 올리는 분도 있습니다. 저는 독심술사가 아닙니다) 해결해달라고 하시면 아무런 도움이 안 됩니다. 2. 에러 메시지를 잘라서 올리지 않아야 합니다. 입문자일수록 에러메시지에서 어떤 부분이 가장 중요한 부분인지 모르실 겁니다. 그러니 통째로 올리셔야 합니다. 3. 코드도 같이 올려주세요. 다만 코드 전체를 다 올리거나, 깃헙 주소만 띡 던지지는 마세요. 여러분이 "가장" 의심스럽다고 생각하는 코드를 올려주세요. 4. 이 강좌를 바탕으로 여러분이 응용을 해보다가 막히는 부분, 여러 개의 선택지 중에서 조언이 필요한 부분, 제 경험이 궁금한 부분에 대한 질문은 대환영입니다. 다만 여러분의 회사 일은 질문하지 마세요. 5. 강좌 하나 끝날 때마다 남의 질문들을 읽어보세요. 여러분이 곧 만나게 될 에러들입니다. 6. 위에 적은 내용을 명심하지 않으시면 백날 강좌를 봐도(제 강좌가 아니더라도) 실력이 늘지 않고 그냥 코딩쇼 관람 및 한컴타자연습을 한 셈이 될 겁니다. 안녕하세요 질문은 인터셉팅라우트의 (.)i폴더 입니다 @modal이 주소에 관계없기때문에 (beforeLogin)의 i/flow/login를 대체할 수 있다고 하셨는데요 (beforeLogin)도 주소와 관계가 없다고 하셨어서 (.)i가 무엇을 기준으로 대체하는 것인지 헷갈립니다. 또한 @modal의 경우에는 @modal/i/flow/login과 같이 연결되는 주소가 있어보여서 (.), (..)등의 인터셉팅라우트의 키워드가 무엇을 기준으로 하는지 명확하게 이해가 안됩니다
툴킷으로 작업을 해보려고 하고 있는데 faker를 써보려다가 제로초님 깃허브에 HYDRATE에 관련된 사항이 있어서 작업을 하려고 하고 잇엇는데 제로초님처럼 똑같이 타이핑을 햇는데 에러가 납니다. const postReducer = createSlice({ name: "postReducer", initialState, reducers: {}, // 청크를 쓸때 필요함 extraReducers: (builder) => builder // 클라이언트 상태를 초기화하는 역할 .addCase(HYDRATE, (state, action) => ({ ...state, ...action.payload.data, })), }); 여기서 에러가 나는 부분은 .. . action.payload.dat a , 중 payload부분이고 에러 사항은 다음과 같이 나옵니다. 'Action<"__NEXT_REDUX_WRAPPER_HYDRATE__">' 형식에 'payload' 속성이 없습니다. next-redux-wrapper 의 버전은 아래와 같습니다. 혹시 "next-redux-wrapper": "^8.1.0", 혹시 next-redux-wrapper로 리덕스 툴킷에 HYDRATE를 하는 방법이 달라진걸까요....
react-query의 쓰임새가 잘 이해가 안가서 질문드립니다. 1. 컴포넌트가 server component 일때는 react-query에 prefetchQuery를 사용하여 미리 서버에서 데이터를 가져오고 dehydrate를 통하여 클라이언트에 전송할수있는 형태로 만들어주고, HydrationBoundary 로 감싸여진 클라이언트 컴포넌트는 서버에서 미리 가져온 데이터를 클라이언트의 쿼리 캐시에 적용하여, getQueryData를 사용하여 네트워크 요청 없이 데이터를 가져올수있고, useQuery 같은 경우에는 미리 가져온 데이터 외에 클라이언트에서 데이터를 가져올 때 사용하는 걸로 이해했습니다. 맞을까요?? 2. queryKey 같은 경우에는 queryFn에 있는 함수에 queryKey를 넘기는 경우가 있고 안넘기는 경우가 있던데 강의에서 props에 따라 키가 바뀌는 경우에만 넘기게 된다고 이해했습니다. 그러면 server component에서 모든걸 prefetchQuery 해서 getQueryData 로 가져다 쓰지 않는 이유가 useQuery를 이용해서 key 값을 다이나믹하게 바뀌는 요청들을 컨트롤 하기 위해서라고 생각이 들었습니다. 하지만 아래와 같이 queryKey를 넘기지 않는 경우에도 useQuery를 사용하는데 prefetchQuery를 해놓고 getQueryData 를 사용할지, prefetchQuery 를 사용하지않고 useQuery를 사용할지 에 대해서 나누는 기준이 있을까요? const { data } = useQuery<Hashtag[]>({ queryKey: ["trends"], queryFn: getTrends, staleTime: 60 * 1000, gcTime: 300 * 1000, enabled: !!session?.user, });
안녕하세요, 강의 잘 듣고 있습니다! 강의를 듣다보니 하나 의문점이 들어 질문드립니다. app 폴더 하위에서 "page.tsx"로 만들면 nextjs에서 자동으로 라우팅하여 경로로 인식한다고 설명해주셨는데요. 강의를 듣다보니 언더바를 붙인 폴더 경로는 라우팅에 포함되지 않는다고 이야기를 하시더라구요. 파일명을 page로 만들지 않으면 라우팅에 포함되지 않는데, 언더바 폴더를 사용하는 이유가 있는지 궁금합니다. 공식 문서에서는 명시적인 구분/이름 충돌 방지등 이점 설명이 있지만, 크게 와닿지 않아서 질문드려요!
[질문 내용] 안녕하세요!! 우선 좋은 강의 만들어주셔서 너무 감사합니다! 이번 강의도 정말 잘 들었습니다!! 저는 자바 입문, 실전 자바 기본편을 듣고 이번 스프링 입문 강의를 완강했습니다. 이전에는 자바에 대해 책으로 공부하고 강의를 통해 이해하는데 큰 어려움이 없었지만 스프링은 처음이라 많이 헤매는 느낌을 받습니다. 궁금한 점은 헤매는 느낌을 받는 이유는 자바에 대한 이해가 부족해서 인지 스프링에 대한 이해가 부족해서 인지 알고싶습니다. 또한 제 계획은 24년도 상반기에 나올 자바 중급,고급 강의를 듣고 스프링 완전정복 강의를 듣고 토이프로젝트를 통해 실력을 향상시키는 것이 목표입니다. 이 방향성이 괜찮은지 아니면 어떤 방향으로 나아가야하는지 조언 부탁드립니다.!! 처음 자바를 공부하고 너무나도 헷갈리고 어려운 순간들이 많았는데 김영한 선생님의 강의를 듣고 나름대로 발전한 것 같아서 항상 감사하고 있습니다. 양질의 강의를 제공해주셔서 감사합니다 !! 24년도 잘 부탁드립니다!!
안녕하세요 강사님! optimistic update 관련 강의를 듣던 도중에 API반환값이 스웨거에 명시된 부분과 다르게 반환이 되는 것 같아서 질문드립니다! 현재 id값을 기반으로 한 유저 정보 api 에 대한 명세가 스웨거에 명시된 바로는 Follwers 배열 이 있어야 하는데 이상하게 브라우저에서는 Follwers 배열 속성이 누락되어 있습니다.. 유저 정보를 가져오는 api를 호출하는 코드입니다 혹시 MSW에서 백엔드 API를 사용하게 될 때 다른 설정도 추가해줘야 하는 것이 있나요?
Server Error TypeError: inst.render is not a function This error happened while generating the page. Any console logs will be displayed in the terminal window. 요런식으로 오류가 뜨는데 어떻게 해야할까요?
안녕하세요? 경로명 관련 질문이 있습니다. 강의에서 경로명과 동일한 닉네임이 존재한다면 우선순위에 의해 경로명이 먼저다 라고 하셨는데요.(동적 경로, 정적 경로 우선순위 때문에) 만약에 그렇게 된다면 경로명과 동일한 닉네임을 사용하는 유저는 개인페이지를 볼 수 없게 될텐데 이런 유저를 위해서 어떻게 처리를 하면 좋을까요? (혹시나해서 z-com에 login이라는 닉네임으로 가입해서 테스트를 해봤는데 그냥 홈으로 라우팅 되더군요) 구글링도 해보고 GPT한테도 물어봤는데 경로와 동일한 닉네임을 못쓰게한다. 접두사를 하나 추가한다. 얼추 추려서 이정도 답변을 해주는 것 같습니다. 그러나 2번 같은 경우에는 X의 경로방식과 다른 것같고 선택지는 1번만 남은거 같은데.. 제가 만약에 모든 서비스의 닉네임을 login으로 한 유저라고 생각했을때 경로때문에 해당 닉네임을 못쓴다면 굉장히 열받을것 같거든요..ㅋㅋ (그럴 일은 없겠지만..) 뭔가 다른 방법이 또 없을까요..?
A라는 페이지에서 리스트를 여러 개 만들고, 각 리스트에 대해 버튼을 클릭하면 동적으로 생성되는 모달을 만들고 싶습니다. 넥스트의 디렉터리 구조가 특이한데, 이 특이한 것들이 조합되면 헷갈리네요. 이 경우에는 @modal/A/[listId] 와 같은 식으로 디렉터리를 구성하면 되나요?