묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
setter 안 쓰고 연관관계 편의 메서드 생성
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]무분별한 setter 사용은 엔티티가 왜 변경되는지 추적하기가 힘들어지므로 가급적 setter은 생성하지 말고 엔티티에 대한 값 변경을 하려면 편의 메서드를 통해 변경하도록 김영한 선생님께서 권고하셨습니다.하지만 연관관계 편의 메서드의 로직을 구성할 때 setter가 사용됐는데 setter을 사용하지 않고 연관관계를 설정하는 방법이 궁금합니다 !
-
해결됨Java/Spring 테스트를 추가하고 싶은 개발자들의 오답노트
테스트 메서드 마다 Environment variables 설정이 불편...
강의시나리오 대로 진행하다보니 살짝 불편한 부분이 있어서..(어쩜 중간에 코멘트가 있었는데 놓친것일 수도..)서비스 설정 중 메일발송 설정 정보를 실행속성으로 구성하는데테스트도 동일하게 구성하다보니(test-application.properties )Intellij >Edit Configurations > JUnit 실행인스턴스 별 Environment variables 를 설정해줘야 실행이 되는듯 합니다. 테스트 메서드를 만들때마다 실행인스턴스를 설정해야하는게 불편해서 그냥 메일발송 설정을 test-application.properties 에 하드코딩하고 진행해봅니다.(혹시.. 다른 더 스마트한 방법이 있을까? Intellij ? spring?) [확인1]'테스트 추가하기: h2를 이용한 repository 테스트' 강의 1:16초를 보면 git에서 받은 application.properties 파일과 강의의 소스가 다른것 으로 보입니다. Environment variables 에서 설정한 속성이 없어서 해당 강의에서는 불편함 없이 진행된 것 으로 이해했습니다. [확인2] 그런데'토이 프로젝트 살펴보기' 강의 7:42 에 확인되는 설정정보는 git 소스와 동일하것으로 확인됩니다. 강의를 훑어볼때는 그냥 넘어갔는데, 따라하며 보니 눈에 밟히는게 좀 있네요. 제가 놓친부분이라면 양해 바라며, 시나리오 상 연결부분이 필요한 내용이면 코멘트 부탁드립니다. 저와 같이 길잃은 양들을 살펴주소서~[git 설정파일]
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
@SpringBootTest 질문드립니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용] 테스트 작성시에 어떤 테스트는 클래스 위에 @SpringBootTest 를 넣으시고 어떤 테스트는 안 넣으시던데 어떨때 넣고 어떨때 안 넣는건지 궁금합니다.
-
미해결재고시스템으로 알아보는 동시성이슈 해결방법
RedissonLock에서 질문드립니다.
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.안녕하세요. 강의 열심히 듣고 있습니다. Redisson 관련 실습을 진행하고 있는데, 시간을 변경해도 계속 test results가 fail이 뜨고 있습니다. 관련 원인을 모르겠습니다. github에서 코드를 복붙해봐도 똑같아서 문의드립니다. 어떤게 오류인지도 잘 모르겠어서 질문드립니다 감사합니다.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.RedissonLockStockFacadeTest.동시에_100개의요청(RedissonLockStockFacadeTest.java:58) 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)
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
엔티티가 복잡할때, 테스트만을 위한 간단한 생성자를 만들어도 될까요?
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]토이프로젝트 진행중 궁금한점이 생겼습니다.핵심 엔티티에 정적 팩토리 메서드로 생성방법을 만들었는데,여러가지 연관관계와 필드값들이 많이 포함되어 있습니다. 리포지토리를 테스트하려고 하니,엔티티 생성에 너무 많은 코드들이 사용되어서,테스트만을 위한 필수 필드값만 포함된 생성자나 메서드를만드는 것이 올바른 방법인지 궁금증이 생겼습니다.
-
해결됨견고한 결제 시스템 구축
Ledger 및 Wallet 서비스에서 Kafka Consumer PaymentEventMessageHandler 에 typecast 문제가 발생됩니다.
@Bean public Consumer<Message<PaymentEventMessage>> consume() { return message -> { PaymentEventMessage payload = message.getPayload(); LedgerEventMessage ledgerEventMessage = doubleLedgerEntryRecordUseCase.recordDoubleLedgerEntry(message.getPayload()); streamBridge.send("ledger", ledgerEventMessage); }; } 해당 로직은 Ledger 서비스의 Kafka 메시지 Consumer 역할을 맡고 있는 'consume' 메소드 입니다. 정상적으로 결제 confirm 완료가 되면 Kafka 에 메시지를 정상적으로 등록 된 것을 확인 하였는데요.이 후 consumer 에서 메시지를 잘 가지고 오지만 byte[] 타입이라 PaymentEventMessage 로 타입캐스트 하는데 문제가 발생되네요.. Kafka 설정에서 Deserialize 설정만 해주면 되는 느낌인데... 구글링 해봐도... 잘 안되어서 이렇게 질문 드립니다! 에러 문구 class [B cannot be cast to class com.example.ledgerservice.ledger.domain.PaymentEventMessage ([B is in module java.base of loader 'bootstrap'; com.example.ledgerservice.ledger.domain.PaymentEventMessage is in unnamed module of loader 'app')
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
th:block을 안쓰는게 좋은 이유가 궁금합니다
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]스프링 MVC 2편 타임리프-블록 강의에서 "이런 거(th:block)은 당연히 안쓰는게 좋"다고 하셨습니다.강의에는 그렇게 말씀하신 이유가 나오지 않아 궁금합니다. 제가 유추한 바로는, th:block은 파일 그대로 열었을 때와 타임리프로 열었을 때 동작이 달라서 내추럴 템플릿이라는 타임리프의 장점을 퇴색시키기 때문에 권장하지 않는다고 생각했습니다.제가 이해한 내용이 맞는지 궁금합니다.
-
해결됨스프링 핵심 원리 - 기본편
섹션 10. 빈 스코프 질문
public class PrototypeTest { @Test void PrototypeBeanTest() { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PrototypeBean.class); System.out.println("find PrototypeBean1"); PrototypeBean prototypeBean1 = ac.getBean(PrototypeBean.class); System.out.println("find PrototypeBean2"); PrototypeBean prototypeBean2 = ac.getBean(PrototypeBean.class); System.out.println("prototypeBean1 = " + prototypeBean1); System.out.println("prototypeBean2 = " + prototypeBean2); assertThat(prototypeBean1).isNotSameAs(prototypeBean2); } static class PrototypeBean { @PostConstruct public void init() { System.out.println("PrototypeBean.init"); } @PreDestroy public void destroy() { System.out.println("PrototypeBean.destroy"); } } }결과prototypeBean1 = hello.core.scope.PrototypeTest$PrototypeBean@29caf222prototypeBean2 = hello.core.scope.PrototypeTest$PrototypeBean@29caf222 강의에서 프로토타입 스코프를 코드로 작성하고 실행하는 도중 깜빡하고 스코프 애노테이션을 넣는 걸 깜빡했습니다.그런데 prototypeBean1 과 prototypeBean2 의 참조값이 같게 나왔습니다.@Configuration을 적지 않았는데 왜 싱글톤이 적용이 된 건지 잘 이해가 가지 않습니다...
-
미해결Practical Testing: 실용적인 테스트 가이드
테스트할 때 Auditing 없이 원하는 날짜를 설정할 수 잇을까요?
공부삼아서 과제 프로젝트에 테스트를 도입하다가 궁금한 게 잇어서 질문드립니다. 거래내역 조회를 구현할 때 2024-05-30 같은 거래가 발생할 날짜는 auditing, @CreatedAt 통해 저장된 createdAt에서 가져오도록 구현했습니다. (디자인과 달리, 최근 거래일수록 위로 오도록 변경되었습니다) 구현이 끝난 뒤, 테스트할 때 createAt을 임의로 변경하기 위해 BaseEntity의 private를 protected, 그리고 createdAt을 변경하는 메서드를 추가햇습니다. (이게 맞는 접근인지는 잘 모르겟네요... 할 때에도 이렇게 해도 되나? 라는 의문이 계속 들엇습니다...)@DisplayName("유저의 계좌 내역을 불러올 수 있다.") @Test void getUserStatements() { // given (6/5 18:00) LocalDateTime now = LocalDateTime.of(2024, 6, 5, 18, 0, 0); User u1 = User.of("test1", "id1", "pw"); User u2 = User.of("test2", "id2", "pw"); List<User> users = userRepository.saveAll(List.of(u1, u2)); User loginUser = users.get(0); User notLoginUser = users.get(1); Account a1 = Account.of("111-222-3333", 1000, loginUser); Account a2 = Account.of("111-222-3334", 2000, notLoginUser); List<Account> accounts = accountRepository.saveAll(List.of(a1, a2)); Account loginUserAccount = accounts.get(0); Account notLoginUserAccount = accounts.get(1); // 자신 계좌로 입금 (조회 대상), 6/5 발생 Statement s1 = createStatementForTest(loginUserAccount, loginUserAccount, 100, DEPOSIT); // 자신 계좌에서 출금 (조회 대상), 6/6 발생 Statement s2 = createStatementForTest(loginUserAccount, loginUserAccount, 200, WITHDRAW); // 자신 계좌에서 타 계좌로 이체 (조회 대상), 6/7 발생 Statement s3 = createStatementForTest(loginUserAccount, notLoginUserAccount, 300, TRANSFER); // 타 계좌에서 자신 계좌로 이체 (조회 대상), 6/8 발생 Statement s4 = createStatementForTest(notLoginUserAccount, loginUserAccount, 400, TRANSFER); // 타 계좌에서 타 계좌로 출금 (조회 대상 X), 6/9 발생 Statement s5 = createStatementForTest(notLoginUserAccount, notLoginUserAccount, 50000, WITHDRAW); statementRepository.saveAll(List.of(s1, s2, s3, s4, s5)); // when StatementResponse userStatement = statementService.getUserStatements(loginUser); // then assertThat(userStatement.getStatementInfos()).as("거래 이력을 조회할 수 있다.").hasSize(4) .extracting("amount", "type") .containsExactly( tuple(400, "이체"), tuple(-300, "이체"), tuple(-200, "출금"), tuple(100, "입금") ); assertThat(userStatement.getBalance()).as("계좌 잔액을 조회할 수 있다.").isEqualTo(1000); }(위 테스트 코드는 시간 설정 및 검증 코드를 제거한 테스트입니다.) 위 메서드와 plusDays() 통해 시간 설정 후, extracting에 "date" (createdAt에 yyyy-MM-dd를 적용시켜 String 형태로 저장) 를 추가해서 확인했을 때에는 의도한 대로 2024-06-08, 2024-06-07, 2024-06-06, 2024-06-05가 아닌, 전부 테스트를 실행한 시간으로(2024-06-05) 나오는 걸 확인했습니다. 일단은 date를 검증하는 로직을 빼고 테스트를 통과시켰고, postman에서 입금/출금/이체 등 실시 후 조회했을 때에도 의도한 대로 최근 거래가 위로 오도록, 날짜 형식도 의도한 대로 나온 것도 볼 수 있었습니다. 하지만 이 date를 postman이 아닌, auditing 없이 임의로 날짜를 설정한 후 테스트해 확인해보고 싶은데, 이 경우에는 어떻게 하면 될까요? auditing 잇는 상태로도 가능하다면 알려주시면 감사하겟습니다! 아래는 BaseEntity와 거래 내역을 저장하는 Statement Entity 코드입니다@Getter @MappedSuperclass @EntityListeners(AuditingEntityListener.class) public abstract class BaseEntity{ @CreatedDate private LocalDateTime createdDate; }import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import java.time.LocalDate; import java.time.LocalDateTime; import static jakarta.persistence.EnumType.*; @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Statement extends BaseEntity{ @Id @GeneratedValue(strategy= GenerationType.IDENTITY) private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="from_account") private Account from; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="to_account") private Account to; private int amount; @Enumerated(STRING) private TransactionType type; @Builder private Statement(Account from, Account to, int amount, transactionType type) { this.from = from; this.to = to; this.amount = amount; this.type = type; } public static Statement of(Account from, Account to, int amount, transactionType type){ return Statement.builder() .from(from) .to(to) .amount(amount) .type(type) .build(); } } 긴 글 읽어주셔서 감사합니다~
-
해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
스프링과 스프링부트
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]강의를 듣다가 api 예외 처리도 스프링 부트가 제공하는 기본 오류 방식을 사용할 수 있다고 말씀하셨는데요그럼 그 전에 사용했던 서블릿 방식은 스프링의 방식인가요?스프링과 스프링 부트의 차이점이 정확히 무엇인가요.??지금 방식들이 스프링 방식과 스프링 부트 방식들이 같이 혼합되어서 설명하고 있는 건가요?갑자기 헷갈려서 질문드립니다.
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
커넥션풀 궁금한게 있습니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]여기에 질문 내용을 남겨주세요.강의 이미지중에 애플리케이션 서버 내에 애플리케이션 로직, db드라이버, 커넥션 풀이 모두 포함되어 있는 이미지가 있습니다. 근데 스프링과같은 프로젝트 내에 db 드라이버, 커넥션 풀이 포함되어있는게 아닌가요? was 내에 db 드라이버, 커넥션풀이 포함되어 있는게 아니라.. 결론으로 1개의 jar, war 파일 내에 db 드라이버, 커넥션풀이 포함되어 있다고 이해하면 될까요? .. 감사합니다.
-
해결됨스프링 핵심 원리 - 기본편
섹션 8. 빈 생명주기 콜백
@Bean에 초기화 소멸 메서드 등록할 때 질문입니다!public class NetworkClient { private String url; public NetworkClient() { System.out.println("생성자 호출, url = " + url); } public void setUrl(String url) { this.url = url; } //서비스 시작시 호출 public void connect() { System.out.println("connect: " + url); } public void call(String message) { System.out.println("call: " + url + " message = " + message); } //서비스 종료시 호출 public void disConnect() { System.out.println("close + " + url); } public void init() { System.out.println("NetworkClient.init"); connect(); call("초기화 연결 메시지"); } public void close() { System.out.println("NetworkClient.close"); disConnect(); }@Configuration static class LifeCycleConfig { @Bean(initMethod = "init", destroyMethod = "close") public NetworkClient networkClient() { NetworkClient networkClient = new NetworkClient(); networkClient.setUrl("http://hello-spring.dev"); return networkClient; } } 결과생성자 호출, url = null NetworkClient.init connect: http://hello-spring.dev call: http://hello-spring.dev message = 초기화 연결 메시지 13:33:10.029 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing NetworkClient.close close + http://hello-spring.dev스프링 빈에 하기위해 networkClient객체가 생성되고 의존관계 주입까지 끝난 다음에 networkClient.setUrl("http://hello-spring.dev"); 로 url을 초기화하기 전에init() 메서드가 실행되는 걸로 이해를 했는데, 그럼 init() 메서드가 connect 호출 할 때 url은 여전히 null일테니 url의 초기화가 먼저 일어나야 합니다.그런데 초기화 콜백은 스프링 빈이 객체를 생성하고 의존관계 주입이 완료된 후,초기화가 되기 전에 일어나는 거 아닌가요..이럼 앞뒤가 안 맞는데 제가 놓치고있는 부분을 알려주시면 감사하겠습니다.
-
미해결견고한 결제 시스템 구축
다음 강의가 너무 기대되요:) 'Sacale-up 하며 배우는 대용량 트래픽 처리'
인프런에서 이런 질문 해도 될지 모르겠네요... fastcampus 에서 준비하고 있는강의 'Sacale-up 하며 배우는 대용량 트래픽 처리' 이부분 질문 및 건의? 사항이 있습니다.이번에 강의 payment 강의 들으면서 정말 유익한 강의라고 생각 합니다!질문 포함해서 조금 아쉬었던 부분이 있어서 개인적인 생각?이니! 참고만...1. 제가 듣기론 최소한 백엔드 측면에서 봤을때 아직까지 코틀린 보다 자바로 개발하신분이 많은거 같은데 굳이 코틀린으로 개발 하셨는지 알고 싶습니다. (참고로 다음 강의에 자바로 해주셨으면 좋겠어요 ㅠㅠ) Webflux 사용한 이유에 대해 https://www.inflearn.com/questions/1281130/%EA%B0%95%EC%9D%98%EB%A5%BC-%EB%93%A3%EA%B3%A0-%EB%AC%B8%EB%93%9D-%EA%B6%81%EA%B8%88%ED%95%9C-%EC%A0%90%EC%9D%B4-%EC%83%9D%EA%B2%BC%EC%8A%B5%EB%8B%88%EB%8B%A4여기서 잘 설명해주셨지만 일단 이 강의를 듣는 수강생들 입장에서는 Webflux 을 이해해야 수강이 가능하니 아무래도 Webflux가 런닝커브가 있는데요 ㅠㅠ 그래서 이 강의 진입하는데 리스크가 있을것 같아요 ㅠ,ㅠ 결제 부분을 가장 강조된 강의인데 Webflux를 알아야 이 강의를 수강 할 수 있다는점 ㅠ,ㅠ 다시한번 말씀드리지만 분명 Webflux 도입 하는것에 있어서 합당성을 이해하지만요 ㅠ,ㅠ fastcampus 에서 출시되는 강의 경우 아무래도 인프런과 비교해서 비용이 만만치가 않아서요 ㅠ,ㅠ 혹시 다음에 출시 되는 'Sacale-up 하며 배우는 대용량 트래픽 처리' 강의 인프런에서도 동일하게 출시가 가능 할까요?.. 다시한번 좋은 강의 기회 주셔서 정말 감사드리고 앞으로 좋은 강의 부탁드립니다 🙂 감사합니다!
-
미해결스프링과 JPA 기반 웹 애플리케이션 개발
postgreSql 연결하여 JPA 를 통해 테이블 생성시 ZONE 테이블 생성에서 에러가 납니다
2024-06-05 08:17:10.986 WARN 86324 --- [ main] o.h.t.s.i.ExceptionHandlerLoggedImpl : GenerationTarget encountered exception accepting command : Error executing DDL " create table zone ( id int8 not null, city varchar(255) not null, local_name_of_city varchar(255) not null, province varchar(255), primary key (id) )" via JDBC Statementorg.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL " create table zone ( id int8 not null, city varchar(255) not null, local_name_of_city varchar(255) not null, province varchar(255), primary key (id) )" via JDBC Statement at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final] at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlString(SchemaCreatorImpl.java:458) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final] at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlStrings(SchemaCreatorImpl.java:442) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final] at org.hibernate.tool.schema.internal.SchemaCreatorImpl.createFromMetadata(SchemaCreatorImpl.java:325) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final] at org.hibernate.tool.schema.internal.SchemaCreatorImpl.performCreation(SchemaCreatorImpl.java:169) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final] at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation(SchemaCreatorImpl.java:138) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final] at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation(SchemaCreatorImpl.java:124) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final] at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:168) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final] at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:85) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final] at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:335) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final] at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:471) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final] at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1498) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final] at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) ~[spring-orm-5.3.23.jar:5.3.23] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.3.23.jar:5.3.23] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-5.3.23.jar:5.3.23] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-5.3.23.jar:5.3.23] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1154) ~[spring-context-5.3.23.jar:5.3.23] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:908) ~[spring-context-5.3.23.jar:5.3.23] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.23.jar:5.3.23] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.4.jar:2.7.4] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) ~[spring-boot-2.7.4.jar:2.7.4] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.4.jar:2.7.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.4.jar:2.7.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.4.jar:2.7.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.4.jar:2.7.4] at com.studyolle.App.main(App.java:10) ~[main/:na]Caused by: org.postgresql.util.PSQLException: ERROR: permission denied for schema public Position: 19 at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2675) ~[postgresql-42.3.7.jar:42.3.7] at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2365) ~[postgresql-42.3.7.jar:42.3.7] at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:355) ~[postgresql-42.3.7.jar:42.3.7] at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:490) ~[postgresql-42.3.7.jar:42.3.7] at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:408) ~[postgresql-42.3.7.jar:42.3.7] at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:329) ~[postgresql-42.3.7.jar:42.3.7] at org.postgresql.jdbc.PgStatement.executeCachedSql(PgStatement.java:315) ~[postgresql-42.3.7.jar:42.3.7] at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:291) ~[postgresql-42.3.7.jar:42.3.7] at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:286) ~[postgresql-42.3.7.jar:42.3.7] at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:94) ~[HikariCP-4.0.3.jar:na] at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java) ~[HikariCP-4.0.3.jar:na] at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:54) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final] ... 34 common frames omittedHibernate:
-
미해결스프링 시큐리티 완전 정복 [6.x 개정판]
JWT 사용관련 질문드립니다.
안녕하세요 현재 강의 초반부 수강중인 수강생입니다. 혹시 실전프로젝트 자료에 포함된 내용중에 JWT를 사용하여 인증을 하는 예제도 제공이될까요?아니면 JWT에 대한 예제는 없는걸까요?github에서 제가 못찾는건지 궁금하여 질문드립니다. 사내 업무에서 전통적인 세션기반인증이 아닌 JWT를 사용한 인증을 사용하려다보니 해당내용이 강의자료에는 없는것 같아 질문드립니다.강의를 전부 수강하지 못하고 질문드리는 점 양해부탁드립니다.
-
미해결스프링 부트 - 핵심 원리와 활용
어디까지 모니터링으로 커버하고, 어디까지 테스트로 커버해야할까요?
모니터링이란, 테스트로 잡지 못한 버그들이 발생했을 때 그 버그의 원인들을 빠르게 알게 해주는데 목적이 있다고 생각합니다. (비즈니스 지표 모니터링은 여기에선 고려하지 않겠습니다.) 그런데, 어디까지 테스트로 해결해야하고 어디서부터는 모니터링으로 해결해야 할까요? 버그를 꼼꼼히 잡겠다고 가능한 모든 루트를 테스트 하려는 것도 생산성 측면에서 옳은 방법은 아니라고 생각합니다. 또한, 서비스의 규모가 작을 때와 서비스의 규모가 클 경우 어떻게 테스트하고 모니터링 할 지 또한 바뀐다고 생각합니다. 제가 생각하는 방법은중요하거나 복잡한 도메인 로직은 유닛테스트로 꼼꼼히 테스트한다프레임워크 및 외부 장치들과 잘 통신하는지는 통합테스트로 happy path 정도만 테스트한다.그 외에 못잡는 버그들은 모니터링을 통해 해결한다.이렇게인데요, 제가 맞는 방향으로 생각하고 있는건지 궁금합니다.또한 서비스의 규모의 차이에 따라 어떻게 테스트하고 모니터링 하는 방법이 달라지는지가 궁금합니다.
-
미해결스프링 핵심 원리 - 기본편
connect()에 url이 null이 안나오는이유
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오) 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 예[질문 내용]안녕하세요 이 강의와 이전강의를 돌려가면서보는중인데도 햇갈리는게있어서 제가 생각하는게 맞는지 궁금해서 질문드립니다.1. 바로이전강의내용에서는 connect() 와 call()를 afterPropertiesSet()에 넣지않은상태에서 코드를 실행하면 url이 null이 뜨는상태였습니다. 그 이유가 그러면 connect() 와 call()함수가 빈 라이프사이클인 "스프링 빈 생성" 중 NetworkClient 생성자안에 있어서 url을 set하기 전 단계에 실행되서 null이 뜨는거고, null이 안뜨고 url이 제대로 나오는 상황은 빈이 완벽하게 생성이 된 이후에 connect() call()이 실행되서 인가요? 제 질문이 잘 전달이된건지 잘 모르겠네요. 빈생성이 되기 전에 connect한거랑 빈생성이완벽하게된후(url도 set된상황) 그 차이인가요?2. 그리고 바로전강의에서 상태출력을 빈생성과정에 출력하신거라 null이 나오는거지 결국 setUrl은 결국 실행되서 url의 최후 상태는 null이 아니지않나요? 그냥 라이프사이클에 중점을두시는 강의인거맞나요?
-
해결됨스프링 핵심 원리 - 기본편
섹션 7. 조회한 Bean 모두 필요 Map, List
public class AllBeanTest { @Test void findAllBean() { ApplicationContext ac = new AnnotationConfigApplicationContext(DiscountPolicy.class); } static class DiscountPolicy { private final Map<String, DiscountPolicy> policyMap; private final List<DiscountPolicy> policies; @Autowired public DiscountPolicy(Map<String, DiscountPolicy> policyMap, List<DiscountPolicy> policies) { this.policyMap = policyMap; this.policies = policies; System.out.println("policyMap = " + policyMap); System.out.println("policies = " + policies); } }테스트를 실행하면policyMap = {}policies = []출력이 됩니다.실행되면서new AnnotationConfigApplicationContext(DiscountPolicy.class);의 스프링 컨테이너가 DiscountPolicy를 빈으로 등록하는데,DiscountPolicy는 @Autowired로 생성자 주입을 받습니다. 그런데 스프링 컨테이너의 스프링 빈에는Map<String, DiscountPolicy> policyMapList<DiscountPolicy> policiespolicyMap와 policies는 생성된 적이 없어서 등록된 빈이 없을테고, final이 붙은 필드에는 초기화가 되지않아서 오류가 나야하지 않나요?어떻게policyMap = {}policies = []처럼 객체가 들어가 있을 수가 있나요??
-
미해결스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
jsp 파일 인식문제
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. build.gradleplugins { id 'java' id 'war' id 'org.springframework.boot' version '3.2.5' id 'io.spring.dependency-management' version '1.1.4' } group = 'hello' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '17' } configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' // jsp 추가 implementation 'org.apache.tomcat.embed:tomcat-embed-jasper:10.1.17' implementation 'javax.servlet:jstl' // jsp 추가 끝 compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } tasks.named('test') { useJUnitPlatform() }현재 aaa.html과 new-form.jsp 파일이 같은 경로에 있는데 jsp 파일만 못찾겠다고 뜹니다..해결해 보려고 webConfig 파일 만들어서 설정도 해보고 properties파일에도 설정을 해보았는데 안되네요.. 무엇이 문제일까요?? WebConfig.java@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void configureViewResolvers(ViewResolverRegistry registry) { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/static/jsp/members/"); resolver.setSuffix(".jsp"); registry.viewResolver(resolver); } }application.propertiesspring.mvc.view.prefix=/static/jsp/members/ spring.mvc.view.suffix=.jsp resources/static/jsp/members/new-fom.jsp<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %> <html> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/jsp/members/save.jsp" method="post"> username: <input type="text" name="username"> age: <input type="text" name="age"> <button type="submit">전송</button> </form> </body> </html>webapp폴더가 없이 resources폴더가 있는게 문제인걸까요? 김영한강사님 강읠르 보면 webapp/... 이런경로에 파일을 생성하시던데 저는 프로젝트를 생성하니 webapp폴더 없이 resources폴더만 있어서 그냥 사용하고 있는데..
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
BlindingResult Validate 질문입니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]회원등록 강의 18분 쯤에서 강사님께서 설명 주시는사이트에서 입력칸에 공백 발생시return "members/createMemberForm";으로 다시 되돌려보내면서 오류화면으로 넘어가지 않으며 입력값은 그대로 유지 하되, 사용자에게"OO 입력은 필수 입니다."라고 글자가 나타나게끔 설계를 해주셨습니다.그런데 createMemberForm.html 파일을 보니그 "~은 필수입니다."하는 문장은 찾아보기가 어려워서어떤 코드에서 이 기능이 작동해서 "~은 필수입니다." 의 문장이 완성되고 출력이 되는지 궁금합니다.name값?을 줄 때 '이름'이라고 준 것 같은데 사이트에서는 어떻게 '회원 이름'이라고 출력이 되나요?