inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

172만명의 커뮤니티!! 함께 토론해봐요.

next Request Memoization과 react cache

미해결

Next + React Query로 SNS 서비스 만들기

next.js에서 제공하는 Request Memoization 기능은 같은 엔드포인트 경로로 여러 개의 요청이 들어왔을 때 하나의 요청으로 캐싱해주는걸로 알고있습니다. 이와 관련해서 3가지 궁금증이 있습니다. Request Memoization 기능은 같은 페이지 한정인가요. 아님 프로젝트 전역에 적용되는걸까요?? 예를 들어 /dashboard 와 /home 두 페이지 모두에서 getUserInfo 라는 fetch 함수를 호출한다면 이 경우도 Request Memoization 이 적용되는건가요. 만약 같은 엔드포인트지만 넘겨주는 파라미터가 다를 경우도 Request Memoization이 적용되나요? axios를 사용한다면 Request Memoization 기능을 활용할 수 없는걸로 알고있는데 react에서 제공하는 cache 함수를 사용하면 동일한 효과를 기대할 수 있나요? 감사합니다!!

  • react
  • next.js
  • react-query
  • next-auth
  • msw
변재정 댓글 2 좋아요 0 조회수 134

ch5-1 관리자 페이지 IP블랙리스트 기능구현 관련

해결됨

React, Node.js, MongoDB로 만드는 나만의 회사 웹사이트: 완벽 가이드

안녕하세요.. 아래와 같이 에러가뜨는데요;; code: 'MODULE_NOT_FOUND', requireStack: [ '/Users/sungwon/Desktop/Project/Web/company_website/backend/index.js' ] } Node.js v24.4.0 [nodemon] app crashed - waiting for file changes before starting... . backend > index.js코드 입니다. require("dotenv").config(); const express = require("express"); const mongoose = require("mongoose"); const cookieParser = require("cookie-parser"); const cors = require("cors"); const app = express(); const PORT = 3000; const userRoutes = require("./routes/user"); app.use(express.json()) app.use(express.urlencoded()) app.use(cookieParser()); app.use(cors({ origin: "*", credentials: true, })); app.use("/api/auth", userRoutes); app.get("/", (req, res) => { res.send("Hello world"); }); app.get("/api/check-ip", (req, res) => { const clientIP = req.ip || req.connection.remoteAddress; const blacklistedIPs = JSON.parse(process.env.IP_BLACKLIST || '[]'); console.log("Client IP:", clientIP); console.log("Blacklisted IPs:", blacklistedIPs); if (blacklistedIPs.includes(clientIP)) { return res.status(403).json({ allowed: false, message: "Access denied - IP is blacklisted" }); } res.json({ allowed: true }); }); mongoose .connect(process.env.MONGO_URI) .then(() => console.log("MongoDB와 연결이 되었습니다.")) .catch((error) => console.log("MongoDB와 연결에 실패했습니다: ", error)); app.listen(PORT, () => { console.log("Server is running"); });

  • HTML/CSS
  • javascript
  • react
  • node.js
  • mongodb
댓글 2 좋아요 0 조회수 113

러버블에 대한 궁금한 점입니다.

해결됨

비개발자 4주만에 수익화 서비스 만들기: AI 바이브코딩 웹 + 앱 ALL IN ONE

러버블과 n8n과 같은 것을 연동하는 이유는 무엇일까요? 러버블로 프로젝트 제작을 해봤는데요. 유뷰트 스크립트를 가져오려고 외부 라이브러리를 설치해서 스크립트를 가져오게 하는 방법을 사용하려고 하고 있는데요. 계속 스크립트를 가져오지 못하고 있습니다. 이와 같은 경우는 러버블이 할 수 없는 영역이라고 봐야 할까요?

  • flutter
  • next.js
  • cursor
  • supabase
  • 바이브코딩
양승근 댓글 1 좋아요 0 조회수 226

그랩님, 상품 상세 페이지 에러와 의문점 질문드립니다.

미해결

비전공자를 위한 진짜 입문 올인원 개발 부트캠프

그랩님, 강의 잘 듣고 있습니다. 다름이 아니라, 상품 상세 페이지 에러와 의문점이 있어서 어떻게 해결해야 하는지 궁금한 사항이 있어 질문 드리게 되었습니다. 일단 src/main/index.js 소스 코드를 첨부합니다. import './index.css'; import axios from "axios"; import React from 'react'; import {Link} from 'react-router-dom'; function MainPage(){ const [products, setProducts]=React.useState([]); React.useEffect( function(){ axios.get("제 mock 서버 주소 넣었습니다/products") .then(function(result){ const products=result.data.products; setProducts(products); }).catch(function(error){ console.error("에러 발생:",error); }); },[]); return ( <div> <div id="header"> <div id="header-area"> <img src="../images/icons/logo.png" /> </div> </div> <div id="body"> <div id="banner"> <img src="../images/banners/banner1.png" /> </div> <h1>판매되는 상품들</h1> <div id="product-list"> { products.map(function(product, index){ return ( <div className="product-card"> <Link className="product-link" to={`/products/${product.id}`}> <div> <img className="product-img" src={product.imageUrl} /> </div> <div className="product-contents"> <span className="product-name">{product.name} </span> <span className="product-price">{product.price}원 </span> <div className="product-seller"> <img className="product-avatar" src="../images/icons/avatar.png" /> <span>{product.seller}</span> </div> </div> </Link> </div> ); }) } </div> </div> <div id="footer"></div> </div> ); } export default MainPage; 2.src/product/index.js 소스 첨부합니다. import {useParams} from 'react-router-dom'; import axios from "axios"; import { useEffect, useState } from 'react'; function ProductPage(){ // const params=useParams(); const {id} = useParams(); const [product, setProduct] = useState(null); useEffect(function(){ axios.get('제 mock 서버 주소 넣었습니다/products/${id}' ) .then(function (result) { setProduct(result.data); // console.log(result); }).catch(function(error){ console.error(error); } ); },[]); console.log(product); // console.log(params); return <h1>상품 상세 페이지 {id} 상품</h1>; } export default ProductPage; -->여기서부터 의문점과 문제점이 발생하게 되니 읽어주시고 해결할 수 있는 방법을 알려주시면 좋겠습니다. 위 소스에서 axios.get('제 mock 서버 주소 넣었습니다/products/ ${id}') 처럼 소스를 달러 중괄호 아이디 입력하면 , 아래와 같은 첨부 사진처럼 에러 가 납니다. --> 위 에러 첨부 사진은 어떻게 해결해야 할까요? 3. 하지만, 위 소스대로 입력 안하면 axios.get('제 mock 서버 주소 넣었습니다 /products/1 ') 하면 제대로 데이터를 오류 없이 아래 첨부 사진처럼 받아 오는 것 을 알 수 있습니다. 3-1. 그랩님, 강의 소스에서 처럼 axios.get('제 mock 서버 주소 넣었습니다/products/ ${id} ')해서 하면 위 첨부 사진 처럼 에러가 나는데요, 성공적으로 오류 없이 불러오고 싶은데요 , 어떻게 해야 하나요? 단계별로 어떻게 소스를 수정해야하는지 알려주시면 좋겠습니다. 확인하시면 답변 부탁 드립니다.

  • HTML/CSS
  • javascript
  • react
  • node.js
  • react-native
  • 머신러닝
  • express
  • tensorflow
isbcom1004 댓글 2 좋아요 0 조회수 127

ch4-6 관리자 계정 로그아웃 , 삭제 관련

해결됨

React, Node.js, MongoDB로 만드는 나만의 회사 웹사이트: 완벽 가이드

7:27 시점에서, 터미널에서 선생님은,, eyJhbGcioiJOUzI1N,......주소명이 뜹니다만,,, 저의 경우, 아래와 같이 몽고DB에 연결이 되었습니다만 뜹니다.... 이 경우 어떻게 해야할가요... [nodemon] starting node index.js [dotenv@17.2.1] injecting env (2) from .env -- tip: 🔐 prevent committing .env to code: https://dotenvx.com/precommit Server is running MongoDB와 연결이 되었습니다. [nodemon] restarting due to changes... [nodemon] starting node index.js [nodemon] restarting due to changes... [nodemon] starting node index.js [dotenv@17.2.1] injecting env (2) from .env -- tip: ⚙ suppress all logs with { quiet: true } Server is running MongoDB와 연결이 되었습니다. 아래는 routes폴더에 있는 user.js const express = require("express"); const router = express.Router(); const bcrypt = require("bcrypt"); const User = require("../models/User"); const axios = require("axios"); const jwt = require("jsonwebtoken"); router.post("/signup", async (req, res) => { try { const { username, password } = req.body; const existingUser = await User.findOne({ username }); if (existingUser) { return res.status(400).json({ message: "이미 존재하는 사용자입니다." }); } const hashedPassword = await bcrypt.hash(password, 10); const user = new User({ username, password: hashedPassword, }); await user.save(); res.status(201).json({ message: "회원가입이 완료되었습니다." }); } catch (error) { res.status(500).json({ message: "서버 오류가 발생했습니다." }); console.log(error); } }); router.post("/login", async (req, res) => { try { const { username, password } = req.body; const user = await User.findOne({ username }).select("+password"); if(!user) { return res.status("401").json({message: "사용자를 찾을 수 없습니다."}); } if(!user.isActive){ return res .status(401) .json({ message: "비활성화된 계정입니다. 관리자에게 문의 주세요."}); } if(user.isLoggedIn){ return res .status(401) .json({message: "이미 다른 기기에서 로그인되어 있습니다."}); } const isValidPassword = await bcrypt.compare(password, user.password); if(!isValidPassword){ user.failedLoginAttempts += 1; user.lastLoginAttempt = new Date(); if(user.failedLoginAttempts >= 5){ user.isActive = false; await user.save(); return res.status(401).json({ message: "비밀번호를 5회이상 틀려 계정이 비활성화되었습니다.", }); } await user.save(); return res.status(401).json({ message: "비밀번호가 일치하지 않습니다.", remainingAttempts: 5 - user.failedLoginAttempts, }); } user.failedLoginAttempts = 0; user.lastLoginAttempt = new Date(); user.isLoggedIn = true; try { const response = await axios.get("https://api.ipify.org?format=json"); const ipAddress = response.data.ip; user.ipAddress = ipAddress; } catch (ipError) { console.error("IP 주소를 가져오는 중 오류 발생:", ipError.message); } await user.save(); const token = jwt.sign( { userId: user._id, username: user.username }, process.env.JWT_SECRET, { expiresIn: "24h" } ); res.cookie("token", token, { httpOnly: true, secure: "production", sameSite: "strict", maxAge: 24 * 60 * 60 * 1000, }); const userWithoutPassword = user.toObject(); delete userWithoutPassword.password; res.json({ user: userWithoutPassword }); } catch (error) { console.error("서버 오류:", error.message); res.status(500).json({ message: "서버 오류가 발생했습니다." }); } }); router.post("/logout", async (req, res) => { try { const token = req.cookies.token; if (!token) { return res.status(400).json({ message: "이미 로그아웃된 상태입니다." }); } try { const decoded = jwt.verify(token, process.env.JWT_SECRET); const user = await User.findById(decoded.userId); if (user) { user.isLoggedIn = false; await user.save(); } } catch (error) { console.log("토큰 검증 오류: ", error.message); } res.clearCookie("token", { httpOnly: true, secure: "production", sameSite: "strict", }); res.json({ message: "로그아웃되었습니다." }); } catch (error) { console.log("로그아웃 오류: ", error.message); res.status(500).json({ message: "서버 오류가 발생했습니다." }); } }); router.delete("/delete/:userId", async (req, res) => { try { const user = await User.findByIdAndDelete(req.params.userId); if (!user) { return res.status(404).json({ message: "사용자를 찾을 수 없습니다." }); } res.json({ message: "사용자가 성공적으로 삭제되었습니다." }); } catch (error) { res.status(500).json({ message: "서버 오류가 발생했습니다." }); } }); module.exports = router; env.에 표기한 부분 MONGO_URI=mongodb+srv://sungwon5623:cho121101!@sungwon.oirqw5d.mongodb.net/?retryWrites=true&w=majority&appName=Sungwon JWT_SECRET=c21b6ba5372fa2b8 models폴더에 있는 User.js const mongoose = require("mongoose"); const userSchema = new mongoose.Schema( { username: { type: String, required: true, trim: true, minlength: 2, maxlength: 30, }, password: { type: String, required: true, select: false, }, isLoggedIn: { type: Boolean, default: false, }, isActive: { type: Boolean, default: true, }, failedLoginAttempts: { type: Number, default: 0, }, lastLoginAttempt: { type: Date, }, ipAddress: { type: String, trim: true, }, createdAt: { type: Date, default: Date.now, }, }, { timestamps: true, } ); const User = mongoose.model("User", userSchema); module.exports = User;

  • HTML/CSS
  • javascript
  • react
  • node.js
  • mongodb
jasan88 댓글 2 좋아요 0 조회수 147

공지사항과 갤러리html파트 강의자료가 없음.

미해결

웹디자인개발기능사 [2025년] 실기전체 (카톡질문가능)

다운로드할 수 있는 강의 자료의 부재로 수업을 진행하는데 어려움이 있음, 강의 제목 옆에 다운로드 버튼도 없을 뿐더러 동영상 재생바 하단에도 자료 다운로드가 없음 강의 자료가 없어서 강의 진행에 어려움이 있어요

  • HTML/CSS
  • jquery
우아한 북극곰 댓글 2 좋아요 0 조회수 112

quasar와 tailwind 조합에 관한 질문

미해결

TailwindCSS 완벽 마스터: 포트폴리오부터 어드민까지!

강사님! 질문이 있습니다. 질문이 좀 길어요. 죄송합니다. 커뮤니티에도 질문을 올렸는데 휴가 중이신지 답변이 없어서 여기에도 남겨봅니다. Vue3 모든 과정을 수강하고 덕분에 프로젝트도 수행을 잘 했습니다. 그런데 프로젝트 할 때 quasar와 사용자 css 적용 문제로 퍼블리셔들이 고생을 많이 했습니다. 저는 PM 역할을 수행합니다. quasar의 css가 사용자가 정의한 css를 덮어 쓰는 경향이 있어 처리한다고 퍼블리셔 분들이 고생들을 많이 했어요. 그래서 다시 프로젝트를 곧 수행할 것 같은데 이번에는 tailwind를 적용해 볼려고 해요. 그러면 nuxt3 + vue3 + quasar + tailwind로 생각하고 있는데 그런데 저희는 포털은 웹 접근성 심사를 받아야 해서 이 조합이 맞는지가 궁금합니다. quasar가 다른 css를 덮어 쓰는 문제가 발생해서 tailwind로 작성한 css도 무용지물이 될까 심히 걱정스럽습니다.

  • HTML/CSS
  • javascript
  • 반응형-웹
  • tailwindcss
gaabi1204 댓글 1 좋아요 0 조회수 122

TypeError: Invalid URL

미해결

Next.js 완벽 마스터 (v15): 노션 기반 개발자 블로그 만들기 (with 커서AI)

안녕하세요, 1) 강사님 깃코드에서 코드 clone해서 가져온 후 2) 노션 환경 변수 세팅 3) npm run dev 실행하니까 localhost:3000에서 저런 에러가 뜨네요 어떻게 해결하면 될까요?

  • react
  • 블로그
  • next.js
  • cursor
  • cursorai
댓글 2 좋아요 0 조회수 218

앱라우팅 방식의 네비게이팅 방식

해결됨

한 입 크기로 잘라먹는 Next.js

1. 앱 라우터에서는 왜 페이지 이동 전에 프리패칭(prefetching)이 이뤄지지 않는 것처럼 보일까요? 페이지 라우터(Page Router) 방식에서는 링크가 뷰에 등장하면 해당 링크의 JS 번들이 자동으로 프리패칭되는 것으로 알고 있습니다. 그런데 앱 라우터의 동작 구조를 설명한 도식(2번 사진)에서는, 사용자가 실제로 페이지 이동을 요청한 이후에 JS 번들과 RSC Payload를 받는 것으로 표현되어 있습니다. 페이지 라이팅과 달라진 점이 RSC payload를 보내주는 것이라 하셨는데 도식에서는 언제 JS 번들을 보내주는지에 차이가 있어보여서 질문드립니다. 2. 앱라우터 방식에서 클라이언트 컴포넌트만 JS 번들에 포함된다는 설명과 관련해서, 다음 내용이 맞는지 확인 부탁드립니다. 초기 접속 시 서버에서 서버컴포넌트를 RSC 페이로드로 해석하고 완성된 HTML을 보내준다. 초기 접속 시 브라우저는 해당 페이지의 클라이언트 컴포넌트 JS Bundle만 받는다. 이후, JS Bundle과 HTML을 하이드레이션 한다. 페이지 전환 시, 새로 이동하는 페이지의 JS Bundle과 함께 서버 컴포넌트에 대한 RSC Payload도 함께 받아 브라우저에서 조합된다. 즉, 페이지 전환 전에 프리패칭이 없다. 이렇게 이해하는게 맞을까요?

  • react
  • typescript
  • next.js
kos7662 댓글 2 좋아요 0 조회수 107

seo 최적화 기준은 데이터 fetching인가요 아님 데이터 렌더링인가요?

미해결

Next + React Query로 SNS 서비스 만들기

seo 관련해서 궁금한게 있습니다. seo 최적화라는게 크롤링 봇이 서버에서 렌더링된 html을 크롤링하고 인덱싱하는걸로 알고 있습니다. 만약 서버 fetch 를 했지만 data 자체는 렌더링하지 않은 경우는 크롤링 봇이 어떻게 인식을 하는지 궁금합니다. 예를 들어 서버 fetch를 했지만 아래와 같이 서스펜스 역할하는 로직으로 인해 클라이언트 환경에서 hydrate 된 이후에 데이터가 렌더링된다면 서버에서 fetch는 이루어졌지만 렌더링된건 아니기 때문에 크롤링봇이 데이터를 인식하지 못하게 되는걸까요?? export function ConditionalClientWrapper({ children, fallback, }: ConditionalClientWrapperProps) { const [mounted, setMounted] = useState(false); useEffect(() => { setMounted(true); }, []); if (!mounted) return fallback ?? null; return children; } <ConditionalClientWrapper fallback={<Loading />}> //dataList에서 서버 fetch 가 이루어집니다. <dataList /> </ConditionalClientWrapper> SEO 최적화를 위한 조건이 데이터 렌더링인지 단순 서버 fetch 만하면 되는건지 궁금합니다. 추가로 리액트 쿼리의 prefetch를 사용하면 seo 최적화를 가질 수 있는건가요?? 감사합니다!

  • react
  • next.js
  • react-query
  • next-auth
  • msw
변재정 댓글 2 좋아요 0 조회수 108

빌드는 잘 되었고 pm2 start를 하는데 typeerror가 발생합니다.

해결됨

한 입 크기로 잘라먹는 Next.js

배포를 준비하고 있는데 개발/로컬 환경에서는 문제가 없이 잘 되다가 상용 환경에 배포를 하려고하니 에러가 발생하고 있습니다. 빌드는 에러 없이 잘 되었는데 pm2 start를 하니 [TypeError: Cannot read properties of undefined (reading 'filter') 타입에러가 갑자기 나타나버렸습니다. 우선 filter 사용하는 부분에 대한 예외처리들을 넣어주었는데 동일한 에러가 계속 발생하고 있습니다. 어떠한 경우에 이런 에러가 발생하는 것일까요?

  • react
  • typescript
  • next.js
Hailey.h.jang 댓글 2 좋아요 1 조회수 70

강의듣는법

미해결

HTML+CSS+JS 포트폴리오 실전 퍼블리싱(시즌1)

■ 질문 남기실 때 꼭! 참고해주세요.- 먼저 유사한 질문이 있었는지 검색해주세요.- 궁금한 부분이 있으시면 해당 강의의 타임라인 부분을 표시해주시면 좋습니다.- HTML, CSS, JQUERY 코드 소스를 텍스트 형태로 첨부해주시고 스크린샷도 첨부해주세요.- 다운로드가 필요한 파일은 해당 강의의 마지막 섹션에 모두 있습니다.책같은거없나요? 그냥 강의들으면되요?

  • HTML/CSS
  • jquery
aad rret 댓글 1 좋아요 1 조회수 103

업데이트 버전 수강

해결됨

[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스

기존에 강의를 구매했었는데 업데이트 버전 수강하려면 재구매 해야 하는 거지요?

  • react
  • node.js
  • seo
  • graphql
  • next.js
강유정 댓글 2 좋아요 0 조회수 112

ch4-5 관리자 계정 로그인, JWT토큰 관련

해결됨

React, Node.js, MongoDB로 만드는 나만의 회사 웹사이트: 완벽 가이드

덕분에 무사히 다음 강의 듣고있는데요 또 막혔습니다;;; MongoDB는 연결이 잘되는데요;; { id : new ObjectId(''''') 등등 터미널에 admin과 패스워드 등의 데이터카 안뜹니다;;;

  • HTML/CSS
  • javascript
  • react
  • node.js
  • mongodb
jasan88 댓글 2 좋아요 0 조회수 122

ch4-4관리자 계정생성하기 문제 발생

해결됨

React, Node.js, MongoDB로 만드는 나만의 회사 웹사이트: 완벽 가이드

아래와 같은 오류가 발생됩니다.... Error: Cannot find module 'bcrypt' Require stack: - /Users/sungwon/Desktop/Project/Web/company_website/backend/routes/user.js - /Users/sungwon/Desktop/Project/Web/company_website/backend/index.js at Module._resolveFilename (node:internal/modules/cjs/loader:1369:15) at defaultResolveImpl (node:internal/modules/cjs/loader:1025:19) at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1030:22) at Module._load (node:internal/modules/cjs/loader:1179:37) at TracingChannel.traceSync (node:diagnostics_channel:322:14) at wrapModuleLoad (node:internal/modules/cjs/loader:235:24) at Module.require (node:internal/modules/cjs/loader:1449:12) at require (node:internal/modules/helpers:135:16) at Object.<anonymous> (/Users/sungwon/Desktop/Project/Web/company_website/backend/routes/user.js:3:16) at Module._compile (node:internal/modules/cjs/loader:1692:14) { code: 'MODULE_NOT_FOUND', requireStack: [ '/Users/sungwon/Desktop/Project/Web/company_website/backend/routes/user.js', '/Users/sungwon/Desktop/Project/Web/company_website/backend/index.js' ] } Node.js v24.4.0 [nodemon] app crashed - waiting for file changes before starting... 아래는 index.js 코드입니다. require('dotenv').config(); const express = require('express'); const mongoose = require('mongoose'); const app = express(); const PORT =3000; const userRoutes = require("./routes/user"); app.use('/api/auth',userRoutes); app.get('/', (req, res) => { res.send('Hello World!'); }); mongoose.connect(process.env.MONGO_URI) .then(() => console.log('MongoDB와 연결이 되었습니다.')) .catch((error)=> console.log('MongoDB와 연결이 실패하였습니다:',error)); app.listen(PORT, () => { console.log("Server is running"); }) models>User.js 코드입니다. const mongoose = require('mongoose'); const userSchema = new mongoose.Schema( { username:{ type:String, require: true, trim: true, minlength:2, maxlength:30, }, password:{ type:String, require:true, select: false, }, isLoggedIn:{ type:Boolean, default:false, }, isActive:{ type:Boolean, default:false, }, failedLoginAttempts:{ type:Number, default:0, }, lastLoginAttempts:{ type:Date, }, ipAddress:{ type:String, trim:true, }, createdAt:{ type:Date, default: Date.now, } }, { timestamps:true, } ); const User = mongoose.model('User', userSchema); module.exports = User; routes>user.js코드 입니다. const express = require('express'); const router = express.Router(); const bcrypt = require('bcrypt'); const User = require('../models/User'); router.post('/signup', async (req, res) => { try { const {username, password} = req.body; const existingUser=await User.findOne({username}); if(existingUser){ return res.status(400).json({message:'이미 존재하는 사용자 입니다.'}); } const hashedPassword = await bcrypt.hash(password,10); const user = new User({ username, password:hashedPassword, }) await user.save(); res.status(201).json({message:'회원가입이 완료되었습니다.'}); } catch(error){ res.status(500).json({message:'서버 오류가 발생되었습니다.'}); console.log(error); } }); module.exports = router;

  • HTML/CSS
  • javascript
  • react
  • node.js
  • mongodb
jasan88 댓글 2 좋아요 0 조회수 135

페이지 라우터의 단점을 보완할 방법

해결됨

한 입 크기로 잘라먹는 Next.js

안녕하세요. 강의에서 설명해주신 페이지 라우터의 단점 중 "불필요한 컴포넌트들도 JS 번들에 포함된다"는 내용에 대해 질문드리고 싶습니다. 제가 이해한 바로는, 초기 HTML은 사전 렌더링 시 모든 컴포넌트를 포함하여 만들어지되, 실제로 브라우저에서 하이드레이션(클라이언트 측 React 활성화)이 일어나는 컴포넌트는 상호작용이 필요한 컴포넌트나 CSR 방식으로 처리된 컴포넌트에 한정 되어 이들만 JS 번들에 포함되는 것으로 생각했습니다. 즉, 단순히 정적인 컴포넌트는 HTML로만 렌더링되고, JS 번들에는 포함되지 않거나 최소화된다고 이해했는데, 혹시 이 부분에서 제가 잘못 이해하고 있는 걸까요? 초기 렌더링 시 어떤 요소들이 HTML로 렌더링되고, 어떤 컴포넌트들이 JS 번들에 포함되는지 기준을 설명해주시면 감사하겠습니다.

  • react
  • typescript
  • next.js
kos7662 댓글 2 좋아요 0 조회수 91

fetchUser 요청시 userPoint.amount

해결됨

[코드캠프] 부트캠프에서 만든 '완벽한' 프론트엔드 코스

충전 금액이 balance에 누적되는 것 같은데, userPoint에는 따로 저장되는 것이 아닌가요? 아니라면 충전 된 유저의 포인트는 어떻게 가져와야 될까요? 그리고, 사진처럼 fetchUser 하면 userPoint.amount 가 non-nullable field 라며 userPoint의 amount를 못가져오는데 혹시 오류일까요?

  • react
  • react-native
  • 하이브리드-앱
  • graphql
  • next.js
mh 댓글 2 좋아요 0 조회수 93

[id].tsx페이지 SEO 관련 질문드립니다.

해결됨

한 입 크기로 잘라먹는 Next.js

안녕하세요. 배포 후 SEO 확인 과정에서 이해되지 않는 부분이 있어 질문드립니다. [id].tsx 에서 동적 라우팅을 처리할 때, getStaticPaths 를 통해 id=1,2,3 에 해당하는 페이지는 빌드 시점에 SSG로 사전 렌더링되도록 설정하였고, 나머지 ID에 대해서는 fallback: true 를 사용해 첫 요청 시 SSR처럼 처리되는 것으로 이해했습니다. 또한 강의에서 router.isFallback 이 true 일 경우, SEO를 고려하여 <Head> 에 별도의 메타 정보를 넣어주는 분기 처리를 하신 것으로 알고 있습니다. 저는 이 분기 처리가 필요한 이유가, 해당 시점에는 실제 데이터가 포함된 HTML이 아직 완성되지 않았기 때문에 SEO 검사 도구나 크롤러에 최소한의 메타 정보를 제공하려는 의도라고 이해했습니다. 하지만 실제 배포된 결과를 확인해보니, id=1,2,3 외의 fallback으로 생성된 페이지들조차도 og:image 등 메타 정보가 정상적으로 노출되고 SNS 공유 시에도 커버 이미지가 잘 보이고 있습니다. 이런 경우, fallback으로 생성된 SSR 페이지임에도 불구하고 og 태그가 잘 노출되는 이유는 무엇인지 궁금합니다. SEO 관점에서 이런 동작이 가능한 이유가 있다면 설명 부탁드립니다.

  • react
  • typescript
  • next.js
kos7662 댓글 1 좋아요 0 조회수 54

eslint 설정

해결됨

한 입 크기로 잘라먹는 Next.js

실제 코드에 나와 있는 설정과 아래의 설명이 반대로 바뀐 거 같은데 어디에 맞춰서 설정해주면 될까요?

  • react
  • typescript
  • next.js
라연 댓글 2 좋아요 0 조회수 98

인기 태그

인프런 TOP Writers

주간 인기글