김영한의 실전 자바 - 고급 3편, 람다, 스트림, 함수형 프로그래밍
₩77,000
초급 / Java, 함수형 프로그래밍, Lambda, optional
4.9
(116)
최신 자바에 꼭 필요한 람다, 스트림, 자바를 활용한 함수형 프로그래밍 기술을 기초부터 실무 레벨까지 깊이있게 학습합니다.
초급
Java, 함수형 프로그래밍, Lambda
교육자
전: 우아한형제들 기술이사, 카카오, SK플래닛
진짜 실무에 필요한 제대로 된 개발자가 될 수 있도록, 교육하는 것이 저의 목표입니다.
EO 인터뷰 영상
개발바닥 - 시골 청년 개발왕 되다
김영한의 실전 자바 - 고급 3편, 람다, 스트림, 함수형 프로그래밍
₩77,000
초급 / Java, 함수형 프로그래밍, Lambda, optional
4.9
(116)
최신 자바에 꼭 필요한 람다, 스트림, 자바를 활용한 함수형 프로그래밍 기술을 기초부터 실무 레벨까지 깊이있게 학습합니다.
초급
Java, 함수형 프로그래밍, Lambda
김영한의 실전 자바 - 고급 2편, I/O, 네트워크, 리플렉션
₩77,000
초급 / Java, 네트워크, 객체지향
5.0
(175)
I/O, 네트워크, 리플렉션, 애노테이션을 기초부터 실무 레벨까지 깊이있게 학습합니다. 웹 애플리케이션 서버(WAS)를 자바로 직접 만들어봅니다.
초급
Java, 네트워크, 객체지향
김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성
₩77,000
초급 / Java, 객체지향, thread, multithread, 동시성
5.0
(303)
멀티스레드와 동시성을 기초부터 실무 레벨까지 깊이있게 학습합니다.
초급
Java, 객체지향, thread
김영한의 실전 자바 - 중급 2편
₩66,000
초급 / Java, 객체지향, 알고리즘, 코딩 테스트
5.0
(505)
자바 제네릭과 컬렉션 프레임워크를 실무 중심으로 깊이있게 학습합니다. 자료 구조에 대한 기본기도 함께 학습합니다.
초급
Java, 객체지향, 알고리즘
김영한의 실전 자바 - 중급 1편
₩66,000
초급 / Java, 객체지향
5.0
(735)
실무에 필요한 자바의 다양한 중급 기능을 예제 코드로 깊이있게 학습합니다.
초급
Java, 객체지향
[30만 수강생 기념] 1/31 김영한님 온라인 밋업 Live
무료
입문 / 자기계발, 커뮤니케이션
5.0
(145)
1월 31일 저녁 7시에 진행되었던 밋업 영상입니다.
입문
자기계발, 커뮤니케이션
질문&답변
querydsl 빌드 문제 질문드립니다.
안녕하세요. 6udguin님스프링 부트 3.x를 사용중이시군요 🙂강의 메뉴얼에 있는 다음 내용을 참고해주세요.> 참고: 스프링 최신 버전에서는 Querydsl 설정이 달라진다. Querydsl 설정이 잘 안된다면 다음을 참고하자. 스프링 부트 2.x, 3.x 모두 참고할 수 있다.> https://bit.ly/springboot3 직접 링크https://docs.google.com/document/d/1j0jcJ9EoXMGzwAA2H0b9TOvRtpwlxI5Dtn3sRtuXQas/edit?tab=t.0#heading=h.iayahq64el0u감사합니다.
질문&답변
ItemUpdateForm의 필드 quantity에 @NotNull이 없는이유
안녕하세요. 만달라님이 예제에서는 수량의 경우 빈 값도 넣을 수 있도록 허용해두었습니다.특별한 이유가 있는 것은 아니고, 이 예제에서는 비즈니스 상황에 따라서 수량이 0일 수도 있지만, 이 경우 수량 자체를 아직 설정하지 않았다는 의미로 보시면 됩니다.감사합니다.
질문&답변
중급문법 벌크연산에서
임다정님 감사합니다 🙂다음 버전에 패치할게요^^!
질문&답변
jpa와 기타 db 기술을 혼합해서 사용할 때 질문드립니다.
안녕하세요. 한현진님하나씩 답변 드릴께요. 1. 여러 Repository를 만들어야 하나요? DIP 위배는 괜찮을까요?결론부터 말씀드리면, 일반적으로 각기 다른 데이터 접근 기술을 사용한다고 해서 MyBatisOrderRepo, JPAOrderRepo처럼 기술 이름을딴 별도의 Repository 인터페이스를 여러 개 만드는 것은 권장하지 않습니다. 이는 DIP(Dependency Inversion Principle, 의존관계 역전 원칙)를 위배할 가능성이 높고, 서비스 계층이 구체적인 구현 기술에 의존하게 만들기 때문입니다.바람직한 접근 방식:도메인 중심의 Repository 인터페이스 정의:OrderRepository라는 인터페이스를 만듭니다. 이 인터페이스는 주문(Order) 도메인과 관련된 데이터 접근 기능을 추상화합니다. (예: save(Order order), findById(Long id), findByCustomerName(String name))서비스 계층은 이 OrderRepository 인터페이스에만 의존합니다.구현체에서 기술 선택:OrderRepository의 구현체인 OrderRepositoryImpl (또는 Spring Data JPA를 사용한다면 프록시 객체) 내부에서 필요에 따라 JPA, MyBatis, JdbcTemplate 등을 조합하여 사용할 수 있습니다.예를 들어, 대부분의 CRUD는 Spring Data JPA로 구현하고, 특정 복잡한 통계 쿼리나 벌크 연산은 MyBatis나 JdbcTemplate을 OrderRepositoryImpl 내부의 private 메서드나 별도의 컴포넌트로 만들어 호출하는 방식입니다.DIP를 지키는 것:이렇게 하면 서비스 계층은 OrderRepository라는 추상화된 인터페이스에만 의존하게 됩니다. 실제 내부 구현에서 JPA를 쓰든 MyBatis를 쓰든 서비스 계층은 알 필요가 없습니다. 이것이 DIP를 지키는 방법입니다.각 repo별로 인터페이스 만드는 것이 이상하게 느껴지신 이유는 아마도 기술별로 인터페이스를 만드려고 생각하셨기 때문일 겁니다. 대신 도메인 작업별로 인터페이스를 정의하고, 그 구현체 안에서 적절한 기술을 조합하는 것이 좋습니다.만약, 특정 기술에 매우 특화된 기능들이 많고, 도메인적으로 분리된 관심사라면 (예: 매우 복잡한 통계 전용 리포지토리), 별도의 인터페이스와 구현체를 고려할 수는 있지만, 일반적인 CRUD와 일부 복잡 쿼리가 섞인 경우라면 하나의 통합된 Repository 인터페이스 접근법이 더 유지보수하기 좋습니다. 2. JPA 사용 후 MyBatis/JdbcTemplate 사용 시 flush()와 EntityManager 의존성JPA를 사용한 후 동일 트랜잭션 내에서 MyBatis나 JdbcTemplate으로 DB를 직접 조회할 때 데이터 정합성 문제가 발생할 수 있습니다. JPA의 영속성 컨텍스트에 있는 변경사항이 아직 DB에 반영(flush)되지 않았기 때문입니다.따라서 JPA 작업 후 MyBatis/JdbcTemplate을 사용하기 전에는 명시적으로 entityManager.flush()를 호출해주는 것이 안전합니다.Service Layer에서 EntityManager 의존:entityManager.flush()를 호출하기 위해 서비스 계층에서 EntityManager를 직접 의존하는 것이 괜찮은지에 대한 고민은 타당합니다.일반적으로 서비스 계층은 비즈니스 로직에 집중하고, 데이터 접근 기술에 대한 직접적인 의존은 최소화하는 것이 좋습니다. @Transactional 어노테이션을 통해 선언적으로 트랜잭션을 관리하는 것도 이러한 관심사 분리를 위한 것입니다.해결 방안 및 고려사항:Repository 계층에서 flush 호출:첫번째 방법은 flush가 필요한 작업을 Repository 메서드 내에서 처리하는 것입니다.예를 들어, OrderRepository의 특정 메서드가 내부적으로 JPA로 कुछ 변경하고, 이어서 JdbcTemplate으로 뭔가를 조회해야 한다면, 해당 Repository 메서드 내부에서 entityManager.flush()를 호출할 수 있습니다. 이 경우 서비스 계층은 EntityManager를 몰라도 됩니다. Service 계층에서 EntityManager 주입 (필요악으로 간주):만약 서비스 계층에서 JPA 작업과 비 JPA 작업의 흐름을 직접 제어해야 하고, 그 사이에 flush가 반드시 필요하다면, 서비스 계층에 EntityManager를 주입받아 사용하는 것도 현실적인 선택일 수 있습니다. @Transactional의 동작 이해:기본적으로 @Transactional 메서드가 종료될 때 (커밋 시점) flush가 발생합니다.또한, JPA는 트랜잭션 내에서 JPQL 쿼리가 실행되기 전에 영속성 컨텍스트에 있는 변경사항 중 해당 쿼리 결과에 영향을 줄 수 있는 것들을 flush하는 메커니즘(auto-flush)을 가지고 있습니다.하지만, MyBatis나 JdbcTemplate은 JPA의 영속성 컨텍스트를 직접 인지하지 못하므로, 이들을 사용한 SQL 실행 전에는 JPA가 자동으로 flush를 해주지 않습니다. 그래서 명시적인 flush()가 필요한 것입니다.결론적으로, 가능하면 Repository 내부에서 flush를 관리하는 것이 좋지만, 서비스 로직 흐름상 명시적인 flush 호출이 서비스 계층에서 필요하다면 EntityManager를 주입받아 사용하는 것도 데이터 정합성을 위해서는 고려할 수 있는 방법입니다.더 나은 대안으로는 플러시용 AOP를 하나 만드는 것입니다. 그리고 특정 리포지토리에 해당 애노테이션을 도입할 수 있습니다.참고로 실무에서는 이 부분이 그렇게 문제가 되지 않는 경우가 많습니다. 왜냐하면 같은 테이블의 데이터를 JPA로 변경하고, 그 다음에 같은 테이블의 데이터를 SQL을 사용해서 조회하는 상황에 이 문제가 발생합니다. 그런데 실무에서 이런 경우가 자주 발생하지는 않습니다. 3. JPA를 이용한 DB 처리 방식은 효율적인가요?JPA의 효율성은 "상황에 따라 다르다" 가 가장 정확한 답변입니다.효율적인 측면:개발 생산성 및 유지보수성: SQL 중심이 아닌 객체 중심으로 개발할 수 있게 해주고, 반복적인 CRUD 코드를 크게 줄여줍니다. 이는 개발 시간 단축과 유지보수 용이성으로 이어져 전체적인 "효율"을 높입니다.1차 캐시 (영속성 컨텍스트 내 캐시): 동일 트랜잭션 내에서 같은 엔티티를 여러 번 조회할 경우, DB를 다시 조회하지 않고 1차 캐시에서 가져오므로 성능 이점이 있습니다.쓰기 지연 (Write-behind) 및 변경 감지 (Dirty checking):엔티티의 변경사항을 즉시 DB에 반영하는 것이 아니라, 트랜잭션 커밋 시점에 모아서 한 번에 UPDATE 쿼리를 생성하여 실행합니다.이를 통해 불필요한 UPDATE 쿼리를 줄일 수 있고, 최적화된 순서로 SQL을 실행할 수도 있습니다. (예: 여러 엔티티의 여러 필드가 변경되어도 엔티티당 하나의 UPDATE문만 생성)Lazy Loading (지연 로딩): 연관된 엔티티를 실제 사용할 때 조회하여 불필요한 데이터 로딩을 피할 수 있습니다.객체지향적인 쿼리 (JPQL, Criteria): 특정 DB 벤더에 종속되지 않는 쿼리를 작성할 수 있으며, 동적 쿼리 생성에도 유리합니다.비효율적일 수 있는 측면 (주의점):N+1 문제: 연관관계 매핑 시 fetch 전략을 잘못 설정하면 (특히 EAGER 로딩 남발 또는 JPQL에서 적절한 fetch join 미사용 시) 의도치 않게 많은 추가 쿼리가 발생하여 성능 저하를 유발합니다.단순 UPDATE의 경우:말씀하신 것처럼, 단순히 특정 필드 하나만 업데이트하기 위해 find()로 엔티티를 조회(SELECT)하고, setXXX()로 변경 후 커밋 시점에 UPDATE 쿼리가 나가는 것은 순수 SQL UPDATE문 하나보다 비효율적일 수 있습니다.대안: 벌크 연산을 사용할 수 있습니다.복잡한 쿼리: 매우 복잡하고 통계적인 쿼리는 JPQL이나 Criteria로 작성하기 어렵거나, 생성된 SQL이 비효율적일 수 있습니다. 이런 경우 Native Query, MyBatis, JdbcTemplate 등을 사용하는 것이 더 나을 수 있습니다.ORM 자체의 오버헤드: SQL을 직접 사용하는 것보다 ORM 프레임워크를 거치면서 발생하는 약간의 오버헤드는 존재합니다.결론:JPA는 개발 생산성과 유지보수성, 그리고 객체지향적인 데이터 처리에 큰 강점이 있습니다. 많은 일반적인 웹 애플리케이션 시나리오에서 충분히 효율적입니다.그러나 JPA의 내부 동작 원리(영속성 컨텍스트, fetch 전략 등)를 잘 이해하고 사용해야 하며, 때로는 성능 최적화를 위해 JPQL 벌크 연산이나 다른 기술(MyBatis, JdbcTemplate)을 함께 사용하는 유연성이 필요합니다.단순히 "JPA가 SELECT 후 UPDATE를 하니 비효율적이다"라고 단정하기보다는, 어떤 상황에 어떤 기능을 사용하는 것이 적합한지 이해하고 활용하는 것이 중요합니다. 대부분의 경우, JPA가 제공하는 이점이 이러한 오버헤드를 상쇄하고도 남습니다.감사합니다.
질문&답변
커스텀aop와 트랜잭션을 같이 사용할때 우선순위에 관한 질문
안녕하세요. 한현진님@Transactional은 Ordered.LOWEST_PRECEDENCE를 가져서, 다른 우선순위가 지정된 AOP들에 비해 상대적으로 안쪽 레이어에서 동작하는 것이 기본 전략입니다. 따라서 다른 AOP보다 가장 늦게 시작됩니다. 이렇게 설정한 이유는 예를 들어, 로깅, 인증, 입력값 검증 등의 대부분의 공통 로직 AOP는 트랜잭션이 실행되기 전에 수행되어야 합니다.만약 트랜잭션 경계 내부에서 특정 AOP 로직을 적용해야 한다면, 그 로직은 AOP보다는 해당 트랜잭션 메소드 내의 일반 호출이나 다른 컴포넌트로 분리하는 것이 더 명확한 설계일 수 있습니다.트랜잭션 커밋/롤백 이후에 특정 동작을 수행해야 한다면 (예: 이벤트 발행, 알림 전송), AOP 우선순위로 해결하기보다는 @TransactionalEventListener를 사용하는 것이 권장됩니다. 이는 트랜잭션의 특정 생명주기(예: AFTER_COMMIT, AFTER_ROLLBACK)에 맞추어 동작합니다. 추가로 @Repository를 사용하면 sql 체크 예외를 DataAccess 언체크 예외로 바꿔주는 aop는 크게 고민하지 않아도 괜찮습니다. 왜냐하면 적용하는 계층이 다르기 때문입니다.보통 @Transactional 은 Service 계층(비즈니스 로직)에 붙인다.@Repository 의 예외 변환 AOP는 DAO/Repository 계층 빈(=다른 프록시)에 붙는다.Service → Repository 호출이 이뤄질 때 이미 트랜잭션은 열려 있으므로, Repository 안쪽에서 발생한 SQLException → DataAccessException 변환이 끝난 뒤 예외가 Service 프록시의 트랜잭션 어드바이스로 전파된다.감사합니다.
질문&답변
다중 스레드 환경에서 ArrayList를 안전하게 사용할 수 있나요?
안녕하세요. 11 1님AI 퀴즈에 문제가 있네요 🙂AI 답변을 참고해주세요.감사합니다.
질문&답변
디폴트 메서드 pdf파일 오류 및 질문
안녕하세요. 생각하는자님모두 실행 시간이 다르게 출력될 것 이어서, 메뉴얼의 경우 제가 간단하게 하루가 지났다고 표현해두었습니다 🙂다른 분들도 혹시 오해하실 수 있으니 메뉴얼에 관련 내용을 보충해두어야겠네요.날짜와 시간 관련된 부분은 크게 중요한 부분은 아니어서 넘어가셔도 괜찮을 것 같아요.필요하다면 자바 중급 1편 날짜와 시간 부분을 참고해주세요 🙂감사합니다.
질문&답변
DispatcherServlet생성과 등록
안녕하세요. 한조님AI 인턴이 잘 답변해주었는데요.관련해서 자세한 내용은 스프링 부트 - 핵심 원리와 활용 강의에서 자세히 설명드립니다 🙂감사합니다.
질문&답변
안녕하세요 질문 컴파일 에러 문제에대해서 질문있습니다.
안녕하세요. 수성강님Gradle을 사용해서 빌드하셔야 합니다.참고로 이 문제는 Build, Execution, Deployment -> Build Tools -> Gradle에서Build and run using를 IntelliJ IDEA로 선택한 경우에만 발생한다. Gradle로 선택한 경우에는 Gradle이 컴파일 시점에 해당 옵션을 자동으로 적용해준다.자세한 내용은 다음을 참고해주세요.https://docs.google.com/document/d/1j0jcJ9EoXMGzwAA2H0b9TOvRtpwlxI5Dtn3sRtuXQas/edit?tab=t.0#heading=h.b1yk4ued1pxo감사합니다.
질문&답변
@Transactional connection 얻는 시점
안녕하세요. rudnf9605님@Transactional이 적용된 메서드를 호출할 때 커넥션 풀에서 커넥션을 획득합니다.감사합니다.