호주에 살고 있는 소프트웨어 개발자입니다. 30년간 다양한 분야의 시스템과 서비스를 개발해본 경험이 있습니다.
스프링 프레임워크와 관련 기술을 좋아하고 JVM 기반 언어를 주로 사용합니다.
한국스프링사용자모임(KSUG)을 설립하고 활동했고, 토비의 스프링이라는 책을 쓰기도 했습니다.
개발과 관련된 다양한 주제에 관해 이야기하는 것을 좋아합니다.
강의
수강평
- 토비의 스프링 부트 - 이해와 원리
- <토비의 스프링6> 출시기념 라이브 영상
- 토비의 스프링 6 - 이해와 원리
- 토비의 스프링 부트 - 이해와 원리
게시글
질문&답변
인프라 빈 구성 정보의 분리에서 EnableMyAutoConfiguration 질문드립니다.
@Configuration은 @Component를 메타 애노테이션으로 가지고 있어서 애노테이션이 붙은 클래스를 빈으로 등록되게 합니다. 그런데 @Configuration이 꼭 클래스에 바로 지정된 애노테이션, 여기서라면 MySpringApplication에 있어야하는 것은 아닙니다. 메타 애노테이션으로 따라가다 @Configuration이 나와도 적용이 되겠죠. 이후에 언제라도 @Bean을 넣어서 수동 빈 등록이 가능하도록 만들기도 하고, 해당 클래스가 전체 애플리케이션 컨텍스트가 등록되는 기반이 되는 클래스임을 나타내도록 하기 위해서라도 @Configuration이 바로 붙어있는게 좋은 것 같습니다. 스프링 부트의 @SpringBootApplication는 @SpringBootConfiguration 애노테이션을 가지고 있고, 이 안에 메타 애노테이션으로 @Configuration이 있습니다. 그래서 @SpringBootApplication이 붙은 클래스가 @Configuration 기능을 수행하는 것이죠.지금 예제에서는 @EnableMyAutoConfiguration 위에 @Configuration이 있어서 이게 적용이 되는 것으로 보이는데, 그래도 @MySpringBooApplication이 기본 @Configuration 클래스임을 쉽게 볼 수 있도록 그 위에 @Configuration이 있는 것이 적절해보입니다. Autoconfiguration은 구현 방법에 따라서 @Configuration이 붙은 config 클래스를 직접 참조하지 않을 수도 있거든요.
- 0
- 2
- 28
질문&답변
질문드립니다.
스프링 부트 3.x에서도 강의 예제는 몇 가지 변경사항만 따르면 문제 없이 동작할 것으로 기대합니다. 부트 3가 되면서 달라지는 점은 마지막 수업 영상에서 설명드렸고, 공식 예제에서 3.0으로 모든 예제를 다시 재개발한 것을 브랜치로 분리해두었습니다. build.gradle은 애초에 Spring Initializer가 만들어준 것을 그대로 사용했기 때문에 다르게 변경할 필요는 없을 것입니다. 혹시라도 3.x의 몇 가지 달라진 점을 알려드린 것 외에 다른 문제가 발생하면 알려주세요.
- 0
- 2
- 34
질문&답변
spring boot 3.3.7로 학습중입니다.
스프링 버전이 올라가면서 DispatcherServlet의 동작 방식이 변경되었습니다. 스프링에선 보통 구버전의 코드와 호환성을 잘 지켜주는 편인데, 이건 예외적으로 @RestController 사용이 강제되었습니다. 관련해서는 마지막 수업으로 추가한 스프링 부트 3으로 학습하실 때 주의할 점을 참고해주세요. 또, 유사하 질문이 여러번 올라왔으니 관련된 기존 답변도 찾아보실 수 있을 겁니다.
- 0
- 2
- 53
질문&답변
spring start io 에서 이제더이상 2.x버전은 지원하지 않는 것 같습니다.
강의나 출시된 이후에 스프링 부트 3이 나왔고 계속 업데이트 중이네요.대부분의 내용은 스프링 부트 3에서도 문제 없이 예제를 통해서 학습하실 수 있습니다. 강의 마지막 수업에 3에서 할 때 몇 가지 주의할 점에 대해서 정리해두었습니다. 그리고 GitHub의 예제를 받으시면 3.0으로 예제를 구성한 브랜치를 찾으실 수 있습니다. https://www.inflearn.com/courses/lecture?courseId=329974&unitId=144737스프링 이니셜라이저(start.spring.io)를 이용해서 강의에 나온 버전을 바로 받아서 할 수 없지만 동일 버전(2.7.6)으로 예제를 해보고 싶으시면 방법이 있습니다. 공식 예제를 GitHub에서 받으시고 IntelliJ의 Git commit 목록에서 가장 최초 커밋을 선택한 후에 checkout을 하면 2.7.6으로 처음 Hello Controller까지만 추가된 예제 상태로 전환할 수 있습니다. 여기서부터 이후 강의 내용을 따라하시면 강의와 동일한 버전과 상태로 코드를 만들어보실 수 있습니다.
- 0
- 2
- 51
질문&답변
Springboot 3.2 이상에서 파라미터 추론관련
좋은 정보 제공해주셔서 감사합니다.자바 컴파일러의 메소드 파라미터 메타정보를 컴파일 시점에 남기려면 -parameters 정보를 줘야하죠. 이를 통해서 파라미터 이름을 가져오는 방식을 스프링 6부터는 디폴트로 만들었기 때문에 이 컴파일 옵션이 없으면 @RequestParam 등에 명시하지 않은 경우 바인딩할 query string 이름을 피라미터 이름으로부터 가져올 수 없는 문제가 발생합니다.스프링 부트 강의에서는 그 이전에 많이 알려져있던, IntelliJ에서 프로젝트 빌드와 테스트 등의 성능을 좀 더 높일 수 있도록 iIIntelliJ의 Gradle build 설정의 디폴트인 Gradle 대신 IntelliJ IDEA로 변경하는 팁을 말씀드렸습니다. 최신 장비가 아닌 경우 조금의 실행 성능 개선 효과가 있었습니다. 하지만 스프링이 기본으로 제공하는 Gradle을 이용한 빌드와 미묘한 차이가 있기 때문에 최근에는 가능한 Gradle을 이용한 빌드를 사용하는 것이 권장됩니다. CI 과정에서 빌드할 때나, 배포 후에 Spring Boot task를 이용해서 실행하는 것과 동일한 설정을 개발 장비에서도 적용하는 것이 바람직하기 때문이죠. 그 중의 하나가 Gradle 대신 IntelliJ로 빌드하는 옵션을 선택하는 경우 -parameters가 추가되지 않습니다. 그래서 예제와 같은 경우에는 에러가 발생하는 것입니다. 반면 스프링 부트 프로젝트에서 사용하는 Gradle 빌드 기본 설정을 사용하면 자바 클래스를 컴파일할 때 -parameters 옵션을 기본으로 추가해줍니다. 그래서 스프링만을 이용하고 독자적인 빌드 코드를 만들어서 만들지 않고, 스프링 부트를 기본 Gradle을 이용해서 개발하고 빌드하는 경우엔 사실 @RequestParam 없이도 메소드 이름을 잘 가져옵니다.저도 IntelliJ에서 스프링 부트 프로젝트를 만들고 디폴트 빌드 옵션(Gradle)을 그대로 사용해서 예제를 만들었기 때문에 최근까지도 별 문제가 없었던 듯합니다.
- 0
- 3
- 275
질문&답변
binding error
일반적으로 properties가 아니고 yml이라고 prefix 관련 문제가 발생하지는 않을텐데요. 정확히 어떤 상황인지 올려주신 코드만으로는 파악하기가 어렵습니다. 실제 에러가 발생하는 코드 전체를 GitHub에 공유해주시면 받아서 한번 확인해보겠습니다. 코드와 함께 어떻게 실행을 할 때 에러가 발생하는지도 알려주세요.
- 0
- 3
- 82
질문&답변
토비님 ! BigDecimal 관련 링크를 못찾겠어요
제가 강의자료에 관련 글 링크를 넣는 것을 깜빡했네요. BigDecimal의 특징과 equals, compareTo의 사용법 등에 관해서 잘 이해하실 필요가 있습니다. 아래 글에 좀 길긴하지만 깔끔하게 잘 설명되어있습니다.https://dev.gmarket.com/75글 아래 참고 항목에 나오는 공식 문서도 함께 읽어보시면 좋습니다.
- 1
- 2
- 59
질문&답변
인터페이스 사용에 관하여 질문드립니다.
좋은 질문해주셔서 감사합니다. 스프링의 스테레오 타입 애노테이션이 붙은 빈 클래스들은 계층형 아키텍처를 구성하는 컴포넌트들이죠. 서비스 빈은 서비스 계층 혹은 비즈니스 로직 계층의 전면에서 계층이 제공하는 서비스를 노출하는 일종의 API입니다. 계층간 결합도를 낮추고, 유지보수성과 확장성을 높이고, 테스트용이성을 극대화하고, 관심사의 분리를 명확하게 하기 위한 캡슐화를 한다면 계층형 아키텍처에서 상위 계층으로 노출되는 건, 제한된 API를 가진 인터페이스를 사용해야 하는 것이 바람직합니다. 서비스 계층 내부에서 프라이빗하게 사용되는 빈이라면 굳이 인터페이스를 쓰지 않을 수도 있겠지만, 프레젠테이션 계층으로 노출되는 서비스 빈이라면 인터페이스를 정의하는 게 자연스럽습니다.프레젠테이션 계층을 고립해서 테스트 하려고 한다면 서비스 계층에 대한 연결을 목이나 스텁 같은 테스트 대역으로 만들어야겠죠. 그 경우만 고려하더라도 서비스 인터페이스의 구현은 하나 이상이 될 겁니다. 물론 그것도 목 프레임워크 등에서 지원하는 클래스를 목으로 만드는 방식을 쓸 수는 있으나, 근본적으로 자바 언어가 지원하는 방식을 넘어서는 제약사항이 있는 부자연스러운 방식입니다. 인터페이스 분리 원칙을 따라서 인터페이스를 사용 의도에 맞춰서 구분해두는 것이 좋습니다. 그런데 처음부터 인터페이스별로 구현 클래스를 다 만들어둘 필요는 굳이 없습니다. 그래서 하나의 서비스 빈이 여러개의 인터페이스를 구현할 수 있습니다. 그러다 코드가 성장하고 복잡해지면 적절한 분리를 할 수도 있죠. 시스템이 성장하면서 계속 발전하게 될 비즈니스 로직을 담당하는 서비스 계층이 그런 주요한 대상입니다. 이렇게 인터페이스를 두고 이를 구현하는 방식으로 서비스 계층을 작성하면 구현 부분이 캡슐화 되고, 리팩터링을 하게 되더라도 이를 사용하는 쪽에 노출되는 서비스 API는 변함없이 유지될 수 있습니다. 의도를 담은 인터페이스로 설계가 유지된다면 말이죠.예전엔 인터페이스를 안 쓰려는 이유중 하나가 메소드를 추가하거나 변경할 때 양쪽(인터페이스, 클래스)을 다 고치는게 귀찮아서라는 것이었는데, 요즘은 IDE가 너무 좋아서 그런 건 그냥 한방에 다 되더라고요. @Transactional과 같은 AOP도 일종의 인터페이스 구현으로 만들어집니다. 그것만 해도 구현이 하나라고 볼 수 없죠. 물론 요즘은 성능과 편의성 때문에 cglib 같은 상속을 이용한 프록시 방식을 주로 쓰지만, 그것도 결국 상위 클래스를 인터페이스로 강제하는 방식이라고 볼 수 있죠. 인터페이스를 클래스와 1:1로 기계적으로 만드는 대신, 상위 계층에 노출하는 API라는 관점에서 어떻게 효과적으로 활용할 수 있을지 생각해보면서 만들면 여러가지 장점을 많이 발견하실 수 있을 겁니다.
- 0
- 3
- 75
질문&답변
Arrays.copyOf 메서드의 타입 세이프
자세한 설명 감사합니다.
- 1
- 2
- 44
질문&답변
Order에서 JPA 메타데이터 분리 - XML 사용
저도 orm.xml을 실무에서 많이 쓴 것은 아니라서 JPA 스펙을 한번 찾아봤습니다.JPA 문서를 보면 JPA 애노테이션과 거의 유사하게 XML 항목이 구성되어 있습니다.@Column 안에 unique를 쓸 수 있는 것처럼 안에 unique 애트리뷰트를 사용할 수 있습니다.
- 0
- 2
- 70