inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

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

error처리 질문드립니다

미해결

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

error처리 질문드립니다. 현재 라우터에는 /about1234는 없습니다. http://localhost:5000/about12344 여기입력해서 들어가면 강의처럼 err로 가서 asdasd가 나와야하는걸로 이해하고있습니다. 이렇게 나옵니다. asdasd가 나와야하는거 같은데 뭐가 잘못된건지 잘모르겠습니다.

  • node.js
  • mysql
  • mongodb
  • express
  • typescript
  • socket.io
  • jwt
밈몀묘 댓글 1 좋아요 0 조회수 435

multer를 사용해서 이미지 업로드할때 db(mysql)에 질문있습니다

미해결

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

uuid를 통해서 file의 원본이름을 변경해서 mysql의 image컬럼에 아래처럼 저장하고있습니다. \images\042c8bb1-e0fd-4005-85e9-68d7c587c02d.png 홈페이지를 접속하면(로그인 안되면 로그인 페이지로 이동) 로그인했을때만(jwt 토큰을 발행해서 cookie에 보내주고) 홈페이지를 접속가능하게 하였습니다. 홈페이지로 이동하면 이미지들을 볼수있도록 했습니다. 근데 이미지주소 복사하면 로그아웃해도 해당이미지가 나옵니다. 제가 하고자는건 로그인했을때만 이미지보여주고 해당 이미지주소입력하면(로그인 안됐을때) 이미지가 안보이도록 하고싶은데 어떻게 해야할까요? db에 image컬럼에 원본이름만 저장하고 다른폴더에 이미지를 저장하고 db 인덱싱을통해서 이미지를 가져와서 이미지를 보여주도록 할려면 어떻게 해야할까요?(db인덱싱을통해(원본이름) 다른폴더에있는 해당이미지 가져오도록 하려면 어떻게해야할지 잘 모르겠습니다). 하나의 게시글에 다중이미지를 업로드하면 다중이미지를 보여주게 할려면 어떻게해야할까요? 현재는 db에 넣으면 num에(ai를통해서) 예를 들어 3장을 업로드하면 num이 1,2,3으로 생성되어서 이미지 경로도 각각 저장되고 홈페이지에서 하나하나씩 보입니다. 그럼 db에 저장을 어떻게해야하나요? 사진을보면 밀리미터까지 똑같이 저장이 되는데 하나의 구분에 다중이미지의 주소를 넣을려면 어떻게해야할지요?... 이렇게해놔도 여기로 들어오지도 않고 바로 이미지주소로 검색하면 바로 이미지가 나옵니다. 초보자라서 자세히 설명해주시면 감사하겠습니다.

  • node.js
  • mysql
  • mongodb
  • express
  • typescript
  • socket.io
  • jwt
밈몀묘 댓글 1 좋아요 0 조회수 479

DMList 선택 시 무한로딩되는 에러

미해결

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

안녕하세요 제로초님. 강의 잘 듣고 있습니다. 다름이 아니라 채널 토글에서 각 채널을 선택하면 정상적으로 이동하지만, DMlist에서 선택하면 아래와 같이 useEffect가 무한루프처럼 호출되어 문제가 발생하는 것 같습니다. 제로초님께서 업로드해주신 코드와 동일하게 def에 workspace를 넣어 작성했는데, 어떠한 부분에서 위와 같이 무한로딩되는 에러가 발생하는지 못 찾겠습니다ㅠㅠ DMList/index.tsx // import useSocket from '@hooks/useSocket'; import { CollapseButton } from '@components/DMList/style'; import { IDM, IUser, IUserWithOnline } from '@typings/db'; import fetcher from '@utils/fetcher'; import React, { FC, useCallback, useEffect, useState } from 'react'; import { useParams } from 'react-router'; import { NavLink } from 'react-router-dom'; import useSWR from 'swr'; const DMList: FC = () => { const { workspace } = useParams<{ workspace?: string }>(); const { data: userData, error, mutate } = useSWR<IUser>('/api/users', fetcher, { dedupingInterval: 2000, // 2초 }); const { data: memberData } = useSWR<IUserWithOnline[]>( userData ? `/api/workspaces/${workspace}/members` : null, fetcher, ); // const [socket] = useSocket(workspace); const [channelCollapse, setChannelCollapse] = useState(false); const [countList, setCountList] = useState<{ [key:string]: number}>({}); const [onlineList, setOnlineList] = useState<number[]>([]); const toggleChannelCollapse = useCallback(() => { setChannelCollapse((prev) => !prev); }, []); const resetCount = useCallback( (id) => () => { setCountList((list) => { return{ ...list, [id]: 0, }; }); }, [], ); const onMessage = (data: IDM) => { console.log("DM 왓따", data); setCountList((list) => { return { ...list, [data.SenderId] : list[data.SenderId] ? list[data.SenderId]+1 : 1, }; }); }; useEffect(() => { console.log('DMList: workspace 바꼈다', workspace); setOnlineList([]); setCountList({}); }, [workspace]); // useEffect(() => { // socket?.on('onlineList', (data: number[]) => { // setOnlineList(data); // }); // socket?.on('dm', onMessage); // console.log('socket on dm', socket?.hasListeners('dm'), socket); // return () => { // socket?.off('dm', onMessage); // console.log('socket off dm', socket?.hasListeners('dm')); // socket?.off('onlineList'); // }; // }, [socket]); return ( <> <h2> <CollapseButton collapse={channelCollapse} onClick={toggleChannelCollapse}> <i className="c-icon p-channel_sidebar__section_heading_expand c-icon--caret-right c-icon--inherit c-icon--inline" data-qa="channel-section-collapse" aria-hidden="true" /> </CollapseButton> <span>Direct Messages</span> </h2> <div> {!channelCollapse && memberData?.map((member) => { const isOnline = onlineList.includes(member.id); return ( <NavLink key={member.id} activeClassName="selected" to={`/workspace/${workspace}/dm/${member.id}`} > <i className={`c-icon p-channel_sidebar__presence_icon p-channel_sidebar__presence_icon--dim_enabled p-channel_sidebar__presence_icon--on-avatar c-presence ${ isOnline ? 'c-presence--active c-icon--presence-online' : 'c-icon--presence-offline' }`} aria-hidden="true" data-qa="presence_indicator" data-qa-presence-self="false" data-qa-presence-active="false" data-qa-presence-dnd="false" /> <span>{member.nickname}</span> {member.id === userData?.id && <span> (나)</span>} </NavLink> ); })} </div> </> ); }; export default DMList;

  • react
  • 웹팩
  • typescript
  • socket.io
  • babel
  • 클론코딩
김호준 댓글 1 좋아요 0 조회수 446

isEqualByComparingTo를 사용하는 이유가 궁금합니다.

미해결

Practical Testing: 실용적인 테스트 가이드

안녕하세요 강의를 듣다가 궁금증이 생겨서 질문을 드립니다. void init() { // given List<Product> products = List.of( createProduct("001", 1000), createProduct("002", 2000) ); // when Order order = Order.create(products, LocalDateTime.now()); // then assertThat(order.getOrderStatus()).isEqualByComparingTo(OrderStatus.INIT); } 강의에서 OrderTest 클래스 테스트 과정에서 enum을 비교할때 isEqualByComparingTo를 사용하셨습니다. assertThat(order.getOrderStatus()).isEqualTo(OrderStatus.INIT); 위와 같이 isEqualTo를 사용해도 enum을 비교할 수 있는데, 혹시 isEqualTo 대신 isEqualByComparingTo를 사용한 이유를 알 수 있을까요? isEqualByComparing가 정의된 AbstractComparableAssert.java를 확인해보면 BigDecimal을 예시로 들어서 사용법을 설명하고 있습니다. BigDecimal의 예시로 Enum을 써야 하는 방법을 생각해보았는데, 유추(?)가 잘 되지 않아서 질문을 남깁니다. 항상 좋은 강의 제공해주셔서 감사합니다!!😀😀

  • 소프트웨어-테스트
  • junit5
  • java
amenable 댓글 2 좋아요 1 조회수 847

api 질문입니다.

해결됨

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

포토폴리오 마이페이지 - 내포인트 부분을 작업하는 도중 api 질문입니다. fetchPointTransactionsOfBuying 이 내포인트 -> 구매내역 api로 알고있습니다. 피그마를 보면 거기서 판매자 데이터를 가져오고있는데 오류가 뜨네요.ㅠ 판매자 데이터를 가져오고 싶은데 여기서 seller {name} 이부분을 넣으면 데이터가 안가져오네요.. 판매자데이터가 없어서 그런건지 왜 그런지와 어떻게 해야하는지 두가지 모두 알고싶습니다.

  • react
  • node.js
  • seo
  • graphql
  • next.js
임프런 댓글 2 좋아요 0 조회수 381

로그인 화면에서 리다이렉트 시 workspace 목록이 표시되지 않는 문제

미해결

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

안녕하세요. 강의 잘 듣고 있습니다. 다름이 아니라 login 한 후 workspace로 리다이렉트 된 후, workspace 목록이 아래와 같이 나타나지 않는 현상이 발생합니다. 하지만 다른 탭을 다녀오거나, workspace 추가를 하면 다시 정상적으로 아래와 같이 workspace 목록이 나타납니다. 아마 userData를 리다이렉트하면서 불러오지 않아 생기는 문제 같습니다. mutate()를 사용하고, dedupinginterval을 줄여도 문제 해결이 안되는 것 같아 리다이렉트됨과 동시에 다시 userData를 불러오도록 수정해야 할 것 같은데, 이를 구현할 수 있는 방법이 생각이 나지 않습니다. 현재 제 코드 일부 아래에 첨부합니다. App.js const App: FC = () => { return ( <Switch> <Redirect exact path="/" to="/login" /> <Route path="/login" component={LogIn} /> <Route path="/signup" component={SignUp} /> <Route path="/workspace/:workspace" component={Workspace} /> </Switch> ); }; Login/index.tsx const LogIn = () => { const {data, error, mutate} = useSWR('/api/users', fetcher, { dedupingInterval: 100000, }); const [logInError, setLogInError] = useState(false); const [email, onChangeEmail] = useInput(''); const [password, onChangePassword] = useInput(''); const onSubmit = useCallback( (e) => { e.preventDefault(); setLogInError(false); axios .post( '/api/users/login', { email, password }, { withCredentials: true }, ) .then((response) => { mutate(response.data, false); //Optimistic UI }) .catch((error) => { setLogInError(error.response?.status === 401); }); }, [email, password], ); if (data === undefined) { return <div>로딩중...</div>; } if (data) { return <Redirect to="/workspace/sleact/channel/일반" />; } Workspace/index.tsx import Menu from "@components/Menu"; import Modal from "@components/Modal"; import CreateChannelModal from "@components/CreateChannelModal"; import useInput from "@hooks/useinput"; import fetcher from "@utils/fetcher"; import axios from "axios"; import React, { FunctionComponent, useCallback, useState } from "react" import { Link, Redirect, Route, Switch, useParams } from 'react-router-dom'; import { toast } from 'react-toastify'; import useSWR from "swr"; import { AddButton, Channels, Chats, Header, LogOutButton, MenuScroll, ProfileImg, ProfileModal, RightMenu, WorkspaceButton, WorkspaceModal, WorkspaceName, WorkspaceWrapper, Workspaces } from "@layouts/Workspace/style"; import gravatar from 'gravatar'; import { Button, Input, Label } from '@pages/SignUp/style'; import { IChannel, IUser } from "@typings/db"; import loadable from "@loadable/component"; const Channel = loadable(() => import('@pages/SignUp')); const DirectMessage = loadable(() => import('@layouts/Workspace')); const Workspace: FunctionComponent = () => { const [showUserMenu, setShowUserMenu] = useState(false); const [showCreateWorkspaceModal, setShowCreateWorkspaceModal] = useState(false); const [showWorkspaceModal, setShowWorkspaceModal] = useState(false); const [showCreateChannelModal, setShowCreateChannelModal] = useState(false); const [newWorkspace,onChangeNewWorkspace, setNewWorkSpace] = useInput(''); const [newUrl, onChangeNewUrl, setNewUrl] = useInput(''); const { workspace } = useParams<{workspace: string}>(); const { data: userData , error, mutate} = useSWR<IUser | false>( '/api/users', fetcher, { dedupingInterval: 2000, } ); const { data: channelData } = useSWR<IChannel[]>( userData? `api/workspaces/${workspace}/channels` : null, fetcher ); const onLogout = useCallback(() => { axios .post('/api/users/logout', null, { withCredentials: true, }) .then(() => { mutate(false, false); }); }, []) const onClickUserProfile = useCallback((e) => { e.stopPropagation(); setShowUserMenu((prev) => !prev); }, []); const onClickCreateWorkSpace = useCallback(() => { setShowCreateWorkspaceModal(true); }, []); const onCreateWorkspace = useCallback((e) => { e.preventDefault(); if(!newWorkspace || !newWorkspace.trim()) return; if(!newUrl || !newUrl.trim()) return; axios .post( '/api/workspaces', { workspace: newWorkspace, url : newUrl, }, { withCredentials: true, }) .then(() => { mutate(); setShowCreateWorkspaceModal(false); setNewWorkSpace(''); setNewUrl(''); }) .catch((error)=>{ console.dir(error); toast.error(error.response?.data, { position: 'bottom-center' }); }); }, [newWorkspace, newUrl]); const onCloseModal = useCallback(() => { setShowCreateWorkspaceModal(false); setShowCreateChannelModal(false); }, []); if(!userData) { return <Redirect to="/login"/> } const toggleWorkspaceModal = useCallback(()=> { setShowWorkspaceModal((prev) => !(prev)); },[]); const onClickAddChannel = useCallback(() => { setShowCreateChannelModal(true); }, []); return ( <div> <Header> <RightMenu> <span onClick = {onClickUserProfile}> <ProfileImg src = {gravatar.url(userData.email, {s: '28px', d: 'retro'})} alt= {userData.nickname}/> {showUserMenu && ( <Menu style={{right:0, top:38}} show={showUserMenu} onCloseModal={onClickUserProfile}> <ProfileModal> <img src={gravatar.url(userData.email, {s: '36px', d: 'retro'})} alt= {userData.nickname}/> <div> <span id="profile-name">{userData.nickname}</span> <span id="profile-active">Active</span> </div> </ProfileModal> <LogOutButton onClick={onLogout}>로그아웃</LogOutButton> </Menu> )} </span> </RightMenu> </Header> <WorkspaceWrapper> <Workspaces> {userData?.Workspaces?.map((ws) => { return ( <Link key={ws.id} to={'/workspace/${123}/channel/일반'}> <WorkspaceButton>{ws.name.slice(0,1).toUpperCase()}</WorkspaceButton> </Link> ); })} <AddButton onClick={onClickCreateWorkSpace}>+</AddButton> </Workspaces> <Channels> <WorkspaceName onClick={toggleWorkspaceModal}> Sleact </WorkspaceName> <MenuScroll> <Menu show={showWorkspaceModal} onCloseModal={toggleWorkspaceModal} style={{ top: 95, left: 80}}> <WorkspaceModal> <h2>Sleact</h2> <button onClick={onClickAddChannel}>채널 만들기</button> <button onClick={onLogout}>로그아웃</button> </WorkspaceModal> </Menu> {channelData?.map((v) => (<div>{v.name}</div>))} </MenuScroll> </Channels> <Chats> <Switch> <Route path="/workspace/:workspace/channel/:channel" component={Channel} /> <Route path="/workspace/:workspace/dm/:id" component={DirectMessage} /> </Switch> </Chats> </WorkspaceWrapper> <Modal show={showCreateWorkspaceModal} onCloseModal={onCloseModal}> <form onSubmit={onCreateWorkspace}> <Label id="workspace-label"> <span>워크스페이스 이름</span> <Input id="workspace" value={newWorkspace} onChange={onChangeNewWorkspace}/> </Label> <Label id="workspace-url-label"> <span>워크스페이스 url</span> <Input id="workspace-url" value={newUrl} onChange={onChangeNewUrl}/> </Label> <Button type="submit">생성하기</Button> </form> </Modal> <CreateChannelModal show={showCreateChannelModal} onCloseModal={onCloseModal} setShowCreateChannelModal={setShowCreateChannelModal} /> </div> ) } export default Workspace

  • react
  • 웹팩
  • typescript
  • socket.io
  • babel
  • 클론코딩
김호준 댓글 1 좋아요 0 조회수 733

ejs, cjs 둘 중 무엇으로 코딩해야하나요?

미해결

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

ejs와 cjs 둘 중 express 프레임워크를 사용해서 프로그래밍을 하려면 어떤 방식을 추천하시나요?

  • node.js
  • mysql
  • mongodb
  • express
  • typescript
  • socket.io
  • jwt
박동규 댓글 1 좋아요 0 조회수 542

발급가능 쿠폰개수가 1인당 2개이상일 때

미해결

실습으로 배우는 선착순 이벤트 시스템

안녕하세요! 강의 재미있고 유익하게 잘 듣고 있습니다 :) 확장에 대해 생각해보니, Set을 이용해서는 중복방지 이상 개수 확장에 대해서 처리는 불가능 할 거 같아서요. 혹시, 2개 이상 N개 제한에 대한 확장 방법은 어떤게 있을까요?? 감사합니다!

  • java
  • docker
  • spring-boot
  • kafka
  • redis
Reid 댓글 2 좋아요 2 조회수 935

강의 초기 셋팅 문제

미해결

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

react를 처음 접해보는 취준생입니다. 제가 강의를 보면서 따라하려는데 settings/js 디렉토리의 디렉토리명을 front로 변경해서 사용하고 back 디렉토리에서 npm start로 백앤드 서버 실행시키고 따라하라고 하신거 같아서 그렇게 따라하고 있습니다. 현재 localhost :3095로 접근하면 슬리액 페이지가 잘 나오는데 front 디렉토리에서 코드 수정해도 반영이 안고 있는데 혹시 어떤걸 잘 못 하고 있는지 알 수 있을까요?

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

orderItems 에 null이 들어가는 이유가 궁금합니다.

해결됨

실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 강의를 듣다 의문점이 생겨 질문 드립니다. OrderDto는 JPA에서 생성된 객체가 아니고 직접 생성자로 만들어서 사용한 객체인데 왜 Hibernate5Module이 프록시 객체로 생각해서 null값을 반환하는지 모르겠습니다. 제가 긴시간 찾아보면서 생각한 이유는 이렇습니다. 강의 5분경 쯤에 api 호출시 Json에서 orderItems 가 null로 반환되는것을 보여주십니다. orderItems가 null로 반환되는것은 스프링이 string으로 응답을 보낼때 messageConverter가 json으로 변환해서 반환을합니다. 이때 orderItems가 JPA(Hibernate)에서 만든 프록시 객체로 되어있어 전강의에서 설정한 Hibernate5Module이 프록시 객체를 null로 바꾸기 때문에 orderItems가 null로 나타낸것으로 생각됩니다. 하지만 제가 디버깅 모드로 확인해본 결과 OrderDto안에 있는 orderItems는 프록시 객체가 아닌 실제로 생성된 객체였습니다.(OrderDto는 단순히 JPA가 관리 하지 않아서 당연하다고 생각합니다.) 강의 기준으로 orderItems 안에 있는 orderItem객체가 2개 존재하는데 orderItem객체는 JPA를 통해 생성된 객체이고 자세히 살펴보면 orderItem 안에 Item은 LAZY로딩으로 프록시 객체가 생성되어있습니다. 혹시몰라 Hibernate5Module을 끄고 실행한 결과 Item이 @JsonIgnore가 있으면 orderItems가 제대로 결과 값이 나오고 @JsonIgnore이 없으면 프록시 객체를 Json으로 변환하지 못해서 오류가 발생합니다. 그럼 Hibernate5Module는 엔티티 안에 객체의 값중 하나라도 프록시 객체가 있다면 다른 객체의 값이 있든 말든 그냥 null을 반환하는 걸까요?? 제가 이해한것이 맞는지 궁금해서 질문드립니다. 긴글 읽어주셔서 감사합니다.

  • java
  • spring
  • spring-boot
  • jpa
이찬원 댓글 3 좋아요 1 조회수 1111

요청을 확인할 수 있는 방법이 있을까요??

해결됨

스프링 시큐리티

안녕하세요 선생님 좋은강의 정말 감사드립니다! 선생님 혹시 사용자의 어떤 request에 의해서 CustomAccessDeniedHandler 여기로 오게 되는지 디버그를 이용해서 확인하고 싶다면 어떤 필터를 확인하면 알 수 있을까요??

  • java
  • spring-boot
  • spring-security
hong090992 댓글 1 좋아요 0 조회수 632

섹션6-주문 도메인 개발-주문 기능 테스트

미해결

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

[질문 내용] 상품주문_재고수량초과 테스트할 때 Junit5 사용해서 expected가 없습니다. import static org.junit.jupiter.api.Assertions.*; @Test public void 상품주문_재고수량초과() throws Exception { //given Member member = createMember(); Item item = createBook("시골", 10000, 10); int orderCount = 11; //when //then assertThrows(NotEnoughStockException.class, ()-> orderService.order(member.getId(), item.getId(), orderCount)); } 그래서 이렇게 작성해서 초록불은 떴는데 적절하게 작성했는지 궁금합니다. 더 좋은 예시가 있는 지 궁금합니다.

  • java
  • spring
  • 웹앱
  • spring-boot
  • jpa
댓글 1 좋아요 0 조회수 547

검증을 사용할때

미해결

자바 ORM 표준 JPA 프로그래밍 - 기본편

만약 Member에 검증이 필요하다고 하면 검증객체를 따로 클래스로 만들어서 사용하나요? 엔티티에 덧붙여서 사용하나요?

  • java
  • jpa
  • mvc2
  • validation
wxogud3377 댓글 1 좋아요 0 조회수 383

양방향 연관관계 순환참조 질문

미해결

자바 ORM 표준 JPA 프로그래밍 - 기본편

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 안녕하세요 강의 잘 듣고 있습니다. 강의를 듣다가 궁금증이 생겨 질문 드립니다. 양방향 연관관계의 설정이 언제 필요할지 생각을 해보았는데 게시글과 댓글의 일대 다 관계에서 게시글을 조회할때 댓글이 같이 조회되는것을 원하는 경우가 있을 것 같습니다. 그렇다면 이전강의에 말씀하셨던 무한 루프(?)에 빠질 수 있을 것 같은데요. 아마 이걸 순환참조라고 말한다고 알고 있습니다. 그러면 애초에 댓글은 댓글대로 따로 조회하고 게시글을 조회할때 댓글 조회하는 방식 즉 연관관계의 주인이 아닌곳에서 리스트를 조회하려고 하는 방식은 안쓰는것이 좋은것인가요?

  • java
  • jpa
// 댓글 1 좋아요 0 조회수 482

cascade 부모, 자식 동시 적용

미해결

자바 ORM 표준 JPA 프로그래밍 - 기본편

[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예 [질문 내용] 안녕하세요, cascade 설정과정에서 궁굼증이 생겨 문의드립니다. 부모 객체와 자식객체 양쪽다 CascadeType. ALL 옵션을 주고, 부모쪽에 orphanRemoval = true 옵션을 준 상태에서 Parent parent = new Parent(); Child child = new Child(); Child child2 = new Child(); parent.addChild(child); parent.addChild(child2); Team findParent = em.find(Parent.class, 1L); findParent.getChild().remove(0); 와 같이 진행 했을때, child가 삭제됨 child가 삭제되며 cascade 옵션에 의해 부모인 team을 삭제함 team을 삭제하기 전 cascade 옵션에 의해 자식에 포함된 child를 모두 삭제함 team이 삭제됨 이렇게 이해했고 실제로 parent, child, child2 모두 삭제 되었습니다. 그런데 Parent parent = new Parent(); Child child = new Child(); Child child2 = new Child(); Child child3 = new Child(); ... Child childN = new Child(); parent.addChild(child); parent.addChild(child2); parent.addChild(child3); ... parent.addChild(childN); Team findParent = em.find(Parent.class, 1L); findParent.getChild().remove(0); 이렇게 자식을 3개 이상 넣어줬을경우 자식객체 2개만 삭제(remove에 넣어주는 index에 따라 2개 삭제될 자식이 결정됨)되고 나머지 자식과 부모는 남아있는걸로 확인되는데... 어떤 매커니즘때문에 이런 현상이 나오는걸까요?..

  • java
  • jpa
문 현필 댓글 2 좋아요 0 조회수 652

코틀린 Companion object

미해결

자바 개발자를 위한 코틀린 입문(Java to Kotlin Starter Guide)

- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 안녕하세요! 선생님! 수업을 잘 듣고있는 백엔드 취준생 입니다! 자바를 공부하다가 코틀린도 공부하면 좋을꺼 같아서 같이 공부하고있는데요.. 혹시 좀더 코틀린을 딥하게 파보고 싶은데 추천하시는 사이트 혹시 있으실까요??

  • java
  • kotlin
  • 객체지향
정훈 댓글 1 좋아요 1 조회수 499

구글 앱스 스크립트는 파일로 다운이 어려운가요?

미해결

현재 구글 앱스 스크랩트를 활용해 특정한 셀의 내용을 다운받는 스크립트를 짜고 있습니다. 자꾸 작동이 되지 않아서 챗gpt에 물어보니 그러려면 자바와 연동을 하든 뭘 하든 구글 앱스 스크립트 내에서는 안된다고 하는데 이거 정말 안되는걸까요?ㅠㅠ

  • googleappsscript
  • java
ymo 댓글 1 좋아요 0 조회수 845

부하테스트중 errors.ETIMEDOUT:

해결됨

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

안녕하세요 json부하테스트중에 에러표시나서 방화벽들어가서 mysql포트 확인하고 3306설정했는데 안되서 포트80도해보고 했는데 에러표시만뜹니다 https://binshuuuu.tistory.com/m/214 제가 따라한 설정입니다

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

선생님 premium 해결했습니다

해결됨

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

선생님 콘솔로그 쳐서 premium위치 찾아서req.user.Domains [5].type === 'premium' 했는데 true 나와서 해결했습니다 감사합니다 앞으로 콘솔로그 쳐서 하는 습관가져야겠습니다 정말 감사합니다 ^_^!!!

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

왜 쿠폰수가 너무 많을까요?

미해결

실습으로 배우는 선착순 이벤트 시스템

분명 현재 없는 상태이고 결과가 자꾸 이상하게 나와서 sout 처리를 잠시 해보았습니다 package com.example.api.service; import com.example.api.domain.Coupon; import com.example.api.repository.CouponCountRepository; import com.example.api.repository.CouponRepository; import org.springframework.stereotype.Service; @Service public class ApplyService { private final CouponRepository couponRepository; private final CouponCountRepository couponCountRepository; public ApplyService(CouponRepository couponRepository, CouponCountRepository couponCountRepository) { this.couponRepository = couponRepository; this.couponCountRepository = couponCountRepository; } public void applyV1(Long userId) { Long count = couponRepository.count(); if(count > 100) { return; } couponRepository.save(new Coupon(userId)); } public void applyV2(Long userId) { Long count = couponCountRepository.increment(); System.out.println(count); if(count > 100) { return; } couponRepository.save(new Coupon(userId)); } } @SpringBootTest class ApplyServiceTest { @Autowired private ApplyService applyService; @Autowired private CouponRepository couponRepository; @Test public void applyOnce() { applyService.applyV1(1L); long count = couponRepository.count(); Assertions.assertEquals(1L, count); } @Test public void 여러명응모V1() throws InterruptedException { int threadCount = 1000; ExecutorService executorService = Executors.newFixedThreadPool(32); CountDownLatch latch = new CountDownLatch(threadCount); for(int i=0; i<threadCount; i++){ long userId = i; executorService.submit(() -> { try { applyService.applyV1(userId); } catch(Exception e) { System.out.println(e); }finally { latch.countDown(); } }); } latch.await(); long count = couponRepository.count(); assertThat(count).isEqualTo(100); } @Test public void 여러명응모V2() throws InterruptedException { int threadCount = 1000; ExecutorService executorService = Executors.newFixedThreadPool(32); CountDownLatch latch = new CountDownLatch(threadCount); for(int i=0; i<threadCount; i++){ long userId = i; executorService.submit(() -> { try { applyService.applyV2(userId); } catch(Exception e) { System.out.println(e); }finally { latch.countDown(); } }); } latch.await(); long count = couponRepository.count(); org.assertj.core.api.Assertions.assertThat(count).isEqualTo(100); } } 그런데 여러명응모V2 test를 실행시에 count를 출력시 다음과 같은 수가 나옵니다. 20003 20011 20012 20013 20015 20016 20017 20018 20020 20022 ??? 한번 할때마다 1000씩 쿠폰의 수가 증가중인데요;;; 조회했을때는 empty라 나오는데 이렇게 되는 연유를 잘 모르갰습니다. 테스트 코드라서 rollback이 되야할거 같은데 그렇지 않는것도 잘 모르겟네요;; ㅠㅠ

  • java
  • docker
  • spring-boot
  • kafka
  • redis
seonjun Moon 댓글 1 좋아요 0 조회수 648

인기 태그

인프런 TOP Writers

주간 인기글