스프링은 왜 만들었나?EJB(Enterprise Java Bean) 란?비즈니스 로직을 개발하면서 데이터베이스 처리 및 트랜잭션 처리의 프로그램이 필요하기 때문에 개발에 어려움이 있었다.각 어플린케이션 서버에서는 독자적인 API가 제공되고 있기 때문에 각사의 API를
객체 지향 프로그래밍이란?객체 지향 프로그래밍은 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러개의 독립된 단위, 즉 객체들의 모임으로 파악하고자 하는 것이다.각각의 객체는 메시지를 주고받고, 데이터를 처리할 수 있다컴퓨터 부품 갈아 끼우듯이 컴포넌트를
SRP(Single responsibility principle) 단일 책임 원칙한 클래스는 하나의 책임만 가져야 한다하나의 챔익이라는 것은 모호하다클 수 있고 작을 수 있다문맥과 상황에 따라 다르다중요한 기준은 변경이다. 변경이 있을 때 파급 효과가 적으면 단일 책임
프로그래머는 추상화에 의존해야지 구체화에 의존하면 안된다. 의존성 주입은 이 원칙을 따르는 방법중 하나쉽게 이야기해서 구현 클래스에 의존하지 말고 인터페이스에 의존하라는 뜻역할에 의존하게 해야 한다는 것 객체 세상도 클라이언트가 인터페이스에 의존해야 유연하게 구현체를
기존 프로그램은 클라이언트의 구현 객체가 스스로 필요한 서버 구현 객체를 생성하고 연결하고 실행했다. 한마디로 구현 객체가 프로그램의 제어 흐름을 스스로 조종했다.AppConfig가 등장한 이후 구현 객체는 자신의 로직을 실행하는 역할만 담당한다.프로그램의 제어 흐름은
ApplicationContext를 스프링 컨테이너라고 한다.ApplicationContext는 인터페이스이다.기존에는 개발자가 AppConfig 를 사용해서 직접 객체를 생성하고 DI를 했지만 이제부터는 스프링 컨테이너를 통해서 사용한다.스프링 컨테이너는 @Confi
스프링 컨테이너에서 스프링 빈을 찾는 가장 기본적인 조회 방법ac.getBean(빈이름, 타입), ac.getBean(타입)조회 대상이 없을 경우 예외 발생 : NoSuchBeanDefinitionException: No bean named 'xxxxx' availab
스프링 컨테이너 최상위 컨테이너스프링 빈을 관리하고 조회하는 역할을 담당getBean() 제공BeanFactory의 기능을 모두 상속받아서 제공빈을 관리하고 조회하거나 기타 부가 기능들을 가지고 있음부가적인 기능들 때문에 BeanFactory가 아닌 Applicatio
설정 정보는 JAVA, XML, Groovy등 으로 만들 수 있다.설정 정보를 지정하는 차이만 있을 뿐 코드는 동일함자바 코드로 설정 정보를 작성함AppConfig.classmainXML 파일로 만듬AppConfig.xmlmain
빈 설정에 대한 메타 정보스프링 컨테이너는 이 메타정보를 기반으로 스프링 빈을 생성함XML, JAVA 등 어떤 설정인지는 몰라도 됨(역할과 구현을 개념적으로 나눔)스프링 컨테이너는 이 메타정보를 기반으로 스프링 빈을 생성함BeanDefinition를 직접 생성해서 스프
웹 어플케이션은 보통 여러 고객이 동시에 요청을 한다.스프링이 없는 순수한 DI컨테이너인 AppConfig는 요청을 할 때 마다 객체를 새로 생성하여 메모리 낭비가 심함이를 해결하기 위하여 해당 객체가 1개만 생성되고 공유하도록 설계하는 것을 싱글톤 패턴이라고 함클래스
싱글톤의 문제점들을 해결한 것스프링 컨테이너는 싱글톤 컨테이너 역할을 하는데 싱글톤 객체를 생성하고 관리하는 기능을 싱글톤 레지스트리라 한다.스프링 컨테이너는 싱글톤 패턴의 문제점을 해결하면서 객체 인스턴스를 싱글톤으로 관리한다스프링 컨테이너는 싱글톤 패턴을 적용하지
스프링 설정 등록을 위한 클래스에 붙이는 어노테이션AppConfig를 살펴보면 memberRepository() 메소드가 2번 호출되어 인스턴스가 2개 생성되므로 싱글톤이 깨지는 것으로 보임그러나 Test를 확인해보면 메소드도 한번만 호출되고 인스턴스도 하나만 생성되어
컴포넌트 스캔, 의존관계 자동 주입 설정 정보가 없어도 자동으로 스프링 빈을 등록 컴포넌트 스캔을 사용하려면 먼저 @ComponentScan 을 설정 정보에 붙여주면 된다. @Component 애노테이션이 붙은 클래스를 스캔해서 스프링 빈으로 등록한다 @Autowir
basePackages : 탐색할 패키지의 시작 위치를 지정한다. 이 패키지를 포함해서 하위 패키지를 모두 탐색basePackageClasses : 지정한 클래스의 패키지를 탐색 시작 위치로 지정한다만약 지정하지 않으면 @ComponentScan 이 붙은 설정 정보 클
스프링 컨테이너가 관리하는 스프링 빈이어야만 동작한다.스프링 빈이 아닌 클래스에 @Autowired를 적용해도 아무일도 일어나지 않음생성자를 통해서 의존관계 주입생성자 호출시점에 딱 1번만 호출되는 것을 보장불변, 필수(final) 의존관계에 사용생성자가 하나만 있을
불변애플리케이션 종료 시점까지 의존관계를 변경할 일이 없음setter를 사용하면 외부에서 변경할 수 있기때문에 좋은 설계방법이 아님생성자는 객체 생성시 딱 1번만 호출되기 떄문에 이후에 호출이 없어서 불변하게 설계할 수 있다.누락컴파일 과정에서 객체를 생성하는 경우 필
생성자, Getter, Setter 등의 코드를 애노테이션만 붙이면 자동으로 메소드를 만들어 주는 기능(코드를 넣을 필요가 없음)개발자에게 편의성을 제공함롬북 적용(bulid.gradle)롬북 적용(플러그인 및 설정)기존코드 Getter, Setter, toString
예시DiscountPolicy 2개 - fixDiscountPolicy, rateDiscountPolicy의존 관계 자동 주입오류 발생 해결방법(@Autowired 필드명)@Autowired는 타입 매칭의 결과가 2개 이상일 때 필드 명, 파라미터 명으로 빈 이름 매칭
동적으로 빈을 바꾸며 사용해야 하는 경우 사용함List, Map 이용모든 종류의 빈을 다 가져옴
@Component 만 넣어주면 끝나는 일을 @Configuration 설정 정보에 가서 @Bean 을 적고, 객체를 생성하고, 주입할 대상을 일일이 적어주는 과정은 상당히 번거롭다설정 정보가 커지면 설정 정보를 관리하는 것 자체가 부담이 된다자동 빈 등록을 사용해도
스프링 빈 라이프 사이클 : 객체생성 -> 의존관계 주입객체가 생성되고 의존관계 주입이 완료된 시점부터 필요한 데이터를 사용할 준비가 완료된다스프링은 초기화 콜백을 통해 초기화 시점을 알려주는 기능과 스프링 컨테이너가 종료되는 시점을 알려주느 소멸전 콜백을 준다초기화
번역 그대로 빈이 존재할 수 있는 범위를 뜻함싱글톤: 기본 스코프, 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프이다. 프로토타입: 스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는 매우 짧은 범위의 스코프이
예시스프링 컨테이너 생성 시점에 ClientBean 빈 생성 후 clientBean에 의존 관계 주입PrototypeBean 빈 생성 후 prototypeBean을 clientBean에 반환(prototypeBean의 count = 0)clientBean의 logic(
이전 게시물 웹 스코프 Provider 코드를 Proxy로 변경대리자 라는 뜻으로, 클라이언트가 사용하려고 하는 실제 대상인 것처럼 위장해서 클라이언트의 요청을 받아주는 역할을 한다proxyMode = ScopedProxyMode.TARGET_CLASS 를 추가 적용
로깅 라이브러리스프링 부트 라이브러리를 사용하면 스프링 부트 로깅 라이브러리( spring-boot-starter-logging )가 함께 포함된다.스프링 부트 로깅 라이브러리는 기본으로 다음 로깅 라이브러리를 사용한다SLF4J 인터페이스Logback 구현체장점쓰레드
로그를 남기는 예제이다정상인 경우 실행 과정을 그대로 출력예외가 발생한 경우 실행 과정과 예외를 출력begin()처음 시작하는 부분에 대한 로그를 출력beginSync()이어받는 부분에 대한 로그를 출력complete()종료에 대한 로그를 출력파라미터로 이전 로그값을
싱글톤에서 필드를 공유하면 발생하는 문제같은 필드를 공유하고 있기 때문에 동시에 접근하는 경우 원하는 값이 나오지 않을 수 있음이름을 저장하고 1초 뒤에 저장한 이름을 조회하는 테스트테스트에서 이름(A)을 저장하자마자 0.1초만에 또다른 쓰레드를 호출하여 다른 이름(B
쓰레드 로컬
쓰레드로컬을 이용하여 필드 동기화에 따른 동시성 문제를 해결할 수 있다
쓰레드 로컬의 값을 사용 후 제거하지 않고 그냥 두면 WAS(톰캣)처럼 쓰레드 풀을 사용하는 경우에 심각한 문제가 발생할 수 있다이런 문제를 예방하려면 사용자A의 요청이 끝날 때 쓰레드 로컬의 값을 ThreadLocal.remove() 를 통해서 꼭 제거해야 한다사용자
이름 그대로 템플릿을 사용하는 방식템플릿은 기준이 되는 거대한 틀템플릿이라는 틀에 변하지 않는 부분을 몰아둔다. 그리고 일부 변하는 부분을 별도로 호출해서 해결추상클래스와 추상메소드를 이용하여 해결함동일한 패턴에 대하여 중복을 제거하고 수정 시에도 템플릿만 수정하면 되
전략 패턴은 변하지 않는 부분을 Context 라는 곳에 두고, 변하는 부분을 Strategy 라는 인터페이스를 만들고 해당 인터페이스를 구현하도록 해서 문제를 해결한다. 상속이 아니라 위임으로 문제를 해결하는 것이다.전략 패턴에서 Context 는 변하지 않는 템플릿
기존 전략 패턴은 Context 와 Strategy 를 조립한 이후에는 전략을 변경하기가 번거롭다는 점이 있었다파라미터를 활용하면 Context 를 실행하는 시점에 원하는 Strategy 를 전달할 수 있다원하는 전략을 더욱 유연하게 변경할 수 있다ContextV1 은
다른 코드의 인수로서 넘겨주는 실행 가능한 코드를 콜백(callback)이라 한다.전략 패턴에서 Context 가 템플릿 역할을 하고, Strategy 부분이 콜백으로 넘어온다 생각하면 된다스프링 안에서만 이렇게 부른다. 전략 패턴에서 템플릿과 콜백 부분이 강조된 패턴
클라이언트가 요청한 결과를 서버에 직접 요청하는 것이 아니라 어떤 대리자를 통해서 대신 간접적으로 서버에 요청하는 것대리자를 영어로 프록시(Proxy)라 한다서버와 프록시는 같은 인터페이스를 사용해야 한다클라이언트가 사용하는 서버 객체를 프록시 객체로 변경해도 클라이언
RealSubject 코드와 클라이언트 코드를 전혀 변경하지 않고, 프록시를 도입해서 접근 제어를 했다클라이언트 코드의 변경 없이 자유롭게 프록시를 넣고 뺄 수 있다. - 실제 클라이언트 입장에서는 프록시 객체가 주입되었는지, 실제 객체가 주입되었는지 알지 못한다
서버 인터페이스 서버 구현체 프록시 클라이언트 TEST
실제 구현 클래스의 객체가 아니라 프록시 객체를 빈으로 등록하여 사용함실제 구현 클래스의 객체는 빈에는 등록되지 않지만 프록시 빈 등록 시 힙메모리에 올라가서 실제 만들어진다구현 클래스의 객체는 프록시 객체에서 target으로 사용함
인터페이스가 없어도 구체 클래스를 기반으로 프록시를 만들 수 있다상속을 이용하여 개발한다서버프록시클라이언트TEST
컨트롤러 서비스 리포지토리
인터페이스가 없어도 클래스 기반으로 프록시를 생성할 수 있다.클래스 기반 프록시는 해당 클래스에만 적용할 수 있다. 인터페이스 기반 프록시는 인터페이스만 같으면 모든 곳에 적용할 수 있다.클래스 기반 프록시는 상속을 사용하기 때문에 몇가지 제약이 있다.부모 클래스의 생
리플렉션 기술을 사용하면 클래스나 메서드의 메타정보를 동적으로 획득하고, 코드도 동적으로 호출할 수 있다.정적인 target.callA() , target.callB() 코드를 리플렉션을 사용해서 Method 라는 메타정보로 추상화했다. 덕분에 공통 로직을 만들 수 있
동적 프록시 기술을 사용하면 개발자가 직접 프록시 클래스를 만들지 않아도 된다. 이름 그대로 프록시 객체를 동적으로 런타임에 개발자 대신 만들어준다. 그리고 동적 프록시에 원하는 실행 로직을 지정할 수 있다.JDK 동적 프록시는 인터페이스를 기반으로 프록시를 동적으로
Handler 설정 메인 정리
바이트코드를 조작해서 동적으로 클래스를 생성하는 기술을 제공하는 라이브러리이다.인터페이스가 없어도 구체 클래스만 가지고 동적 프록시를 만들어낼 수 있다.원래는 외부 라이브러리인데, 스프링 프레임워크가 스프링 내부 소스 코드에 포함했다. 따라서 스프링을 사용한다면 별도의
동적 프록시를 통합(JDK 동적 프록시, CGLIB)해서 편리하게 사용하는 기능인터페이스가 있으면 JDK 동적 프록시를 사용하고, 구체 클래스만 있다면 CGLIB를 사용한다. 그리고 이 설정을 변경할 수도 있다.Pointcut을 이용하여 특정 조건에 맞을 때 프록시 로
인터페이스AdviceTimeAdvice 는 앞서 MethodInterceptor 인터페이스를 구현한다. 패키지 이름(org.aopalliance.intercept.MethodInterceptor)Object result = invocation.proceed()invoc
포인트컷( Pointcut ): 어디에 부가 기능을 적용할지, 어디에 부가 기능을 적용하지 않을지 판단하는 필터링 로직이다. 주로 클래스와 메서드 이름으로 필터링 한다. 이름 그대로 어떤 포인트(Point)에 기능을 적용할지 하지 않을지 잘라서(cut) 구분하는 것이다
설정 방법이 다르지 않음
@Bean 이나 컴포넌트 스캔으로 스프링 빈을 등록하면, 스프링은 대상 객체를 생성하고 스프링 컨테이너 내부의 빈 저장소에 등록한다. 그리고 이후에는 스프링 컨테이너를 통해 등록한 스프링 빈을 조회해서 사용하면 된다.스프링이 빈 저장소에 등록할 목적으로 생성한 객체를
수동으로 등록하는 빈은 물론이고, 컴포넌트 스캔을 사용하는 빈까지 모두 프록시를 적용할 수 있다설정 파일에 있는 수 많은 프록시 생성 코드도 한번에 제거할 수 있다.
bulid.gradleimplementation 'org.springframework.boot:spring-boot-starter-aop'이 라이브러리를 추가하면 aspectjweaver 라는 aspectJ 관련 라이브러리를 등록하고, 스프링 부트가 AOP 관련 클래스
어드바이저 2개를 만족해도 프록시는 1개만 생성된다프록시 팩토리가 생성하는 프록시는 내부에 여러 advisor 들을 포함할 수 있기 때문advisor1 의 포인트컷만 만족 프록시1개 생성, 프록시에 advisor1 만 포함advisor1 , advisor2 의 포인트컷
스프링은 @Aspect 애노테이션으로 매우 편리하게 포인트컷과 어드바이스로 구성되어 있는 어드바이저 생성 기능을 지원자동 프록시 생성기는 Advisor 를 자동으로 찾아와서 필요한 곳에 프록시를 생성하고 적용해준다 여기에 추가로 하나의 역할을 더 하는데, 바로 @Asp
핵심 기능은 해당 객체가 제공하는 고유의 기능이다. 예를 들어서 상품 주문 로직이다.부가 기능은 핵심 기능을 보조하기 위해 제공되는 기능이다. 예를 들어서 로그 추적 로직, 트랜잭션 기능이 있다. 이러한 부가 기능은 단독으로 사용되지 않고, 핵심 기능과 함께 사용된다.
.java 소스 코드를 컴파일러를 사용해서 .class 를 만드는 시점에 부가 기능 로직을 추가할 수 있다. 이때는AspectJ가 제공하는 특별한 컴파일러를 사용해야 한다. 컴파일 된 .class 를 디컴파일 해보면 애스펙트 관련 호출 코드가 들어간다. 이해하기 쉽게
조인 포인트(Join point)어드바이스가 적용될 수 있는 위치, 메소드 실행, 생성자 호출, 필드 값 접근, static 메서드 접근 같은 프로그램 실행 중 지점조인 포인트는 추상적인 개념이다. AOP를 적용할 수 있는 모든 지점이라 생각하면 된다.스프링 AOP는
@Around 애노테이션의 값인 execution(\* hello.aop.order..\*(..)) 는 포인트컷이 된다.@Around 애노테이션의 메서드인 doLog 는 어드바이스( Advice )가 된다.execution(\* hello.aop.order..\*(..
@Pointcut@Pointcut 에 포인트컷 표현식을 사용한다.메서드 이름과 파라미터를 합쳐서 포인트컷 시그니처(signature)라 한다.메서드의 반환 타입은 void 여야 한다.코드 내용은 비워둔다.포인트컷 시그니처는 allOrder() 이다. 이름 그대로 주문과
allOrder() 포인트컷은 hello.aop.order 패키지와 하위 패키지를 대상으로 한다.allService() 포인트컷은 타입 이름 패턴이 \*Service 를 대상으로 하는데 쉽게 이야기해서 XxxService 처럼 Service 로 끝나는 것을 대상으로 한
사용하는 방법은 패키지명을 포함한 클래스 이름과 포인트컷 시그니처를 모두 지정하면 된다
애스펙트를 별도의 클래스로 분리해야 한다하나의 애스펙트 안에 있던 어드바이스를 LogAspect , TxAspect 애스펙트로 각각 분리했다. 그리고 각 애스펙트에 @Order 애노테이션을 통해 실행 순서를 적용했다. 참고로 숫자가 작을 수록 먼저 실행된다참고로 클래스
@Around : 메서드 호출 전후에 수행, 가장 강력한 어드바이스, 조인 포인트 실행 여부 선택, 반환 값 변환, 예외 변환 등이 가능@Before : 조인 포인트 실행 이전에 실행@AfterReturning : 조인 포인트가 정상 완료후 실행@AfterThrowin
포인트컷 표현식은 execution 같은 포인트컷 지시자(Pointcut Designator)로 시작한다. 줄여서 PCD라 한다포인트컷 지시자의 종류execution : 메소드 실행 조인 포인트를 매칭한다. 스프링 AOP에서 가장 많이 사용하고, 기능도 복잡하다.wit
문법execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)execution(접근제어자? 반환타입 선언타입?메서드이름(파라
within 지시자는 특정 타입 내의 조인 포인트들로 매칭을 제한한다. 쉽게 이야기해서 해당 타입이 매칭되면 그 안의 메서드(조인 포인트)들이 자동으로 매칭된다.문법은 단순한데 execution 에서 타입 부분만 사용한다고 보면 된다
args : 인자가 주어진 타입의 인스턴스인 조인 포인트로 매칭기본 문법은 execution 의 args 부분과 같다.execution과 args의 차이점execution 은 파라미터 타입이 정확하게 매칭되어야 한다. execution 은 클래스에 선언된 정보를 기
@target 실행 객체의 클래스에 주어진 타입의 애노테이션이 있는 조인 포인트인스턴스의 모든 메서드를 조인 포인트로 적용한다.@within 주어진 애노테이션이 있는 타입 내 조인 포인트해당 타입 내에 있는 메서드만 조인 포인트로 적용한다.@target 은 부모 클래스
@annotation메서드가 주어진 애노테이션을 가지고 있는 조인 포인트를 매칭@args 전달된 실제 인수의 런타임 타입이 주어진 타입의 애노테이션을 갖는 조인 포인트전달된 인수의 런타임 타입에 @Check 애노테이션이 있는 경우에 매칭한다. @args(test.Che
스프링 전용 포인트컷 지시자, 빈의 이름으로 지정한다스프링 빈의 이름으로 AOP 적용 여부를 지정한다. 이것은 스프링에서만 사용할 수 있는 특별한 지시자이다.bean(orderService) || bean(\*Repository)\* 과 같은 패턴을 사용할 수 있다
다음은 포인트컷 표현식을 사용해서 어드바이스에 매개변수를 전달할 수 있다.this, target, args,@target, @within, @annotation, @args포인트컷의 이름과 매개변수의 이름을 맞추어야 한다. 추가로 타입이 메서드에 지정한 타입으로 제한된
스프링에서 AOP를 적용하면 실제 target 객체 대신에 프록시 객체가 스프링 빈으로 등록된다.this 는 스프링 빈으로 등록되어 있는 프록시 객체를 대상으로 포인트컷을 매칭한다.target 은 실제 target 객체를 대상으로 포인트컷을 매칭한다프록시 생성 방식에
5의 배수마다 예외를 던지는 테스트일단 모든 메소드 실행 시 Trace 로그가 찍히도록 AOP 지정만약 5의 배수가 나와 예외가 발생한 경우 재시도를 한다예) 0, 1, 2, 3 까지는 정상작동4 부터 seq=5 이므로 예외 발생재시도 AOP에서 예외를 잡은 후 재시도
AOP를 적용하려면 항상 프록시를 통해서 대상 객체(Target)을 호출해야 한다만약 프록시를 거치지 않고 대상 객체를 직접 호출하게 되면 AOP가 적용되지 않고, 어드바이스도 호출되지 않는다서비스AOPTEST결과external()문제는 callServiceV0.ext
자기 자신을 의존관계 주입 받는 것스프링 부트 2.6부터는 순환 참조를 기본적으로 금지하도록 정책이 변경 되어 아래와 같은 옵션을 추가해 줘야 한다application.propertiesspring.main.allow-circular-references=true생성자
스프링 빈을 지연해서 조회하면 되는데, ObjectProvider(Provider) , ApplicationContext 를 사용하면 된다.ObjectProvider 는 객체를 스프링 컨테이너에서 조회하는 것을 스프링 빈 생성 시점이 아니라 실제 객체를 사용하는 시점으
내부 호출이 발생하지 않도록 구조를 변경하는 것권장하는 방법서비스테스트결과이 방법도 괜찮고클라이언트에서 둘다 따로 호출하는 것도 방법이다
JDK 동적 프록시는 인터페이스가 필수이고, 인터페이스를 기반으로 프록시를 생성한다.CGLIB는 구체 클래스를 기반으로 프록시를 생성한다인터페이스가 없고 구체 클래스만 있는 경우에는 CGLIB를 사용해야 한다. 그런데 인터페이스가 있는 경우에는 JDK 동적 프록시나 C
JDK 동적 프록시를 구체 클래스 타입에 주입CGLIB 프록시를 구체 클래스 타입에 주입
대상 클래스에 기본 생성자 필수CGLIB는 구체 클래스를 상속 받는다. 자바 언어에서 상속을 받으면 자식 클래스의 생성자를 호출할 때 자식 클래스의 생성자에서 부모 클래스의 생성자도 호출해야 한다. (이 부분이 생략되어 있다면 자식 클래스의 생성자 첫줄에 부모 클래스의
스프링 3.2, CGLIB를 스프링 내부에 함께 패키징CGLIB를 사용하려면 CGLIB 라이브러리가 별도로 필요했다. 스프링은 CGLIB 라이브러리를 스프링 내부에 함께 패키징해서 별도의 라이브러리 추가 없이 CGLIB를 사용할 수 있게 되었다. CGLIB spring
테스트 주도 개발테스트를 먼저 설계 및 구축 후 테스트를 통과할 수 있는 코드를 짜는 것애자일 개발 방식 중 하나코드 설계 시 원하는 단계적 목표에 대해 설정하여 진행하고자 하는 것에 대한 결정 방향의 갭을 줄이고자 함최초 목표에 맞춘 테스트를 구축하여 그에 맞게 코드
JUint 테스트를 위한 클래스 Controller Service Dao JUint 사용 Controller 테스트 Service 테스트
스프링에서 제공하는 테스트 도구 중 하나로, 컨트롤러의 테스트를 지원하는 모듈이다서버를 띄우지 않고도 컨트롤러의 동작을 테스트할 수 있다브라우저에서 요청을 보낼 떄와 동일한 방식으로 HTTP 요청을 생성할 수 있으며, 이를통해 컨트롤러의 응답 결과를 검증할 수 있다컨트
인증 인가에 대한 정보가 필요한 경우 사용할 수 있는 어노테이션 정리스트에 필요한 인증된 인증 정보를 제공하며 간단한 정보를 기본으로 설정할 수 있게끔 도와준다.미리 인증된 사용자를 만들어놓지 않아도 간단하게 인증이 필요한 메소드를 테스트할 수 있다userName, p
간편하게 Rest 방식 API를 호출할 수 있는 Spring 내장 클래스json, xml 응답을 모두 받을 수 있다Rest API 서비스를 요청 후 응답 받을 수 있도록 설계되어있으며 HTTP 프로토콜의 메소드(ex. GET, POST, DELETE, PUT)들에 적합