묻고 답해요
158만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결손에 익는 Next.js - 블로그 만들기
sitemap 에 Pormise가 필요한 이유
5:53 부분에서 sitemap 에서 Promise가 필요하다 하셨는데 왜 필요한지 궁금합니다.
-
미해결Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
private folders 와 전역 폴더
프로젝트 개발 중에, src/components 폴더에 재사용할 것들을 만들어서 사용하는 것과, src/app/_components 를 사용하는 것을 배웠는데, 둘의 사용성 차이가 있나요? 굳이 이 두 기능을 둘 다 사용을 할 필요가 있을까요? 오히려 하나만 사용하는게 좋지 않나 싶었습니다. 반드시 분리를 해야만 하는 특별한 이유가 있어서 굳이 분리를 하게 되는 것일까요?
-
미해결손에 익는 Next.js - 블로그 만들기
getPostData 함수 질문
return 문에 왜 matterResult.data를 반환해주나요? id 와 content만 있으면 되는거 아닌가요??추가해주는 이유가 궁금합니다.
-
미해결Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
퀴즈 질문 풀이 오류
저는 아무래도 정답이 C 같은데.. 질문에서 /docs도 포함되어야 한다고 했으므로, 옵셔널 캐치올만이 루트 경로(/docs)까지 모두 처리할 수 있는거 아닌가요? 다 학습하고 혼란이 오네요..
-
미해결React 기반 Gatsby로 기술 블로그 개발하기
썸네일 이미지가 보이지 않습니다!
PostItem.tsximport React, { FunctionComponent } from 'react' import styled from '@emotion/styled' import { Link } from 'gatsby' type PostItemProps = { title: string date: string categories: string[] summary: string thumbnail: string link: string } const PostItemWrapper = styled(Link)` display: flex; flex-direction: column; border-radius: 10px; box-shadow: 0 0 8px rgba(0, 0, 0, 0.15); transition: 0.3s box-shadow; cursor: pointer; &:hover { box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); } ` const ThumbnailImage = styled.img` width: 100%; height: 200px; border-radius: 10px 10px 0 0; object-fit: cover; ` const PostItemContent = styled.div` flex: 1; display: flex; flex-direction: column; padding: 15px; ` const Title = styled.div` display: -webkit-box; overflow: hidden; margin-bottom: 3px; text-overflow: ellipsis; white-space: normal; overflow-wrap: break-word; -webkit-line-clamp: 2; -webkit-box-orient: vertical; font-size: 20px; font-weight: 700; ` const Date = styled.div` font-size: 14px; font-weight: 400; opacity: 0.7; ` const Category = styled.div` display: flex; flex-wrap: wrap; margin-top: 10px; margin: 10px -5px; ` const CategoryItem = styled.div` margin: 2.5px 5px; padding: 3px 5px; border-radius: 3px; background: black; font-size: 14px; font-weight: 700; color: white; ` const Summary = styled.div` display: -webkit-box; overflow: hidden; margin-top: auto; text-overflow: ellipsis; white-space: normal; overflow-wrap: break-word; -webkit-line-clamp: 2; -webkit-box-orient: vertical; font-size: 16px; opacity: 0.8; ` const PostItem: FunctionComponent<PostItemProps> = function ({ title, date, categories, summary, thumbnail, link, }) { return ( <PostItemWrapper to={link}> <ThumbnailImage src={thumbnail} alt="Post Item Image" /> <PostItemContent> <Title>{title}</Title> <Date>{date}</Date> <Category> {categories.map(category => ( <CategoryItem key={category}>{category}</CategoryItem> ))} </Category> <Summary>{summary}</Summary> </PostItemContent> </PostItemWrapper> ) } export default PostItemPostList.tsximport React, { FunctionComponent } from 'react' import styled from '@emotion/styled' import PostItem from 'components/Main/PostItem' const POST_ITEM_DATA = { title: 'Post Item Title', date: '2020.01.29.', categories: ['Web', 'Frontend', 'Testing'], summary: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Provident repellat doloremque fugit quis rem temporibus! Maxime molestias, suntrem debitis odit harum impedit. Modi cupiditate harum dignissimos eos in corrupti!', thumbnail: 'https://i.ytimg.com/vi/pmnv2J2fyJg/hqdefault.jpg?sqp=-oaymwEnCNACELwBSFryq4qpAxkIARUAAIhCGAHYAQHiAQoIGBACGAY4AUAB&rs=AOn4CLCIBVaOEdLTo8W392meul19B3RFeQ', link: 'https://www.google.co.kr/', } const PostListWrapper = styled.div` display: grid; grid-template-columns: 1fr 1fr; grid-gap: 20px; width: 768px; margin: 0 auto; padding: 50px 0 100px; ` const PostList: FunctionComponent = function () { return ( <PostListWrapper> <PostItem {...POST_ITEM_DATA} /> <PostItem {...POST_ITEM_DATA} /> <PostItem {...POST_ITEM_DATA} /> <PostItem {...POST_ITEM_DATA} /> </PostListWrapper> ) } export default PostListindex.tsximport React, { FunctionComponent } from 'react' import styled from '@emotion/styled' import GlobalStyle from 'components/Common/GlobalStyle' import Footer from 'components/Common/Footer' import CategoryList from 'components/Main/CategoryList' import Introduction from 'components/Main/Introduction' const CATEGORY_LIST = { All: 5, Web: 3, Mobile: 2, } const Container = styled.div` display: flex; flex-direction: column; height: 100vh; ` const IndexPage: FunctionComponent = function () { return ( <Container> <GlobalStyle /> <Introduction /> <CategoryList selectedCategory="Web" categoryList={CATEGORY_LIST} /> <Footer /> </Container> ) } export default IndexPage전 단계인 태그까지는 됐는데, 게시글 목록 부분 컴포넌트 구현하기부터 뭔가 잘 안 뜹니다. 게시글 썸네일 바꿔보고, 꺾쇠도 없애봤는데 별 반응이 없네요... 어느 부분을 놓친 건지, 더 확인할 부분이 있는지 알려주시면 감사드리겠습니다.
-
미해결Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
Streaming 관련해서 문의드립니다.
Stream을 구현할 때 posts, tags 정보를 서버사이드에서 호출하고 promises 를 클라이언트 컴포넌트에 넘겨 use 훅으로 받는데요. 서버와 클라이언트의 경계가 살짝 이해가 안되네요. 서버사이드에서 promise객체를 클라이언트로 던지고 클라이언트에서 promise를 resolve하는 건가요?
-
미해결Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
ISR 매커니즘에 대한 궁금증
안뇽하세요. 몇일 전 구매하고 열강하고 있는 개발자입니다. ISR 매커니즘에 대한 궁금증이 있는데요. 저희가 작성한 코드에 보면 export const generateStaticParams = async () => { const { posts } = await getPublishedPosts(); return posts.map((post) => ({ slug: post.slug, })); }; 이렇게 게시글들을 미리 ISR 하는 코드가 있습니다. 특정 게시글의 slug 정보 기반으로 미리 SSG 만드는 것으로 이해했는데요. 그래서 빌드를 하면 SSG + 두 개의 슬러그 페이지가 존재합니다. (getPubishedPosts의 기본 사이즈가 2개이기 때문) 그런데 제가 궁금한게 위 ISR 적용하기 전에 빌드한 후 상세 페이지에 진입을하면 약 1초 정도? 딜레이가 발생하고 화면이 렌더링이 되는데요. ISR을 적용한 후 기대한 동작은미리 생성된 두 개의 slug에 대해서는 바로 화면에 보이지만 무한스크롤로 발생한 동적 블로그에 대해서는 빌드 전과 동일하게 1초의 딜레이가 발생하고 이후 접근 시 정적페이지가 생성되어 빠르게 보이는게 맞지 않나요?하지만 현재 동작을 보면 미리 생성된 slug를 제외한 모든 게시글에 대해 빠르게 화면이 보여 제가 이해한게 아닌가 싶네요. 공식문서를 봐도 이해가 잘되지 않아 확인차 문의드립니다.
-
미해결Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
cursor AI 프로젝트 룰 관련 질문 드립니다.
안녕하세요 강사님! 강의 항상 재밌게 잘 보고 있습니다.다름이 아니라 cursor AI가 영상의 버전과 다른 것 같은데, 프로젝트 룰을 어떤 걸로 설정해야하는지 모르겠습니다.공식 문서와 다른 블로그들을 참고해도 모르겠어서 질문 올립니다ㅠㅠ
-
미해결Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
params 에 Promise 객체 타입이 지정되어야 하는 이유? 최신?
안녕하세요! 강의 5:15초 부터의 설명에 조금만 더 자세히 설명해주시면 감사할것 같아서요!"이러한 파람즈도 프라미스로 가져와야겠죠 우리가 최신을 사용하고 있기 때문에 다시 generateMetadata 함수를"라고 스크립트(영상자막)는 나와 있는데, 이유를 설명하는 파트가 잘 안 와닿아서 혹시 설명해주실 수 있나요?직관적으로 생각하면 export generateStaticParams에서 slug 를 params으로 가져오는데 시간이 걸리니까, 기다려야 하니까 await 으로 params를 기다리는건 알겠는데, 'params'가 왜, 어떻게 해서 Promise 타입인지 궁금합니다. 너무 두서없었네요. 정리하자면1.왜 params 가 Promise 객체 타입인지, 코드 어디에서, 어떻게 해서 Promise 객체 타입이 되었는지 궁금합니다.2. 혹시 params 가 Promise 객체 타입인 이유는, 그저, [slug]폴더로 동적페이지로 정의되었으니, 컴포넌트로 들어오는 입력값 {params}는 [] 안에 들어간 변수값이 들어오는 건가요? 그래서 그냥 nextjs 스펙상 무조건promise 로 params 가 주어지게 되는건가요?너무너무 헷갈려서 그런데, 동적라우팅/정적 라우팅 별, 그리고 Clientside /serverside 별로 4가지로 나누어서 params 가져오는 방법을 설명해주실수 있나요? 너무너무 헷갈리네요.... 동적/정적라우팅에 따라 나뉘나요, client/server 에 따라 나뉘나요? 후자인걸로 생각하고 있긴 한데 맞는지 너무 헷갈리네요.. 감사합니다! 좋은 하루 되세요!
-
미해결Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
streaming 페이지 보완 필요
안녕하세요, 잘 학습하고 있는 학생입니다. 강의 따라가면서, streaming 파트는 다 적용을 했습니다. 소개 탭에서 홈 탭으로 이동 시에 태그목록과 포스트리스트도 skeleton 로딩페이지 잘 적용됩니다.'홈'을 눌렀을때, 기존의 '로딩 되는 중에 아무 변화 없이 사용자를 마냥 기다리게 함'에서 현재의 '로딩 되는 중에 skeleton 보여줌으로써 로딩되고 있음을 나타내줌'으로의 개선은 사용자 경험에 있어서, 정말 효과적인 방법이라고 느꼈습니다. 다만, 문제가 있습니다. '홈' 을 눌러 이동하는 경우말고, 태그 목록에서 나머지 'css'태그, 'git'태그 등등 이를 직접 클릭해서 이동하는 경우에는 streaming 이 적용되지 않습니다.예를 들어, 홈을 클릭한 상황에서는 skeleton ui가 잘 나타나지만, 그렇게 홈으로 이동한 상황에서 다른 태그(css,Git 등)로 다시 이동하는 상황에서는 적용되지 않고 그대로입니다. 이를 해결하기 위해선 어떻게 해야 하나요?
-
미해결Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
remark-gfm
remark-gfm 설치 이후 모든 css 가 망가지고 글자와 이미지만 렌더링 되는데 뭐가 문제일까요? global css 에서 import 한것도 아니고 영상과 같이 Plugin 으로 했어요.next-mdx-remote 깃헙 보니까 업데이트도 1년 지났고 버그 로그 많던데 그거 때문이려나요? https://github.com/hashicorp/next-mdx-remotenext 공식문서에서도 next-mdx-remote 는 더이상 없고 next-mdx-remote-client 만 있던데 그거 쓰면 되는걸까요?
-
미해결Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
마크업 파트 가독성 향상 방법
전부 다 따라하면서 배우고 있습니다!다만, 마크업 파트 에서 이렇게 글자 색으로 인해 가독성이 떨어지는데 마크업 파트 속성을 바꿀 방법은 없을까요?
-
미해결Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
Next.js 블로그 결과물 공유 이벤트 진행 여부
안녕하세요, 선생님. 아직 디스코드에 Next.js 블로그 결과물 공유하면 실용적인 블로그 소스코드 받을 수 있는 이벤트 진행하고 있나요?
-
미해결Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
블로그 PostCard 이미지 상단 여백
주신 코드 그대로 이해하면서 보고 했는데, 분명 postcard 내부에서 Image태그를 감고 있는 div 태그들을 봐도, object-cover 로 부모 요소를 가득 채우는 양식으로 되고 있는데, 왜 이미지 상단에 여백이 생기는걸까요?
-
미해결Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
flex-col 과 space-y-6 차이
space-y-6과 flex-col 로 gap-6(또는 gap-y-6)을 주는 방식의 차이를 모르겠어요둘다 같은 결과를 초래하는것 아닌가요?이번 코드에서 둘다 사용하시길래, 어떤 상황의 차이로 코드를 다르게 사용했는지 궁금해서 여쭙니다
-
미해결Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
컴파일 에러 및 의존성 충돌 문제
안녕하세요, 진행하다가 여러 이슈가 발생해서 한 번에 묶어 여쭤보고자 합니다!오류가 계속 발생해서 강사님 코드도 보았는데도 잘 모르겠습니다. Q: Hydration Mismatch 에러가 발생합니다. 서버와 클라이언트에서 렌더링되는 HTML이 다르다는데 어떻게 해결하면 될까요? Q: Next.js 15.3.0에서 remarkGfm과 rehype 플러그인들이 호환성 문제가 발생합니다."Cannot read properties of undefined (reading 'inTable')" 에러 // app/blog/[slug]/page.tsx <MDXRemote source={markdown} options={{ mdxOptions: { remarkPlugins: [remarkGfm], rehypePlugins: [withSlugs, rehypeSanitize, rehypePrettyCode], }, }} /> Q: next-mdx-remote에서 rehype 플러그인 사용 시 타입 에러가 발생합니다."Type 'Transformer<Root, Root>' is not assignable to type 'Transformer<any, any>'" 에러// app/blog/[slug]/page.tsx (164번째 줄) rehypePlugins: [withSlugs, rehypeSanitize, rehypePrettyCode],Failed to compile. ./app/blog/[slug]/page.tsx:164:62 Type error: Type '(options?: Options | undefined) => void | Transformer<Root, Root>' is not assignable to type 'Pluggable<any[]>'. 162 | mdxOptions: { 163 | remarkPlugins: [remarkGfm], > 164 | rehypePlugins: [withSlugs, rehypeSanitize, rehypePrettyCode], | ^ Next.js build worker exited with code: 1 and signal: null Q: react-day-picker와 date-fns 버전 충돌이 발생합니다.react-day-picker@8.10.1은 date-fns@^2.28.0 || ^3.0.0을 요구하는데,현재 date-fns@4.1.0이 설치되어 있어서 충돌합니다. // package.json { "dependencies": { "date-fns": "^4.1.0", "react-day-picker": "^8.10.1" } }Error: Command "npm install" exited with 1 npm error code ERESOLVE npm error ERESOLVE could not resolve npm error While resolving: react-day-picker@8.10.1 npm error Found: date-fns@4.1.0 npm error Could not resolve dependency: npm error peer date-fns@"^2.28.0 || ^3.0.0" from react-day-picker@8.10.1
-
미해결Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
TypeError: Invalid URL
안녕하세요,1) 강사님 깃코드에서 코드 clone해서 가져온 후2) 노션 환경 변수 세팅3) npm run dev 실행하니까 localhost:3000에서 저런 에러가 뜨네요어떻게 해결하면 될까요?
-
미해결Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
세션 6의 퀴즈 5번 정답 옵셔널 캐치올 아닌가요?
문제에서도 /docs 가 있고, 해설에도 옵셔널 캐치올에는 /docs가 포함 될때도 사용된다고 되어 있는데, 막상 답은 캐치올을 선택해야 답으로 나오네요.
-
미해결Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
상세 페이지 404 에러 발생
안녕하세요, 짐코딩님.덕분에 재밌는 수업 듣고 있습니다. :) 현재 저는 짐코딩 님의 깃허브에서=> 최종 코드를 clone해서 모두 받은 후 그 중에서 Notion API만 변경해서 제 notion과 연결을 한 후 수업을 수강하고 있습니다. (API 연결 활성화가 되어 있는 캡처본/.env에서도 환경변수로 설정 완료) 혼자서 노션 블로그 게시물 등록 및 조회 테스트를 해보다가 2가지 문제점이 발생했습니다. 제가 직접 노션에 추가한 게시물의 경우 '게시물 목록'에는 뜨지만 상세페이지 클릭했을 경우 404 에러 발생 예를 들어) localhost:3000/blog/web (web은 slug 값) 이렇게 타이핑하면 상세 페이지에 잘 들어가는데, 해당 블로그를 클릭해서 들어가면 아직 url에 localhost:3000/blog/243888f~~ 이런식으로 뜨네요 ㅜㅜ 반영이 늦는걸까요직접 노션에 추가한 게시물을 노션에서삭제한 후브라우저에서 보면 사라지지 않고 '게시물 목록'에 뜨고, 상세페이지를 클릭했을 경우 '404 에러 발생' 제가 직접 올린 노션 게시물만 저런 현상이 발생하고. 짐코딩님께서 미리 작성해놓으신 '웹 개발 학습 가이드'나 'Git 시작하기' 등은 상세 페이지를 클릭하면 잘 뜹니다. 이유를 모르겠습니다 ㅜㅜ 코드를 전달 드리고 싶은데,짐코딩님 코드를 모두 클론한 걸 사용하고 있어서 어떻게 전달드려야 할지 모르겠어서 우선은 404 에러가 뜨는 이미지와 상황 설명만 먼저 전달 드립니다! 참고로 현재까지 저는 remark and rehype 플러그인 설치 강의까지 학습했습니다! 제가 왕초보라 많이 미흡합니다. 최대한 쉽게 설명해주시면 너무나 감사드리겠습니다!항상 친절한 답변과 강의 감사드립니다.
-
미해결Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)
스타일이 적용 안되는 문제
안녕하세요, 선생님.현재 블로그 상세 목차 UI까지 강의 수강했는데 코드 수정한 후 local에 띄어보니 스타일이 적용 안되는 문제가 발생했습니다. 선생님 github에서 해당 강의 관련 코드 다 가져와서 복붙 했는데도 저러네요...제가 왕초보라서 도와주시면 감사하겠습니다!