Spring

    [spring] 싱글톤 레지스트리

    [spring] 싱글톤 레지스트리

    대부분의 스프링 애플리케이션은 웹 애플리케이션이다. 웹 애플리케이션은 여러 클라이언트들이 동시에 요청을 보낸다. 그럴 때마다 객체를 생성하고 소멸되는 과정이 반복되면 메모리 낭비가 심하게 된다. 그래서 스프링에서 스프링 컨테이너는 싱글톤 패턴을 적용하지 않아도, 객체 인스턴스를 싱글톤으로 관리한다. 이렇게 싱글톤 객체를 생성하고 관리하는 기능을 싱글톤 레지스트리라 한다. 지금부터 사례로 싱글톤 레지스트리에 대해 알아보도록 하자. 현재 클래스 다이어그램을 보면 Pitcher 클래스와 Catcher 클래스는 Equipment 인터페이스에 의존하고 있다. 그리고 Glove 클래스는 Equipment 인터페이스를 구현한 클래스이다. Pitcher 클래스와 Catcher 클래스는 외부에서 Glove 클래스의 객체..

    [spring] 스프링에서 DI를 하는 이유

    [spring] 스프링에서 DI를 하는 이유

    스프링으로 사용하다 보면 항상 나오는 말이 DI이고 그만큼 강력한 기술이라고 생각한다. 더불어 자바가 객체지향 언어라는 것을 다시금 알 수 있게 해주는 기술이 DI이다. 그래서 이번에는 DI를 사용함으로써 어떤 점이 좋은지 예시를 들어 설명해보려고 한다. 먼저 Player 클래스와 Bat 인터페이스를 만들고 Bat를 구현한 WoodBat 클래스를 추가해준다. 언뜻 보면 Player 클래스는 Bat인터페이스를 의존하고 있고 WoodBat 클래스는 Bat 인터페이스를 구현하여 의존 관계가 잘 성립된 것처럼 보인다. 하지만 Player 클래스를 보면 Bat 인터페이스에도 의존하며 인터페이스를 구현한 WoodBat 클래스에도 의존하고 있는 것을 볼 수 있다. 하지만 배트를 알루미늄 배트로 바꾼다면 인터페이스를 ..

    5장 서비스 추상화

    5장 서비스 추상화

    - 사용자 레벨 관리 기능 추가 지금까지 만든 UserDao는 CRUD라고 불리는 가장 기초적인 작업만 가능하다. 이제 여기에 간단한 비즈니즈 로직을 추가해보자. 지금까지 만들었던 UserDao를 다수의 회원이 가입할 수 있는 인터넷 서비스의 사용자 관리 모듈에 적용해보자. 필드 추가 먼저 UserVO 클래스에 사용자의 레벨을 저장할 필드를 추가하자. private static final int BASIC = 1;처럼 숫자 타입을 직접 사용하는 것보다는 자바 5 이상에서 제공하는 이늄enum을 이용하는 게 안전하고 편리하다. 이늄은 아래와 같이 정의한다. 이렇게 만들어진 Level 이늄은 내부에는 DB에 저장할 int 타입의 값을 갖고 있지만, 겉으로는 Level 타입의 오브젝트이기 때문에 안전하게 사용..

    3.5 템플릿과 콜백

    3.5 템플릿과 콜백

    지금까지 UserDao와 StatementStrategy, JdbcContext를 이용해 만든 코드는 일종의 전략 패턴이 적용된 것이라고 볼 수 있다. 전략 패턴의 기본 구조에 익명 내부 클래스를 활용한 방식이다. 이런 방식을 스프링에서는 템플릿/콜백 패턴이라고 부른다. 전략 패턴의 컨텍스트를 템플릿이라 부르고, 익명 내부 클래스로 만들어지는 오브젝트를 콜백이라고 부른다. -템플릿/콜백의 동작원리 템플릿 : 고정된 작업 흐름을 가진 코드를 재사용한다는 의미에서 붙인 이름 콜백 : 템플릿 안에서 호출되는 것을 목적으로 만들어진 오브젝트 템플릿/콜백의 특징 콜백은 보통 단일 메소드 인터페이스를 사용한다. 하나의 템플릿에서 여러 가지 종류의 전략을 사용해야 한다면 하나 이상의 콜백 오브젝트를 사용할 수 있다...

    3.3 JDBC 전략 패턴의 최적화, 3.4 컨텍스트와 DI

    3.3 JDBC 전략 패턴의 최적화, 3.4 컨텍스트와 DI

    지금까지 기존의 deleteAll() 메소드에 담겨 있던 변하지 않는 부분, 자주 변하는 부분을 전략 패턴을 사용해 깔끔하게 분리해냈다. 독립된 JDBC 작업 흐름이 담긴 jdbcContextWithStatementStrategy()는 DAO메소드들이 공유할 수 있게 되었다. DAO 메소드는 전략 패턴의 클라이언트로서 컨텍스트에 해당하는 jdbcContextWithStatementStrategy() 메소드에 적절한 전략, 즉 바뀌는 로직을 제공해주는 방법으로 사용할 수 있다. 여기서 컨텍스트는 PreparedStatement를 실행하는 JDBC의 작업 흐름이고, 전략은 PreparedStatement를 생성하는 것이다. - 전략 클래스의 추가 정보 이번에 add() 메소드에 적용해보자. 변하는 부분을 A..

    3.1 다시 보는 초난감 DAO

    3.1 다시 보는 초난감 DAO

    학습 목표 스프링에 적용된 템플릿 기법을 살펴보고, 이를 적용해 완성도 있는 DAO코드를 만드는 방법을 알아보자. UserDao코드에는 예외상황에 대한 처리라는 문제점이 남아있다. 먼저 UserDao의 가장 단순한 메소드인 deleteAll()을 살펴보자. 반환되지 못한 Connection이 계속 쌓이면 어느 순간에 커넥션 풀에 여유가 없어지고 리소스가 모자란다는 심각한 오류를 내며 서버가 중단될 수 있다. 장시간 운영되는 다중 사용자를 위한 서버에 적용하기에는 치명적인 위험을 내포하고 있다. 리소스 반환과 close() close()메소드는 이름을 보면 열린 것은 닫는다는 의미지만 보통 리소스를 반환한다는 의미로 이해하는 것이 좋다. Connection과 PreparedStatament는 보통 풀 방식..

    2.5 학습 테스트로 배우는 스프링

    2.5 학습 테스트로 배우는 스프링

    개발자가 자신이 만든 코드가 아닌 다른 사람이 만든 코드와 기능에 대한 테스트를 작성할 필요가 있을까? 일반적으로 자신이 만들고 잇는 코드에 대한 테스트만 작성하지만 때로는 자신이 만들지 않은 프레임워크나 다른 개발팀이 만든 라이브러리 등에 대해서도 테스트를 작성해야 한다. 이것을 학습 테스트learning test라고 한다. 학습 테스트의 목적은 자신이 사용할 API나 프레임워크의 기능을 테스트로 보면서 사용방법을 익히려는 것이다. - 학습 테스트의 장점 1. 다양한 조건에 따른 기능을 손쉽게 확인해볼 수 있다 학습 테스트는 자동화된 테스트 코드로 만들어지기 때문에 다양한 조건에 따라 기능이 어떻게 동작하는지 빠르게 확인할 수 있다. 2. 학습 테스트 코드를 개발 중에 참고할 수 있다 다양한 기능과 조..

    2.4 스프링 테스트 적용

    2.4 스프링 테스트 적용

    2.3 개발자를 위한 테스팅 프레임워크 JUnit 학습 목표 JUnit 프레임워크를 좀 더 자세히 살펴보자. "테스트 없이는 스프링도 없다."라고 할 정도로 스프링에서 테스트의 중요성은 크다고 할 수 있다. 스프링의 핵심 기능 중 하나인 스프링 테 gwamssoju.tistory.com 이제 테스트 코드도 어느 정도 깔끔하게 정리를 마쳤다. 하지만 아직 부족한 부분이 있다. 바로 애플리케이션 컨텍스트 생성 방식이다. @Before 메소드가 테스트 메소드 개수만큼 반복되기 때문에 애플리케이션 컨텍스트도 그만큼 만들어진다. 지금은 크게 문제는 안되지만 빈이 복잡해지고 많아지면 생성에 적지 않은 시간이 걸릴 수 있다. 따라서 애플리케이션 컨텍스트는 한 번만 만들고 여러 테스트가 공유해서 사용해도 된다. 스프링..

    2.3 개발자를 위한 테스팅 프레임워크 JUnit

    2.3 개발자를 위한 테스팅 프레임워크 JUnit

    학습 목표 JUnit 프레임워크를 좀 더 자세히 살펴보자. "테스트 없이는 스프링도 없다."라고 할 정도로 스프링에서 테스트의 중요성은 크다고 할 수 있다. 스프링의 핵심 기능 중 하나인 스프링 테스트 모듈도 JUnit을 이용한다. 따라서 스프링의 기능을 익히기 위해서라도 JUnit는 꼭 사용할 줄 알아야 한다. JUnit는 단순하기 때문에 빠르게 작성할 수 있고 대부분 자바 IDE에서 JUnit 테스트를 손쉽게 실행할 수 있는 JUnit 테스트 지원 기능 내장하고 있어서 더욱 편하게 활용할 수 있게 해 준다. 테스트 결과의 일관성 지금까지 JUnit을 적용해서 깔끔한 테스트 코드를 만들었지만 아직은 좀 더 개선했으면 하는 아쉬운 점이 있다. 가장 불편한 점은 매번 테스트 실행 전에 DB의 user테이블..

    2.2 UserDaoTest 개선

    2.2 UserDaoTest 개선

    학습 목표 UserDaoTest의 두 가지 문제점을 개선해보자. 테스트 검증의 자동화 첫 번째 문제점인 테스트 결과의 검증 부분을 코드로 만들어보자. 이 테스트를 통해 확인하고 싶은 사항은 add()로 등록한 사용자 정보와 get()으로 가져온 사용자 정보가 일치하는가이다. 테스트는 성공과 실패라는 두 가지 결과를 보여준다. 테스트에 실패했을 경우 "테스트 실패"이라는 메시지를 출력하고, 성공했을 경우 "테스트 성공"이라는 메시지를 출력하도록 하자. 테스트 결과가 우리가 원하는 대로 잘 나온 것을 확인할 수 있다. 하지만 UserDao 클래스에서 get() 메소드의 user.setName(rs.getNString("name")); 이 부분을 주석 처리하고 테스트를 진행한다면 아래와 같은 테스트 실패 메시..