학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문 전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예 [질문 내용] ExecutorService.submit 시점에 디버깅을 걸어서 확인해보니 BlockingQueue 필드인 workQueue 내부에 task가 들어가지 않고 workers라는 HashSet에 들어가지는 것 같습니다 혹시 제가 어디서 놓친건지 모르겠어서 여쭤봅니다 이거 때문에 계속 헷갈려요..ㅜ
강사님, 안녕하세요. 강의를 들으면서 살짝 혼란스러운 부분이 있습니다. 사실 Next.js 도 바탕은 React 인데요. React 에서 제일 많이 언급되고 중요시되는 부분은 상태(state)관리라고 생각이 되는데 Next.js 로 SSR 위주의 페이지를 작성하게 되면 결국 상태관리는 최소화하게 되는 것인데 이게 React 의 컨셉과 맞는 것인지 살짝 이해가 되지 않습니다. (강의에서도 state 는 거의 언급이 되지 않고요) 그렇다고 상태관리를 최대한 활용하는 CSR 위주의 개발을 하게 되면 Next.js 의 장점을 거의 얻지 못하게 될 것 같기도 하고요. 저는 Next.js 가 제공하는 프레임워크 측면의 혜택을 얻고자 Next.js 로 어플리케이션 구축을 해보고 싶은데 해당 어플리케이션이 CSR 의 비중이 적지 않을 것 같아서 좀 망설여지는 부분이 있습니다. 현대 애플리케이션들은 사용자들과의 상호작용이 적을 수가 없을텐데 대다수의 앱들이 Next.js 의 SSR 위주의 개발로 충분히 커버가 가능한 것일까요?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 안녕하세요 ~! 강의 자료에서 처럼 이런 자료들을 draw.io에서 만든다는 정보는 찾았는데요 ! 그 내부에서 어떤 템플릿을 사용하시는지 궁금합니다..! 몇 시간 동안 여러가지 클릭 해봤는데 못 찾아서요 ㅠㅠ 크래파스로 그은듯한 네모와 점선으로 연결된 화살표, dot 네모박스가 궁금합니다 !
package com.example.stock.repository; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.time.Duration; @Component public class RedisLockRepository { private RedisTemplate<String, String> redisTemplate; public RedisLockRepository(RedisTemplate<String, String> redisTemplate) { this.redisTemplate = redisTemplate; } public Boolean lock(Long key) { return redisTemplate .opsForValue() .setIfAbsent(generateKey(key), "lock", Duration.ofMillis(3_000)); } public void unlock(Long key) { redisTemplate.delete(generateKey(key)); } private String generateKey(Long key) { return key.toString(); } } package com.example.stock.facade; import com.example.stock.repository.RedisLockRepository; import com.example.stock.service.StockService; import org.springframework.stereotype.Component; @Component public class LettuceLockStockFacade { private final RedisLockRepository redisLockRepository; private final StockService stockService; public LettuceLockStockFacade(RedisLockRepository redisLockRepository, StockService stockService) { this.redisLockRepository = redisLockRepository; this.stockService = stockService; } public void decrease(Long key, Long quantity) throws InterruptedException { while(!redisLockRepository.lock(key)){ Thread.sleep(100); } try{ stockService.decrease(key, quantity); }finally { redisLockRepository.unlock(key); } } } package com.example.stock.facade; import com.example.stock.domain.Stock; import com.example.stock.repository.StockRepository; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import static org.junit.jupiter.api.Assertions.*; @SpringBootTest class LettuceLockStockFacadeTest { @Autowired private LettuceLockStockFacade lettuceLockStockFacade; @Autowired private StockRepository stockRepository; @BeforeEach public void before(){ stockRepository.saveAndFlush(new Stock(1L, 100L)); } @AfterEach public void after(){ stockRepository.deleteAll(); } @Test public void 동시에_100개의_요청() throws InterruptedException { int threadCount = 100; ExecutorService executorService = Executors.newFixedThreadPool(32); CountDownLatch latch = new CountDownLatch(threadCount); for(int i = 0; i < threadCount; i++){ executorService.submit(() -> { try{ lettuceLockStockFacade.decrease(1L, 1L); } catch (InterruptedException e) { throw new RuntimeException(e); } finally { latch.countDown(); } }); } latch.await(); Stock stock = stockRepository.findById(1L).orElseThrow(); assertEquals(0, stock.getQuantity()); } } 이렇게 코딩했고 dockre에 redis를 설치하고 window Shell에서 데이터가 남아 있을까봐 1번 key 값을 삭제해서 돌렸는데도 오류가 발생했습니다. 또한 레디스가 실행이 되지 않은 채 했을까봐 ping을 입력했는데 pong이라는 응답을 받았습니다. Hibernate: drop table if exists stock 2024-11-03T22:08:40.414+09:00 DEBUG 17108 --- [ Test worker] org.hibernate.SQL : create table stock (id bigint not null auto_increment, product_id bigint, quantity bigint, version bigint, primary key (id)) engine=InnoDB Hibernate: create table stock (id bigint not null auto_increment, product_id bigint, quantity bigint, version bigint, primary key (id)) engine=InnoDB 2024-11-03T22:08:40.439+09:00 INFO 17108 --- [ Test worker] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' 2024-11-03T22:08:41.136+09:00 INFO 17108 --- [ Test worker] o.s.d.j.r.query.QueryEnhancerFactory : Hibernate is in classpath; If applicable, HQL parser will be used. 2024-11-03T22:08:42.092+09:00 WARN 17108 --- [ Test worker] 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 2024-11-03T22:08:42.990+09:00 INFO 17108 --- [ Test worker] c.e.s.facade.LettuceLockStockFacadeTest : Started LettuceLockStockFacadeTest in 6.21 seconds (process running for 7.345) 2024-11-03T22:08:43.504+09:00 DEBUG 17108 --- [ Test worker] org.hibernate.SQL : insert into stock (product_id,quantity,version) values (?,?,?) Hibernate: insert into stock (product_id,quantity,version) values (?,?,?) 2024-11-03T22:08:44.203+09:00 DEBUG 17108 --- [ Test worker] org.hibernate.SQL : select s1_0.id,s1_0.product_id,s1_0.quantity,s1_0.version from stock s1_0 where s1_0.id=? Hibernate: select s1_0.id,s1_0.product_id,s1_0.quantity,s1_0.version from stock s1_0 where s1_0.id=? 2024-11-03T22:08:44.245+09:00 DEBUG 17108 --- [ Test worker] org.hibernate.SQL : select s1_0.id,s1_0.product_id,s1_0.quantity,s1_0.version from stock s1_0 Hibernate: select s1_0.id,s1_0.product_id,s1_0.quantity,s1_0.version from stock s1_0 2024-11-03T22:08:44.252+09:00 DEBUG 17108 --- [ Test worker] org.hibernate.SQL : delete from stock where id=? and version=? Hibernate: delete from stock where id=? and version=? Expected :0 Actual :100 <Click to see difference> org.opentest4j.AssertionFailedError: expected: <0> but was: <100> at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151) at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132) at org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:197) at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:182) at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:177) at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:639) at com.example.stock.facade.LettuceLockStockFacadeTest.동시에_100개의_요청(LettuceLockStockFacadeTest.java:55) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended 어디를 더 수정해야 하는지 모르겠습니다..
package collection.deque.test.stack; import java.util.ArrayDeque; import java.util.Deque; public class BrowserHistory { private Deque<String> history = new ArrayDeque<>(); private String currentPage = null; public void visitPage(String s) { if(currentPage != null){ history.push(currentPage); } currentPage = s; System.out.println("방문 : "+s); } @Override public String toString() { return "BrowserHistory{" + "stack=" + history + '}'; } public String goBack() { if(!history.isEmpty()){ currentPage = history.pop(); System.out.println("뒤로가기 : "+currentPage); return currentPage; } return null; } } ////////////////////// package collection.deque.test.stack; public class BrowserHistoryTest { public static void main(String[] args) { BrowserHistory browser = new BrowserHistory(); // 사용자가 웹페이지를 방문하는 시나리오 browser.visitPage("youtube.com"); browser.visitPage("google.com"); browser.visitPage("facebook.com"); // 뒤로 가기 기능을 사용하는 시나리오 String currentPage1 = browser.goBack(); System.out.println("currentPage1 = " + currentPage1); String currentPage2 = browser.goBack(); System.out.println("currentPage2 = " + currentPage2); System.out.println(browser); } } 위의 goBack 메서드 실행코드가 Pop()인데 currentPage1 에서 facebook이 출력이되지않고 google이 출력되는 이유가 궁금합니다 스택구조는 마지막에 입력한것이 나오게 되어있는데 그 전에 입력한것이 왜 나오는 이유가 궁금합니다
따라하며 배우는 노드, 리액트 시리즈 - 레딧 사이트 만들기(NextJS)(Pages Router)
postgres 강의 중 docker compose up을 실행하면 아래와 같이 오류가 뜹니다. version: "3" services: db: image: postgres: latest container_name: postgres restart: always ports: - "5432:5432" environment: POSTGRES_USER: "${DB_USER_ID}" POSTGRES_PASSWORD: "${DB_USER_PASSWORD}" volumes: - ./data:/var/lib/postgresql/data yml 파일은 수업 그대로 위/아래와 같이 작성했는데 4번쨰 줄 postgres 부분이 인식이 안되는것 같아서 이것 때문인지... 구글링을 해봐도 해결 방법을 모르겠습니다!
Next에서 자체적으로 제공하는 에러 바운더리인 error.js 와 서스펜스인 loading.js는 '서버 컴포넌트'의 에러와 로딩만 처리하는 것인가요? 예를 들어 서버 컴포넌트인 page.tsx의 하위 클라이언트 컴포넌트에서 에러가 발생했을 때는 error.js에서 캐치가 안 되는 것인가요...?
안녕하세요! 너무 알찬강의 잘 듣고 있습니다! 강의에서 BlockingQueue의 offer와 poll은 일정시간만큼 대기하신다고 하셨는데요, 이때 이들이 기다리는 영역은 어디가 되는건가요..? ReentrantLock을 획득하기 위한 대기 wait()을 위한 대기 아니면 그 어느것도 상관없이 항상 대기 Queue가 된 후 2초인걸까요?! 그리고 만약 어떤 상황이든 2초만을 기다리고 종료시키는 방법이라면, Lock을 획득하고, 생산자나 소비자가 무언가 데이터를 처리하는 과정에서 2초가 지났을 때 이 작업을 강제 종료해 버리면 동일하게 동시성 문제가 발생할 수 있지 않을까요? (실제 처리하지 않았지만 실패로 결과가 나타난다던가..)
1. 강의 내용과 관련된 질문인가요?예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예 [질문 내용] 쓰레드 풀 core사이즈와 max사이즈가 어떻게 관리 되는지는 어느정도 이해한 것 같은데, 이 예제에서 BlockingQueue안에서 쓰레드들이 스레드 대기 집합, 락 대기 집합에 어떻게 관리되는 것 까지 이해해보려고 하니 매우 어렵네요.. ai야 도와줘~!
LocalDateTime.now()로 현재 시간을 출력하면 소수점 아래 단위는 9자리(ns)까지 출력이 됐습니다. 근데 Windows에서 시스템 시계(?) 클럭(?)의 정밀도는 ms까지 보장한다고 알고 있는데 LocalDateTime.now()의 정밀도는 ns(소수점 아래 9자리)까지 보장하나요 ms(소수점 아래 3자리)까지 보장하나요??
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. package memory; public class JavaMemoryMain2 { public static void main(String[] args) { System. out .println("main start"); method1 (); System. out .println("main end"); } static void method1() { System. out .println("method1 start"); Data data1 = new Data(10); method2 (data1); System. out .println("method1 end"); } static void method2(Data data2) { System. out .println("method2 start"); System. out .println("data.value=" + data2.getValue()); System. out .println("method2 end"); } } 다음과 같은 코드로 자바 프로그램을 1번 실행했다가 종료하면, 강의 내용에선 x001(예를 들어서) 참조값을 가진 Data 인스턴스를 참조하는 곳이 더이상 없기에 GC의 제거 대상이 된다고 하셨는데요, 그렇다면 어떤 자바 프로그램이든 한 번 실행했다가 종료된 직후에는 자바 메모리 힙 영역에 한 번 실행될 때 사용했던 객체들이 남아있게 되고 전부 참조하는 곳이 더 이상 없기에 전부 GC의 제거 대상이 된다고 생각하면 될까요? 마치 콘서트 한 번 진행하고 나서 발생한 쓰레기들을 청소한다고 생각하면 될지 궁금해서 여쭤봅니다~
비즈니스 로직만을 담당하는 BookApplicationService 를 두는게 새롭고 좋은 구조 아닐까 생각이 들어서 제 생각이 맞는지 궁금해서 여쭙습니다. Query 이름의 서비스는 조회만을 Command 는 등록, 수정, 삭제 담당하는 것이고 또한 이런 서비스 구조가 순환참조 발생 가능성도 줄일 수 있겠죠? p.s 강의 잘 듣고 있습니다. 처음 겪어보는 내용들이 많아서 재밌고 배울게 많네요. 강의 빨리 더 내주십시오.
<섹션 2 - 제네릭이 필요한 이유> 부분인데요. IntegerBox 클래스는 set 메서드에 변수가 value로 작명 되어있습니다. 그러나,StringBox 클래스는 set 메서드에 변수가 object로 작명 되어 있습니다. StringBox에 set 함수 매개변수에, String str이 아니라, String object라고 하신 이유가 혹시 있는걸까요? String str이라고 해도 물론 되겠지만, 혹시 "String object"로 매개변수를 받도록 하신 특별한 의도가 있는건가 싶어서요.