inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

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

SendGird가입

미해결

파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트

안녕하세요 api 인증키를 발급받기 위해 sendgrid를 가입하려고 하는데 가입이 되지 않아서 질문남깁니다!!

  • react
  • python
  • django
  • docker
chlendyd7 댓글 3 좋아요 1 조회수 1126

BottomTabScreen 관련 질문입니다.

해결됨

따라하며 배우는 리액트 네이티브 기초

import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'; import {createNativeStackNavigator} from '@react-navigation/native-stack'; import React from 'react'; import Home from './src/screens/Home'; import Search from './src/screens/Search'; import Profile from './src/screens/Profile'; import Activity from './src/screens/Activity'; import {NavigationContainer} from '@react-navigation/native'; import Status from './src/screens/Status'; import FriendProfile from './src/screens/FriendProfile'; import EditProfile from './src/screens/EditProfile'; const App = () => { const Stack = createNativeStackNavigator(); const Tab = createBottomTabNavigator(); const BottomTabScreen = () => { return ( <Tab.Navigator screenOptions={() => ({ tabBarHideOnKeyboard: true, // tabBarShowLabel: false, headerShown: false, tabBarStyle: { height: 70, }, })}> <Tab.Screen name="Home" component={Home} /> <Tab.Screen name="Search" component={Search} /> <Tab.Screen name="Activity" component={Activity} /> <Tab.Screen name="Profile" component={Profile} /> </Tab.Navigator> ); }; return ( <NavigationContainer> <Stack.Navigator screenOptions={{headerShown: false}}> <Stack.Screen name="Bottom" component={BottomTabScreen} /> <Stack.Screen name="Status" component={Status} /> <Stack.Screen name="FriendProfile" component={FriendProfile} /> <Stack.Screen name="EditProfile" component={EditProfile} /> </Stack.Navigator> </NavigationContainer> ); }; export default App; 강의 내용과 같이 App 컴포넌트 안에서 BottomTabScreen 컴포넌트를 선언하면 "Do not define components during render." 라는 경고문이 뜹니다. 그래서 아래와 같이 코드를 수정하였는데 App 컴포넌트 바깥에서 이렇게 선언해도 문제가 없는건가요? import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'; import {createNativeStackNavigator} from '@react-navigation/native-stack'; import React from 'react'; import Home from './src/screens/Home'; import Search from './src/screens/Search'; import Profile from './src/screens/Profile'; import Activity from './src/screens/Activity'; import {NavigationContainer} from '@react-navigation/native'; import Status from './src/screens/Status'; import FriendProfile from './src/screens/FriendProfile'; import EditProfile from './src/screens/EditProfile'; const Stack = createNativeStackNavigator(); const Tab = createBottomTabNavigator(); const BottomTabScreen = () => { return ( <Tab.Navigator screenOptions={() => ({ tabBarHideOnKeyboard: true, // tabBarShowLabel: false, headerShown: false, tabBarStyle: { height: 70, }, })}> <Tab.Screen name="Home" component={Home} /> <Tab.Screen name="Search" component={Search} /> <Tab.Screen name="Activity" component={Activity} /> <Tab.Screen name="Profile" component={Profile} /> </Tab.Navigator> ); }; const App = () => { return ( <NavigationContainer> <Stack.Navigator screenOptions={{headerShown: false}}> <Stack.Screen name="Bottom" component={BottomTabScreen} /> <Stack.Screen name="Status" component={Status} /> <Stack.Screen name="FriendProfile" component={FriendProfile} /> <Stack.Screen name="EditProfile" component={EditProfile} /> </Stack.Navigator> </NavigationContainer> ); }; export default App;

  • react
  • react-native
  • expo
댓글 3 좋아요 1 조회수 612

비동기를 동기로 처리하는 이유

해결됨

한 입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지

비동기 함수를 왜 굳이 동기처럼 실행시키기 위해 await을 사용하는 건가요? 처음부터 함수를 만들때 동기로 만들면 되는거 아닌가요? 동기, 비동기가 잘이해가 안가네요..

  • javascript
  • react
  • node.js
조우현 댓글 1 좋아요 0 조회수 2196

tailwindcss 라이브러리 받은 후 실행이 안됩니다.

미해결

따라하며 배우는 노드, 리액트 시리즈 - 쇼핑몰 사이트 만들기[전체 리뉴얼]

npm i -D postcss autoprefixer tailwind npx tailwindcss init -p 모두 작업을 마치고 /** @type {import('tailwindcss').Config} */ export default { content: [ "./index.html", "./src/**/*.{js,jsx,ts,tsx}" ], theme: { extend: {}, }, plugins: [], } index.css @tailwind base; @tailwind components; @tailwind utilities; npm run dev 를 돌리면, node:internal/process/promises:246 triggerUncaughtException(err, true /* fromPromise */); [Failed to load PostCSS config: Failed to load PostCSS config (searchPath: C:/WebStudy/WebDevelement/React/fullstack-react/front): [Error] Loading PostCSS Plugin failed: Cannot find module 'tailwindcss' 라는 오류가 뜹니다. 원인파악이 어려운데 문의드립니다!

  • react
  • redux
  • node.js
  • 웹앱
  • mongodb
코딩도니 댓글 1 좋아요 0 조회수 1903

next.js 환경에서 이 수업을 들을 수 있나요?

미해결

따라하며 배우는 리액트, 파이어베이스 - 채팅 어플리케이션 만들기[2023.12 리뉴얼]

next.js 환경에서 이 수업을 들을 수 있나요?

  • react
  • 웹앱
  • firebase
댓글 1 좋아요 0 조회수 413

이미지가 안떠요...

미해결

따라하며 배우는 노드, 리액트 시리즈 - 영화 사이트 만들기

13분 정도까지 했는데 이미지가 안뜨네요... 이유가 무엇인지 아시나요?

  • react
  • node.js
  • 웹앱
  • mongodb
  • express
택기 댓글 2 좋아요 0 조회수 394

포스팅 오류

미해결

깃헙 블로그(Github blog)로 차별화 된 나만의 홈페이지 만들기!

새로운 md 파일 포스팅하려고 주피터 노트북에서 작업후 Md 파일로 다운로드 후, 커밋하고 원격저장소에 푸시하여 업로드 하였는데 블로그에 포스팅되지 않습니다. github에 들어가서 원격저장소 확인 결과 파일 업로드 되었는데 업로드가 되지 않습니다

  • 블로그
  • github
댓글 1 좋아요 0 조회수 337

개인공부

해결됨

처음 만난 리액트(React)

안녕하세요! 리액트를 처음접하고 공부하고 있는 사람입니다.. 강의 해주신 내용이 너무 깔끔하고 좋아서 강의보면서 실습해보고, 복습개념으로 블로그에 글을 정리하려고 하는데 괜찮을까요?? 출처는 당연히 남기고, 광고나 이런거는 전혀없고 그냥 개인 공부하는 블로그입니다..!!

  • HTML/CSS
  • javascript
  • react
히수 댓글 1 좋아요 0 조회수 580

str.toLowerCase is not a function

미해결

Slack 클론 코딩[실시간 채팅 with React]

예상하지 못한 부분에서 에러가 나와서 질문 남겨드립니다 ! ChatBox.tsx import React, { useCallback, useEffect, useRef, VFC } from 'react'; import { ChatArea, EachMention, Form, MentionsTextarea, SendButton, Toolbox } from './styles'; import autosize from 'autosize'; import { Mention, SuggestionDataItem } from 'react-mentions'; import { useParams } from 'react-router'; import useSWR from 'swr'; import { IUser } from '@typings/db'; import fetcher from '@utils/fetcher'; import gravatar from 'gravatar'; interface Props { chat: string; onSubmitForm: (e: any) => void; onChangeChat: (e: any) => void; placeholder?: string; } const ChatBox: VFC<Props> = ({ chat, onSubmitForm, onChangeChat, placeholder }) => { const { workspace } = useParams<{ workspace: string }>(); const { data: userData, error, revalidate, mutate, } = useSWR<IUser | false>('/api/users', fetcher, { dedupingInterval: 2000, // 2초 }); const { data: memberData } = useSWR<IUser[]>(userData ? `/api/workspaces/${workspace}/members` : null, fetcher); const textareaRef = useRef<HTMLTextAreaElement>(null); useEffect(() => { if (textareaRef.current) { autosize(textareaRef.current); } }, []); const onKeydownChat = useCallback( (e) => { if (e.key === 'Enter') { if (!e.shiftKey) { e.preventDefault(); onSubmitForm(e); } } }, [onSubmitForm], ); const renderSuggestion = useCallback( ( suggestion: SuggestionDataItem, search: string, highlightedDisplay: React.ReactNode, index: number, focus: boolean, ): React.ReactNode => { if (!memberData) return; return ( <EachMention focus={focus}> <img src={gravatar.url(memberData[index].email, { s: '20px', d: 'retro' })} alt={memberData[index].nickname} /> <span>{highlightedDisplay}</span> </EachMention> ); }, [memberData], ); return ( <ChatArea> <Form onSubmit={onSubmitForm}> <MentionsTextarea id="editor-chat" value={chat} onChange={onChangeChat} onKeyPress={onKeydownChat} placeholder={placeholder} inputRef={textareaRef} allowSuggestionsAboveCursor > <Mention appendSpaceOnAdd trigger="@" data={memberData?.map((v) => ({ id: v.id, display: v.nickname })) || []} renderSuggestion={renderSuggestion} /> </MentionsTextarea> <Toolbox> <SendButton className={ 'c-button-unstyled c-icon_button c-icon_button--light c-icon_button--size_medium c-texty_input__button c-texty_input__button--send' + (chat?.trim() ? '' : ' c-texty_input__button--disabled') } data-qa="texty_send_button" aria-label="Send message" data-sk="tooltip_parent" type="submit" disabled={!chat?.trim()} > <i className="c-icon c-icon--paperplane-filled" aria-hidden="true" /> </SendButton> </Toolbox> </Form> </ChatArea> ); }; export default ChatBox; 혼자서 해결해보려다가 못찾고 있어서 질문 남겨드려요 ㅠㅠ

  • react
  • 웹팩
  • typescript
  • socket.io
  • babel
  • 클론코딩
유니크한 고슴도치 댓글 2 좋아요 0 조회수 832

mysql_secure_installation 정책에 관해

미해결

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

제가 다른게시물 보고 https://www.digitalocean.com/community/tutorials/how-to-install-mysql-on-ubuntu-20-04 이거까지 했는데 계속 새로운 비밀번호 입력 하라고 뜨네요 ㅠㅠ 이런 경우 어떻게 해야할까요 비밀번호도 보안수준에 맞게 했는데 계속 뜨네요 ㅠㅠ

  • react
  • redux
  • node.js
  • express
  • next.js
장산 댓글 3 좋아요 0 조회수 565

강의 pdf, 구글 드라이브에 대해 질문있습니다!

미해결

따라하며 배우는 도커와 CI환경 [2023.11 업데이트]

안녕하세요 강사님의 도커강의 잘 듣고 있습니다. 다름이 아니라 제가 현재 도커 강의를 복습하고 있는데, pdf파일이나 구글drive에서 강의 자료 파일을 확인해보면, 반정도 짤려있거나, 깨져있었습니다. 혹시 window pdf나 구글 드라이브에 있는 파일 다시 올려주실 수 있으실까요?

  • aws
  • docker
  • github
  • ci/cd
  • travis-ci
  • 데이터-엔지니어링
이수찬 댓글 2 좋아요 1 조회수 722

강의자료 pdf에서 우분투에서 도커 다운받는 링크 복사할때

미해결

따라하며 배우는 노드, 리액트 시리즈 - 레딧 사이트 만들기(NextJS)(Pages Router)

도커 다운받는 링크 복사 할때 공백 생겨서 필요 하신분 쓰시라고 링크 올려 두겠습니다. https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-22-04

  • react
  • node.js
  • postgresql
  • docker
  • typescript
  • 클론코딩
  • next.js
rhkdtjd_12 댓글 2 좋아요 2 조회수 1163

socket.io 실행

미해결

안녕하세요 채팅을 구현하기위해 socket.io를 썼는데 통신이 안되는 것같습니다 io에 주소를 제대로 넣었고 서버 on 마다 클라이언트에서 emit으로 작성했는데 작동하지 않습니다 이유가 무엇일까요? // server 파일의 코드입니다 require('dotenv').config(); const { createApp } = require('./app'); const { appDataSource } = require('./models/index'); const startServer = async () => { const app = createApp(); const PORT = process.env.PORT; await appDataSource .initialize() .then(() => { const server = app.listen(PORT, () => { console.log(`🟢server is listening on ${PORT}🟢`); }); const io = require('socket.io')(server, { cors: { origin: true, credentials: true, }, }); const { socketMessage } = require('./middlewares/socket.io'); socketMessage(io); }) .catch((err) => { console.log(`❌Failed server connect❌`); appDataSource.destroy(); }); }; startServer(); // server의 socket 파일의 코드입니다 const jwt = require('jsonwebtoken'); const chatDao = require('../models/chatDao'); const { catchAsync } = require('../utils/error'); const socketMessage = (io) => { io.use((socket, next) => { const token = socket.handshake.headers.authorization; if (!token) { return next(new Error('Authentication error')); } jwt.verify(token, process.env.SECRET_KEY, async (err, decoded) => { if (err) { return next(new Error('Authentication error')); } userId = decoded.userId; next(); }); }); io.on('connection', (socket) => { console.log('A User Connected.'); socket.on( 'create_room', catchAsync(async (postId, callback) => { const room = await chatDao.createRoom(userId, postId); socket.join(room.raw.insertId); callback(room.raw.insertId); }) ); socket.on( 'enter_room', catchAsync(async (roomId, callback) => { socket.join(roomId); callback(roomId); }) ); socket.on('new_text', async (content, roomId, callback) => { await chatDao.createChat(userId, content, roomId); socket.to(roomId).emit('new_text', content); callback(content); }); socket.on('disconnect', () => { console.log('접속이 해제되었습니다', socket.id); clearInterval(socket.interval); }); socket.on('error', (error) => { console.error(error); }); ​ socket.on('send', (data) => { console.log(data); socket.emit('reply', { data, }); }); socket.interval = setInterval(() => { socket.emit('news', 'Hello Socket.IO'); }, process.env.SOCKET_INTERVAL || 1000); }); }; module.exports = { socketMessage }; ​ // client 코드입니다 import React, { useState, useContext } from 'react'; import io from 'socket.io-client'; import './chat.css'; import { MenuContext } from '../../components/Nav/MenuProvider'; const Token = localStorage.getItem('accessToken'); const socket = io.connect('http://192.168.0.194:4000', { withCredentials: true, extraHeaders: {Authorization: `Bearer ${Token}` } appDataSource.destroy(); }), }); socket.on('connection', () => { console.log('Connected to server'); }); const Chat = () => { const [roomId, setRoomId] = useState([]); const [searchData, setSearchData] = useContext(MenuContext); const handleCreateRoom = event => { event.preventDefault(); socket.emit('create_room', searchData, ({ searchData, roomId }) => { console.log(`Joined room ${roomId}`); setRoomId(roomId); }); }; const handleJoinRoom = roomId => { socket.emit('enter_room', roomId, roomId => { console.log(`Joined room ${roomId}`); setRoomId(roomId); }); }; const handleNewText = content => { socket.emit('new_text', content, roomId, content => { console.log(`Sent message: ${content}`); }); }; const handleNewText = content => { socket.emit('new_text', content, roomId, content => { console.log(`Sent message: ${content}`); }); }; const onCheckEnter = e => {if (e.key === 'Enter') { handleNewText(); } }; return ( <div className="h-screen pt-36"> <button onClick={handleCreateRoom}>테스트</button> <button onClick={() => handleJoinRoom(roomId)}>테스트2</button> <input id="input-text" type="text" onKeyDown={onCheckEnter} /> <button onClick={handleCreateRoom}>제출</button> </div> ); }; export default Chat;

  • react
  • javascript
  • socket
  • socket.io
  • node.js
bin 댓글 1 좋아요 0 조회수 745

시작할 때 가이드

미해결

깃헙 블로그(Github blog)로 차별화 된 나만의 홈페이지 만들기!

1강 시작이 뭔가 이상하게 느끼신분들은 아래 링크를 참고 클론하시면 됩니다. https://github.com/teddynote/teddynote.github.io https://teddynote.github.io/ https://mmistakes.github.io/minimal-mistakes/docs/quick-start-guide/

  • 블로그
  • github
따라쟁이 댓글 2 좋아요 3 조회수 841

mysql_secure_installation password 질문이요

미해결

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

... Failed! Error: SET PASSWORD has no significance for user 'root'@' localhost ' as the authentication method used doesn't store authentication data in the MySQL server. Please consider using ALTER USER instead if you want to change authentication parameters. 구글링도하고 mysql다시깔아서 local password도 다시 설정했는데 자꾸 이 오류가 나오네요.. 혹시 해결 방법이 있을까요?

  • react
  • redux
  • node.js
  • express
  • next.js
dsfsdf 댓글 2 좋아요 0 조회수 663

소스트리 history에 대해서 질문 드립니다.

해결됨

팀 개발을 위한 Git, GitHub 입문

"GUI add, commit, push, pull 하기" 강의 보다가 질문 드립니다. 소스트리를 이용해 Boxiting-cat 폴더의 index.html과 README.md의 내용을 변경하고 "고양이 커밋2"라는 메세지로 커밋해 push 했습니다. 이후 소스트리에서 Boxiting-oct 폴더를 열었는데 history에 Boxiting-cat 폴더에서 push한 내용이 없습니다. [origin/mater origin/HEAD 고양이 커밋2] 이 표시되지 않고 [Master origin/master origin/HEAD 문어의 커밋] 만 나옵니다. 어떻게 해야 하나요?

  • git
  • github
  • 버전관리시스템
뚜벅 댓글 1 좋아요 0 조회수 534

깃헙입문!

해결됨

팀 개발을 위한 Git, GitHub 입문

안녕하세요~ 이번에 부트캠프에 참여하게 되어 급하게 깃헙 사용법을 알아보다가 우연히 강사님의 강의를 알게 됐습니다. 쉽게 설명해주셔서 시간 절약을 할 수 있을 것 같습니다. 배운 내용을 까먹지 않게 한 번 씩 보려고 하는데 강의자료 부탁드립니다.

  • git
  • github
  • 버전관리시스템
뚜벅 댓글 1 좋아요 0 조회수 469

유투브 강의랑 내용이 같은것같은데....

미해결

깃헙 블로그(Github blog)로 차별화 된 나만의 홈페이지 만들기!

선생님!!! 유투브 강의랑 내용이 같은것같은데.... 혹시 내용 업데이트 될예정인가요 ㅜㅜ??? 아니면 그대로 유지인가요..?

  • 블로그
  • github
댓글 1 좋아요 2 조회수 562

강의에 나오는 문법이 적용되지 않습니다

미해결

따라하며 배우는 노드, 리액트 시리즈 - 기본 강의

MongooseError: Model.prototype.save() no longer accepts a callback 이 오류가 떠서 확인해보니 Mongoose6부터 callback 문법이 사용되지 않는다고 합니다 버전을 바꾸는 것은 시도 하지 않았고 .then .catch or async await 로 바꾸고 싶은데 수 시간 시도해보다가 안되서 글 남깁니다. callback 구문을 보고 .then .catch or async await 이 방식으로 바꾸는 법을 알고 싶습니다. 이 부분에서만 에러가 발생하는지는 모르겠으나 stack Overflow에 적어봤는데 역시 답을 얻을 수 없더라구요 app.post("/login", (req, res) => { User.findOne({ email: req.body.email }, (err, user) => { if (!user) { return res.json({ loginSuccess: false, message: "제공된 이메일에 해당하는 유저가 없습니다.", }); } user.comparePassword(req.body.password, (err, isMatch) => { if (!isMatch) return res.json({ loginSuccess: false, message: "비밀번호가 틀렸습니다." }); user.generateToken((err, user) => { if (err) return res.status(400).send(err); res.cookie("x-auth", user.token).status(200).json({ loginSuccess: true, userId: user._id }); }); }); }); });

  • react
  • node.js
exwhite 댓글 2 좋아요 0 조회수 4276

docker-compose up 시 오류

미해결

따라하며 배우는 도커와 CI환경 [2023.11 업데이트]

다른 질문도 참고해보았지만 도저히 해결이 안되네요 아래는 오류 로그입니다. ui-MacBookAir docker-compose-app % docker-compose up [+] Running 2/0 ⠿ Container docker-compose-app-node-app-1 Created 0.0s ⠿ Container docker-compose-app-redis-server-1 Recreated 0.0s Attaching to docker-compose-app-node-app-1, docker-compose-app-redis-server-1 docker-compose-app-redis-server-1 | 1:C 04 Mar 2023 11:43:49.189 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo docker-compose-app-redis-server-1 | 1:C 04 Mar 2023 11:43:49.189 # Redis version=7.0.9, bits=64, commit=00000000, modified=0, pid=1, just started docker-compose-app-redis-server-1 | 1:C 04 Mar 2023 11:43:49.189 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf docker-compose-app-redis-server-1 | 1:M 04 Mar 2023 11:43:49.189 * monotonic clock: POSIX clock_gettime docker-compose-app-redis-server-1 | 1:M 04 Mar 2023 11:43:49.190 * Running mode=standalone, port=6379. docker-compose-app-redis-server-1 | 1:M 04 Mar 2023 11:43:49.190 # Server initialized docker-compose-app-redis-server-1 | 1:M 04 Mar 2023 11:43:49.192 * Ready to accept connections docker-compose-app-node-app-1 | server is running docker-compose-app-node-app-1 | events.js:174 docker-compose-app-node-app-1 | throw er; // Unhandled 'error' event docker-compose-app-node-app-1 | ^ docker-compose-app-node-app-1 | docker-compose-app-node-app-1 | Error: Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED 127.0.0.1:6379 docker-compose-app-node-app-1 | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1107:14) docker-compose-app-node-app-1 | Emitted 'error' event at: docker-compose-app-node-app-1 | at RedisClient.on_error (/usr/src/app/node_modules/redis/index.js:341:14) docker-compose-app-node-app-1 | at Socket.<anonymous> (/usr/src/app/node_modules/redis/index.js:222:14) docker-compose-app-node-app-1 | at Socket.emit (events.js:198:13) docker-compose-app-node-app-1 | at emitErrorNT (internal/streams/destroy.js:91:8) docker-compose-app-node-app-1 | at emitErrorAndCloseNT (internal/streams/destroy.js:59:3) docker-compose-app-node-app-1 | at process._tickCallback (internal/process/next_tick.js:63:19) docker-compose-app-node-app-1 exited with code 1 ^CGracefully stopping... (press Ctrl+C again to f 나머지는 소스 파일입니다. version: "3" services: redis-server: image: "redis" node-app: build: . ports: - "8080:8080" FROM node WORKDIR /usr/src/app COPY ./ ./ RUN npm install CMD ["node", "server.js"] { "name": "docker-compose-app", "version": "1.0.0", "description": "", "main": "server.js", "scripts": { "start": "node server.js", "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { "express": "4.17.1", "redis": "3.0.2" }, "author": "", "license": "ISC" } const express = require("express"); const redis = require("redis"); // 레디스 클라이언트 생성 const client = redis.createClient({ socket: { host: "redis-server", port: 6379 } }); const app = express(); app.get("/", async (req, res) => { await client.connect(); let number = await client.get("number"); if(number === null){ number = 0; } console.log(`Number : ${number}`); res.send(`숫자가 1씩 올라갑니다. 숫자 : ${number}`); await client.set("number", parseInt(number) + 1); await client.disconnect(); }); app.listen(8080); console.log("server is running"); 강의 진도를 나갈 수가 없어서 답답합니다. 혹시 해결하신분들은 있으신가요..

  • aws
  • docker
  • github
  • ci/cd
  • travis-ci
  • 데이터-엔지니어링
느엉느엉느엉 댓글 7 좋아요 0 조회수 2837

인기 태그

인프런 TOP Writers

주간 인기글