inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

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

게시글 작성시 post.id를 읽지 못 하는 문제가 있습니다.

미해결

[리뉴얼] React로 NodeBird SNS 만들기

안녕하세요, 제로초님. 문제에 대한 고민을 공유하기 앞서 현재 저는 [해시태그 등록하기]까지 수강한 상태입니다. 공유하려는 문제는 제목과 같이 게시글 작성시 post.id를 읽지 못 하여 컴포넌트가 렌더링 되지 않습니다. 그러나 새로고침을 하면 작성한 게시글이 정상적으로 렌더링됩니다. 네트워크와 redux 데브툴즈에는 액션들이 모두 정상적으로 작동하고 있음을 확인하였고, 콘솔을 확인해보니 아래와 같은 오류가 뜹니다. 위 오류는 비동기로 데이터를 받아오기 전에 먼저 render가 되서 발생하는 에러 임을 검색을 통해 확인하였습니다. 그래서 react suspense를 이용하여 해결해보려 했으나 해결하지 못 했습니다. 혹시 제가 해당 오류의 원인을 제대로 파악하지 못 하고 있는 걸까요? 알려주시면 감사하겠습니다.

  • react
  • redux
  • node.js
  • express
  • next.js
윤섭 댓글 2 좋아요 0 조회수 392

setValue가 함수가 아니라는 오류 발생

미해결

따라하며 배우는 리액트 A-Z[19버전 반영]

TailwindCss 적용하기 실습 중 발생한 문제입니다. setValue is not a function TypeError: setValue is not a function at handleChange ( http://localhost:3000/static/js/bundle.js:167:5 ) at HTMLUnknownElement.callCallback ( http://localhost:3000/static/js/bundle.js:11038:18 ) at Object.invokeGuardedCallbackDev ( http://localhost:3000/static/js/bundle.js:11082:20 ) at invokeGuardedCallback ( http://localhost:3000/static/js/bundle.js:11139:35 ) at invokeGuardedCallbackAndCatchFirstError ( http://localhost:3000/static/js/bundle.js:11153:29 ) at executeDispatch ( http://localhost:3000/static/js/bundle.js:15297:7 ) at processDispatchQueueItemsInOrder ( http://localhost:3000/static/js/bundle.js:15323:11 ) at processDispatchQueue ( http://localhost:3000/static/js/bundle.js:15334:9 ) at dispatchEventsForPlugins ( http://localhost:3000/static/js/bundle.js:15343:7 ) at http://localhost:3000/static/js/bundle.js:15503:16 이러한 오류가 발생하였습니다. 아래는 코드입니다. 지난 시간에서 딱히 바꾼게 없는데 오류의 원인을 잘 모르겠어서 질문드립니다. App.js import React, {useState} from "react"; import "./App.css"; import List from "./components/List"; import Form from "./components/Form" export default function App (){ const [todoData, setTodoData] = useState([]); const [value,setValue] = useState(""); const handleSubmit = (e) =>{ e.preventDefault(); // 전송시 페이지 새로고침 방지 함수 let newTodo = { id : Date.now(), title: value, completed : false }; // 새로운 할 일 데이터의 형성 setTodoData(prev => [...prev,newTodo] ) setValue("") // 원래 할 일에 새로운 할 일 데이터의 update 해주는 setState 함수 } const btnStyle = { color: "#fff", border: "none", padding : "5px 9px", borderRadius: "50%", cursor: "pointer", float:"right" } return( <div className="container"> <div className='todoBlock'> <div className="title"> <h1>To do list</h1> </div> <h1 className='text-3xl font-bold underline'>Hello world!</h1> <List todoData= {todoData} setTodoData = {setTodoData}/> <Form handleSubmit = {handleSubmit} value ={value} setValue = {setValue}/> </div> </div> ); } list.js import React from 'react' export default function List({todoData , setTodoData}) { const btnStyle = { color: "#fff", border: "none", padding : "5px 9px", borderRadius: "50%", cursor: "pointer", float:"right" } const handleClick = (id) => { let newTodoData = todoData.filter(data => data.id !== id) console.log('newTodoData',newTodoData); setTodoData(newTodoData); } const getStyle = (completed) => { return { padding : "10px", borderBottom: "1px #ccc solid", textDecoration: completed ? 'line-through' : 'none', } } const handleCompleteChange = (id) => { let newTodoData = todoData.map(data => { if (data.id === id){ data.completed = !data.completed; } return data; }); setTodoData(newTodoData); }; return ( <div> {todoData.map((data)=>( <div style = {getStyle(data.completed)} key = {data.id}> <input type = "checkbox" defaultChecked = {false} onChange = {() => handleCompleteChange(data.id)}/> {data.title} <button style = {btnStyle} onClick = {() => handleClick(data.id)}>X</button> </div> ))} </div> ) } form.js import React from 'react' export default function Form(handleSubmit,value,setValue) { const handleChange = (e) =>{ setValue(e.target.value); } return ( <form style = {{display:"flex"}} onSubmit = {handleSubmit}> <input type = "text" name = "value" style = {{flex: '10', padding :'5px'}} placeholder = "해야 할 일을 입력하세요." value ={value} onChange ={handleChange} /> <input type = "submit" value = "입력" className="btn" style ={{flex:'1'}} /> </form> ) }

  • react
  • redux
  • tdd
  • typescript
  • next.js
이성현 댓글 1 좋아요 0 조회수 663

DB 엔티티와 도메인 분리

해결됨

Java/Spring 주니어 개발자를 위한 오답노트

어디까지 추상화 해야 하는가? 강의에서 2분 17초에 toDomain()으로 바꿔서 반환을 했는데 이렇게하면 JPA 엔티티가 아니라서 변경감지를 사용하지 못하는거 아닌가요? 이러한 방식으로 작성한다면 업데이트가 필요할 때는 어떤식으로 처리하나요?

  • java
  • spring
  • 객체지향
  • 소프트웨어-테스트
yhwjd 댓글 2 좋아요 3 조회수 4732

훈훈한 자바스크립트 강의 문제점

해결됨

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

appendchild강의에서 addEventListener 로 넘어갈 때, const KeyCodeCheck = function () { if (window.event.keyCode === 13 && todoInput.value !== "") { createTodo(); } }; 위 코드에서 const KeyCodeCheck = function () { if (window.event.keyCode === 13 && todoInput.value) { createTodo(); } }; 로 아무런 설명없이 바뀌어 있네요. 이유를 설명해주세요. 이거 외에도 아무 부연설명없이, 코드가 바뀌어 있는 경우가 매우 많습니다. 수정해서 다시 올려주세요

  • react
  • node.js
  • seo
  • graphql
  • next.js
b18lue 댓글 2 좋아요 0 조회수 397

리액트기초 yarn 설치 질문

해결됨

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

*우분투안쓰고 윈도우로 이용중입니다. 질문1. 강의자료 보면서 따라하는 중인데요. 강의자료에 나온 화면과 다르게 저는 style.thirteen도 없고 삭제부분을 삭제하면 오류가 많습니다. 마찬가지로 첫번째 div인 container가 저는 애초에 존재하지않고 <>형식으로 되어있는데 따로 타이핑해서 만들어줘야하나요? 질문2: 버전: 강의자료에 나온것 외에도 전부 no하는게 맞나요? 잘따라가고 있는지 모르겠습니다 ㅠ 질문3: 저는 yarn dev를 해서 페이지에 접속하니 컴파일 실패가 뜨네요.. 질문4: 혹시나 powershell로 설치한게 문제인건가 싶어서 폴더를 다 삭제하고 재생성후 gitBash를 사용해봤는데 yarn설치 명령어가 안먹히네요 그리고 powershell에선 먹히던 기본 명령어들이 Gitbash에선 안먹힙니다 어디서 부터 잘못된건지 막혀서 진도를 못나가고 있습니다. 도와주십쇼.. + 실무에서 설치할때는 이런일이 발생하지 않으려면 신경써야 하는 것들이 어떤게 있을까요?

  • react
  • node.js
  • seo
  • graphql
  • next.js
전현욱 댓글 2 좋아요 0 조회수 560

처음부터 막히는데 어떻게 해야하는 건지 자세한 답변 바랍니다.

해결됨

Next.js 시작하기(feat. 지도 서비스 개발)

https://nextjs.org/docs/getting-started/installation 공식문서, 아래 명령어 실행. npx create-next-app@latest 폴더명 적고 아래와 같이 선택하여 설치. ✔ Would you like to use TypeScript? … Yes ✔ Would you like to use ESLint? … Yes ✔ Would you like to use Tailwind CSS? … Yes ✔ Would you like to use `src/` directory? … No ✔ Would you like to use App Router? (recommended) … Yes ✔ Would you like to customize the default import alias? … No 강좌 그대로 따라하려고 했는데 아래 캡쳐화면이 현재 제가 설치한 화면 입니다. 강의 화면 처럼 pages 이런 폴더들이 없는데, 대체 어떻게 하라는 건가요?? 사용하지 않는 코드를 모두 정리하라고 했는데, 정리해야하는 코드들이 없을 경우 어떻게 처리를 해야 하는 지 상세한! 자세한! 답변 바랍니다.

  • seo
  • next.js
  • vercel
  • csr
  • ssg
  • ssr
이은혜 댓글 2 좋아요 1 조회수 823

로그아웃 질문

해결됨

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

로그아웃 버튼 클릭후에 setAccessToken을통해 accessToken이 공백으로 바뀌고 로그아웃 mutation 결과값 true 반환까지 확인되는데 쿠키의 refreshtoken 값이 사라지지않습니다ㅜㅜ 도와주세요

  • react
  • node.js
  • seo
  • graphql
  • next.js
dydtjq324 댓글 2 좋아요 0 조회수 525

D-Day강의 중에 오류가 있네요. 수정 좀 해줘요

해결됨

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

훈훈한 자바스크립트 강의 중에 D-Day 사이트 만들기 강의가 있는데, 설명 복잡한 건 그렇다 쳐도, 최종적으로 코드에 오류가 있더라고요. 새로 고침을 하게 되면 사이트 로컬 스토리지 에서, 데이터가 사라져 있는 걸 볼 수가 있어요. 해결 방법 알려주세요.

  • react
  • node.js
  • seo
  • graphql
  • next.js
b18lue 댓글 2 좋아요 0 조회수 343

실행안됨

해결됨

Next.js 시작하기(feat. 지도 서비스 개발)

위와 같이 실행이 안되고 저 상태로 계속 멈춰있습니다. 종료하고 다시해도 안되고, 삭제했다 다시 설치해도 안되고, 컴퓨터를 껐다 켜도, NPM을 업그레이드 시켜도 계속 저 창에서 멈춰있는 것만 반복하는데 뭐가 문제일까요?

  • seo
  • next.js
  • vercel
  • csr
  • ssg
  • ssr
shj41738866 댓글 1 좋아요 1 조회수 487

getStaticPaths 질문

해결됨

Next.js 시작하기(feat. 지도 서비스 개발)

1. fallback:true 인 경우 npm run build 할때 정적 페이지를 생성하는게 아니라 외부사용자가 접근한 시점에 생성을해서 보여준다는 것인가요? 맞다면 npm build 시점에는 생성을 하나도 안한다는 건가요? 2. fallback: false 인 경우 npm run build 시에 getStaticPaths 에서 return한 path에 대한 페이지만 생성하는게 맞나요? 3. getStaticProps 안에서 fallback에 대한 처리는 fallback:true인 경우에만 처리하는거죠? (return { notFound: true } 같은것) 4. getStaticPaths는 path에 따른 페이지를 생성시켜주는 함수이니 동적 라우팅에만 사용하는 함수인가요? 5. 데이터가 자주 바뀌는 페이지도 이러한 방식을 적용가능한것 같은데 초기 페이지에 대해서 SSR과 SSG 중 하나의 선택지로 골라서 적용을 해야할것 같네요. 어떤것을 선택해야 하는지는 직접 성능을 측정해가면서 비교하는게 정확한가요? 아니면 강좌에서 말씀하신것 처럼 웬만하면 SSR를 지양하고 SSG를 적용하는쪽으로 가는게 좋은건가요? CSR, SSR, SSG 적용을 하는 판단기준이 잘 안서네요.

  • seo
  • next.js
  • vercel
  • csr
  • ssg
  • ssr
kenny 댓글 1 좋아요 1 조회수 486

UPDATE_BOARD 400error

해결됨

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

useForm 이용해서 하고있는데 update_board를 할때 계속 try에서 catch(error)로 넘어가네요 ㅠ presenter.js import * as S from "./BoardWriter.styles"; export default function BoardWriteUI(props) { return ( <S.Wrapper onSubmit={props.isEdit? props.handleSubmit(props.onClickUpdate, props.onInValid) : props.handleSubmit(props.onValid, props.onInValid)}> <S.Title>{props.isEdit? "게시글 수정": "게시글 등록"}</S.Title> <S.WriterWrapper> <S.InputWrapper> <S.Label>작성자</S.Label> <S.Writer {...props.register("writer", { validate : (value) => value ? true:"작성자를 작성해주세요."} )} onChange={e => props.onChangeWriter(e)} type="text" placeholder="이름을 적어주세요."/> <S.Error>{props.errors.writer?.message}</S.Error> </S.InputWrapper> <S.InputWrapper> <S.Label>비밀번호</S.Label> <S.Password {...props.register("password", { validate : (value) => value? true: "비밀번호를 작성해주세요."} )} onChange={e => props.onChangePassword(e)} type="password" placeholder="비밀번호를 작성해주세요." /> <S.Error>{props.errors.password?.message}</S.Error> </S.InputWrapper> </S.WriterWrapper> <S.InputWrapper> <S.Label>제목</S.Label> <S.Subject {...props.register("title", { validate : (value) => value? true: "제목을 작성해주세요."} )} onChange = {e => props.onChangeTitle(e)} type="text" placeholder="제목을 작성해주세요." /> <S.Error>{props.errors.title?.message}</S.Error> </S.InputWrapper> <S.InputWrapper> <S.Label>내용</S.Label> <S.Contents {...props.register("contents", { validate : (value) => value? true: "내용을 작성해주세요."} )} onChange={e => props.onChangeContents(e)} placeholder="내용을 작성해주세요." /> <S.Error>{props.errors.contents?.message}</S.Error> </S.InputWrapper> <S.InputWrapper> <S.Label>주소</S.Label> <S.ZipcodeWrapper> <S.Zipcode {...props.register("boardAddress")} placeholder="07250" /> <S.SearchButton>우편번호 검색</S.SearchButton> </S.ZipcodeWrapper> <S.Address /> <S.Address /> </S.InputWrapper> <S.InputWrapper> <S.Label>유튜브</S.Label> <S.Youtube {...props.register("youtubeUrl")} placeholder="링크를 복사해주세요." /> </S.InputWrapper> <S.ImageWrapper> <S.Label>사진첨부</S.Label> <S.UploadButton>+</S.UploadButton> <S.UploadButton>+</S.UploadButton> <S.UploadButton>+</S.UploadButton> </S.ImageWrapper> <S.OptionWrapper> <S.Label>메인설정</S.Label> <S.RadioButton type="radio" id="youtube" name="radio-button" /> <S.RadioLabel htmlFor="youtube">유튜브</S.RadioLabel> <S.RadioButton type="radio" id="image" name="radio-button" /> <S.RadioLabel htmlFor="image">사진</S.RadioLabel> </S.OptionWrapper> <S.ButtonWrapper> <S.SubmitButton isActive={props.isActive} type="submit">{props.isEdit? "수정하기": "등록하기"}</S.SubmitButton> </S.ButtonWrapper> </S.Wrapper> ); } quires.js import { gql } from '@apollo/client' export const CREATE_BOARD = gql` mutation createBoard($createBoardInput: CreateBoardInput!) { createBoard(createBoardInput : $createBoardInput){ _id } } ` export const UPDATE_BOARD = gql` mutation updateBoard($updateBoardInput: updateBoardInput!, $password: String, $boardId: ID!) { updateBoard(updateBoardInput: $updateBoardInput, password: $password, boardId: $boardId) { _id } } ` container.js import { useState } from 'react' import { useForm } from 'react-hook-form'; import { useRouter } from 'next/router'; import { useMutation } from '@apollo/client' import BoardWriteUI from './BoardWriter.presenter'; import { CREATE_BOARD, UPDATE_BOARD } from './BoardWriter.queries'; export default function BoardsWriteContainer(props) { const router = useRouter() const [isActive, setIsActive] = useState(true) const [createBoard] = useMutation(CREATE_BOARD) const [updateBoard] = useMutation(UPDATE_BOARD) const { register, watch, handleSubmit, formState: { errors } } = useForm(); const onChangeWriter = (e) => { e.target.value && watch("password") && watch("title") && watch("contents") ? setIsActive(false) : setIsActive(true) } const onChangePassword = (e) => { e.target.value && watch("writer") && watch("title") && watch("contents") ? setIsActive(false) : setIsActive(true) } const onChangeTitle = (e) => { e.target.value && watch("password") && watch("writer") && watch("contents") ? setIsActive(false) : setIsActive(true) } const onChangeContents = (e) => { e.target.value && watch("password") && watch("title") && watch("writer") ? setIsActive(false) : setIsActive(true) } const onValid = async (data) => { try { const result = await createBoard({ variables: { createBoardInput: { writer: data.writer, title: data.title, password: data.password, contents: data.contents, } } }) console.log(result.data.createBoard._id) alert("게시물이 정상적으로 등록되었습니다.") router.push(`/boards/${result.data.createBoard._id}`) } catch(error) { alert(error.message) } } const onInValid = (error) => { console.log("에러입니다", error) } const onClickUpdate = async (data) => { try { const result = await updateBoard({ variables: { updateBoardInput : { title: data.title, contents: data.contents }, password : data.password, boardId : router.query.boardid, } }) console.log(result) // router.push(`/boards/${router.query.boadid}`) } catch(error) { console.log(error) } } return <BoardWriteUI onValid = {onValid} oninValid = {onInValid} register = {register} handleSubmit = {handleSubmit} errors = {errors} onChangeContents = {onChangeContents} onChangeTitle = {onChangeTitle} onChangePassword = {onChangePassword} onChangeWriter = {onChangeWriter} onClickUpdate = {onClickUpdate} isActive={isActive} isEdit={props.isEdit} /> }

  • react
  • node.js
  • seo
  • graphql
  • next.js
김무연 댓글 1 좋아요 0 조회수 426

gradle 사용하시는 분 도움

미해결

더 자바, 코드를 조작하는 다양한 방법

일단 새로운 프로젝트 만들고 premain 추가해주는 것 까진 강의를 그대로 따라하시면 됩니다. manifest plugin 부터 조금 차이가 있어서 거기부터 설명하면, build gradle 에 다음과 같이 추가한다. tasks.named('jar') { manifest { attributes( 'Implementation-Title': project.name, 'Implementation-Version': project.version, 'Premain-Class' : "com.java.magicianAgent.MagicianAgent", 'Can-Redefine-Classes' : true, 'Can-Retransform-Classes' : true) } } 터미널에서 다음 명령어를 통해 build 한다 ./gradlew clean build build.libs file 안에 있는 jar file 을 확인한다. (옵션) 강의에서와 마찬가지로 zip file 로 변경하면 확인가능합니다. 저같은 경우 SNAPSHOT.jar 과 SNAPSHOT -plain.jar 이렇게 2개가 생겼는데 SNAPSHOT.jar 은 제가 spring boot 로 실행서 그런지 관련 설정들이 보이고 SNAPSHOT -plain.jar 이 맞는거 같더라구요. jar file 의 절대 경로를 복사해 VM option 에 추가한다. 여기서부터는 다시 강의와 같습니다. VM option 이 안보이시면 오른쪽에 Modify options 클릭하면 add vm options 라고 보이실 겁니다. 이상한거나 궁금한거 있으시면 말씀해주세요. gradle 을 쓰시는 모든 분들도 마술을 성공시킵시다 하하

  • java
  • spring
안호성 댓글 1 좋아요 4 조회수 788

fetchUserLoggedIn가 안됩니다 도와주세요

해결됨

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

강의를 따라 순서대로 따라했는데 마지막에 cannot read property _id 오류가뜹니다 ㅠㅠ

  • react
  • node.js
  • seo
  • graphql
  • next.js
dydtjq324 댓글 2 좋아요 0 조회수 396

안녕하세요 강사님 질문드립니다.

해결됨

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

현재 저는 국비학원을 마치고 취업을 준비중 현실을 맞닥들이고 다시 공부를 시작하였습니다. 국비는java를 기반으로 수료했지만 저의 적성이 백엔드보다는 프론트가 맞을 것 같아 본 강의를 구매했습니다. 기본적인 html,css는 이해하고있지만 js는 다소 약한 부분이있습니다. 강의를 들으려고 보니 새로 시작한 사람은 새셕23부터 시작하면 된다고 설명이 되어있길래 살펴봤더니 바로 리액트부터 시작하는 것 같았더라구요. js가 다소 약하더라도 따라가는데 어려움이 없을지 질문 드립니다.

  • react
  • node.js
  • seo
  • graphql
  • next.js
simple 댓글 1 좋아요 0 조회수 553

Quiz 코드

해결됨

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

Quiz에 관한 코드는 따로 없을까요?

  • react
  • node.js
  • next.js
__LuvH 댓글 1 좋아요 0 조회수 243

영상에서 사용하신 커맨드가 궁금합니다.

미해결

따라하며 배우는 리액트 A-Z[19버전 반영]

섹션 2 할 일 목록 추가하기 영상 3분 4초 부분에서 Ctrl + K + F가 아니라면 어떤 커맨드 사용하신 건지 알 수 있을까요?

  • react
  • redux
  • tdd
  • typescript
  • next.js
  • 소프트웨어-테스트
dcnm19 댓글 1 좋아요 0 조회수 461

playground createProfile error

해결됨

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

오타있는지도 확인하고 껐다가 다시 실행시켜봐도 안됩니다 ㅠ 어떻게 해결해야 하나요?

  • react
  • node.js
  • seo
  • graphql
  • next.js
joka 댓글 1 좋아요 0 조회수 318

Number 로 변환

해결됨

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

const { data } = useQuery(FETCH_BOARD, { // $: { number: 1 }, // variables: { number: Number(router.query.qqq) }, variables: { number: Number(router.query.number) }, }); const { data } = useQuery(FETCH_BOARD, { variables: { boardId: router.query.boardId }, }); 포트폴리오에서는 router.query 부분을 문자인데 숫자로 왜 변형을 안 시키는 걸까요 ? 05-04 수업에서는 router.query.qqq 를 문자니까 Number 로 변환시켜주어 포트폴리오에서도 똑같이 했는데 안되더라고요!

  • react
  • node.js
  • seo
  • graphql
  • next.js
매력적인 토끼 댓글 1 좋아요 0 조회수 352

버전 문의

미해결

[리뉴얼] React로 NodeBird SNS 만들기

버전 문의있습니ㄷㅏ. 지금 최신버전으로 만ㄷㅡㄹ고싶으면 제로초님의 github에서 ch7을 보면 ㄷㅚㄹ까요?

  • react
  • redux
  • node.js
  • express
  • next.js
박경빈 댓글 1 좋아요 1 조회수 377

Next.js를 이용한 설계방식에 궁금한 점이 있습니다.

해결됨

현재 개인 프로젝트로 next.js를 사용하고 있는데 처음이다 보니 잘 감이 오지 않는 것이 있어서요. next.js를 사용한다면 보통의 서비스는 클라이언트 - Next.js 서버 - api 서버 - db 대략 이런 구조로 진행이 될것으로 이해하고 있는데요, 혹시 클라이언트 - Next.js 서버 - db 로 Next.js 서버가 api서버 역할까지 하는 식으로 구성하는 경우가 있나요? 찾아보니 Next.js에서도 db를 연결하는 경우가 있는걸 보았는데, 그러면 간단한 crud만 하는 api 서버일 경우 굳이 api서버를 따로 둘 필요가 없을 수도 있을 거란 생각을 해서요! 만약 이러한 방식이 그닥 권장되지 않는다면 이유가 무엇인가요?

  • next.js
  • 프론트엔드
cosmo 댓글 1 좋아요 0 조회수 1471

인기 태그

인프런 TOP Writers

주간 인기글