inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

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

10.6 재질문…!

해결됨

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

exports.apiLimiter = async (req, res, next) => { let user; if (res.locals.decoded) { user = await User.findOne({ where: { id: res.locals.decoded.id } }); } rateLimit({ widowMs: 60 * 1000, max: user?.type === "premium" ? 10 : 1, handler(req, res) { res.status(this.statusCode).json({ code: this.statusCode, message: "1분에 열 번만 요청 할 수 있습니다...", }); }, })(req, res, next); }; Api 프리미엄고객만 1분에 열번만요청할수있게 미들웨어 확장패턴으로 만들었습니다 그런데 localhost:4000/myposts 접속해서 10 번이상새로고침해도 api가 제한이 안되고 제가작성한 게시글 목록만 뜹니다

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

Chap7 퀴즈

해결됨

나도코딩의 자바 기본편 - 풀코스 (20시간)

안녕하세요! 7강 마무리 퀴즈를 스스로 풀어보며 의문점이 생겨 질문 남깁니다. 저는 이런식으로 name 변수를 선언하고 cook() 메소드에 this.name을 활용했는데, 강의에선 기본 생성자와 name을 매개변수로 하는 생성자를 정의하고 풀어 주셨더라구요! 결과는 같게 나오지만 혹시 생성자를 사용하는게 더 좋은 코딩 방법인지, 제가 한 방식이 결과는 맞지만 논리적 오류가 있는지 궁금합니다. 그리고 강의 잘 듣고 있습니다. 감사합니다!

  • java
  • 객체지향
andy15948 댓글 1 좋아요 0 조회수 176

10.6 사용량 제한 질문

해결됨

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

nodebird-api 미들웨어 index.js 타입이 any로 떠서 프리미엄이 체크가 안되고 계속 제가 작성한 게시글정보만 뜹니다 사용량제한 어떻게 하나요? ㅠㅠ const jwt = require("jsonwebtoken"); const rateLimit = require("express-rate-limit"); const User = require("../models/user"); exports.isLoggedIn = (req, res, next) => { if (req.isAuthenticated()) { next(); } else { res.status(403).send("로그인 필요"); } }; exports.isNotLoggedIn = (req, res, next) => { if (!req.isAuthenticated()) { next(); } else { const message = encodeURIComponent("로그인한 상태입니다."); res.redirect(`/?error=${message}`); } }; exports.verifyToken = (req, res, next) => { try { res.locals.decoded = jwt.verify( req.headers.authorization, process.env.JWT_SECRET ); return next(); } catch (error) { if (error.name === "TokenExpiredError") { return res.status(419).json({ code: 419, message: "토큰이 만료되었습니다.", }); } return res.status(401).json({ code: 401, message: "유효하지 않은 토큰입니다.", }); } }; exports.apiLimiter = rateLimit({ windowMs: 60 * 1000, // 1분 max: 1, handler(req, res) { res.status(this.statusCode).json({ code: this.statusCode, // 기본값 429 message: "1분에 한 번만 요청할 수 있습니다.", }); }, }); exports.apiLimiter = async (req, res, next) => { let user; if (res.locals.decoded) { user = await User.findOne({ where: { id: res.locals.decoded.id } }); } rateLimit({ widowMs: 60 * 1000, max: user?.type === "premium" ? 10 : 1, handler(req, res) { res.status(this.statusCode).json({ code: this.statusCode, message: "1분에 열 번만 요청 할 수 있습니다...", }); }, })(req, res, next); }; exports.deprecated = (req, res) => { res.status(410).json({ code: 410, message: "새로운 버전이 나왔습니다. 새로운 버전을 사용하세요", }); };

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

현재 mysql 연동하기 강의를 듣고 있는데, ..

미해결

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

안녕하세요. 현재 mysql 연동하기 강의를 듣고 있는데, sql 워크벤치에서 어떻게 칼럼을 넣어야 하는지 알수있을까요?

  • node.js
  • mysql
  • mongodb
  • express
  • 웹-크롤링
  • socket.io
단오 댓글 1 좋아요 0 조회수 412

10.6 사용량 제한 구현하기파트 질문

해결됨

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

nodebird-api 미들웨어 index.js코드 const jwt = require("jsonwebtoken"); const rateLimit = require("express-rate-limit"); const User = require("../models/user"); exports.isLoggedIn = (req, res, next) => { if (req.isAuthenticated()) { next(); } else { res.status(403).send("로그인 필요"); } }; exports.isNotLoggedIn = (req, res, next) => { if (!req.isAuthenticated()) { next(); } else { const message = encodeURIComponent("로그인한 상태입니다."); res.redirect(`/?error=${message}`); } }; exports.verifyToken = (req, res, next) => { try { res.locals.decoded = jwt.verify( req.headers.authorization, process.env.JWT_SECRET ); return next(); } catch (error) { if (error.name === "TokenExpiredError") { return res.status(419).json({ code: 419, message: "토큰이 만료되었습니다.", }); } return res.status(401).json({ code: 401, message: "유효하지 않은 토큰입니다.", }); } }; exports.apiLimiter = async (req, res, next) => { let user; if (res.locals.decoded) { user = await User.findOne({ where: { id: res.locals.decoded.id } }); } rateLimit({ windowMs: 60 * 1000, max: user?.type === "premium" ? 1000 : 10, handler(req, res) { res.status(this.statusCode).json({ code: this.statusCode, message: "1분에 열 번만 요청할 수 있습니다.", }); }, }); }; exports.deprecated = (req, res) => { res.status(410).json({ code: 410, message: "새로운 버전이 나왔습니다. 새로운 버전을 사용하세요", }); }; nodebird-api routes v2.js 코드 const express = require("express"); const { verifyToken, apiLimiter } = require("../middlewares"); const { createToken, tokenTest, getMyPosts, getPostsByHashtag, } = require("../controllers/v2"); const router = express.Router(); router.post("/token", apiLimiter, createToken); router.get("/test", verifyToken, apiLimiter, tokenTest); router.get("/posts/my", verifyToken, apiLimiter, getMyPosts); router.get("/posts/hashtag/:title", verifyToken, apiLimiter, getPostsByHashtag); module.exports = router; 프리미엄으로 클라이언트 비밀키 발급하고 프리미엄만 사용량제한 구현했는데 터미널에 GET/search/%EA%B3%A0%EC%96%91%EC%9D%B4 - - ms - - 이렇게 나오고 사이트로딩만 뜹니다 ㅜㅜ

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

querydsl 테스트시 에러입니다.

미해결

실전! Querydsl

<code> 17:02:50.381 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating CacheAwareContextLoaderDelegate from class [org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate] 17:02:50.391 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating BootstrapContext using constructor [public org.springframework.test.context.support .DefaultBootstrapContext(java.lang.Class,org.springframework.test.context.CacheAwareContextLoaderDelegate)] 17:02:50.427 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating TestContextBootstrapper for test class [study.querydsl.QuerydslBasicTest] from class [org.springframework.boot.test.context.SpringBootTestContextBootstrapper] 17:02:50.439 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Neither @ContextConfiguration nor @ContextHierarchy found for test class [study.querydsl.QuerydslBasicTest], using SpringBootContextLoader 17:02:50.443 [main] DEBUG org.springframework.test.context.support .AbstractContextLoader - Did not detect default resource location for test class [study.querydsl.QuerydslBasicTest]: class path resource [study/querydsl/QuerydslBasicTest-context.xml] does not exist 17:02:50.444 [main] DEBUG org.springframework.test.context.support .AbstractContextLoader - Did not detect default resource location for test class [study.querydsl.QuerydslBasicTest]: class path resource [study/querydsl/QuerydslBasicTestContext.groovy] does not exist 17:02:50.444 [main] INFO org.springframework.test.context.support .AbstractContextLoader - Could not detect default resource locations for test class [study.querydsl.QuerydslBasicTest]: no resource found for suffixes {-context.xml, Context.groovy}. 17:02:50.445 [main] INFO org.springframework.test.context.support .AnnotationConfigContextLoaderUtils - Could not detect default configuration classes for test class [study.querydsl.QuerydslBasicTest]: QuerydslBasicTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 17:02:50.482 [main] DEBUG org.springframework.test.context.support .ActiveProfilesUtils - Could not find an 'annotation declaring class' for annotation type [org.springframework.test.context.ActiveProfiles] and class [study.querydsl.QuerydslBasicTest] 17:02:50.541 [main] DEBUG org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider - Identified candidate component class: file [C:\Users\alita\Desktop\querydsl\querydsl\out\production\classes\study\querydsl\QuerydslApplication.class] 17:02:50.542 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Found @SpringBootConfiguration study.querydsl.QuerydslApplication for test class study.querydsl.QuerydslBasicTest 17:02:50.646 [main] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - @TestExecutionListeners is not present for class [study.querydsl.QuerydslBasicTest]: using defaults. 17:02:50.646 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener, org.springframework.boot.test.autoconfigure.webservices.client.MockWebServiceServerTestExecutionListener, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support .DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.event.ApplicationEventsTestExecutionListener, org.springframework.test.context.support .DependencyInjectionTestExecutionListener, org.springframework.test.context.support .DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener, org.springframework.test.context.event.EventPublishingTestExecutionListener] 17:02:50.664 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@3a1dd365, org.springframework.test.context.support .DirtiesContextBeforeModesTestExecutionListener@395b56bb, org.springframework.test.context.event.ApplicationEventsTestExecutionListener@256f8274, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@68044f4, org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@52d239ba, org.springframework.test.context.support .DirtiesContextTestExecutionListener@315f43d5, org.springframework.test.context.transaction.TransactionalTestExecutionListener@68fa0ba8, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@6c5945a7, org.springframework.test.context.event.EventPublishingTestExecutionListener@2f05be7f, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener@640f11a1, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener@5c10f1c3, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener@7ac2e39b, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener@78365cfa, org.springframework.boot.test.autoconfigure.webservices.client.MockWebServiceServerTestExecutionListener@64a8c844, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener@3f6db3fb] 17:02:50.668 [main] DEBUG org.springframework.test.context.support .AbstractDirtiesContextTestExecutionListener - Before test class: context [DefaultTestContext@424fd310 testClass = QuerydslBasicTest, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@1a45193b testClass = QuerydslBasicTest, locations = '{}', classes = '{class study.querydsl.QuerydslApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@1e13529a, org.springframework.boot.test.autoconfigure.properties .PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@93081b6, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@16c069df, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@7c3fdb62, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@4d6025c5, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@80ec1f8], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true]], class annotated with @DirtiesContext [false] with mode [null]. . ____ _ /\\ / ___'_ __ ( _)_ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.7.12) 2023-06-26 17:02:51.012 INFO 16528 --- [ main] study.querydsl.QuerydslBasicTest : Starting QuerydslBasicTest using Java 11.0.15 on DESKTOP-UKCCBE9 with PID 16528 (started by alita in C:\Users\alita\Desktop\querydsl\querydsl) 2023-06-26 17:02:51.013 INFO 16528 --- [ main] study.querydsl.QuerydslBasicTest : No active profile set, falling back to 1 default profile: "default" 2023-06-26 17:02:51.530 INFO 16528 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode. 2023-06-26 17:02:51.544 INFO 16528 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 7 ms. Found 0 JPA repository interfaces. 2023-06-26 17:02:52.025 INFO 16528 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default] 2023-06-26 17:02:52.079 INFO 16528 --- [ main] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.6.15.Final 2023-06-26 17:02:52.234 INFO 16528 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations { 5.1.2.Final } 2023-06-26 17:02:52.480 INFO 16528 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2023-06-26 17:02:52.647 INFO 16528 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2023-06-26 17:02:52.678 INFO 16528 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL8Dialect 2023-06-26 17:02:53.242 DEBUG 16528 --- [ main] org.hibernate.SQL : alter table member drop foreign key FKcjte2jn9pvo9ud2hyfgwcja0k Hibernate: alter table member drop foreign key FKcjte2jn9pvo9ud2hyfgwcja0k 2023-06-26 17:02:53.256 DEBUG 16528 --- [ main] org.hibernate.SQL : drop table if exists hello Hibernate: drop table if exists hello 2023-06-26 17:02:53.260 DEBUG 16528 --- [ main] org.hibernate.SQL : drop table if exists hibernate_sequence Hibernate: drop table if exists hibernate_sequence 2023-06-26 17:02:53.266 DEBUG 16528 --- [ main] org.hibernate.SQL : drop table if exists member Hibernate: drop table if exists member 2023-06-26 17:02:53.270 DEBUG 16528 --- [ main] org.hibernate.SQL : drop table if exists team Hibernate: drop table if exists team 2023-06-26 17:02:53.275 DEBUG 16528 --- [ main] org.hibernate.SQL : create table hello ( id bigint not null, primary key (id) ) engine=InnoDB Hibernate: create table hello ( id bigint not null, primary key (id) ) engine=InnoDB 2023-06-26 17:02:53.286 DEBUG 16528 --- [ main] org.hibernate.SQL : create table hibernate_sequence ( next_val bigint ) engine=InnoDB Hibernate: create table hibernate_sequence ( next_val bigint ) engine=InnoDB 2023-06-26 17:02:53.296 DEBUG 16528 --- [ main] org.hibernate.SQL : insert into hibernate_sequence values ( 1 ) Hibernate: insert into hibernate_sequence values ( 1 ) 2023-06-26 17:02:53.297 DEBUG 16528 --- [ main] org.hibernate.SQL : create table member ( member_id bigint not null, age integer not null, username varchar(255), team_id bigint, primary key (member_id) ) engine=InnoDB Hibernate: create table member ( member_id bigint not null, age integer not null, username varchar(255), team_id bigint, primary key (member_id) ) engine=InnoDB 2023-06-26 17:02:53.309 DEBUG 16528 --- [ main] org.hibernate.SQL : create table team ( id bigint not null, name varchar(255), primary key (id) ) engine=InnoDB Hibernate: create table team ( id bigint not null, name varchar(255), primary key (id) ) engine=InnoDB 2023-06-26 17:02:53.317 DEBUG 16528 --- [ main] org.hibernate.SQL : alter table member add constraint FKcjte2jn9pvo9ud2hyfgwcja0k foreign key (team_id) references team (id) Hibernate: alter table member add constraint FKcjte2jn9pvo9ud2hyfgwcja0k foreign key (team_id) references team (id) 2023-06-26 17:02:53.342 INFO 16528 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] 2023-06-26 17:02:53.351 INFO 16528 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' 2023-06-26 17:02:53.538 WARN 16528 --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning 2023-06-26 17:02:54.098 INFO 16528 --- [ main] study.querydsl.QuerydslBasicTest : Started QuerydslBasicTest in 3.391 seconds (JVM running for 4.357) 2023-06-26 17:02:54.207 INFO 16528 --- [ main] o.s.t.c.transaction.TransactionContext : Began transaction (1) for test context [DefaultTestContext@424fd310 testClass = QuerydslBasicTest, testInstance = study.querydsl.QuerydslBasicTest@4504a4ed, testMethod = startQuerydsl@QuerydslBasicTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@1a45193b testClass = QuerydslBasicTest, locations = '{}', classes = '{class study.querydsl.QuerydslApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@1e13529a, org.springframework.boot.test.autoconfigure.properties .PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@93081b6, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@16c069df, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@7c3fdb62, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@4d6025c5, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@80ec1f8], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true, 'org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@250e8712]; rollback [true] 2023-06-26 17:02:54.308 DEBUG 16528 --- [ main] org.hibernate.SQL : select next_val as id_val from hibernate_sequence for update Hibernate: select next_val as id_val from hibernate_sequence for update 2023-06-26 17:02:54.328 DEBUG 16528 --- [ main] org.hibernate.SQL : update hibernate_sequence set next_val= ? where next_val=? Hibernate: update hibernate_sequence set next_val= ? where next_val=? 2023-06-26 17:02:54.355 DEBUG 16528 --- [ main] org.hibernate.SQL : select next_val as id_val from hibernate_sequence for update Hibernate: select next_val as id_val from hibernate_sequence for update 2023-06-26 17:02:54.356 DEBUG 16528 --- [ main] org.hibernate.SQL : update hibernate_sequence set next_val= ? where next_val=? Hibernate: update hibernate_sequence set next_val= ? where next_val=? 2023-06-26 17:02:54.359 DEBUG 16528 --- [ main] org.hibernate.SQL : select next_val as id_val from hibernate_sequence for update Hibernate: select next_val as id_val from hibernate_sequence for update 2023-06-26 17:02:54.359 DEBUG 16528 --- [ main] org.hibernate.SQL : update hibernate_sequence set next_val= ? where next_val=? Hibernate: update hibernate_sequence set next_val= ? where next_val=? 2023-06-26 17:02:54.362 DEBUG 16528 --- [ main] org.hibernate.SQL : select next_val as id_val from hibernate_sequence for update Hibernate: select next_val as id_val from hibernate_sequence for update 2023-06-26 17:02:54.363 DEBUG 16528 --- [ main] org.hibernate.SQL : update hibernate_sequence set next_val= ? where next_val=? Hibernate: update hibernate_sequence set next_val= ? where next_val=? 2023-06-26 17:02:54.365 DEBUG 16528 --- [ main] org.hibernate.SQL : select next_val as id_val from hibernate_sequence for update Hibernate: select next_val as id_val from hibernate_sequence for update 2023-06-26 17:02:54.365 DEBUG 16528 --- [ main] org.hibernate.SQL : update hibernate_sequence set next_val= ? where next_val=? Hibernate: update hibernate_sequence set next_val= ? where next_val=? 2023-06-26 17:02:54.367 DEBUG 16528 --- [ main] org.hibernate.SQL : select next_val as id_val from hibernate_sequence for update Hibernate: select next_val as id_val from hibernate_sequence for update 2023-06-26 17:02:54.368 DEBUG 16528 --- [ main] org.hibernate.SQL : update hibernate_sequence set next_val= ? where next_val=? Hibernate: update hibernate_sequence set next_val= ? where next_val=? 2023-06-26 17:02:54.409 INFO 16528 --- [ main] o.s.t.c.transaction.TransactionContext : Rolled back transaction for test: [DefaultTestContext@424fd310 testClass = QuerydslBasicTest, testInstance = study.querydsl.QuerydslBasicTest@4504a4ed, testMethod = startQuerydsl@QuerydslBasicTest, testException = java.lang.NullPointerException, mergedContextConfiguration = [WebMergedContextConfiguration@1a45193b testClass = QuerydslBasicTest, locations = '{}', classes = '{class study.querydsl.QuerydslApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@1e13529a, org.springframework.boot.test.autoconfigure.properties .PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@93081b6, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@16c069df, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@7c3fdb62, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@4d6025c5, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@80ec1f8], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true, 'org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]] java.lang.NullPointerException at study.querydsl.QuerydslBasicTest.startQuerydsl( QuerydslBasicTest.java:57 ) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke( NativeMethodAccessorImpl.java:62 ) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke( DelegatingMethodAccessorImpl.java:43 ) at java.base/java.lang.reflect.Method.invoke( Method.java:566 ) at org.junit.platform.commons.util.ReflectionUtils.invokeMethod( ReflectionUtils.java:725 ) at org.junit.jupiter.engine.execution.MethodInvocation.proceed( MethodInvocation.java:60 ) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed( InvocationInterceptorChain.java:131 ) at org.junit.jupiter.engine.extension.TimeoutExtension.intercept( TimeoutExtension.java:149 ) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod( TimeoutExtension.java:140 ) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod( TimeoutExtension.java:84 ) at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0( ExecutableInvoker.java:115 ) at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0( ExecutableInvoker.java:105 ) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed( InvocationInterceptorChain.java:106 ) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed( InvocationInterceptorChain.java:64 ) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke( InvocationInterceptorChain.java:45 ) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke( InvocationInterceptorChain.java:37 ) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke( ExecutableInvoker.java:104 ) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke( ExecutableInvoker.java:98 ) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7( TestMethodTestDescriptor.java:214 ) at org.junit.platform.engine.support .hierarchical.ThrowableCollector.execute( ThrowableCollector.java:73 ) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod( TestMethodTestDescriptor.java:210 ) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute( TestMethodTestDescriptor.java:135 ) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute( TestMethodTestDescriptor.java:66 ) at org.junit.platform.engine.support .hierarchical.NodeTestTask.lambda$executeRecursively$6( NodeTestTask.java:151 ) at org.junit.platform.engine.support .hierarchical.ThrowableCollector.execute( ThrowableCollector.java:73 ) at org.junit.platform.engine.support .hierarchical.NodeTestTask.lambda$executeRecursively$8( NodeTestTask.java:141 ) at org.junit.platform.engine.support .hierarchical.Node.around( Node.java:137 ) at org.junit.platform.engine.support .hierarchical.NodeTestTask.lambda$executeRecursively$9( NodeTestTask.java:139 ) at org.junit.platform.engine.support .hierarchical.ThrowableCollector.execute( ThrowableCollector.java:73 ) at org.junit.platform.engine.support .hierarchical.NodeTestTask.executeRecursively( NodeTestTask.java:138 ) at org.junit.platform.engine.support .hierarchical.NodeTestTask.execute( NodeTestTask.java:95 ) at java.base/java.util.ArrayList.forEach( ArrayList.java:1541 ) at org.junit.platform.engine.support .hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll( SameThreadHierarchicalTestExecutorService.java:41 ) at org.junit.platform.engine.support .hierarchical.NodeTestTask.lambda$executeRecursively$6( NodeTestTask.java:155 ) at org.junit.platform.engine.support .hierarchical.ThrowableCollector.execute( ThrowableCollector.java:73 ) at org.junit.platform.engine.support .hierarchical.NodeTestTask.lambda$executeRecursively$8( NodeTestTask.java:141 ) at org.junit.platform.engine.support .hierarchical.Node.around( Node.java:137 ) at org.junit.platform.engine.support .hierarchical.NodeTestTask.lambda$executeRecursively$9( NodeTestTask.java:139 ) at org.junit.platform.engine.support .hierarchical.ThrowableCollector.execute( ThrowableCollector.java:73 ) at org.junit.platform.engine.support .hierarchical.NodeTestTask.executeRecursively( NodeTestTask.java:138 ) at org.junit.platform.engine.support .hierarchical.NodeTestTask.execute( NodeTestTask.java:95 ) at java.base/java.util.ArrayList.forEach( ArrayList.java:1541 ) at org.junit.platform.engine.support .hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll( SameThreadHierarchicalTestExecutorService.java:41 ) at org.junit.platform.engine.support .hierarchical.NodeTestTask.lambda$executeRecursively$6( NodeTestTask.java:155 ) at org.junit.platform.engine.support .hierarchical.ThrowableCollector.execute( ThrowableCollector.java:73 ) at org.junit.platform.engine.support .hierarchical.NodeTestTask.lambda$executeRecursively$8( NodeTestTask.java:141 ) at org.junit.platform.engine.support .hierarchical.Node.around( Node.java:137 ) at org.junit.platform.engine.support .hierarchical.NodeTestTask.lambda$executeRecursively$9( NodeTestTask.java:139 ) at org.junit.platform.engine.support .hierarchical.ThrowableCollector.execute( ThrowableCollector.java:73 ) at org.junit.platform.engine.support .hierarchical.NodeTestTask.executeRecursively( NodeTestTask.java:138 ) at org.junit.platform.engine.support .hierarchical.NodeTestTask.execute( NodeTestTask.java:95 ) at org.junit.platform.engine.support .hierarchical.SameThreadHierarchicalTestExecutorService.submit( SameThreadHierarchicalTestExecutorService.java:35 ) at org.junit.platform.engine.support .hierarchical.HierarchicalTestExecutor.execute( HierarchicalTestExecutor.java:57 ) at org.junit.platform.engine.support .hierarchical.HierarchicalTestEngine.execute( HierarchicalTestEngine.java:54 ) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute( EngineExecutionOrchestrator.java:107 ) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute( EngineExecutionOrchestrator.java:88 ) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0( EngineExecutionOrchestrator.java:54 ) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams( EngineExecutionOrchestrator.java:67 ) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute( EngineExecutionOrchestrator.java:52 ) at org.junit.platform.launcher.core.DefaultLauncher.execute( DefaultLauncher.java:114 ) at org.junit.platform.launcher.core.DefaultLauncher.execute( DefaultLauncher.java:86 ) at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute( DefaultLauncherSession.java:86 ) at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute( SessionPerRequestLauncher.java:53 ) at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs( JUnit5IdeaTestRunner.java:57 ) at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute( IdeaTestRunner.java:38 ) at com.intellij.rt.execution.junit.TestsRepeater.repeat( TestsRepeater.java:11 ) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs( IdeaTestRunner.java:35 ) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart( JUnitStarter.java:235 ) at com.intellij.rt.junit.JUnitStarter.main( JUnitStarter.java:54 ) 2023-06-26 17:02:54.428 INFO 16528 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default' 2023-06-26 17:02:54.430 INFO 16528 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated... 2023-06-26 17:02:54.443 INFO 16528 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed. Process finished with exit code -1 </code> [질문 내용] QType 활용 2:22초에서 강사님처럼 리팩토링 후 코드 실행시 NullPointer Exception이 발생합니다. 구글 파일 링크입니다. https://drive.google.com/drive/folders/1FxQskkAngeLJcGPtmKUoj-XCmnxm0MVa?usp=sharing

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

p6spy 1.9.0 -> 1.8.1 버전 관련 내용 공유

해결됨

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

p6spy releases를 확인해보면 1.9.0부터 Spring boot 3을 지원한다고 되어있고 테스트시 로그가 안뜹니다. 다른 질문에서보니 해당 버전이 메이븐에서만 지원되어서 그런 듯 합니다. 그래서 바로 아래 버전인 1.8.1을 사용해서 정상적으로 로그가 뜨는 것을 확인했습니다. 그래서 앞으로 최신 버전으로 했을때 안뜬다면 버전을 내려보시면 좋을 것 같습니다.

  • java
  • spring
  • 웹앱
  • spring-boot
  • jpa
김주영 댓글 1 좋아요 3 조회수 829

Direct Messages에 값이 없어요

미해결

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

안녕하세요. import React from 'react'; import { Container, Header } from './styles'; import useSWR from 'swr'; import fetcher from '@utils/fetcher'; import { useParams } from 'react-router'; import gravatar from 'gravatar'; const DirectMessage = () => { const { workspace, id } = useParams<{ workspace: string; id: string }>(); const { data: userData } = useSWR(`api/workspaces/${workspace}/members/${id}`, fetcher); const { data: myData } = useSWR('api/users', fetcher); if (!userData || !myData) { return null; } return ( <Container> <Header> <img src={gravatar.url(userData.email, { s: '24px', d: 'retor' })} alt={userData.nickname} /> <span>{userData.nickname}</span> </Header> {/* <ChatList /> <ChatBox /> */} </Container> ); }; export default DirectMessage; 이건 DirectMessage입니다. // import EachDM from '@components/EachDM'; // import useSocket from '@hooks/useSocket'; import { CollapseButton } from '@components/DMList/styles'; 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 } = 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); // }); // console.log('socket on dm', socket?.hasListeners('dm'), socket); // return () => { // 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 p-channel_sidebar__section_heading_expand--show_more_feature 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); const count = countList[member.id] || 0; <NavLink key={member.id} activeClassName="selected" to={`/workapce/${workspace}/dm/${member.id}`} onClick={resetCount(member.id)} > ; <i className={`c-icon p-channel_sidebar__presence_icon p-channel_sidebar__presence_icon--dim_enabled 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 className={count > 0 ? 'bold' : undefined}>{member.nickname}</span> {member.id === userData?.id && <span> (나)</span>} {count > 0 && <span className="count">{count}</span>} </NavLink>; // return <EachDM key={member.id} member={member} isOnline={isOnline} />; })} </div> </> ); }; export default DMList; 이건 DMList입니다. 현재 DM페이지 만들기 강의를 듣고 있는데, DM리스트에 사용자가 하나도 표시가 되지 않는데 원래 지금 강의까지는 표시가 되지 않는게 맞나요? 워크스페이스 초대, 채널 멤버 초대해도 에러는 발생하지 않는데 DM리스트에 추가는 다음 강의에서 진행하나요? 아니면 지금도 되야하는게 정상인가요..?

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

사용자 초대 모달에서 에러가 발생했습니다.

미해결

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

import fetcher from '@utils/fetcher'; import axios from 'axios'; import React, { VFC, useCallback, useState } from 'react'; import { Redirect, Route, Switch, useParams } from 'react-router'; import useSWR from 'swr'; import { Header, ProfileImg, RightMenu, WorkspaceWrapper, WorkspaceName, Workspaces, Channels, Chats, MenuScroll, ProfileModal, LogOutButton, WorkspaceButton, AddButton, WorkspaceModal, } from './styles'; import gravatar from 'gravatar'; import loadable from '@loadable/component'; import Menu from '@components/Menu'; const Channel = loadable(() => import('@pages/Channel')); const DirectMessage = loadable(() => import('@pages/DirectMessage')); import { Link } from 'react-router-dom'; import { IChannel, IUser } from '@typings/db'; import Modal from '@components/Modal'; import { Button, Input, Label } from '@pages/SignUp/styles'; import useInput from '@hooks/useInput'; import { toast } from 'react-toastify'; import CreateChannelModal from '@components/CreateChannelModal'; import InviteWorkspaceModal from '@components/InviteWorkspaceModal'; import InviteChannelModal from '@components/InviteChannelModal'; // import ChannelList from '@components/ChannelList'; import DMList from '@components/DMList'; import ChannelList from '@components/ChannelList'; // FC타입안에 children이 알아서 들어있음 // children 안쓸거면 VFC const Workspace: VFC = () => { const [showUserMenu, setShowUserMenu] = useState(false); const [showCreateWorkspaceModal, setShowCreateWorkspaceModal] = useState(false); const [showInviteWorkspaceModal, setShowInviteWorkspaceModal] = useState(false); const [showInviteChannelModal, setShowInviteChannelModal] = useState(false); const [newWorkspace, onChangeNewWorkspace, setNewWorkspace] = useInput(''); const [newUrl, onChangeNewUrl, setNewUrl] = useInput(''); const [showWorkspaceModal, setShowWorkspaceModal] = useState(false); const [ShowCreateChannelModal, setShowCreateChannelModal] = useState(false); const { workspace } = useParams<{ workspace: string }>(); // 사용자 데이터 가져오기 const { data: userData, error, revalidate, mutate, } = useSWR<IUser | false>('/api/users', fetcher, { dedupingInterval: 2000, }); // channel 데이터 가져오기 const { data: channelData } = useSWR<IChannel[]>(userData ? `/api/workspaces/${workspace}/channels` : null, fetcher); // 워크스페이스에 있는 멤버 데이터 const { mutate: revalidateMembers } = useSWR<IUser[]>( userData ? `/api/workspaces/${workspace}/members` : null, fetcher, ); // 로그아웃 const onLogout = useCallback(() => { axios .post('/api/users/logout', null, { withCredentials: true, }) .then((response) => { mutate(response.data); // 기존에 받은 데이터를 mutate의 data에 담음 }) .catch((error) => { console.log(error); }); }, []); // 프로필 누르면 메뉴 보이기 const onClickUserProfile = useCallback(() => { setShowUserMenu((prev) => !prev); }, []); // 프로필 닫기 const onCloseUserProfile = useCallback((e) => { e.stopPropagation(); setShowUserMenu(false); }, []); // 워크스페이스 모달 열기 const onClickCreateWorkspace = useCallback(() => { setShowCreateWorkspaceModal(true); }, []); // 워크스페이스 모달 닫기 const onCloseModal = useCallback(() => { setShowCreateWorkspaceModal(false); setShowCreateChannelModal(false); setShowInviteChannelModal(false); setShowInviteWorkspaceModal(false); }, []); // 워크스페이스 생성 const onCreateWorkspace = useCallback( (e) => { e.preventDefault(); // trim() 안넣으면 띄어쓰기 넣으면 걍 통과됨 if (!newWorkspace || !newWorkspace.trim()) return; if (!newUrl || !newUrl.trim()) return; axios .post( '/api/workspaces', { workspace: newWorkspace, url: newUrl, }, { withCredentials: true, }, ) .then(() => { revalidate(); setShowCreateWorkspaceModal(false); setNewWorkspace(''); setNewUrl(''); }) .catch((error) => { console.log(error); toast.error(error.response?.data, { position: 'bottom-center' }); }); }, [newWorkspace, newUrl], ); // 워크스페이스 사용자 초대 const onClickInviteWorkspace = useCallback(() => { setShowInviteWorkspaceModal(true); }, []); // Channel // 토글 const toggleWorkspaceModal = useCallback(() => { setShowWorkspaceModal((prev) => !prev); }, []); // 채널 만들기 const onClickAddChannel = useCallback(() => { setShowCreateChannelModal(true); }, []); if (!userData) { return <Redirect to="/login" />; } return ( <div> <Header> <RightMenu> <span onClick={onClickUserProfile}> <ProfileImg src={gravatar.url(userData.nickname, { s: '28px', d: 'retro' })} alt={userData.nickname} /> {showUserMenu && ( <Menu style={{ right: 0, top: 38 }} show={showUserMenu} onCloseModal={onCloseUserProfile}> <ProfileModal> <img src={gravatar.url(userData.nickname, { 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={onClickInviteWorkspace}>워크스페이스에 사용자 초대</button> <button onClick={onClickAddChannel}>채널 만들기</button> <button onClick={onLogout}>로그아웃</button> </WorkspaceModal> </Menu> <ChannelList /> <DMList /> {/* {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" value={newUrl} onChange={onChangeNewUrl} /> </Label> <Button type="submit">생성하기</Button> </form> </Modal> <CreateChannelModal show={ShowCreateChannelModal} onCloseModal={onCloseModal} setShowCreateChannelModal={setShowCreateChannelModal} /> <InviteWorkspaceModal show={showInviteWorkspaceModal} onCloseModal={onCloseModal} setShowInviteWorkspaceModal={setShowInviteWorkspaceModal} /> <InviteChannelModal show={showInviteChannelModal} onCloseModal={onCloseModal} setShowInviteChannelModal={setShowInviteChannelModal} /> </div> ); }; export default Workspace; 이건 제가 작성한 WorkSpace 입니다. import Modal from '@components/Modal'; import useInput from '@hooks/useInput'; import { Button, Input, Label } from '@pages/SignUp/styles'; import { IUser } from '@typings/db'; import fetcher from '@utils/fetcher'; import axios from 'axios'; import React, { FC, useCallback } from 'react'; import { useParams } from 'react-router'; import { toast } from 'react-toastify'; import useSWR from 'swr'; interface Props { show: boolean; onCloseModal: () => void; setShowInviteChannelModal: (flag: boolean) => void; } const InviteChannelModal: FC<Props> = ({ show, onCloseModal, setShowInviteChannelModal }) => { const { workspace, channel } = useParams<{ workspace: string; channel: string }>(); const [newMember, onChangeNewMember, setNewMember] = useInput(''); const { data: userData } = useSWR<IUser>('/api/users', fetcher); const { revalidate: revalidateMembers } = useSWR<IUser[]>( userData ? `/api/workspaces/${workspace}/channels/${channel}/members` : null, fetcher, ); console.dir(channel); const onInviteMember = useCallback( (e) => { e.preventDefault(); if (!newMember || !newMember.trim()) { return; } axios .post(`/api/workspaces/${workspace}/channels/${channel}/members`, { email: newMember, }) .then(() => { revalidateMembers(); setShowInviteChannelModal(false); setNewMember(''); }) .catch((error) => { console.dir(error); toast.error(error.response?.data, { position: 'bottom-center' }); }); }, [channel, newMember, revalidateMembers, setNewMember, setShowInviteChannelModal, workspace], ); return ( <Modal show={show} onCloseModal={onCloseModal}> <form onSubmit={onInviteMember}> <Label id="member-label"> <span>채널 멤버 초대</span> <Input id="member" value={newMember} onChange={onChangeNewMember} /> </Label> <Button type="submit">초대하기</Button> </form> </Modal> ); }; export default InviteChannelModal; 이건 제가 작성한 InviteChannelModal입니다. xhr.js:210 GET http://localhost:3090/api/workspaces/sleact/channels/undefined/members 404 (Not Found) dispatchXhrRequest @ xhr.js:210 xhrAdapter @ xhr.js:15 dispatchRequest @ dispatchRequest.js:58 request @ Axios.js:108 Axios.<computed> @ Axios.js:129 wrap @ bind.js:9 fetcher @ fetcher.ts:18 eval @ use-swr.js:392 step @ use-swr.js:43 eval @ use-swr.js:24 eval @ use-swr.js:18 __awaiter @ use-swr.js:14 eval @ use-swr.js:344 softRevalidate @ use-swr.js:532 onFocus @ use-swr.js:550 revalidate_1 @ use-swr.js:73 eval @ use-swr.js:77 eval @ web-preset.js:29 그런데 위와 같은 에러가 발생합니다. 콘솔에 channel을 출력해도 undefined가 뜹니다.. 그런데 url을 보면 http://localhost:3090/workspace/sleact/channel/테스트채널 이렇게 채널 명이 표시가 되는데 도대체 뭐 때문에 undefined라고 뜨는지 모르겠습니다... 아무리 찾아봐도 알 수가 없어서 글 남깁니다... 분명 WorkSpace의 route에도 오타가 없고 url도 표시가 잘되는데 왜 undefined일까요...

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

화살표 함수 자동완성이 궁금합니다

해결됨

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

안녕하세요 선생님 강의를 보다보니 그림판에서 텍스트로 코딩을 하시는데 화살표함수 작성시 뒤에 구문이 자동으로 입력이 되던데 그림판에 어떤 플러그인을 설치하셨길래 이런 기능이 되는건지 궁금합니다.

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

원래 깃허브에 올려주신 파일과 강의 파일이 다른가요...?

미해결

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

안녕하세요. 먼저 제로초님 강의 보면서 공부 열심히 하고 있습니다. 감사합니다!. 현재 DMList 만드는 중인데 깃허브에 올려주신 front의 DMList와 제로초님이 강의하면서 작성하시는 DMList의 코드가 서로 다른 부분이 꽤 있던데 원래 그런가요...? 영상을 정지해가면서 수정하고 있지만 안보이는 코드가 있어서 많이 헷갈리네요 ㅠㅠ

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

메일 질문있습니다

해결됨

Windows 소켓 프로그래밍 입문에서 고성능 서버까지!

5/31 이벤트 유튜브 영상 ( https://youtu.be/3rpEsV0vnB8 ) 보고서 선생님께 메일 보냈었는데 메일이 안 간건지 보낸 메일 주소가 잘못된건지 보낸 방식이 잘못된건지 답변을 못 받았습니다. 어떤 메일 주소로 어떻게 캡쳐해서 보내드리면 될까요?

  • socket.io
  • udp
  • iocp
  • tcpip
선종원 댓글 1 좋아요 0 조회수 286

Callback 기반 비동기 파일 입/출력 질문

해결됨

Windows 소켓 프로그래밍 입문에서 고성능 서버까지!

안녕하세요 수업 잘 듣고 있습니다 감사합니다. Callback 기반 비동기 파일 입/출력 부분에 질문이 있습니다. 만약 IoThreadFunction 함수에서 다수의 WriteFileEx 를 호출하고 콜백을 모두 같은 FileIoComplete 함수로 받는상황이 있을경우 테스트 해보니 하나의 파일 IO만 완료되도 SleepEx 가 통과되는 상황이 발생하는데요 이경우 만약 모든 콜백을 받길 원하면 구조적으로 스래드 하나당 하나의 WriteFileEx를 호출하도록 하거나 별도로 이벤트를 이용해서 처리하거나 하는 방법이 떠오르긴 한데 이방법이외에 다른 방법도 있을까요??

  • socket.io
  • udp
  • iocp
  • tcpip
고대괴물 댓글 2 좋아요 0 조회수 480

스프링 부트3와 카운트 쿼리 분리

해결됨

실전! 스프링 데이터 JPA

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 안녕하세요. 카운트 쿼리 분리 부분을 듣는 도중에 카운트 쿼리에 LEFT JOIN이 사용되는 결과를 확인하기 위해 다음처럼 코드를 작성하였습니다. public interface MemberRepository extends JpaRepository<Member, Long> { @Query(value = "select m from Member m left join m.team t") Page<Member> findByAge(int age, Pageable pageable); ... } @Test public void paging() throws Exception { //given memberRepository.save(new Member("member1", 10)); memberRepository.save(new Member("member2", 10)); memberRepository.save(new Member("member3", 10)); memberRepository.save(new Member("member4", 10)); memberRepository.save(new Member("member5", 10)); //when PageRequest pageRequest = PageRequest.of(0, 3, Sort.by(Sort.Direction.ASC, "username")); Page<Member> page = memberRepository.findByAge(10, pageRequest); //then List<Member> content = page.getContent(); assertThat(content.size()).isEqualTo(3); assertThat(page.getTotalElements()).isEqualTo(5); assertThat(page.getNumber()).isEqualTo(0); assertThat(page.getTotalPages()).isEqualTo(2); assertThat(page.isFirst()).isTrue(); assertThat(page.hasNext()).isTrue(); } 그런데 결과는 강의와는 달리 카운트 쿼리에 LEFT JOIN 이 사용되지 않았고, 심지어 JPQL select m from Member m left join m.team t 을 @Query에 작성했음에도 조회 쿼리도 LEFT JOIN을 사용하지 않은 것을 확인했습니다. 이후 스프링 부트 3 이하 버전에서 동일한 코드로 실행해보니 강의와 동일한 결과를 얻을 수 있었습니다. 스프링 부트 3 부터 적용된 스프링 데이터 JPA 에서는 이러한 부분의 최적화를 자동으로 제공하는 것일까요?

  • java
  • spring
  • spring-boot
  • jpa
조약돌 댓글 1 좋아요 1 조회수 773

자바 공부법

미해결

즐거운 자바

안녕하세요. 백엔드 개발자 희망하고 있습니다. 자바 독학 공부 시작했는데 기본문법 예제들은 혼자 짤 수 있는데 객체지향/3 로또 부분부터 어렵네요. 구구단, 별찍기 하다가 로또 구현할 수 있을때까지 공부 방법이 궁금합니다. ㅠ.ㅠ 자바 공부 방법 알려주세요 ㅠㅠㅠ 지금은 강사님 강의 보고 이해가 부족하다는 부분 이론서 보면서 나가고있습니다. 이론서에 나와있는 문제들도 타이핑 하면서 진행하구 있습니다. 길게 코드 작성할 수 있을때까지 자바 공부 방법 알려주세요.

  • java
  • 자바공부
댓글 2 좋아요 1 조회수 1725

강의자료 ppt는 어디서 받을 수 있나요?

미해결

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

안녕하세요 11강에서 강의자료 ppt 파일을 올려주신다고 했는데 어디서 다운로드 받을수 있나요?

  • node.js
  • mysql
  • mongodb
  • express
  • typescript
  • socket.io
  • jwt
정상원 댓글 1 좋아요 1 조회수 962

9장 추가 과제 관련 질문

미해결

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

안녕하세요. 9장강의를 듣고 추가 과제를 시도해보던 중 궁금증이 생겨 질문드립니다. 스스로 해보기 -> 팔로잉 끊기 에서 destory와 라우터를 사용하라고 안내해주셨는데 user자체를 삭제하는 것이 아닌 중간테이블(follow)에서 해당 로우만 삭제하는 방법이 따로 있나요? if (user) { const a = await user.destroy({ where: { Followings: { followerId: req.params.id } }, }); 위와 같이 방법을 여러가지로 시도해보았지만 계속해서 유저 삭제(탈퇴)가 되는 상황이라 도움주시면 감사하겠습니다..!

  • node.js
  • mysql
  • mongodb
  • express
  • typescript
  • socket.io
  • jwt
최지인 댓글 1 좋아요 0 조회수 310

spring 2.x - Querydsl 이슈있는분들 참고하세요

미해결

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

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] plugins { id 'org.springframework.boot' version '2.6.5' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' ext["hibernate.version"] = " 5.6.5.Final " configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'javax.validation:validation-api' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5' //JdbcTemplate 추가 //implementation 'org.springframework.boot:spring-boot-starter-jdbc' //MyBatis 추가 implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.0' //JPA, 스프링 데이터 JPA 추가 implementation 'org.springframework.boot:spring-boot-starter-data-jpa' //Querydsl 추가 implementation 'com.querydsl:querydsl-jpa' annotationProcessor "com.querydsl:querydsl-apt:$ { dependencyManagement.importedProperties['querydsl.version'] } :jpa" annotationProcessor "jakarta.annotation:jakarta.annotation-api" annotationProcessor "jakarta.persistence:jakarta.persistence-api" //H2 데이터베이스 추가 runtimeOnly 'com.h2database:h2' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' //테스트에서 lombok 사용 testCompileOnly 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok' } tasks.named('test') { useJUnitPlatform() } //querydsl 추가 //def querydslDir = '$buildDir/generated' def querydslDir = "src/main/generated" //clean { // delete file(generated) //} querydsl { library = "com.querydsl:querydsl-apt" jpa = true querydslSourcesDir = querydslDir } sourceSets { main { java { srcDirs = ['src/main/java', querydslDir] } } } compileQuerydsl { options.annotationProcessorPath = configurations.querydsl } configurations { querydsl.extendsFrom compileClasspath } 강사님이 올려주신 내용 + 구글링 + 직접 수정했습니다. 간혹, 빌드는 되는데 generated 파일에 QClass 안보이시는 분들은 queryDsl 저장되는 경로에 $buildDir 대신 'src/main/'으로 해보세요

  • java
  • spring
  • spring-boot
  • jpa
henn36 댓글 1 좋아요 4 조회수 1263

JPA 특징 중 자동 업데이트 관련

미해결

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

주문 서비스 개발 부분 강의를 듣다가 궁금한 점이 있어 질문드립니다. 주문 취소(OrderService.cancelOrder) 부분에서order.cancel() 만 작성하면 JPA 특징으로 인해, 데이터 업데이트 관련 쿼리 로직 없이 자동으로 업데이트 된다고 하셨는데요. 주문 생성(OrderService.order)의 EntityManager 가 사용된 orderRepository.save (order);  와 혼동이 와서 질문 남깁니다. 주문 취소 order.cancel() 메서드를 타면서 엔티티의 값(status, count 등) 변경 내역이 자동으로 업데이트 되는 것이라고 하면, 주문 생성도 Order.createOrder(member, delivery, orderItem); 를 타면서 엔티티의 값들을 설정하기 때문에 orderRepository.save (order); 를 사용하지 않아도 되는게 아닌가 라는 생각이 듭니다. 제가 JPA 를 잘 몰라서 혼란이 오는 것 같은데.. 쿼리는 직접 작성하지 않아도 업데이트/저장/삭제 등 DB 조작이 일어나려면 EntityManager 를 통해야 된다고 생각하고 있었습니다. 주문 취소는 EntityManager 없이 업데이트 되고, 주문 생성은 EntityManager의 persist() 를 사용해서 저장하는 것 이 2가지 차이점에 대해서 설명 부탁드립니다! 감사합니다 :)

  • java
  • spring
  • 웹앱
  • spring-boot
  • jpa
빈빈 댓글 1 좋아요 2 조회수 510

19:04 초 where in 쿼리 대신 where array_conatins 쿼리가 나왔습니다. (스프링 부트 3.1)

해결됨

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

[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 현재 스프링 부트 3.1 로 강의를 따라가고 있습니다. default_batch_fetch_size:10 을 설정해서 나가는 쿼리가 줄어드는 것을 확인했습니다만, 쿼리가 두 개가 아니고 총 세 개가 나왔습니다. 023-06-13T23:24:02.666+09:00 DEBUG 68750 --- [nio-8080-exec-5] org.hibernate.SQL : select o1_0.order_id, d1_0.delivery_id, d1_0.city, d1_0.street, d1_0.zipcode, d1_0.status, m1_0.memeber_id, m1_0.city, m1_0.street, m1_0.zipcode, m1_0.name, o1_0.order_date, o1_0.status from orders o1_0 join member m1_0 on m1_0.memeber_id=o1_0.member_id join delivery d1_0 on d1_0.delivery_id=o1_0.delivery_id offset ? rows fetch first ? rows only 2023-06-13T23:24:02.676+09:00 INFO 68750 --- [nio-8080-exec-5] p6spy : #1686666242676 | took 2ms | statement | connection 8| url jdbc:h2:tcp://localhost/~/springbootjpa select o1_0.order_id,d1_0.delivery_id,d1_0.city,d1_0.street,d1_0.zipcode,d1_0.status,m1_0.memeber_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name,o1_0.order_date,o1_0.status from orders o1_0 join member m1_0 on m1_0.memeber_id=o1_0.member_id join delivery d1_0 on d1_0.delivery_id=o1_0.delivery_id offset ? rows fetch first ? rows only select o1_0.order_id,d1_0.delivery_id,d1_0.city,d1_0.street,d1_0.zipcode,d1_0.status,m1_0.memeber_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name,o1_0.order_date,o1_0.status from orders o1_0 join member m1_0 on m1_0.memeber_id=o1_0.member_id join delivery d1_0 on d1_0.delivery_id=o1_0.delivery_id offset 0 rows fetch first 100 rows only; 2023-06-13T23:24:02.681+09:00 DEBUG 68750 --- [nio-8080-exec-5] org.hibernate.SQL : select o1_0.order_id, o1_0.order_item_id, o1_0.count, o1_0.item_id, o1_0.order_price from order_item o1_0 where array_contains(?,o1_0.order_id) 2023-06-13T23:24:02.689+09:00 INFO 68750 --- [nio-8080-exec-5] p6spy : #1686666242689 | took 0ms | statement | connection 8| url jdbc:h2:tcp://localhost/~/springbootjpa select o1_0.order_id,o1_0.order_item_id,o1_0.count,o1_0.item_id,o1_0.order_price from order_item o1_0 where array_contains(?,o1_0.order_id) select o1_0.order_id,o1_0.order_item_id,o1_0.count,o1_0.item_id,o1_0.order_price from order_item o1_0 where array_contains('ar2: ARRAY [CAST(1 AS BIGINT), CAST(2 AS BIGINT), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL]',o1_0.order_id); 2023-06-13T23:24:02.690+09:00 DEBUG 68750 --- [nio-8080-exec-5] org.hibernate.SQL : select i1_0.item_id, i1_0.dtype, i1_0.category_item_id, i1_0.name, i1_0.price, i1_0.stock_quantity, i1_0.author, i1_0.isbn, i1_0.artist, i1_0.etc from item i1_0 where array_contains(?,i1_0.item_id) 2023-06-13T23:24:02.691+09:00 INFO 68750 --- [nio-8080-exec-5] p6spy : #1686666242691 | took 0ms | statement | connection 8| url jdbc:h2:tcp://localhost/~/springbootjpa select i1_0.item_id,i1_0.dtype,i1_0.category_item_id,i1_0.name,i1_0.price,i1_0.stock_quantity,i1_0.author,i1_0.isbn,i1_0.artist,i1_0.etc from item i1_0 where array_contains(?,i1_0.item_id) select i1_0.item_id,i1_0.dtype,i1_0.category_item_id,i1_0.name,i1_0.price,i1_0.stock_quantity,i1_0.author,i1_0.isbn,i1_0.artist,i1_0.etc from item i1_0 where array_contains('ar3: ARRAY [CAST(1 AS BIGINT), CAST(2 AS BIGINT), CAST(3 AS BIGINT), CAST(4 AS BIGINT), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL]',i1_0.item_id); 수강 중에 제가 따라 작성한 코드를 스프링부트 2.4.1에 그대로 옮겨보니 강의 내용대로 where in 쿼리가 나오는 것을 확인했습니다. 스프링부트 버전 차이에서 나오는 쿼리가 달라진 것 같은데, 제 생각이 맞을까요? 답변 확인 : 빠르게 답변해주셔서 감사합니다!! 덕분에 array_contains 로 최적화된 이유를 쉽게 이해할 수 있었습니다. (Hibernate에서 최적화를 했었었군요!) 아 그리고 강의 내용에서 쿼리 세 개 나온다는 것을 확인했습니다(잘못 본 것에 대해 질문글에서 수정을 해놨어야 했는데 빼놓지 않았었네요 ㅠㅠ) 다시 한번 상세한 답변 정말 감사드립니다.

  • java
  • spring
  • spring-boot
  • jpa
말랑한참깨 댓글 1 좋아요 1 조회수 1928

인기 태그

인프런 TOP Writers

주간 인기글