inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

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

onScroll 스크롤 위치 유지가 안됩니다 ㅠ

미해결

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

import Chat from '@components/Chat'; import { ChatZone, Section, StickyHeader } from '@components/ChatList/style'; import { IChat, IDM } from '@typings/db'; import React, { FC, RefObject, VFC, forwardRef, useCallback, useRef } from 'react'; import { Scrollbars } from 'react-custom-scrollbars'; interface Props { scrollRef: RefObject<Scrollbars>; chatSections: { [key: string]: IDM[] }; setSize: (f: (index: number) => number) => Promise<IDM[][] | undefined>; isEmpty: boolean; isReachingEnd: boolean; } const ChatList: VFC<Props> = (({ chatSections, setSize, isEmpty, scrollRef, isReachingEnd}) => { const onScroll = useCallback((values) => { // 끝에 도달하면 불러오지 않기 if(values.scrollTop === 0 && !isReachingEnd){ console.log('가장 위'); setSize((prevSize) => prevSize + 1).then(()=>{ // 스크롤 위치 유지 if(scrollRef?.current){ scrollRef.current?.scrollTop(scrollRef.current?.getScrollHeight() - values.scrollHeight); } }); } }, []); return ( <ChatZone> <Scrollbars autoHide ref={scrollRef} onScrollFrame={onScroll}> {Object.entries(chatSections).map(([date, chats]) => { return ( <Section className={`section-${date}`} key={date}> <StickyHeader> <button>{date}</button> </StickyHeader> {chats.map((chat) => ( <Chat key={chat.id} data={chat} /> ))} </Section> ); })} </Scrollbars> </ChatZone> ); }); export default ChatList; 이쪽 코드는 문제가 없는것같은데 희한하게 위치가 유지가 되지않고 원래처럼 쭉 올라가버립니다.. ref쪽이 문제인가요..? 혹시몰라 DirectMessage 컴포넌트도 아래에 첨부하겠습니다. import React, { useCallback, useEffect, useRef } from 'react'; import gravator from 'gravatar'; import useSWR, { mutate } from 'swr'; // swr 인피니티스크롤링 전용 메서드 import useSWRInfinite from 'swr/infinite'; import { IDM, IUser } from '@typings/db'; import fetcher from '@utils/fetcher'; import { useParams } from 'react-router'; import ChatBox from '@components/ChatBox'; import { Container, Header } from '@pages/DirectMessage/style'; import ChatList from '@components/ChatList'; import useInput from '@hooks/useInput'; import axios from 'axios'; import makeSection from '@utils/makeSection'; import Scrollbars from 'react-custom-scrollbars'; const DirectMessage = () => { const { workspace, id } = useParams<{ workspace: string; id: string }>(); const { data: userData } = useSWR(`http://localhost:3095/api/workspaces/${workspace}/users/${id}`, fetcher); // 내정보 const { data: myData } = useSWR(`http://localhost:3095/api/users`, fetcher); const [chat, onChangeChat, setChat] = useInput(''); // 과거 채팅리스트에서 채팅을 치면 최신목록으로 바로 스크롤을 내려줄려면 ref를 // 이 컴포넌트에서 props로 내려줘야하기 때문에 forwardRef를 사용해서 props로 넘겨준다 // 💡 HTML 엘리먼트가 아닌 React 컴포넌트에서 ref prop을 사용하려면 React에서 제공하는 forwardRef()라는 함수를 사용해야 합니다 const scrollbarRef = useRef<Scrollbars>(null); // 채팅 받아오는곳 (setSize : 페이지수를 바꿔줌) // useSWRInfinite를 쓰면 [{id:1},{id:2},{id:3},{id:4}] 1차원배열이 [[{id:1},{id:2}],[{id:3},{id:4}]] 2차원배열이 된다. const { data: chatData, mutate: mutateChat, setSize, } = useSWRInfinite<IDM[]>( (index) => `http://localhost:3095/api/workspaces/${workspace}/dms/${id}/chats?perPage=20&page=${index + 1}`, fetcher, ); // 데이터 40 개중에 20개씩 사져오면 첫번째페이지부터 20 + 20 + 0 세번째 페이지 0 이되면 isEmpty, isReachingEnd는 true가 됨 // 반대의 상황에서 데이터가 45개면 20 + 20 + 5 isEmpty는 0이 아니라서 false isReachingEnd는 여전히 데이터 가져옴 const isEmpty = chatData?.[0]?.length === 0; const isReachingEnd = isEmpty || (chatData && chatData[chatData.length - 1]?.length < 20) || false; const onSubmitForm = useCallback( (e) => { e.preventDefault(); if (chat?.trim() && chatData) { const savedChat = chat; // 💡 옵티미스틱 UI // 서버쪽에 다녀오지 않아도 성공해서 데이터가 있는거처럼 보이게 미리 만듦 mutateChat((prevChatData) => { // infinite 스크롤링은 2차원 배열이다. prevChatData?.[0].unshift({ // unshift : 앞쪽에 추가 id: (chatData[0][0]?.id || 0) + 1, content: savedChat, SenderId: myData.id, Sender: myData, ReceiverId: userData.id, Receiver: userData, createdAt : new Date(), }); return prevChatData; },false) // 옵티미스틱 UI 할땐 이부분이 항상 false .then(()=>{ setChat(''); // 버튼클릭 시 기존 채팅지우기 scrollbarRef.current?.scrollToBottom(); // 채팅 첬을때 맨 아래로 }) axios .post( `http://localhost:3095/api/workspaces/${workspace}/dms/${id}/chats`, { content: chat, }, { withCredentials: true, }, ) .then(() => { mutateChat(); // SWR에서 데이터를 다시 불러와서 캐시를 갱신하는 역할을 합니다. }) .catch(() => { console.error; }); } }, [chat, chatData, myData, userData, workspace, id], ); // (채팅이 최신것을 아래에 두기 위함) = 기존것 데이터를두고 새 데이터를 뒤집어서 출력 / flat() 배열을 1차원 배열로 만들어줌 const chatSections = makeSection(chatData ? [...chatData].flat().reverse() : []); // 로딩 시 스크롤바 제일 아래로 useEffect(()=>{ if(chatData?.length === 1){ // 채팅 데이터가 있어서 불러온 경우 scrollbarRef.current?.scrollToBottom(); // 가장 아래쪽으로 내려줌 } },[chatData]) // 로딩 if (!userData || !myData) { return null; } return ( <Container> <Header> <img src={gravator.url(userData.email, { s: '24px', d: 'retro' })} alt={userData.nickname}></img> <span>{userData.nickname}</span> </Header> {/* 컴포넌트 위치를 미리 지정해도 좋다. */} {/* 전역 상태관리 라이브러리를 사용해도 컴포넌트상황에따라 props 로 넘겨줌*/} <ChatList scrollRef={scrollbarRef} chatSections={chatSections} setSize={setSize} isEmpty={isEmpty} isReachingEnd={isReachingEnd} /> <ChatBox chat={chat} onChangeChat={onChangeChat} onSubmitForm={onSubmitForm} /> </Container> ); }; export default DirectMessage;

  • react
  • 웹팩
  • typescript
  • socket.io
  • babel
  • 클론코딩
복실묘 댓글 2 좋아요 0 조회수 529

서버 실패시, 패스포트 로그인 실패시 통합테스트 방법

미해결

[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지

exports.login = (req, res, next) => { passport.authenticate('local', (authError, user, info) => { // 1. 서버 실패 부분 if (authError) { console.error(authError); return next(authError); } if (!user) { return res.redirect(`/?error=${info.message}`); } return req.login(user, (loginError) => { //2. 패스포트 로그인 실패 if (loginError) { console.error(loginError); return next(loginError); } return res.redirect('/'); }); })(req, res, next); }; --------------------- 1번과 2번은 통합테스트 코드로 어떻게 테스트 코드를 작성해야 하는지 여쭤봐도 될까요? 1번은 try - catch 로 어떻게 해보려해도 생각이 안나용 2번은 아애 생각이 안납니다 ㅜㅜ controllers를 자체를 단위테스트를 하는 것이 아니라 분기마다 test를 작성하라고 하신 말씀에 이 부분은 통합테스트로 코드를 짤 수 있나 의문이 들어서요! 감사합니다

  • node.js
  • mysql
  • mongodb
  • express
  • typescript
  • socket.io
  • jwt
kyh_0625 댓글 2 좋아요 1 조회수 422

jpql 엔티티 인지 오류

미해결

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 일단은 해결 했습니다. findAllString 이용하는데 Order를 얘가 모르는 거 같아서.. String jpql = "select o From jpabook.jpashop.domain.Order o join o.member m"; 이렇게 패키지경로까지 다 명시해줬더니 인지를 하더라구요.. 안 그러면 org.hibernate.query.sqm.UnknownEntityException: Could not resolve root entity 'Order' at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitRootEntity(SemanticQueryBuilder.java:1960) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final] at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitRootEntity(SemanticQueryBuilder.java:253) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final] ............... 얘가 이렇게 Order 인지 못한다고 오류가 뜹니다.. 원래 엔티티는 그냥 @Entity 등록 하면 알아서 인지 되는걸로 알고 있었는데.. 왜 이런 걸까요? package jpabook.jpashop.domain; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @Entity(name = "orders") @Getter @NoArgsConstructor(access = AccessLevel.PUBLIC) public class Order { @Id @GeneratedValue @Column(name = "order_id") private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id") private Member member; @OneToMany(mappedBy = "order", cascade = CascadeType.ALL) private List<OrderItem> orderItems = new ArrayList<>(); @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumn(name = "delivery_id") private Delivery delivery; private LocalDateTime orderDate; @Enumerated(EnumType.STRING) private OrderStatus status; public void changeMember(Member member){ this.member = member; member.getOrders().add(this); } public void addOrderItem(OrderItem orderItem){ orderItems.add(orderItem); orderItem.setOrder(this); } private void setOrderDate(LocalDateTime orderDate) { this.orderDate = orderDate; } public void changeDelivery(Delivery delivery){ this.delivery = delivery; delivery.setOrder(this); } private void setStatus(OrderStatus status) { this.status = status; } public static Order createOrder(Member member, Delivery delivery, OrderItem... orderItems){ Order order = new Order(); order.changeMember(member); order.changeDelivery(delivery); for (OrderItem orderItem : orderItems) { order.addOrderItem(orderItem); } order.setStatus(OrderStatus.ORDER); order.setOrderDate(LocalDateTime.now()); return order; } public void cancel(){ if(delivery.getStatus() == DeliveryStatus.COMP){ throw new IllegalStateException("이미 배송완료된 상품은 취소가 불가능합니다."); } this.setStatus(OrderStatus.CANCEL); for (OrderItem orderItem : orderItems) { // orderItem.getItem().removeStock(orderItem.getCount()); orderItem.cancel(); } } public int getTotalPrice(){ int totalPrice = 0; for( OrderItem orderItem : orderItems){ totalPrice += orderItem.getTotalPrice(); } return totalPrice; } }

  • java
  • spring
  • 웹앱
  • spring-boot
  • jpa
궁금이 댓글 1 좋아요 0 조회수 2889

7.5 시퀄라이즈 사용하기 에러

미해결

[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지

7.5 시퀄라이즈 사용하기 강좌 부분입니다.피피티와 동일하게 작성했는데 sync에러가 자꾸 뜹니다. 어떻게 고쳐야할지 모르겠습니다. app.js const express = require('express'); const path = require('path'); const morgan = require('morgan'); const nunjucks = require('nunjucks'); const { sequelize } = require('./models'); const app = express(); app.set('port', process.env.PORT || 3001); app.set('view engine', 'html'); nunjucks.configure('views', { express: app, watch: true, }); sequelize.sync({ force: false }) .then(() => { console.log('데이터베이스 연결 성공'); }) .catch((err) => { console.error(err); }); app.use(morgan('dev')); app.use(express.static(path.join(__dirname, 'public'))); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use((req, res, next) => { const error = new Error(`${req.method} ${req.url} 라우터가 없습니다.`); error.status = 404; next(error); }); app.use((err, req, res, next) => { res.locals.message = err.message; res.locals.error = process.env.NODE_ENV !== 'production' ? err : {}; res.status(err.status || 500); res.render('error'); }); app.listen(app.get('port'), () => { console.log(app.get('port'), '번 포트에서 대기 중'); }); index.js const Sequelize = require('sequelize'); const env = process.env.NODE_ENV || 'development'; const config = require('../config/config')[env]; const db = {}; const sequelize = new Sequelize(config.database, config.username, config.password, config); db.seqelize = sequelize; module.exports = db; error ->[nodemon] restarting due to changes...[nodemon] starting node app.js C:\Users\jyoun\udr_node\lecture\app.js:15sequelize.sync({ force: false }) ^TypeError: Cannot read properties of undefined (reading 'sync') at Object.<anonymous> (C:\Users\jyoun\udr_node\lecture\app.js:15:11) at Module._compile (node:internal/modules/cjs/loader:1241:14) at Module._extensions..js (node:internal/modules/cjs/loader:1295:10) at Module.load (node:internal/modules/cjs/loader:1091:32) at Module._load (node:internal/modules/cjs/loader:938:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12) at node:internal/main/run_main_module:23:47Node.js v20.7.0[nodemon] app crashed - waiting for file changes before starting... [제로초 강좌 질문 필독 사항입니다] 질문에는 여러분에게 도움이 되는 질문과 도움이 되지 않는 질문이 있습니다. 도움이 되는 질문을 하는 방법을 알려드립니다. https://www.youtube.com/watch?v=PUKOWrOuC0c 0. 숫자 0부터 시작한 이유는 1보다 더 중요한 것이기 때문입니다. 에러가 났을 때 해결을 하는 게 중요한 게 아닙니다. 왜 여러분은 해결을 못 하고 저는 해결을 하는지, 어디서 힌트를 얻은 것이고 어떻게 해결한 건지 그걸 알아가셔야 합니다. 그렇지 못한 질문은 무의미한 질문입니다. 1. 에러 메시지를 올리기 전에 반드시 스스로 번역을 해야 합니다. 번역기 요즘 잘 되어 있습니다. 에러 메시지가 에러 해결 단서의 90%를 차지합니다. 한글로 번역만 해도 대부분 풀립니다. 그냥 에러메시지를 올리고(심지어 안 올리는 분도 있습니다. 저는 독심술사가 아닙니다) 해결해달라고 하시면 아무런 도움이 안 됩니다. 2. 에러 메시지를 잘라서 올리지 않아야 합니다. 입문자일수록 에러메시지에서 어떤 부분이 가장 중요한 부분인지 모르실 겁니다. 그러니 통째로 올리셔야 합니다. 3. 코드도 같이 올려주세요. 다만 코드 전체를 다 올리거나, 깃헙 주소만 띡 던지지는 마세요. 여러분이 "가장" 의심스럽다고 생각하는 코드를 올려주세요. 4. 이 강좌를 바탕으로 여러분이 응용을 해보다가 막히는 부분, 여러 개의 선택지 중에서 조언이 필요한 부분, 제 경험이 궁금한 부분에 대한 질문은 대환영입니다. 다만 여러분의 회사 일은 질문하지 마세요. 5. 강좌 하나 끝날 때마다 남의 질문들을 읽어보세요. 여러분이 곧 만나게 될 에러들입니다. 6. 위에 적은 내용을 명심하지 않으시면 백날 강좌를 봐도(제 강좌가 아니더라도) 실력이 늘지 않고 그냥 코딩쇼 관람 및 한컴타자연습을 한 셈이 될 겁니다.

  • node.js
  • mysql
  • mongodb
  • express
  • typescript
  • socket.io
  • jwt
박예원[ 학부재학 / 컴퓨터융합 댓글 1 좋아요 0 조회수 345

그럼 그걸 다 들어야 하나요?

미해결

[웹 개발 풀스택 코스] Node.js 프로젝트 투입 일주일 전 - 기초에서 실무까지

다른 강의에 테이블이 있다고 해서 가보니..파일로 있는 게 아니고 화면에 있던데.. 그러면 저 처럼 그런 강의가 필요 없는 사람은..그걸 다 보고 만들라는 건가요? 그러기엔 시간이 아까운데요? 하루죙일..개발 하다가 왔는데..그걸 보고 일일이 쳐서 만들라는 건 좀 아니지 않나요?

  • node.js
  • mysql
  • mongodb
  • express
  • 웹-크롤링
  • socket.io
민경언 댓글 1 좋아요 0 조회수 297

useSwr 여러컴포넌트에 사용가능한가요

미해결

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

workSpace 에도 useSwr 로 유저데이터랑 채널데이터 요청하고 모달안에서도 유저데이터랑 채널데이터 요청하는데 이러면 불필요한 요청이 모달하나 띄운다고 실행되는거 아닌가요? workSpace에서 revalidate 함수만 넘겨서 하면 어떤가요?

  • react
  • 웹팩
  • typescript
  • socket.io
  • babel
  • 클론코딩
쵸잉 댓글 1 좋아요 0 조회수 359

useState 오류

해결됨

React + GPT API로 AI회고록 서비스 개발 (원데이 클래스)

GPT API 호출, 프롬프트 연동 강의 0:24 계속해서 useState에 다음과 같은 오류가 뜹니다. import { useState } from "react"; 오류 사유는'useState' is declared but its value is never read. 대체 왜 해결이 안되는 것일까요..?ㅜ.ㅜ

  • HTML/CSS
  • javascript
  • react
  • node.js
  • chatgpt
한나 댓글 2 좋아요 1 조회수 836

MemberForm은 이미 모델에 들어가 있는거죠?

해결됨

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 검증오류가 날 시 BindingResult에 의해 들어가는 게 아니라, 저렇게 인자로 받는 건 이미 모델에 들어가 주는거죠?

  • java
  • spring
  • 웹앱
  • spring-boot
  • jpa
궁금이 댓글 1 좋아요 0 조회수 384

코드에 대한 질문이 잇습니다.

미해결

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

강의를 전부 진행한지 시간이 좀 된 상태에서 프로젝트 리팩토링중 이해가 안되는 부분이 있어 질문드립니다. 아래 의문점에 대해 확인과 의견을 부탁드립니다. 작성된 코드는 제로초님의 front / nest-typeorm 에서 가져온 코드입니다. 의문점 : 채팅 데이터 전송에 웹소켓이 역할을 하지 않는것 같다. 그렇게 생각한 근거 : 1-1 : useSocket을 이용해서 소켓에 연결하는데 ws-${workspace} 의 message에 onMessage 함수를 연결하고 있다 const Channel = () => { const [socket] = useSocket(workspace); useEffect(() => { socket?.on('message', onMessage); return () => { socket?.off('message', onMessage); }; }, [socket, onMessage]); } const useSocket = (workspace?: string): [Socket | undefined, () => void] => { const disconnect = useCallback(() => { if (workspace && sockets[workspace]) { console.log('소켓 연결 끊음'); sockets[workspace].disconnect(); delete sockets[workspace]; } }, [workspace]); if (!workspace) { return [undefined, disconnect]; } if (!sockets[workspace]) { sockets[workspace] = io(`${backUrl}/ws-${workspace}`, { transports: ['websocket'], }); console.info('create socket', workspace, sockets[workspace]); sockets[workspace].on('connect_error', (err) => { console.error(err); console.log(`connect_error due to ${err.message}`); }); } return [sockets[workspace], disconnect]; }; 1-2 : 백엔드에서 채팅을 수신받는 createWorkspaceChannelChats는 ws-${url}-${chatWithUser.ChannelId} 의 message에 받아온 채팅을 보내고 있다. async createWorkspaceChannelChats( url: string, name: string, content: string, myId: number, ) { const channel = await this.channelsRepository .createQueryBuilder('channel') .innerJoin('channel.Workspace', 'workspace', 'workspace.url = :url', { url, }) .where('channel.name = :name', { name }) .getOne(); const chats = new ChannelChats(); chats.content = content; chats.UserId = myId; chats.ChannelId = channel.id; const savedChat = await this.channelChatsRepository.save(chats); const chatWithUser = await this.channelChatsRepository.findOne({ where: { id: savedChat.id }, relations: ['User', 'Channel'], }); this.eventsGateway.server // .of(`/ws-${url}`) .to(`/ws-${url}-${chatWithUser.ChannelId}`) .emit('message', chatWithUser); } 2 : 네트워크 탭의 웹소켓 메시지에 채팅내역 수신내역이 남지 않는다 이미지가 보일지는 모르겟지만 빨간 박스가 새로 전송한 채팅이고 정상적으로 수신받으면 네트워크 탭에 messag에 내역이 남아야 하는걸로 알고 있는데 남지 않는걸로 확인됩니다. 3 : 웹페이지에서 포커스를 유지한 상태로 모바일에서 입력시 채팅이 전송되지 않음 왜 채팅이 정상적으로 전송된거 처럼 보일까 생각해보니 swr이 브라우저를 포커스 아웃후 재 포커스하면 채팅데이터를 다시 가져오는걸로 추측하여 웹페이지 포커스 유지중 모바일로 테스트해보니 채팅이 전송되지 않습니다.

  • react
  • 웹팩
  • typescript
  • socket.io
  • babel
  • 클론코딩
최석우 댓글 1 좋아요 1 조회수 430

const handleEnter 문에 궁금한게 있습니다.

해결됨

React + GPT API로 AI회고록 서비스 개발 (원데이 클래스)

setUserInput("")을 하면 userInput 값이 ""로 바뀌고 그다움 num 선언문에 ""의 숫자변환값이 들어가는게 아닌가 궁금합니다.

  • HTML/CSS
  • javascript
  • react
  • node.js
  • chatgpt
최지훈 댓글 2 좋아요 2 조회수 348

NODE로 프로그램을 WINDOW 설치 프로그램으로 만들고싶습니다.

미해결

[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지

제가 만든 NODEJS 프로그램을 한글처럼 WINDOW 환경에서 통합설치 프로그램 하나만 설치하면 DB, NODE 프로그램이 설치되도록 하고싶은데 어떤 방법이 있고 구글에 어떻게 검색해야 하는지 궁금합니다.

  • node.js
  • mysql
  • mongodb
  • express
  • typescript
  • socket.io
  • jwt
gm k 댓글 1 좋아요 0 조회수 444

Spring Security 6.0 이상 (Spring boot 3.0 이상)에서 다중 config 설정 방법

미해결

스프링 시큐리티

안녕하세요 이렇게 좋은 Spring Security에 애를 많이 먹던 도중 늦게나마 열심히 듣고 있는 사람입니다. 강의를 들으면서 Spring Security 6.0 이상 버전으로 혼자 마이그레이션 해보며 공부를 진행하는데요.. 다른 분들은 모르겠지만 저는 6.0 이상 버전에서의 다중 보안 설정에서 애를 좀 먹어서.. 혹시나 저 같으신 분들이 있으실까봐 글을 남깁니다..! 다름이 아니라 Spring Security 6.0 이상 버전에서는 먼저 오버라이드해서 함수를 구현하는 것이 아니라 컴포넌트화 시켜서 진행합니다. 또한 HttpSecurity 안의 내용을 구현하는데 변경점이 있다는 것이 가장 큰 차이점인 것 같습니다. 예를 들어 UserSecurityConfig, AdminSecurityConfig를 만들어서 각 경우에 따라 다른 설정을 적용하고 싶은 경우에 두 가지의 config 파일을 만들 수 있다고 가정하면.. 저의 경우에는 AdminSecurityConfig에서 지정한 부분이 권한 정보에 따라 접근이 막히지 않고 다 접근이 가능한 ("/admin/pay"를 user가 접근 가능) 상황이었습니다. 뭐가 문제인지 한참을 찾던 도중 https://docs.spring.io/spring-security/reference/servlet/configuration/java.html 공식 문서를 통해 답을 찾았습니다. 간략하게 해결법부터 말씀드리자면 path로 접근 제한을 하는 경우에 http.securityMatcher()를 사용해야 한다는 점 입니다. 이렇게 하면 아주 잘 구분이 되더군요..! 혹시나 저처럼 하시는 분이 계실까봐 남깁니다..! @Bean @Order(0) public SecurityFilterChain adminFilterChain(HttpSecurity http) throws Exception{ http .securityMatcher("/admin/pay") .authorizeHttpRequests(request -> request.anyRequest().hasRole("ADMIN")); return http.build(); } @Bean @Order(1) public SecurityFilterChain systemFilterChain(HttpSecurity http) throws Exception{ http .securityMatcher("/admin/**") .authorizeHttpRequests(request -> request .anyRequest().hasAnyRole("SYS", "ADMIN")); return http.build(); } @Bean @Order(2) public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{ http .authorizeHttpRequests(request -> request .requestMatchers(antMatcher("/user/**")).hasRole("USER") .anyRequest().authenticated());

  • java
  • spring-boot
  • spring-security
jwl5015 댓글 3 좋아요 4 조회수 3375

MentionsTextarea 와 autoSize 사이 버그가 하나 있습니다.

해결됨

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

MentionsTextarea 에 ctrl+c ctrl+v 를 이용하여 값을 입력시 사이즈는 조절되나 글자 줄 수가 잘려서 보이는 버그가 있습니다. MentionsTextarea 을 사용시 실제보이는 textarea와 보이지 않는 span 영역이 생성되는데 이 중 autosize에 span ref만 넘어가서 span영역만 커지고 textarea의 영역은 유지되서 생기는 버그로 보입니다. 이후 글자를 제거 하거나 추가로 입력시 정상적으로 보이게 됩니다.

  • react
  • 웹팩
  • typescript
  • socket.io
  • babel
  • 클론코딩
최석우 댓글 1 좋아요 0 조회수 385

named lock vs 비관적 락

미해결

재고시스템으로 알아보는 동시성이슈 해결방법

좋은 강의 너무 감사합니다. 강의를 보며 궁금한 점이 생겨서 질문 드립니다. named lock을 통해 동시성 문제를 해결하는 예시를 보았을 때, 비관적 락과 무엇이 다른 것인지 큰 차이를 느끼지 못했습니다. named lock이 비관적 락에 비해 가지는 장단점에 비해 찾아보니, timeout 설정이 좀 더 간편하다는 내용 말고는 유의미한 차이를 찾지 못했습니다. (그러나 비관적 락 + queryhint 를 사용하면 비관적 락 사용 시에도 딱히 어려움 없이 timeout을 설정할 수 있었습니다.) 혹시 named lock이 비관적 락에 비해 지니는 장단점과, 어떤 경우에 비관적 락 대신 Named lock을 통해 분산락을 구현하시는지 궁금하여 질문드립니다.

  • java
  • spring
  • 동시성
신동훈 댓글 1 좋아요 0 조회수 1427

SpringPhysicalNamingStrategy 바뀐건가요?

해결됨

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 찾아도 안나오는데 CamelCaseToUnderscoresNamingStrategy 이걸로 바뀐 것 같네요.

  • java
  • spring
  • 웹앱
  • spring-boot
  • jpa
궁금이 댓글 3 좋아요 0 조회수 1460

정적 팩토리 메서드에 static이 붙어야 하는 이유

미해결

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

안녕하세요. 강의 잘 보고 있습니다! 다른 분 질문에 궁금한 것이 해소되지 않아 질문드립니다. https://www.inflearn.com/course/lecture?courseSlug=%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-JPA-%ED%99%9C%EC%9A%A9-1&unitId=24297&category=questionDetail&q=30892&tab=community 정적 팩토리 메소드 사용 이유중에 static 메모리에 올라가기때문에 새로운 객체를 생성하지 않는 장점이 있는 거라고 알고 있습니다. 이 예제의 경우 static을 빼도 JPA가 엔티티로 관리하면서 어차피 사용할 수 있는 부분아닌가요..? 라는 질문에서 강사님께서는 static을 빼보면 이해될 거라고 답변하셨습니다. 제가 생각하기로는 정적 팩토리 메서드 안에서 생성자를 통해 인스턴스를 생성하는 것은 똑같아 보이고, 호출할 때 new가 아닌 Order.createOrder()로 호출하는 것 외에는 차이점을 못 느꼈습니다. 조금 더 상세한 가르침을 주시면 감사하겠습니다!

  • java
  • spring
  • 웹앱
  • spring-boot
  • jpa
저스트 댓글 2 좋아요 1 조회수 1132

sequelize initiate() 쓰는 방식 최신인지, 공식문서 방법인지 궁금합니다

미해결

[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지

영상에서는 sequelize 공식문서에서 바뀌어서 따라갔다고 하는데 공식문서에서 initiate() 쓰는 것 검색하였을 때 안보이며 static이랑 같이 쓴 것도 아직은 못찾았습니다 공식문서 따라가보면 주로 define(), init()을 쓰는데 강의영상의 방식과는 차이점이 있습니다. define() const { Sequelize, DataTypes } = require('sequelize'); const sequelize = new Sequelize('sqlite::memory:'); const User = sequelize.define('User', { // Model attributes are defined here firstName: { type: DataTypes.STRING, allowNull: false }, lastName: { type: DataTypes.STRING // allowNull defaults to true } }, { // Other model options go here }); // `sequelize.define` also returns the model console.log(User === sequelize.models.User); // true init() // Invalid class User extends Model { id; // this field will shadow sequelize's getter & setter. It should be removed. otherPublicField; // this field does not shadow anything. It is fine. } User.init({ id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true } }, { sequelize }); const user = new User({ id: 1 }); user.id; // undefined 강의에서 알려주는 방식으로 DB연결도 되고 조작도 잘되지만 이렇게 질문을 남긴 이유는 강의에서는 공식문서를 따라갔다고 하는데 공식문서에서는 찾기 어렵다는 점과 강의에 나오는 방식이 시기가 지난 방법이 아닐까 하는 생각에 질문 남기게 되었습니다 제가 찾아본게 잘못된걸수도 있기에 그런점 있다면 알려주세요 글읽어주셔서 고맙습니다:)

  • node.js
  • mysql
  • mongodb
  • express
  • typescript
  • socket.io
  • jwt
진호 댓글 2 좋아요 0 조회수 500

ApolloError: request to http://mock.com/graphql failed, reason: response3.headers.all is not a function

미해결

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

33-05 강의에서 test에서 자꾸 이 오류가 뜹니다 apis.js import { graphql } from "msw"; const gql = graphql.link("http://mock.com/graphql") export const apis = [ gql.mutation("createBoard", (req, res, ctx) => { const { writer, title, contents } = req.variables.createBoardInput return res( ctx.data({ createBoard: { _id: "qqq", writer, title, contents, __typepname: "Board", }, }) ); }), // gql.query("fetchBoards", () => {}) ]; jest.setup.js import { server } from "./src/commons/mocks/index" beforeAll(() => server.listen()); afterAll(() => server.close()); index.test.tsx import { fireEvent, render, screen, waitFor } from "@testing-library/react"; import StaticRoutingMovedPage from "../../pages/section33/33-05-jest-unit-test-mocking"; import { ApolloClient, ApolloProvider, HttpLink, InMemoryCache, } from "@apollo/client"; import fetch from "cross-fetch"; import mockRouter from "next-router-mock"; jest.mock("next/router", () => require("next-router-mock")); it("게시글이 잘 등록되는지 테스트 하자!", async () => { const client = new ApolloClient({ link: new HttpLink({ uri: "http://mock.com/graphql", fetch, }), cache: new InMemoryCache(), }); render( <ApolloProvider client={client}> <StaticRoutingMovedPage /> </ApolloProvider> ); fireEvent.change(screen.getByRole("input-writer"), { target: { value: "맹구" }, }); fireEvent.change(screen.getByRole("input-title"), { target: { value: "안녕하세요" }, }); fireEvent.change(screen.getByRole("input-contents"), { target: { value: "방가방가" }, }); fireEvent.click(screen.getByRole("submit-button")); await waitFor(() => { expect(mockRouter.asPath).toEqual("/boards/qqq"); }); }); 도와주십쇼 ㅠㅠ

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

인기 태그

인프런 TOP Writers

주간 인기글