어노테이션 프로세서 활용 예와 관련해 질문 있습니다.
미해결
더 자바, 코드를 조작하는 다양한 방법
'마무리' 한 강 남았네요. 덕분에 많이 배우고 많이 성장한 것 같습니다. 그런데, 어노테이션 프로세서 활용과 관련해서,, QueryDSL 사용 시 생성되는 엔티티의 Q파일도 어노테이션 프로세서를 활용한 기술인지 궁금합니다. 짐작으로는 맡긴 한데, 관련 언급이 없었어서요.
- java
- querydsl
- jpa
- spring
172만명의 커뮤니티!! 함께 토론해봐요.
미해결
더 자바, 코드를 조작하는 다양한 방법
'마무리' 한 강 남았네요. 덕분에 많이 배우고 많이 성장한 것 같습니다. 그런데, 어노테이션 프로세서 활용과 관련해서,, QueryDSL 사용 시 생성되는 엔티티의 Q파일도 어노테이션 프로세서를 활용한 기술인지 궁금합니다. 짐작으로는 맡긴 한데, 관련 언급이 없었어서요.
해결됨
Slack 클론 코딩[실시간 채팅 with React]
Environment - Synology NAS - code-server - MySQL(mariaDB) - Node.js@latest | v18.16.0 - npm@latest | v9.5.1 - nvm@latest | v0.39.3 sequelize 사용 시, 로컬이 아닌 외부 DB에 연결하는 경우 저 같은 경우, Synology NAS로 code-server를 사용하고 있습니다. 저와 비슷한 환경에서 개발하시는 경우, 포트 설정에 애먹으시는 분 있을까봐 메모 납깁니다. db의 port를 방화벽에서 해제하기 해당 포트 포트포워딩(공유기) 참고로, phpMyAdmin이나 WorkBench에서 외부 DB에 접근이 가능한데, squelize 로 접근하면 ERROR: connect ETIMEDOUT 과 같은 메시지가 출력되는 경우가 있는데, 저는 아래 방법으로 해결할 수 있었습니다. (위 에러메시지는 host는 찾았지만 DB를 찾지 못했거나, DB가 있어도 접근할 수 없을 때 출력된다고 합니다.) { "development": { "username": "slackk", "password": process.env.DB_PASSWORD, "database": "slack-db", "host": "***.***.***.***", //IP "port": 3307, //source|target 다를 경우 별도로 지정 "dialect": "mysql" } } port 를 별도로 지정해주어야 합니다. ERROR: getaddrinfo ENOTFOUND {IP address} 메시지가 출력되는 경우 host 에 입력한 주소 문제입니다.
해결됨
실전 금융 머신러닝: 파이썬으로 구축하는 중급 투자 전략
안녕하세요 예측에 관련되서 여쭤볼게 있어서 질문 드립니다. LSTM훈련 후 Original Price와 Predicted Price의 그래프를 그리실 때 자세히 보시면 Predict price가 Original price의 데이터를 1스탭 뒤로 그려지는 것을 볼 수 있습니다. 그렇다면 이건 예측이 아니라 전 스탭에 있는 데이터를 어느정도 이동평균 또는 지수 이동평균과 같이 보정해서 쓴다고 보는게 맞지 않을까요? 이렇게 나오는 것보다 완전히 맞지 않더라도 1스탭 뒤로 예측되는 예측되는 것보다 어느정도 맞게 따라가는 방법은 없을까요?
미해결
Slack 클론 코딩[실시간 채팅 with React]
App.tsx import React, { FC } from 'react'; import loadable from '@loadable/component'; import { Switch, Route, Redirect } from 'react-router'; const Login = loadable(() => import('@pages/Login')); const SignUp = loadable(() => import('@pages/SignUp')); const Channel = loadable(() => import('@pages/Channel')); const App: FC = () => { return ( <Switch> <Redirect exact path="/" to="/login" /> <Route path="/login" component={Login} /> <Route path="/signUp" component={SignUp} /> <Route path="/workspace/channel" component={Channel} /> </Switch> ); }; export default App; Login/ index.tsx import React, { useState, useCallback } from 'react'; import useInput from '@pages/hooks/useinput'; import axios from 'axios'; import { Error, Form, Label, Input, LinkContainer, Button, Header } from '@pages/SignUp/styles'; import { Link, Redirect } from 'react-router-dom'; import useSWR from 'swr'; import fetcher from '@utils/fetcher'; const Login = () => { const { data, error, revalidate } = useSWR('http://localhost:3095/api/users', fetcher); //주소를 fetcher로 옮겨주고 실제로 주소를 어떻게 처리할지 정해줌 const [logInError, setLogInError] = useState(false); const [email, onChangeEmail] = useInput(''); const [password, onChangePassword] = useInput(''); const onSubmit = useCallback( (e) => { e.preventDefault(); setLogInError(false); axios .post( 'http://localhost:3095/api/users/login', { email, password }, { withCredentials: true, }, ) .then(() => { revalidate(); }) .catch((error) => { setLogInError(error.response?.data?.statusCode === 401); }); }, [email, password], ); if (data) { return <Redirect to="/workspace/channel" />; } Channel / index.tsx import Workspace from '@layouts/Workspace'; import React from 'react'; const Channel = () => { return ( <Workspace> <div>로그인을 축하합니다.</div> </Workspace> ); }; export default Channel; Workspace.tsx import React, { FC, useCallback } from 'react'; import useSWR from 'swr'; import fetcher from '@utils/fetcher'; import axios from 'axios'; import { Redirect } from 'react-router'; const Workspace: FC = ({ children }) => { const { data, error, revalidate } = useSWR('http://localhost:3095/api/users', fetcher); const onLogout = useCallback(() => { axios .post('http://localhost:3095/api/users/logout', null, { withCredentials: true, }) .then(() => { revalidate(); }); }, []); if (!data) { return <Redirect to="/login" />; } return ( <div> <button onClick={onLogout}>로그아웃</button> {children} </div> ); }; export default Workspace; 현재 코드에서 로그인 성공까지 되는데 페이지 이동이 없습니다... 하나하나 빠짐없이 확인 해봤는데 제가 찾지 못하는거 같습니다 ㅠㅠ 더군다나 URl 주소를 다이렉트로 localhost:3090/workspace/channel 입력해도 아무런 창이 뜨지 않고 있어서 어떤 문제가 있는지 확인이 어렵습니다.. 도움을 부탁드려요
해결됨
Slack 클론 코딩[실시간 채팅 with React]
만약에 닉네임을 name[react](23) 라고 지었고, id가 20이라면 data.content는 @[name[react](23)](20) 이런식으로 되잖아요. 그런데 거기서 코드에 있는 정규표현식을 쓰면 match는 ](1) 부분을 빼먹게 되고 그 상태에서 arr을 구하면 닉네임이 name[react 으로, id는 1이 아닌23으로 출력되더라고요. 실제로 예시와 똑같이 회원가입 하고 name[react](23)에게 멘션 해보니 클릭했을 때 초깃값으로 파란줄이 name[react 까지만 생성되고 추가로 ](20) 이란 텍스트가 더해지더라고요. (참고로 name[react](23)의 ID가 20입니다.)물론 Link로 넘어가는 것도 안되고요. 그래서 +? 말고 그냥 +로 해보니깐 위처럼 잘 매칭 되는 것 같아서 코드에 적용시켰더니 이제 Link부분은 잘 나오는데 멘션 클릭시 초깃값이 여전히 이상하게 나옵니다. 저 부분은 어딜 고쳐야 되는 건가요?
미해결
실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
지연 로딩을 사용하면 그 객체를 사용할 때 프록시 객체에서 영속성 컨텍스트에 연결을 요청해서 진짜 객체를 가져오는 거로 알고 있는데요 이번에는 단순히 Order만 Return 했기 때문에 Order객체 안에 있는 프록시 객체(Member, Delivery, OrderItems)는 사용할 일이 없는 것 아닌가요 ? 왜 프록시 객체를 사용하려다 문제가 발생했는지 알 수 있을까요?
미해결
실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예 [질문 내용] 강사님과 코드를 똑같이 작성했는데 distinct를 사용하기 전에도 데이터 뻥튀기 없이 올바르게 데이터가 나옵니다. 제가 어떤 부분을 잘못한 건지 궁금합니다.
미해결
실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
@PutMapping("/api/v2/members/{id}") public UpdateMemberResponse updateMemberV2( @PathVariable("id") Long id, @RequestBody @Valid UpdateMemberRequest request) { memberService.update(id, request.getName()); return new UpdateMemberResponse(id, request.getName()); } 파라미터로 들어온 값으로 UpdateMemberResponse를 만들어주지 않고 memberService.findOne을 통해 하는 이유가 있을까요?
해결됨
Slack 클론 코딩[실시간 채팅 with React]
웹 소켓쓸 때 폴링방식으로 쓰면 http갔다가 웹 소켓으로 전환되기 때문에 CORS문제가 발생한다고 했는데 http요청을 한다 한들 저희는 이미 proxy를 설정한 상태인데 왜 cors문제가 발생하는 건가요?
해결됨
Slack 클론 코딩[실시간 채팅 with React]
다시 시도해보고 질문하겠습니다.
해결됨
실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 안녕하세요. 김영한님 JPA강의를 모두 듣고 개인프로젝트를 하던 중에 궁금한 점이 생겨서 질문 올리게 되었습니다. 김영한님께서 데이터의 업데이트는 변경감지를 통해서 하는 것이 좋다고 말씀하셨던 게 기억이 나는데요. 물론 변경감지만을 이용하라는 말씀은 아니시겠지만 변경감지를 통한 업데이트를 어디까지 사용해야 하는 가에 대해서 좀 의문이 생겼습니다. 예를 들어 이런 경우입니다. 회원이 게시판을 조회하면 조회수를 조회수를 증가시키는 로직인데요. (조회수 증가와 게시판 조회를 서로 다른 트랜잭션으로 했음) 이럴 때에 변경감지를 통해서 조회수를 증가시킬 경우에 변경감지를 통해 변경된 값이 그대로 update되는 형태를 취하는 것인데, 이럴 경우 요청이 한 번에 많이 들오면 update순서가 보장되지 않아 정확한 조회수 증가가 이뤄지지 않을 것 같았습니다. 하지만 그렇다고 LOCK을 걸자니 조회수 하나 때문에 게시판 조회까지 LOCK이 걸려 조회 속도를 낮추는 것도 문제인 듯 하였습니다. 생각해 보면 이러한 조회수 증가는 쿼리를 UPDATE .. SET column = column +1 이런 식으로 만들고 처리하면 현재 컬럼의 값을 기준으로 1씩 증가하기 때문에 LOCK을 걸 필요도 없고 순서에 상관없이 일관된 값이 보장될 것 같은데 변경감지를 통해 값을 업데이트 하는 방식을 사용하면 현재 조회된 Entity의 조회수 값에 1을 추가하고 그 값으로 직접 UPDATE되는 형태라서 문제가 된 것이 아닐까 싶었습니다. 이런 경우 UPDATE쿼리를 따로 날려 주는 방식이 더 효율적인 방식이 맞을까요? 실무에서는 어떤 방식을 취하고 있는 지 궁금합니다..!
미해결
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
@PostMapping("/members/new") public String create(@Valid @ModelAttribute MemberForm form, BindingResult result) { if (result.hasErrors()) { return "members/createMemberForm"; } Address address = new Address(form.getCity(), form.getStreet(), form.getZipcode()); Member member = new Member(); member.setName(form.getName()); member.setAddress(address); memberService.join(member); return "redirect:/"; } @GetMapping("/members/new") public String createForm(Model model) { return "members/createMemberForm"; } 이런식으로 @ModelAttribute를 사용하여 코드를 짜보려고 하니 에러가 나왔고, 아마 html에서 memberForm 객체가 없어서 이용하지 못했고, 결국 매핑에 문제가 생겨 출력(?)을 하지 못해서 그런 것 같은데 예전 스프링 MVC강의에서는 @ModelAttriute를 이용해 코드를 잘 작성했던 거 같은데 왜 이번 강의에서는 사용하지 않았는지 궁금합니다. @PostMapping("/members/new") public String create(@Valid MemberForm form, BindingResult result) { MemberForm이 어떻게 파라미터로 받을 수 있는지 궁금합니다. (이미 Model에 객체가 있으면 파라미터로 받듯이 받을 수 있는 건지?) 위의 코드를 이용해서 웹페이지를 만드려면 createMemberForm.html 에서 <form role="form" action="/members/new" th:object="${memberForm}" method="post"> 이부분 대신 html 파라미터를 넘겨주는 식으로 고쳐야하는 것 일까요? html을 잘 몰라 질문드립니다.
해결됨
Slack 클론 코딩[실시간 채팅 with React]
정보를 입력 후 회원가입 버튼을 클릭하면 콘솔창에 제로초님 화면처럼 정보들이 나열되지않습니다! -백 콘솔창 Executing (default): SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'ChannelMembers' AND TABLE_SCHEMA = 'sleact' Executing (default): SHOW INDEX FROM ChannelMembers FROM sleact DB 연결 성공 GET /api/users 304 24.697 ms - - GET /api/users 200 4.038 ms - 5 GET /api/users 304 2.241 ms - - GET /api/users 304 3.459 ms - - GET /api/users 304 2.637 ms - - GET /api/users 304 2.528 ms - - -회원가입 index import useInput from '@hooks/useInput'; import { Header, Form, Label, Input,Error, Success, LinkContainer, Button } from "./style"; import fetcher from '@utils/fetcher'; import axios from 'axios'; import React, { useCallback, useState } from "react"; import { Redirect } from "react-router-dom"; import useSWR from 'swr'; const Signup = () => { const [email, setEmail] = useState(''); const [nickname, setNickname] = useState(''); const [password, setPassword] = useState(''); const [passwordCheck, setPasswordCheck] = useState(''); const {data: userData} = useSWR('/api/users', fetcher); const [signupError, setSignUpError] = useState(false); const [signUpSuccess, setSignUpSuccess] = useState(false); const [mismatchError, setMismatchError] = useState(false); const onChangeEmail = useCallback ( (e) => { setEmail(e.target.value); }, []); const onChangeNickname = useCallback ( (e) => { setNickname(e.target.value); }, []); const onChangePassword = useCallback ( (e) => { setPassword(e.target.value); setMismatchError(passwordCheck !== e.target.value); }, [passwordCheck, setPassword], ); const onChangePasswordCheck = useCallback( (e) => { setPasswordCheck(e.target.value); setMismatchError(password !== e.target.value); }, [password, setPasswordCheck], ); const onSubmit = useCallback( (e) => { e.preventDefault(); if(!nickname || nickname.trim()) { return; } if(! mismatchError) { setSignUpError(false); setSignUpSuccess(false); axios .post('/api/users', {email, nickname, password }) .then(() => { setSignUpSuccess(true); }) .catch((error) => { console.log(error.response?.data); setSignUpError(error.response?.data?.code ===403); }); } }, [email, nickname, password, mismatchError], ); if (userData) { return <Redirect to ="/workspace/sleact"/>; } return ( <div id="container"> <Header>Sleact</Header> <Form onSubmit={onSubmit}> <Label id="email-label"> <span>이메일 주소</span> <div> <Input type="email" id="email" name="email" value={email} onChange={onChangeEmail}/> </div> </Label> <Label id="nickname-label"> <span>닉네임</span> <div> <Input type="text" id="nickname" name="nickname" value={nickname} onChange={onChangeNickname}/> </div> </Label> <Label id="password-label"> <span>비밀번호</span> <div> <Input type="password" id="password" name="password" value={password} onChange={onChangePassword}/> </div> </Label> <Label id="password-check-label"> <span>비밀번호 확인</span> <div> <Input type="password" id="password-check" name="password-check" value={passwordCheck} onChange={onChangePasswordCheck}/> </div> {mismatchError && <Error>비밀번호가 일치하지 않습니다.</Error>} {!nickname && <Error>닉네임을 입력해주세요</Error>} {signupError && <Error>이미 가입된 이메일입니다.</Error>} {signUpSuccess && <Success>회원 가입되었습니다! 로그인해주세요.</Success>} </Label> <Button type="submit">회원가입</Button> </Form> <LinkContainer> 이미 회원이신가요? <a href="/login">로그인 하러 가기</a> </LinkContainer> </div> ); }; export default Signup; -개발자도구 콘솔창 -개발자도구 네트워크 요청 URL: http://localhost:3090/api/users 요청 메서드: GET 상태 코드: 304 Not Modified 원격 주소: [::1]:3090 리퍼러 정책: strict-origin-when-cross-origin 응답 헤더소스 보기 access-control-allow-credentials: true connection: close date: Wed, 26 Apr 2023 05:29:10 GMT etag: W/"5-fLbvuYullyqbUJDcLlF/4U0SywQ" vary: Origin x-powered-by: Express 요청 헤더소스 보기 Accept: application/json, text/plain, / Accept-Encoding: gzip, deflate, br Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7 Connection: keep-alive Host: localhost:3090 If-None-Match: W/"5-fLbvuYullyqbUJDcLlF/4U0SywQ" Referer: http://localhost:3090/signup sec-ch-ua: "Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "Windows" Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-origin User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36
미해결
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
ItemService에서는 ItemRepository의 기능을 위임받아 저장 및 검색 기능을 구현했는데 OrderService에서는 검색기능을 구현하지 않았더라구요. ItemService에서 위임 받는 것 처럼 하면 간단할 것 같은데 굳이 만들지 않고 OrderRepository의 findOne기능을 사용하는 이유가 따로 있는 것일까요?
미해결
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
main/resources/application.yml 을 따라가게 되는 건가요 ? 자바에서는 디비를 사용하고 싶고, test에서만 메모리 DB를 사용하고 싶다면 아무런 내용이 없는 application.yml를 test/resources 아래 생성만 하면 되는 건가요 ?
미해결
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
//==연관관계 메서드==// 가 주석으로 달린 메서드들이 연관관계에 있는 객체에 값을 넣어줄 때 반대편에도 자동으로 값을 넣어주는 역할을 하는 메서드가 맞나요? 이렇게 따로 메서드를 구현해주는 이유가 있나요? CASCADE 옵션을 사용하면 어차피 알아서 다 해주지 않나요 ?? 기본편에서 설명해주셨다고 했는데 어떤 강의를 다시 수강해보면 될까요 ? 지연로딩에서 ***ToMany의 디폴트는 Lazy고, ***ToOne의 디폴트는 Eager인 이유가 ***ToMany같은 경우 하나만 불러와도 기본적으로 수많은 값이 따라오기 때문에 스프링 측에서 Lazy로 해놓았고, (Member의 Order을 조회하면 수많은 Order이 자동으로 따라오기 때문에 디폴트가 Lazy) ***ToOne의 경우 객체 하나만 조회하면 쿼리문을 하나밖에 더 날리지 않기 때문에 Eager로 해놓았지만, 실무에서는 테이블 전체를 조회할 때가 있기 때문에 디폴트값인 Eager를 쓰지 않고 Lazy를 사용한다 이게 맞을까요? (Order하나만 조회하면 Member 1개만 따라오기때문에 디폴트가 Eager지만, select o from Order o 와 같은 쿼리문으로 Order를 전체 조회했을 때는 Order에 따른 멤버가 전부 따라오므로 그냥 Lazy 옵션을 준다) 이렇게 이해했는데 맞을까요?
미해결
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
기본편에서 관계에 따른 연관관계 설정하는 방법은 공부했는데, 위와 같은 기능 목록을 보고 기능목록을 보고 위와 같이 어떤 도메인을 써야 할지, 도메인끼리 1:N인지, N:N인지, 1:1인지 단방향인지, 양방향인지(실무에서는 N:N과 양방향은 지양하라고 하셨지만) 등 도메인 모델과 테이블 설계가 어렵다면 무엇을 참고하는 것이 좋을까요 ? ( 영한님이 분석해 놓은 회원 엔티티와 회원 테이블을 보고 코드를 작성할 순 있는데 스스로 회원 엔티티와 테이블을 분석하기가 너무 어렵습니다.) Category 클래스 안에서 스스로 일대다 관계를 맺고 있는데 이것은 무엇을 위해 만든건가요 ?
미해결
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
카테고리 : 과일, 빨강, 노랑 // 아이템 : 사과, 배, 체리 이렇게 존재할 때 ================== 과일 -> 사과 배 체리 빨강 -> 사과 체리 노랑 -> 배 ================== 사과 -> 과일 빨강 배 -> 과일 노랑 체리 -> 과일 빨강 ================== 사과(아이템)같은 경우 과일과 빨강이라는 카테고리에 속해있고, 과일(카테고리)같은 경우 사과 배 체리라는 아이템이 속해있기 때문에 다대다 관계가 맞나요?
미해결
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
@GetMapping("/") public String index() { return "index"; } 이런 소스 없이 자동으로 localhost:8080 들어가면 Index.html로 연결되는 이유가 무엇일까요?
해결됨
Slack 클론 코딩[실시간 채팅 with React]
const onCreateWorkspace = useCallback( (e: any) => { e.preventDefault(); if (!newWorkspace || !newWorkspace.trim()) return; // trim : 앞 뒤 공백제거 if (!newUrl || !newUrl.trim()) return; axios .post( 'http://localhost:3095/api/workspaces', { Workspace: newWorkspace, url: newUrl, }, { withCredentials: true }, ) .then(() => { mutate(userData, true); setShowCreateWorkspaceModal(false); setNewWorkspace(''); setNewUrl(''); }) .catch((error) => { console.dir(error); toast.error(error.response?.data, { position: 'bottom-center' }); }); }, [newWorkspace, newUrl], ); 뭐가 문제인건가요?