묻고 답해요
161만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결따라하며 배우는 리액트 A-Z[19버전 반영]
PostDetailPage params 이 어디서 온건가요?
async function PostDetailPage({ params }: any) { const post = await getPost(params.id); return ( <div> <h1>Posts/{post.id}</h1> <div> <h3>{post.title}</h3> <p>{post.created}</p> </div> </div> ); }PostDetailPage 에서 params을 콘솔에 출력하면 id값이 나오는거는 주소에서 받아오는건가요?
-
해결됨[리뉴얼] React로 NodeBird SNS 만들기
노드 버드 강의에서 배포 파트 관련 질문
혹시 해당 강의에서 진행하는 배포 파트의 경우 아래 내용이 포함되어 있을까요?현재 강의 진행전에 따로 공부 중인 내용인데 혼자 진행하기엔 좀 햇갈리는 부분이 있어 강의에 포함된다면 강의를 먼저 들어보고 진행하려합니다. 노드버드 강의에 없더라도 다른강의에 상세하게 다루고 있다면 해당 강의 명을 부탁드립니다. 실무에 적용될수있는 CI/CD가 내용에 포함되어있는지?2. 빌드와 관련해 Webpack, ESBuild, SWC, Babel에 관한 내용이 있는지?3. 개인도메인으로 배포하는법
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
Warning: React has detected a change in the order of Hooks called by BoardDetail. This will lead to bugs and errors if not fixed. For more information
위에 코드 대로 하면 제목에 오류가 뜨고 if문을 지우고 varables에 boardId : String(router.query.boardId)로 하면 제목에 오류가 안뜨는데 어떻게 해결하면 좋을까요
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
이미지 업로드 최적화에 대해 고민이 있습니다.
안녕하세요! 이미지 업로드 최적화에 대해서 질문이 있습니다. (수정하기 부분) 최적화 진행전에는 상품 수정페이지에서 useEffect를 사용해서 이미지 주소를 가져온다음 state에 저장한 후 props로 전달하여 작성했던 이미지를 보여주고 있었습니다 .하지만 최적화에서는 미리보기 주소를 사용해서 보여주고 있어서 미리보기 주소를 넘기고 싶은데 fetchUseditem에서는 images를 File[]이 아니라 String[]으로 받아오고 있어서 미리보기 주소를 어떻게 만들어서 전달해야 할지 고민입니다... 수정하기 페이지 접속시 state값이 초기화되어서 이 값을 어떻게 유지해야할지 모르겠습니다. 현재 이미지 버튼 컴포넌트에서는 onChangeFileUrls함수에 file과 미리보기 주소 , 해당 인덱스를 전달하고 있습니다.onChangeFileUrls함수에서 state에 저장후 uploadFile를 하여 받은 결과를 사용해서 상품을 작성하고 있습니다.
-
해결됨손에 익는 Next.js - 공식 문서 훑어보기
글 내용을 보면 깃북에 이미지를 올려두신 것 같은데
이런식으로 출처만 나타나고 이미지가 보이지 않아요
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
CORS 설정을 했지만 CORS오류가 발생합니다.
안녕하세요 제로초님 다름이 아니라 로그인 기능을 모두 구현하고 혹시나 원래 잘되던 회원가입이 안되나해서 돌려보던 참에 갑자기 회원가입에서 CORS오류가 발생해서 멘붕이 왔습니다.처음에 CORS설정하고 회원가입을 했을땐 잘 작동했었습니다...설정도 그대로구요.. 어떤게 문제인지 모르겠어서 질문남깁니다.콘솔 오류 사진 2.back/app.js 코드const express = require("express"); const postRouter = require("./routes/post"); const userRouter = require("./routes/user"); const cors = require("cors"); const session = require("express-session"); const passport = require("passport"); const cookieParser = require("cookie-parser"); const dotenv = require("dotenv"); const app = express(); //익스프레스 서버 const db = require("./models"); const passportConfig = require("./passport"); db.sequelize .sync() .then(() => { console.log("db 연결 성공"); }) .catch(console.error); dotenv.config(); passportConfig(); app.use(express.json()); //익스프레스서버에 뭔가를 장착하겠다. //프론트에서 Json 형식으로 받은 것을 req.body에 넣어준다. app.use(express.urlencoded({ extended: true })); //form에서 제출한 것을 넘겨준다. //front에서 보낸 action.data를 req.body에 넣어주느 역할 app.use( session({ saveUninitialized: false, resave: false, secret: process.env.COOKIE_SECRET, }) ); app.use(passport.initialize()); app.use(passport.session()); app.use(cookieParser(process.env.COOKIE_SECRET)); app.get("/", (req, res) => { res.send("hello express"); }); app.get("/api", (req, res) => { res.send("hello api"); }); app.get("/api/posts", (req, res) => { res.json([ { id: 1, content: "hello" }, { id: 2, content: "hello2" }, { id: 3, content: "hello3" }, ]); }); app.use( cors({ origin: true, credentials: false, }) ); //cors설정 //res.setHeader("Access-Control-Allow-Origin", "http://localhost:3060"); //CORS해결법 *은 모든 주소에 대해서 라는 뜻 //localhost 3060에서 온 것은 허용해주게싸 app.use("/post", postRouter); //"/post"가 중복되므로 앞으로 뽑아줄 수 있다. app.use("/user", userRouter); //"/post"가 중복되므로 앞으로 뽑아줄 수 있다. app.listen(3065, () => { console.log("서버 실행 중"); });
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
회원가입 status 500 findOne 오류
안녕하십니까 제로초님 회원가입 구현 관련 질문드립니다.강의를 보며 코딩을 하였고 오타도 없는 것을 확인을 했습니다.그런데 response로 계속 500이 들어오며 findOne 관련 오류가 납니다.. 혹시 해결책을 알수있을까요?models/user.js//model은 mysql의 테이블과 같은 개념이다. module.exports = (sequelize, DataTypes) => { const User = sequelize.define( //여기서 User는 모델이름 => 자동으로 소문자화되고 복수형이 된다. ex)users "User", { //id는 mysql에서 자동으로 넣어주기 때문에 필요없다. email: { type: DataTypes.STRING(30), //STRIN, INTEGER, BOOLEAN, FLOAT, DATATIME 등이 자주 사용된다. //이메일은 문자열이고 30글자 이내여야한다. allowNull: false, //false면 필수 -> 무조건 입력해야함. unique: true, //이메일은 고유한 값이어야함. 중복값이 있으면 안된다. }, nickname: { type: DataTypes.STRING(30), allowNull: false, //false면 필수 -> 무조건 입력해야함. }, password: { type: DataTypes.STRING(100), //비밀번호는 암호화를 하게되면 길이가 늘어나기 때문에 여유있게 100글자 allowNull: false, //false면 필수 -> 무조건 입력해야함. }, }, { charset: "utf8", collate: "utf8_general_ci", //한글 저장 } ); User.associate = (db) => { db.User.hasMany(db.Post); //한 사람이 포스트를 여러개 가질 수 있음 db.User.hasMany(db.Comment); //한 사람이 댓글 여러개 가질 수 있음 db.User.belongsToMany(db.Post, { through: "Like", as: "Liked" }); //게시글 좋아요와 유저는 다대다 관계, 중간 테이블으 이름은 Like db.User.belongsToMany(db.User, { through: "Follow", as: "Followers", foreignKey: "FollowingId", }); db.User.belongsToMany(db.User, { through: "Follow", as: "Followings", foreignKey: "Followerid", }); //내가 팔로잉하는 사람을 찾으려면 나를 먼저 찾아야 한다. }; return User; };routes/user.jsconst express = require("express"); const { User } = require("../models"); const router = express.Router(); const bcrypt = require("bcrypt"); router.post("/", async (req, res, next) => { // POST /user/ try { const exUser = await User.findOne({ where: { email: req.body.email, }, }); if (exUser) { return res.status(403).send("이미 사용 중인 아이디입니다."); //여기서 리턴을 해주지 않으면 밑에 있는 res.json() 과 더불어서 응답이 두번이라 안된다. } const hashedPassword = await bcrypt.hash(req.body.password, 12); await User.create({ //순서를 맞춰주기 위한 Await //테이블안에 데이터 넣기 email: req.body.email, nickname: req.body.nickname, password: hashedPassword, //여기서 req.body가 프론트엔드 Signup에서 보낸 action.data와 같다. }); res.status(201).send("ok"); } catch (error) { console.error(error); next(error); // status 500 } }); module.exports = router;back/app.jsconst express = require("express"); const cors = require("cors"); const postRouter = require("./routes/post"); const userRouter = require("./routes/user"); const app = express(); const db = require("./models"); db.sequelize .sync() .then(() => { console.log("db 연결 성공"); }) .catch(console.error); app.use(express.json()); app.use(express.urlencoded({ extended: true })); //여기서 use는 express서버에서 뭔가 장착한다는 뜻 //또한 이 두 문장이 프론트에서 받아온 action.data를 req.body에 넣어준다는 뜻 app.get("/", (req, res) => { res.send("hello express"); }); app.get("/api", (req, res) => { res.send("hello api"); }); app.get("/api/posts", (req, res) => { res.json([ { id: 1, content: "hello" }, { id: 2, content: "hello2" }, { id: 3, content: "hello3" }, ]); }); app.use( cors({ origin: "*", //모두 허용 credentials: false, }) ); app.use("/post", postRouter); //"/post"가 중복되므로 앞으로 뽑아줄 수 있다. app.use("/user", userRouter); app.listen(3065, () => { console.log("서버 실행 중"); });
-
미해결따라하며 배우는 리액트 A-Z[19버전 반영]
netlify를 배포를 했는데 문제 생겼습니다
netlify를 배포 했는데 경고와 빌드 문제 인 것 같습니다 어떻게 하면 될까요?
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
다이나믹 라우팅 안에서 다른 다이나믹 라우팅으로 이동할때 발생하는 에러.
안녕하세요!user/[id].js 페이지 안에서 hashtag/[tag] 페이지로 이동하는 버튼을 만들에 사용 하면 알맞은 페이지로 이동하는 것이 아니라 user/hashtag/[tag]로 이동하게 됩니다.참고로, hashtag/[tag]로 이동하는 버튼을 Applayout에 추가 하고 user/[id]페이지에서 Applayout 컴퍼턴트로 감싸 줬습니다. 이 페이지에서 상단에 Search버튼을 누르면,이런 페이지로 이동합니다...import React,{useCallback} from 'react' import {HStack, Input, Button, Modal, ModalOverlay, ModalContent, ModalHeader, ModalBody, ModalCloseButton, useDisclosure} from '@chakra-ui/react' import {BiSearch} from 'react-icons/bi' import { css } from '@emotion/react' import Router from 'next/router' import PropTypes from 'prop-types' import useInput from '../hooks/useInput' import Spacer from './CustomizedUI/Spacer' const buttonCss = css` :hover { background-color: transparent; color: #1890ff; } `; export default function SearchButton({type, children}) { const { isOpen, onOpen, onClose } = useDisclosure(); const [value, onChangeValue, setValue] = useInput('') const onClickHandler = useCallback(()=>{ Router.push(`hashtag/${value}`); },[value]) const ConditionButton = type; return ( <> <ConditionButton variant="ghost" aria-label="Search Button" icon={<BiSearch />} leftIcon={type === Button && <BiSearch />} onClick={onOpen} fontSize="25px" css={buttonCss} > {children} </ConditionButton> <Modal isOpen={isOpen} onClose={onClose} size="md" isCentered> <ModalOverlay /> <ModalContent> <ModalHeader>Search</ModalHeader> <ModalCloseButton /> <ModalBody> <HStack> <Input type="text" value={value} onChange={onChangeValue} required /> <Button onClick={onClickHandler}>Search</Button> </HStack> <Spacer /> </ModalBody> </ModalContent> </Modal> </> ); } SearchButton.propTypes = { type: PropTypes.elementType.isRequired, children: PropTypes.node.isRequired, }이것은 제가 만든 컴퍼넌트인데, 혹시 어디서 문제가 있는걸까요? 혹시나 해서 Chakra UI 상의 문제 아닐까 해서 antd로도 해봤는데, 같은 오류가 납니다.신기한 오류라서 질문드립니다.감사합니다.
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
sql에 User테이블만 존재하고 utf관련 오류와 sequelizeDatabaseError가 납니다.
안녕 하십니까 제로초님다름이 아니라 강의를 수강하는 중에 아래와 같은 오류가 발생했는데 해결법을 모르겠어서 질문을 남깁니다.제로초님이 말씀하신대로 npx sequelize db:create를 하고테이블을 봤는데 user밖에 없어서 터미널을 봤더니 아래와같은 오류가 났습니다. 찾아보려고 했지만 도저히 모르겠어서 질문을 남깁니다.<오류코드>Executing (default): SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'Users' AND TABLE_SCHEMA = 'react-nodebird'Executing (default): SHOW INDEX FROM Users FROM react-nodebirdExecuting (default): SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'Posts' AND TABLE_SCHEMA = 'react-nodebird'Executing (default): CREATE TABLE IF NOT EXISTS Posts (`id` INTEGER NOT NULL auto_increment , content TEXT NOT NULL, createdAt DATETIME NOT NULL, updatedAt DATETIME NOT NULL, UserId INTEGER, RetweetId INTEGER, PRIMARY KEY (`id`), FOREIGN KEY (`UserId`) REFERENCES Users (`id`) ON DELETE SET NULL ON UPDATE CASCADE, FOREIGN KEY (`RetweetId`) REFERENCES Posts (`id`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8_general_ci;Error at Query.run (/Users/ihyeoncheol/Desktop/nodebird_project/prepare/back/node_modules/sequelize/lib/dialects/mysql/query.js:52:25) at /Users/ihyeoncheol/Desktop/nodebird_project/prepare/back/node_modules/sequelize/lib/sequelize.js:315:28 at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async MySQLQueryInterface.createTable (/Users/ihyeoncheol/Desktop/nodebird_project/prepare/back/node_modules/sequelize/lib/dialects/abstract/query-interface.js:98:12) at async Post.sync (/Users/ihyeoncheol/Desktop/nodebird_project/prepare/back/node_modules/sequelize/lib/model.js:942:7) at async Sequelize.sync (/Users/ihyeoncheol/Desktop/nodebird_project/prepare/back/node_modules/sequelize/lib/sequelize.js:377:9) { name: 'SequelizeDatabaseError', parent: Error: COLLATION 'utf8mb3_general_ci' is not valid for CHARACTER SET 'utf8mb4' at Packet.asError (/Users/ihyeoncheol/Desktop/nodebird_project/prepare/back/node_modules/mysql2/lib/packets/packet.js:728:17) at Query.execute (/Users/ihyeoncheol/Desktop/nodebird_project/prepare/back/node_modules/mysql2/lib/commands/command.js:29:26) at Connection.handlePacket (/Users/ihyeoncheol/Desktop/nodebird_project/prepare/back/node_modules/mysql2/lib/connection.js:478:34) at PacketParser.onPacket (/Users/ihyeoncheol/Desktop/nodebird_project/prepare/back/node_modules/mysql2/lib/connection.js:97:12) at PacketParser.executeStart (/Users/ihyeoncheol/Desktop/nodebird_project/prepare/back/node_modules/mysql2/lib/packet_parser.js:75:16) at Socket.<anonymous> (/Users/ihyeoncheol/Desktop/nodebird_project/prepare/back/node_modules/mysql2/lib/connection.js:104:25) at Socket.emit (node:events:517:28) at addChunk (node:internal/streams/readable:335:12) at readableAddChunk (node:internal/streams/readable:308:9) at Readable.push (node:internal/streams/readable:245:10) { code: 'ER_COLLATION_CHARSET_MISMATCH', errno: 1253, sqlState: '42000', sqlMessage: "COLLATION 'utf8mb3_general_ci' is not valid for CHARACTER SET 'utf8mb4'", sql: 'CREATE TABLE IF NOT EXISTS Posts (`id` INTEGER NOT NULL auto_increment , content TEXT NOT NULL, createdAt DATETIME NOT NULL, updatedAt DATETIME NOT NULL, UserId INTEGER, RetweetId INTEGER, PRIMARY KEY (`id`), FOREIGN KEY (`UserId`) REFERENCES Users (`id`) ON DELETE SET NULL ON UPDATE CASCADE, FOREIGN KEY (`RetweetId`) REFERENCES Posts (`id`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8_general_ci;', parameters: undefined }, original: Error: COLLATION 'utf8mb3_general_ci' is not valid for CHARACTER SET 'utf8mb4' at Packet.asError (/Users/ihyeoncheol/Desktop/nodebird_project/prepare/back/node_modules/mysql2/lib/packets/packet.js:728:17) at Query.execute (/Users/ihyeoncheol/Desktop/nodebird_project/prepare/back/node_modules/mysql2/lib/commands/command.js:29:26) at Connection.handlePacket (/Users/ihyeoncheol/Desktop/nodebird_project/prepare/back/node_modules/mysql2/lib/connection.js:478:34) at PacketParser.onPacket (/Users/ihyeoncheol/Desktop/nodebird_project/prepare/back/node_modules/mysql2/lib/connection.js:97:12) at PacketParser.executeStart (/Users/ihyeoncheol/Desktop/nodebird_project/prepare/back/node_modules/mysql2/lib/packet_parser.js:75:16) at Socket.<anonymous> (/Users/ihyeoncheol/Desktop/nodebird_project/prepare/back/node_modules/mysql2/lib/connection.js:104:25) at Socket.emit (node:events:517:28) at addChunk (node:internal/streams/readable:335:12) at readableAddChunk (node:internal/streams/readable:308:9) at Readable.push (node:internal/streams/readable:245:10) { code: 'ER_COLLATION_CHARSET_MISMATCH', errno: 1253, sqlState: '42000', sqlMessage: "COLLATION 'utf8mb3_general_ci' is not valid for CHARACTER SET 'utf8mb4'", sql: 'CREATE TABLE IF NOT EXISTS Posts (`id` INTEGER NOT NULL auto_increment , content TEXT NOT NULL, createdAt DATETIME NOT NULL, updatedAt DATETIME NOT NULL, UserId INTEGER, RetweetId INTEGER, PRIMARY KEY (`id`), FOREIGN KEY (`UserId`) REFERENCES Users (`id`) ON DELETE SET NULL ON UPDATE CASCADE, FOREIGN KEY (`RetweetId`) REFERENCES Posts (`id`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8_general_ci;', parameters: undefined }, sql: 'CREATE TABLE IF NOT EXISTS Posts (`id` INTEGER NOT NULL auto_increment , content TEXT NOT NULL, createdAt DATETIME NOT NULL, updatedAt DATETIME NOT NULL, UserId INTEGER, RetweetId INTEGER, PRIMARY KEY (`id`), FOREIGN KEY (`UserId`) REFERENCES Users (`id`) ON DELETE SET NULL ON UPDATE CASCADE, FOREIGN KEY (`RetweetId`) REFERENCES Posts (`id`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8_general_ci;', parameters: {}}
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
게시글 디테일 페이지에 댓글부분 레퍼런스코드
게시글 디테일 페이지에 댓글부분 레퍼런스코드는 따로 없을까요 31-2 레퍼런스 코드에는 나와있지 않아서요
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
전역상태관리에 추가적으로 특정페이지별로 상태관리가 필요할때에 대해 질문드립니다
안녕하세요 선생님,전역상태관리에 추가적으로 특정페이지별로 상태관리가 필요할때에 대해 질문드립니다, 아토믹패턴을 구현할려다보니 props drilling이 너무 많이 일어나서 recoil로 상태관리를 시도했는데 전역에 필요한 상태들말고 특정페이지에서만 쓰이는 상태들까지 포함이 되니 파일이 너무 지저분해져서요, 특정페이지 상태관리는 context api, 전역은 recoil, 이런 조합으로 써도 될까요?아니면 다른 더 좋은 방법이 있을까요? 감사합니다
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
싸이월드 만들기 똑같이 했는데 예제랑 다릅니다 ㅠㅠ
코드는 이렇게 작성했는데아래 있는 wrapper__left__body 가 너무 작게 나오는데 이유가 뭘까요?
-
해결됨Next.js 시작하기(feat. 지도 서비스 개발)
interface 와 type
선생님, 안녕하세요. 좋은 강의 너무 감사해요. 답변도 잘해주셔서 너무 감사해요. 선생님은 천재에요. 강의를 보다보니 (보통 prop을 받을 때)어떤때는 type을 사용하시고, 어떤때는 interface를 사용하시던데, 각각 어떤 경우에 사용하시는 지 설명해주실수있을까요?
-
미해결따라하며 배우는 리액트 A-Z[19버전 반영]
Netlify 배포 가능할까요?
혹시 넷플릭스로 Netlify 배포 가능할까요?
-
해결됨손에 익는 Next.js - 공식 문서 훑어보기
Hydration 개념.
질문 가이드 📖강의에서 이해가 안가는 부분이 있나요?강사님께서 hydration이라고 언급하셨는데 정확히 어떠한 개념인지 설명해주실 수 있나요??Next.js 공부 1년동안 했는데도 개념이 모호하네요.. 😅 좋은 퀄리티의 강의 감사합니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
33-01-jest 실습 도중 에러가 발생합니다.
콘솔 메시지jest.config.jspackage.json라이브러리들을 전부 설치하고 버전도 맞춰 보았는데 "Cannot use import statement outside a module"이 에러가 뜨면서 테스트가 진행이 되지 않습니다.무슨 문제인지 모르겠습니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
코드지갑 저장할 떄 오류가 나요
오류가 생기는 이유는 무엇인가요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스
CSS 첫번째 과제 관련 질문입니다!
htmlcss안녕하세요! 얼마 전부터 강의 결제해서 보고 있는 코린이입니다.언제나 도움 많이 받고 있습니다. css 첫번째 과제로 웹페이지 구현하던 중 질문이 생겼는데요,전화번호 사이에 들어가는 '-' 부호는 어떻게 코드를 작성하면 될지 알 수 있을까요?픽셀 크기가 지정되어있어 뭔가 코드를 쓰는 것 같기는 한데 감이 안 오더라구요ㅠㅠ그리고 지금까지 구현한 내용도 이 김에 검토 받고 싶습니다! 확인해주시면 감사하겠습니다 :)
-
해결됨Next.js 시작하기(feat. 지도 서비스 개발)
엘리맨트들의 자식관계가 어떻게 이렇게 되나 궁금합니다.
선생님 안녕하세요. 좋은강의 너무 감사드립니다!다름이 아니라 이번 강의에서MapSection.tsx에서const MapSection = () => { const { initializeMap } = useMap(); const onLoadMap = (map: NaverMap) => { initializeMap(map); }; return ( <> <Map onLoad={onLoadMap} /> // 이부분 <Markers /> // 이부분 </> ); }; export default MapSection; 이런식으로 return값에 위에 Map 컴포넌트, 아래에 Markers컴포넌트가 왔잖아요.그래서 저는 맵위에 마커들을 덮어씌우는(?)형식으로 나오게 될 줄 알았습니다. 그런데 결과를 보니, 이렇게 map div밑에 자식으로 들어가있더라구요. 어떻게 이렇게 되는지 설명해주시면 감사하겠습니다!!