강의 소개
스프링 그 자체에 매몰되지 말고 어떻게 사용해야 하는지에 초점을 맞추자.
실무에서 거의 안 쓰이는 오래된 스프링 기술과 마이너한 스프링 기술은 강의에서 최대한 다루지 않게끔 구성했다.
학습 방법 : 처음부터 끝까지 다 직접 코딩해보면 된다.
프로젝트 생성
https://start.spring.io/ : 보통 요즘은 다 스프링 부트를 활용해서 스프링 프로젝트를 첨에 딱 만듦. 이 사이트 활용하자
메이븐, 그래들 : 요즘은 거의 다 그래들 쓰긴 함. 얘네는 라이브러리 필요한 걸 땡겨오고 빌드 사이클도 관리해주는 툴
build.gradle : 버전 관리, 라이브러리 떙겨 오는 역할 등.
-> dependencies에 있는 것들을 repositories에 명시된 mavenCentral() 이란 곳에서 받아와라.
인텔리제이 compact middle package 설정 : 패키지 A-B에서 A에 B만 있으면 A.B로 표시되는 설정(기본적으로 설정돼있음. 별로면 체크해제해도됨)
main 메소드 실행하면 SpringApplication.run 여기에 클래스 넘겨서 실행하면서 안에 자체적으로 내장된 톰캣으로 웹 서버를 띄움
라이브러리 살펴보기
gradle이 라이브러리 의존 관계를 다 관리해줌. 아주 편해졌음. 내가 A를 필요로해서 build.gradle에 명시해두면, A가 필요한, 의존하는 또 다른 라이브러리들을 그래들이 알아서 다 땡겨옴. 스타터 웹 명시해두면 관련된 거 땡기는데, 톰캣같은 웹 서버도 그냥 임베디드돼서 소스파일에서 웹 서버를 걍 들고있는 셈이 됨
로그에 대해 궁금하면 slf4j랑 logback에 대해 알아보면 됨
현업에선 system.out.println 이거 안 쓰고 다 로그 씀!
view 환경설정
thymeleaf 템플릿 엔진
thymeleaf 공식 사이트: https://www.thymeleaf.org/
스프링 공식 튜토리얼: https://spring.io/guides/gs/serving-web-content/
스프링부트 메뉴얼: https://docs.spring.io/spring-boot/docs/2.3.1.RELEASE/reference/html/spring-boot-features.html#boot-features-spring-mvc-template-engines
서버 재시작 없이 변경사항 바로 띄우기 : spring-boot-devtools 라이브러리, 그리고 크롬 확장프로그램의 LiveReload 활용하면 더 편함
https://mmee2.tistory.com/60
빌드하고 실행하기
./gradlew build 로 빌드하고 build/libs로 이동하면 jar 파일있는데, 그거 java -jar 파일명 로 실행하면 웹 서버 실행됨. 배포할 때는 이걸 올리고 이거 실행해주면 됨.
정적 컨텐츠
스프링 웹 개발 3가지
정적 컨텐츠 : 서버에서 클라이언트에게 정적인 html 주기
MVC와 템플릿 엔진 : 서버에서 동적으로 html 템플릿을 만들어서 클라이언트에게 줌. 이 때 MVC 패턴을 적용하여 많이들 개발함 (관리자 페이지에 쓰면 될 듯)
API : html을 주지 않고 클라이언트가 필요로 하는 데이터를 JSON 형식으로 주고, 그 데이터를 가지고 클라이언트 측에서 html 렌더링하는 방식 (요즘 웹페이지 다 이 방식인듯)
MVC와 템플릿 엔진
ctrl + p : 파라미터 정보 (꿀팁!)
API
@ResponseBody : HTTP 통신 프로토콜 응답 body에다가 return 값을 직접 넣어서 응답 (뷰 리졸버를 사용하지 않는다!). 이 때 기본적으로 JSON 형태로 클라이언트에게 줌! 물론 원하면 xml 형태같은걸로도 보낼 수 있긴 함. 근데 뭐 대부분 JSON 다 쓰니까 이제..
꿀팁 : 생성자같은거 객체 생성 코드 칠 때 자동 완성 제안 뜰 때 ctrl+shift+엔터 치면 괄호랑 세미콜론까지 다 완성시켜줌.
게터 세터 같은걸 자바 빈 표준 규약이라고 함. 또는 프로퍼티 접근 방식이라고도 부름.
컨트롤러의 메소드에 @ResponseBody를 붙였으면, 스프링 컨테이너는 이걸 보고 뷰 리졸버로 넘기지 않고, HttpMessageConverter한테 넘김. 만약 넘길게 단순 문자라면 StringHttpMessageConverter 쓰고(문자열 그 자체로 그냥 응답), 객체라면 MappingJackson2HttpMessageConverter가 실행됨. 이것들이 다 JSON으로 바꿔줌
실무에선 그냥 이거 거의 손 안대고 그대로 씀. 꼭 깊이 있게 공부할 필요까진 없음
만약 클라이언트의 HTTP Accept에 꼭 XML로 받고싶다고 돼있으면, 그거에 맞는 컨버터가 동작해서 XML 형태로 변환해서 리턴되게 됨.
회원 도메인과 레포지토리 만들기
Optional 객체 : java 8부터 나온 스펙인데, 요즘 null 처리하는 방식이, null일 가능성이 있는 객체를 그대로 리턴하는 것보단 Optional로 감싸서 보낸다고 함.
인텔리제이 제안 기능을 통해(alt + enter) 인터페이스 구현체를 만들 때 인터페이스에 명시했던 추상 메소드들의 구현 메소드를 자동으로 틀을 다 만들어줄 수 있음.
findAny() : Stream에서 뭐가 하나라도 있으면 그걸 Optional로 감싸서 내보내고, 암것도 안 들어있으면 그 때도 Optional 리턴
회원 레포지토리 테스트 케이스 작성
보통 Repository에 대한 테스트면 테스트 디렉토리에서 패키지도 또한 repository 이런 식으로 작성.
테스트 클래스는 굳이 public으로 안해도 됨. 딴데서 갖다쓸게아니니깐
꿀팁 : 어떤 괄호 안의 문자열을 입력하고나서 ctrl + shift + enter 치면, 다음 줄로 바로 편하게 넘어갈 수 있음!
Optional 안의 객체는 get()으로 꺼낼 수 있다.
Assertions.assertThat(~).isEqualTo(~); 에서
Assertions에서 alt + enter 치고 static import 어쩌구하면, 저 Assertions 클래스에 정의된 모든 메소드를 import static으로 import해서, 바로 assertThat만 쳐서 쓸 수 있게 됨
같은 변수명들 rename 한꺼번에 하기 : 커서 올리고 shift + F6
패키지 내 전체 테스트를 한꺼번에 같이 돌릴 수도 있음
테스트 메소드들 실행 순서는 보장이 안됨! 그래서 순서 의존적으로 테스트 설계하면 안됨. 그래서 하나의 테스트가 끝날 때마다 다시 테스트 전 상태로 돌리는 일련의 작업들까지 해줘야함.
이런 테스트를 먼저 작성하고 그 다음에 비즈니스 로직이나 레포지토리를 개발할 수도 있는데, 이런걸 TDD라고 함. (test driven development)
프로젝트 규모가 커지고 많은 이들과 협업할수록 이 테스트가 정말 중요함. 테스트 코드 없이는 개발하는게 거의 불가능할 정도. 할 순 있는데 너무 문제가 많이 생김. 그래서 테스트 관련해서는 깊이 있게 공부하는 것을 권장!
회원 서비스 개발
ctrl + alt + v : 표현식까지만 적어두고 이 단축키 쓰면 알아서 바인딩할 변수 왼쪽에 작성해서 해당 라인 완성시켜줌
하나의 기능을 수행하는 로직이 작성됐으면(검증 로직 하나 같은거) 그런건 메소드로 분리해내는게 좋음. ctrl + alt + m
레포지토리는 약간 DB와 상호작용하는 간단한 기능들이 정의돼있고, 서비스에는 약간 비즈니스적인 메소드 명칭들을 쓰고, 비즈니스 로직들도 포함됨.(뭐 중복 이름의 회원 생성불가? 이런 검증 로직이라던가 등등등). 그래야 개발자든 기획자든 봐도 이해 가능
서비스는 약간 비즈니스 의존적으로 구현을 해야하고, 레포지토리는 좀 더 기계적으로 약간 개발자스럽게 구현하면 됨
회원 서비스 테스트
ctrl + shift : t : 해당 클래스에 대한 테스트 클래스 만들기
테스트 메소드 이름은 과감하게 한글로 작성해도 괜찮음. 얘네 테스트 코드를 뭐 배포할것도 아니고 영어권 사람들과 일할게 아니라면 더 직관적이라 굿
테스트 메소드는 보통 given - when - then 이 구조로 쓰는걸 추천. (각 부분에 //given //when //then 이런 주석 달아서 한눈에 뭐가 뭔지 파악할 수 있도록) 뭔가 주어졌을 때 이거를 실행했을 때 결과가 이걸로 나와야 해. 이런 느낌
물론 상황에 따라 저 구조가 안 맞을 때도 있음. 처음엔 저 구조로 계속 연습하다가, 그런 상황이 올 때는 알맞게 변형해서 쓰면 된다.
자바 코드로 직접 스프링 빈 등록하기
스프링 빈으로 등록된 컴포넌트여야 autowired같은 DI가 작동함
구현체를 변경(다른걸로 교체)해야할 일이 있는 것이라면 컴포넌트 스캔보다는 자바 코드로 직접 스프링 빈으로 등록하자
스프링 통합 테스트
자바 코드에 더해서 스프링 컨테이너까지 실행해서 수행하는 테스트를 통합 테스트
스프링 실행 없이 순수 자바 코드 테스트하는걸 단위 테스트라고 함. 스프링을 실행 안해도 돼서 훨씬 빠름.
보통 뭐가 더 맞다고는 할 수 없지만, 잘 쪼개서 단위 테스트로도 테스트할 수 있게 잘 만들면 그게 훌륭한 테스트일 확률이 높음.
통합 테스트로밖에 안되는 상황이면, 테스트 설계가 잘못됐을 확률이 높긴 함. 물론 통합 테스트도 필요한 상황이 있음. 근데 아무튼 단위 테스트 잘 만드는게 진짜 테스트 잘 짜는 거임
JPA
JPA는 표준으로 정의되어 있는 인터페이스임. 이걸 여러 업체들이 구현체로 만들었고 그걸 우리는 갖다쓰면됨. 보통은 하이버네이트 쓰게 될 듯
엔티티 매핑과, transactional 어노테이션 필요
DB에서 pk 값 알아서 정해주는걸 identity 전략이라고 함
jpql : 테이블이 아닌 객체를 대상으로 하는 쿼리
jpa도 기술의 범위와 깊이가 스프링만큼 빡세서 실무에서 잘 적용하기 위해 얘도 깊이 있게 공부해야함
스프링 데이터 JPA
스프링 데이터 JPA는 JPA를 더 편리하게 쓸 수 있게 하기 위한 프레임워크이므로, JPA를 먼저 학습한 후에 스프링 데이터 JPA를 학습해야함
인터페이스가 인터페이스를 상속받을 때는 implements가 아니고 extends로 받음
실무에선 스프링 데이터 JPA를 기본으로 깔고, 복잡한 동적 쿼리는Querydsl이라는 라이브러리로 구현. 이 조합으로도 해결하기 어려운 쿼리는 JPA가 제공하는 네이티브 쿼리를 사용하거나, 스프링 JdbcTemplate을 쓰면 됨
AOP가 필요한 상황