좋은 강의 잘 듣고 있습니다. <의존성 검증: Controller는 Entity를 사용하고 있을까?> 강의에서요. 11:40초 쯤에서 에러 로그들이 의미하는 것이 궁금합니다. Class <com.jyujyu.dayonetest.model.StudentFail> is annotated with <jakarta.persistence.Entity> Class <com.jyujyu.dayonetest.model.StudentPass> extends class <java.lang.Object> .. 위 같은 에러는 해당 모델들(StudentFail, StudentPass) 이 @Entity 로 정의되었으므로 jakarta.persistence.Entity, jakarta.persistence.Table> 에서 사용된 것은 알겠는데 java.lang.Object 로 사용된 것은 어떻게 봐야 하나요? 단순 Object 라면, 모든 클래스는 Object 를 의존하는 것 아닌가요? 미리 답변 감사합니다!
MacOS M2에서 설치 진행하다 vagrant up 진행 시 아래와 같은 오류가 발생합니다. box도 설치하고 했는데 여기서 막히네요. 확인 부탁 드립니다. Bringing machine 'cp-k8s-1.30.0' up with 'vmware_desktop' provider... Bringing machine 'w1-k8s-1.30.0' up with 'vmware_desktop' provider... Bringing machine 'w2-k8s-1.30.0' up with 'vmware_desktop' provider... Bringing machine 'w3-k8s-1.30.0' up with 'vmware_desktop' provider... ==> cp-k8s-1.30.0: Box 'sysnet4admin/Ubuntu-k8s' could not be found. Attempting to find and install... cp-k8s-1.30.0: Box Provider: vmware_desktop, vmware_fusion, vmware_workstation cp-k8s-1.30.0: Box Version: >= 0 ==> cp-k8s-1.30.0: Loading metadata for box 'sysnet4admin/Ubuntu-k8s' cp-k8s-1.30.0: URL: https://vagrantcloud.com/api/v2/vagrant/sysnet4admin/Ubuntu-k8s The box you're attempting to add doesn't support the provider you requested. Please find an alternate box or use an alternate provider. Double-check your requested provider to verify you didn't simply misspell it. If you're adding a box from HashiCorp's Vagrant Cloud, make sure the box is released. Name: sysnet4admin/Ubuntu-k8s Address: https://vagrantcloud.com/api/v2/vagrant/sysnet4admin/Ubuntu-k8s Requested provider: vmware_desktop vmware_fusion vmware_workstation (amd64)
타켓이 된 해당 인스턴스 세부 정보에 있는 서브넷 id를 보고 똑같은 거를 선택하라고 하셨는데요. 강의 중 내용에서는 `2b`로 되어있어서 2a,2c는 상관 없지만 ,2b는 무조건 골라야 한다고 하셨는데, 제가 강의를 보고 작성 해봤을 때 제 서브넷 ID는 `2a`로 되어있더라구요, 그럼 이때는 `2a`를 무조건 고르고, 2b, 2c는 상관 없다로 받아들여도 되는 걸 까요??
graphql-upload 버전 13.0.0으로 강의와 똑같이 맞춰줬는데도 에러가납니다 ㅠ_ㅠ 혹시 해결방안이있을까요? 계속 검색중인데 힘드네유.. 혹시나 제가 해결했다면 해결했다고 댓글달겠습니다 해결했다는 댓글이 없으면 계속해서 트라이중인거니 댓글로 도와주시면 너무 감사하겠습니다
우선 이런 강의를 올려주셔서 감사드립니다. 궁금한 점은 이미지는 레이어로 되어 있고, 이미 존재하는 레이어의 경우 추가로 다운로드 하지 않는다고 이해했습니다. 그리고 실제로 두 번째 이미지인 config-nginx 다운로드 받을 때도 이미 있는 레이어의 경우 Already exists 라고 다운로드 하지 않는 부분도 확인했습니다. 그런데 docker image ls 로 검색했을 때 나오는 size는 다 142M으로 동일하게 나오는 데 이미지 용량이 아닌건가요? 물리 용량이 아닌 논리 용량 일까요?
docker run -e MYSQL_ROOT_PASSWORD=pwd1234 -d -p 3306:3306 -v /mnt/c/Users/SSAFY/desktop/docker/docker-mysql/mysql_data:/var/lib/mysql mysql 명령어 실행시 2024-07-03T08:05:15.221312Z 0 [ERROR] [MY-010295] [Server] Could not set file permission for ca.pem 2024-07-03T08:05:15.221336Z 0 [ERROR] [MY-013236] [Server] The designated data directory /var/lib/mysql/ is unusable. You can remove all files that the server added to it. 이런 오류가 발생합니다. 권한부여 등 여러 방법을 시도했지만 모두 실패했고 wsl이 아닌 그냥 윈도우 터미널로 실행했을때는 정상 작동 하엿습니다 어떻게 해결할까요??
질문 답변을 제공하지만, 강의 비용에는 Q&A는 포함되어 있지 않습니다. 다만 실습이 안되거나, 잘못된 내용의 경우는 알려주시면 가능한 빠르게 조치하겠습니다! [질문 전 답변] 1. 강의에서 다룬 내용과 관련된 질문인가요? [예 | 아니요] 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? [예 | 아니요] 3. 질문 잘하기 법을 읽어보셨나요? [예 | 아니요] ( https://www.inflearn.com/blogs/1719 ) 4. 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 5. vagrant up 에서 발생하는 문제는 주로 호스트 시스템(Windows, MacOS)과 연관된 다양한 조건에 의해 발생합니다. 따라서 이를 모두 제가 파악할 수 없어서 해결이 어렵습니다. vagrant up 으로 진행이 어렵다면 제공해 드리는 가상 머신(VM) 이미지를 import해서 진행하시기 바랍니다. ( https://www.inflearn.com/questions/992407/comment/281901 ) [질문 하기] k run chk-info --image=sysnet4admin/chk-info 입력 후 서버에 접속할 수 없다는 메세지가 뜹니다. 물론 k get po 를 입력해도 오류가 나네요
안녕하세요! 강사님 덕분에 현재 진행중인 프로젝트 코드에 동시성 문제 잘 적용하고 있습니다. 다름이 아니라, 현재 MSA 프로젝트를 하고 있어 쿠폰 쪽 DB는 쿠폰만 쓰기 때문에 부하에 따른 걱정은 덜어도 될 것 같아 카프카가 아닌 Redis의 INCR 명령어를 통해서 선착순 쿠폰 로직의 Race condition 문제를 잡아보려고 하고 있는데요. 질문에 앞서 프로젝트 환경을 말씀드리자면 강의와 동일하게 docker pull redis 해서 이미지로 다운받아 실행했고, 6380 포트로 연결해줘서 yml 설정과 Config 설정 또한 해줬습니다. INCR 키 값을 살짝 바꿔서 coupon_count:{couponId} 가 되도록 해줬습니다. 문제는 1000개의 쓰레드로 요청을 날렸을 때 여러번의 요청 테스트는 통과가 안된다는 점입니다.. 쿠폰 발급이 100개 되어야하는데 102, 103번 애매하게 되고 있습니다. (postman으로 API 요청 날릴 때마다 해당 키 값의 value가 1씩 잘 증가하는 것은 확인했습니다) RDB 상에서도 100개의 발급 내역이 잘 들어오고 있구요. (물론 테스트가 DB에 영향을 미치면 안되지만요ㅠㅠ) 이런 경우는 왜 그런건가요?? 코드도 첨부 하겠습니다. 감사합니다!! /* * 선착순 쿠폰 발급 */ @Transactional public CouponIssuedResponseDto issueFirstComeCoupon(CouponIssuedRequestDto request) { // 쿠폰 ID로 쿠폰을 찾고, 존재하지 않으면 예외 처리 Coupon coupon = couponRepository.findById(request.couponId()) .orElseThrow(() -> new CustomException(ErrorCode.COUPON_NOT_FOUND)); // 발급 가능한 쿠폰 수량 확인 -> Redis Long currentCount = couponCountRepository.getCount(request.couponId()); if (currentCount > coupon.getMaxQuantity()) { throw new CustomException(ErrorCode.COUPON_ISSUE_LIMIT_EXCEEDED); } // 새로운 쿠폰 발급 -> Redis에서 수량 증가 Long newCount = couponCountRepository.increment(request.couponId()); if (newCount > coupon.getMaxQuantity()) { throw new CustomException(ErrorCode.COUPON_ISSUE_LIMIT_EXCEEDED); } CouponIssued issued = CouponIssued.builder() .coupon(coupon) .userId(request.userId()) .issuedAt(LocalDateTime.now()) .build(); CouponIssued saved = couponIssuedRepository.save(issued); return CouponIssuedResponseDto.fromEntity(saved); } @Repository public class CouponCountRepository { private final RedisTemplate<String, Long> redisTemplate; public CouponCountRepository(RedisTemplate<String, Long> redisTemplate) { this.redisTemplate = redisTemplate; } public Long increment(Long couponId) { String key = "coupon_count:" + couponId; return redisTemplate.opsForValue().increment(key, 1); } public Long getCount(Long couponId) { String key = "coupon_count:" + couponId; Long count = redisTemplate.opsForValue().get(key); return count != null ? count : 0L; } } @BeforeEach public void setUp() { // Redis 초기화 redisTemplate.opsForValue().set("coupon_count:10", 0L); } @AfterEach public void tearDown() { couponRepository.deleteAll(); couponIssuedRepository.deleteAll(); redisTemplate.delete("coupon_count:10"); // 테스트 끝난 후 Redis 데이터 삭제 } @Test public void multipleUserIssueCoupon() throws InterruptedException { // Given // 쿠폰을 생성 Coupon coupon = Coupon.builder() .name("Test Coupon") .couponCode("TEST100") .discountRate(10) .maxQuantity(100L) .issuedQuantity(0L) .expiresAt(LocalDateTime.now().plusDays(30)) .couponType(CouponTypeEnum.FIRST_COME) .build(); couponRepository.save(coupon); Long couponId = coupon.getCouponId(); // 고정된 couponId 사용 Long userId = 1L; // 고정된 userId 사용 // When int threadCount = 1000; ExecutorService executorService = Executors.newFixedThreadPool(50); CountDownLatch latch = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { executorService.submit(() -> { try { CouponIssuedRequestDto request = new CouponIssuedRequestDto(10L, userId); couponIssuedService.issueFirstComeCoupon(request); } catch (CustomException e) { // Expected exception when limit is exceeded } finally { latch.countDown(); } }); } latch.await(20, TimeUnit.SECONDS); // Then Long count = redisTemplate.opsForValue().get("coupon_count:10"); System.out.println("coupon_count:10 = " + count); // 디버깅용 로그 추가 assertThat(count).isNotNull(); // count가 null이 아닌지 확인 assertThat(count).isEqualTo(100); // 발급된 쿠폰의 수를 확인 long issuedCount = couponIssuedRepository.count(); assertThat(issuedCount).isEqualTo(100); }
선생님 좋은 강의 감사합니다. 도중에 문제가 생겼는데 도무지 해결이 안 돼 글 남깁니다. ㅠㅠ 너무 위험해 보여서 제 IP로 진행하고 싶어 보안 그룹에서 SSH 22번 포트 설정할 때 제 IP로 설정을 하였습니다. 제 맥북 터미널을 통한 SSH 원격 접속은 잘 되는데, 콘솔에서 강의에 나오는 웹 방식으로는 접속이 안 되고 있습니다. 왜 이럴까요? IP가 잘못된 것은 아닙니다. IP를 바꾸고 제 맥북 터미널에서 SSH 접속을 해보면 접속에 실패하는 것으로 확인했습니다. 도대체 왜 이럴까요?
안녕하세요. https://kubetm.github.io/k8s/09-intermediate-architecture/networking/ 위 부분의 네트워킹 실습 중 docker ps 명령어를 입력했는데 -bash: docker: command not found ^ 위처럼 명령어를 찾을 수 없다고 하더라구요. 찾아보니 쿠버네티스 1.27 버전에서는 containerd가 container-runtime으로 변경된듯 합니다. Dockershim이 1.24부터 빠졌다는데 이거랑 관련이 있을까요?: https://kubernetes.io/blog/2022/02/17/dockershim-faq/ [root@k8s-master ~]# kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME k8s-master Ready control-plane 35d v1.27.2 192.168.56.30 <none> Rocky Linux 8.9 (Green Obsidian) 4.18.0-513.18.1.el8_9.x86_64 containerd://1.6.21 k8s-node1 Ready <none> 35d v1.27.2 192.168.56.31 <none> Rocky Linux 8.9 (Green Obsidian) 4.18.0-513.24.1.el8_9.x86_64 containerd://1.6.21 k8s-node2 Ready <none> 35d v1.27.2 192.168.56.32 <none> Rocky Linux 8.9 (Green Obsidian) 4.18.0-513.24.1.el8_9.x86_64 containerd://1.6.21 혹시 시간되시면 나중에 실습파트의 명령어 부분을 수정해 주실 수 있으신가요? 강의 정말 잘 듣고 있습니다. 많은 가르침을 주셔서 감사합니다.
안녕하세요 선생님. 저는 next.js로 만든 프론트엔드와, nestjs로 만든 백엔드를 ECS에 각각 서비스로 만들어 클러스터를 관리하고 있습니다. 프론트엔드에서 fetch() 함수로 백엔드에 요청을 보내는데, 이 때 백엔드 url을 결정하는데 어려움을 겪고 있습니다. 처음에는, 서비스 연결 을 적용해서 Request URL: http://languin-backend-container-8000-tcp.languin-cluster:8000/auth/check/email 이런식으로 적용했었는데, ERR_NAME_NOT_RESOLVED 이란 에러를 만났습니다. 혹시 이 문제가 fetch() 함수가 프론트엔드가 실행되고 있는 컨테이너가 아니라, 사용자 브라우저이기 때문에 Inter Service Communication이 적용이 안되는 건가요? 프론트에서 백엔드로 요청을 보낼 수 있도록 하려면, 백엔드 주소를 어떻게 정해야 하나요? Route53을 사용해야 하는건가요?
index.html 파일 혹은 nginx.conf 파일을 수정한다고 했을때 읽기 레이어에 있는 파일들을 수정하는게 아니라 읽기 레이어에 있는 파일들을 읽기/쓰기 레이어로 COPY 해오고 COPY 해온 파일들을 수정해서 사용하는 건가요? 위 내용이 맞다면 굳이 읽기쪽 레이어에 있는 파일을 COPY 안하고 읽기/쓰기에 있는 파일을 바로 수정하면 안되는건지 궁금합니다. 읽기/쓰기 레이어에 있는 nginx.conf 파일을 수정한다고 했을때 실무에서의 흐름이 EC2에 접속하고 docker를 설치하고 nginx 이미지를 pull 하고 nginx 컨테이너를 띄운다음 nginx 컨테이너에 접속해서 nginx.conf 파일을 수정하기 가 맞는건지 궁금합니다.
입문자를 위한 Spring Boot with Kotlin - 나만의 포트폴리오 사이트 만들기
안녕하세요. 강의 내용중에 궁금한게 있어서 질문 드립니다. 로그인 폼을 거치지 않고 POST body를 전달해서 바로 로그인 해보면 어떨까 해서 시도 했는데 잘 되지 않네요 ... fun filterChain(httpSecurity: HttpSecurity): SecurityFilterChain { return httpSecurity .authorizeHttpRequests { authorizeHttpRequests -> authorizeHttpRequests .requestMatchers(AntPathRequestMatcher("/admin/**")).authenticated() .anyRequest().permitAll() }.csrf {csrf -> csrf.disable() }.headers { headers -> headers.addHeaderWriter(XFrameOptionsHeaderWriter(XFrameOptionsHeaderWriter.XFrameOptionsMode.SAMEORIGIN)) }.formLogin { formLogin -> formLogin.defaultSuccessUrl("/h2-console") // 추가 ////////////////////////////////////////// formLogin.loginProcessingUrl("/login") formLogin.usernameParameter("email") formLogin.passwordParameter("password") }.logout { logout-> logout.logoutRequestMatcher(AntPathRequestMatcher("/admin/logout")) .logoutSuccessUrl("/") }.build() } 강의 내용중에 제가 주석으로 추가 내용 달았어요... 그리고 Entity는 아래처럼 구성했습니다. class Account(email: String, pw: String): BaseEntity(), UserDetails { ........ @field:NotNull @Column(unique = true) var email: String = email @Column(name = "password") var pw: String = pw 그래서 위에처럼 전달했습니다. 그리고 run accountRepository에 디버깅 브레이크를 걸고 Post 메세지를 쐈습니다. 그런데 디버깅 걸린건 "" 공백이네요. 프론트 엔드에서 시큐리티 로그인페이지를 만들고 아디이 패스워드를 전달해서 제어하려고 시도 했는데 뭔가 문제가 있나봐요... 답변 해주지면 감사하겠습니다. @Service class AdminSecurityService( private val accoutRepository: AccountRepository ) : UserDetailsService { override fun loadUserByUsername(email: String): UserDetails { return accoutRepository.findByEmail(email) .orElseThrow{RuntimeException("사용자 정보를 찾을 수없습니다.") } } } ========= 추가 질문 드려요 지금 시큐리티 로그인은 Spring boot 초기화 스타트 한후 유저의 접근을 막는 방화벽 같은 용도로 사용하는건가요?? 아니면 웹 "react" http://localhost:3000/ 에서 로그인 폼 게발한후에 로그인 정보(이메일, 패스워드 아이디)를 http://localhost:8080/login 에 POST / GET 방식으로 전달하고 시큐리티에 접근해서 로그인 하는 사용자 로그인 목적으로 사용하는건지 ... 이게 intellij IDEA에 웹페이지랑 스프링 부트를 개발해서 강의내용은 이해하는데 프론트 엔드와 백엔드와의 통신으로 본다면 좀 헛깔려요 로그인 페이지는 프론트 엔드에서 만드는게 아니라 백엔드에서 만들어야하나... 그럼 프론트엔드에서 백엔드에 접근해 시큐리티 로그인을 한후 로그인 성공 했다는 메세지를 어떻게 프론트 엔드에 전달해야되는지... 그냥 관리자 페이지(사용자 목록 리스트나 사용자 로그인 접근 정보를 보는 용도)를 사용할때 시큐리티 로그인을 사용하고 user로그인(작성한 글, 좋아요 같은 카운트, 로그인한 전화번호, 사진 정보)은 따로 user 로그인하는 Api Controller에 접근해서 로그인 하는건지 좀 헛깔려요. 현재 구글에서 찾아보면 관리페이지는 시큐리티로 접근 사용자, 게스트튼 로그인 API로 접근해서 관리하는거 같은데 정보 찾는게 어렵네요...
안녕하세요 mysql_data는 어떤 역할하고 있는지 궁금합니다. mysql_data를 없이 docker에 mysql를 넣었는데 실행이 중단되고 아래와 같은 오류가 나와서 이유를 알고싶습니다 그리고 항상 docker에 mysql에 호스트 내부에 파일을 저장할때 새로운 my_data의 이름이 아니여도 다른 파일경로를 지정을 해줘야하는건가요?