2020년 4월 19일 일요일

예외처리 핸들러 테스트

예외처리 핸들러 테스트

  • 토이프로젝트의 예외처리를 어떻게 할까 고민하다 검색과 백기선님 웹MVC강의에 예외처리 부분을 복습하였다. (회사소스에 존재하는 ExceptionHandler에는 로그만 남기도록 되어있었다.)
  • MVC에서 요청을 처리하다가 에러가 발생하거나 자바에서 지원하는 예외가 발생했을 때 정의한 핸들러로 그 예외를 어떻게 처리할지?, 어떤응답을 만들지를 정의할 수 있다.
      @ExceptionHandler
      public String RuntimeExceptionHandler(RuntimeException e, Model model){
        model.addAttribute("message", "runtime error");
        return "error"
      }
    
    • 예외처리를 핸들러를 전역 컨트롤러에 선언할 수 있다. (모든 컨트롤러에 적용됨)
      // 모든 컨트롤러 적용
      @ControllerAdvice("com.edu.controller")
      public class CommonExceptionHandler {
        ...
      }
    
    
      // 다수의 특정 컨트롤러 지정 가능
      @ControllerAdvice(assignableTypes = {EventController.class, EventApi.class})
      public class CommonExceptionHandler {
        ...
      }
    
    
      // 패키지 지정 가능
      @ControllerAdvice("com.edu.controller")
      public class CommonExceptionHandler {
        ...
      }
    
  • @RestControllerAdvice 는 @ResponseBody 가 붙은거 라고 생각하면될듯!

내가 테스트해본 것

아쉬운 점 : 그냥 잘못된 값을 던지고 해당 메서드에서 exception이 발생하였을 때 처리하는 테스트를 하였는데, 테스트 시 예외를 강제로 줘서 테스트를 하고 싶었는데 못하였음 ㅠㅠ(의미가 없으려나??)
  • CommonExceptionHandler.java
@ControllerAdvice
public class CommonExceptionHandler {
    private static final Logger logger = LoggerFactory.getLogger(CommonExceptionHandler.class);

    public static final String DEFAULT_ERROR_VIEW = "exception";

    @ExceptionHandler(value = RuntimeException.class)
    public ModelAndView defaultRuntimeErrorHandler(HttpServletRequest req, RuntimeException e) {
        logger.debug("RuntimeException: " + e);
        logger.debug("url: " + req.getRequestURL());

        ModelAndView mav = new ModelAndView();
        mav.addObject("exception", e);
        mav.addObject("url", req.getRequestURL());
        mav.setViewName(DEFAULT_ERROR_VIEW);

        return mav;

    }
}
  • LectureControllerTest.java
public class LectureControllerTest extends BaseControllerTest {

/* 전역 Exception Handler 설정
CommonExceptionHandler 에서 처리하기 위한 셋팅: standaloneSetup, setControllerAdvice 지정

지정 파라미터를 다른 값으로 변경하면 CommonExceptionHandler에 안들어온다.
하지만 아예 이 부분을 제거해도 CommonExceptionHandler에 옴.
 */
    @Before
    public void setUp() {
        this.mockMvc = MockMvcBuilders
                .standaloneSetup(lectureController)
                .setControllerAdvice(new CommonExceptionHandler())
                .build();
    }

  ...


    @Test
    @Description("Exception 발생 테스트")
    public void exceptionTest() throws Exception{

        // Given
        String userId = "admin2";

        // When (실패함. 어떻게 사용하는 지 더 찾아볼 것)
        //when(lectureController.checkedLecture(anyString(),anyString(),anyString())).thenThrow(new Exception("테스트입니다."));

        // Then
        mockMvc.perform(post("/lecture/checkedLecture")
                .param("userId", userId)

        ).andDo(print())
                .andExpect(status().is2xxSuccessful())
                .andExpect(view().name("exception"))
                .andExpect(model().attributeExists("exception"))
        ;

    }
}

Error, Exception 참고

  • Error : 개발자가 미리 예측하여 처리할 수 없는 경우 (JVM 자원 부족 등의 문제?)
    • 관례적으로 Error에 대해서는 Custom Class를 만들지 않는다
  • Exception : 개발자가 구현한 로직에서 발생하기 때문에 미리 예측하여 처리할 수 있음
    • RuntimeException
      • 처리를 강제하지 않음(동작하다 exception 발생)
      • 하위 Exception: NullPoint, IllegalArgument, IndexOutOfBound, System)
      • Custom UnChecked Exception 을 만들 경우 RuntimeException 클래스를 상속하여 만든다.
    • CheckedException
      • 반드시 예외처리를 해야함(처리안하면 컴파일 오류)
      • RuntimeException을 제외한 모든 클래스
      • Custom checked Exception을 만들 경우 Exception 클래스를 상속하여 만든다.
  • 예외처리 팁
    • 아무것도안하는 에러처리는 피하기 : catch 영역에 아무 동작도 안하면 예외 발생 시 추적하기 힘들어짐. 처리를 못한다면 로그라도 남길 것
    • exception.printStackTrace()는 쓰지 말 것 : 에러가 발생한 원인에 대한 Stack Trace를 추적하여 개발자에게 디버깅할 수 있는 힌트를 제공해주지만, 운영 시 성능을 생각한다면 지양해야한다. java reflection을 사용하여 trace를 추적하기 때문에 오버헤드가 발생한다고한다.
    • 반복문 내에서 Checked Exception에 대한 처리는 지양할 것 : 반복문 내에서 Checked Exception에 대한 예외처리 구문이 들어가게 되면 성능은 2배 3배 떨어지게 된다.

2020년 3월 8일 일요일

클린 코드 책 메모

클린코드

취업 전 도서관에서 클린코드를 빌려서 읽어본적이 있었다. 물론 2장 중간에 포기하고 반납을 했었다.
그때는 무슨 소리를 하는 지 이 책은 왜이리 어려운 책인가 하고 바로 반납을 해버렸지만....
이번엔 3일만에 읽어버렸다. (물론 저자가 직접 리팩토링하면서 설명하는 부분은 좀 빠르게 읽었다)
작년에 회사 업무시간 전 차곡차곡 읽을 생각으로 산 이후로 방치되었었는데, 이번주에는 조금 시간이 넉넉하여 업무시간을 활용하였다.
지금 읽어보니 정말 쉽게 설명되어있고, 기본적으로 코드를 짤 때 필요한 내용이어서 너무 재미있게 읽었다.
왜 우아한형제 기술블로그에서 이 책의 제목이 자주 언급되는 지에 대해서 조금은 알 것 같았다.
반성도 많이하게 되고, 머리에 꽂히는 것도 많은 책이다.
꼭 다시 한번 더 읽으리라~~~ (입사,이직 전 한번 읽으면 엄청 좋을 듯!!)
이 책을 모두 정리한다는 것은 어려울 것 같다. 모든 내용이 중요해보였고, 나에게 필요해 보인다.
밑의 내용은 그냥 읽으면서 체크한 내용을 메모한 것이다.

1장 깨끗한 코드

  • 자신이 짠 쓰레기 코드를 보고 나중에 정리하겠다고 다짐하지만, 나중은 결코 오지 않는다.
  • 나쁜 코드의 위험을 이해하지 못하는 관리자 말을 그대로 따르는 행동은 전문가답지 못하다.

2장 의미있는 이름

  • 의도가 분명하게 이름을 지으라

3장 함수

  • 작게 만들어라!
  • 함수는 한 가지를 해야한다.
  • 인수를 줄이자
  • 부수효과를 일으키지 마라!
  • 반복하지 마라
  • 함수를 작게 만든담녀 간혹 return, break, continue를 여러 차례 사용해도 괜찮다. 오히로 때로는 단일 입/출구 규칙보다 의도를 표현하기 쉬워진다. 반면 goto문은 큰 함수에서만 의미가 있으므로, 작은 함수에서는 피해야만 한다.
  • 소프트웨어를 짜는 행위는 여느 글짓기와 비슷하다. 먼서 생각을 기록한 후 읽기 좋게 다듬는다. 초안은 대개 서투르고 어수선하므로 원하는 대로 읽힐 때까지 말을 다듬고 문장을 고치고 문단을 정리한다.

4장 주석

  • 코드로 의도를 표현하라 : 코드로 대다수의 의도를 표현할 수 있다. 많은 경우 주석으로 달려는 설명을 함수로 만들어 표현해도 충분하다.

5장 형식 맞추기

  • 오늘 구현한 기능이 다음 버전에서 바뀔 확률은 아주 높다. 그런데 오늘 구현한 코드의 가독성은 앞으로 바뀔 코드의 품질에 지대한 영향을 미친다. 오랜 시간이 지나 원래 코드의 흔적을 더 이상 찾아보기 어려울 정도로 코드가 바뀌어도 맨 처음 잡아놓은 구현 스타일과 가독성 수준은 유지보수 용이성과 확장설에 계속 영향을 미친다.
  • 변수는 사용하는 위치에 최대한 가까이 선언한다.

6장 객체와 자료구조

  • 디미터 법칙 : 모듈은 자신이 조작하는 개체의 속사정을 몰라야 한다. 객체는 조회 함수로 내부 구조를 공개하면 안된다.
  • 시스템을 구현할 떼, 새로운 자료 타입을 추가하는 유연성이 필요하면 객체가 더 적절하다. 다른 경우로 새로운 동작을 추가하는 유연성이 필요하면 자료구조와 절차적인 코드가 더 적합하다. 우수한 소프트웨어 개발자는 편견없이 이 사실을 이해해 직면한 문제에 최적인 해결책을 선택한다.

7장 오류 처리

  • null을 반환하지 마라 : null을 반환하는 코드는 일거리를 늘릴 뿐만 아니라 호출자에게 문제를 떠넘긴다. 누구 하나라도 null 확인을 빼먹는다면 애플리케이션이 통제 불능에 빠질지도 모르다.

8장 경계

  • 외부 패키지를 호출하는 코드를 가능한 줄여 경계를 관리하자. 새로운 클래스로 경계를 감싸거나 아니면 ADAPTER 패턴을 사용해 우리가 원하는 인터페이스를 패키지가 제공하는 인터페이스로 변환하자. 어느 방법이든 코드 가독성이 높아지며, 경계 인터페이스를 사용하는 일관성도 높아지며, 외부 패키지가 변했을 때 변경할 코드도 줄어든다.

9장 단위 테스트

  • 테스트는 유연성, 유지보수성, 재사용성을 제공한다.
  • F.I.R.S.T : 꺠끗한 테스트는 다음 다섯가지 규칙을 따른다.
    • Fast 빠르게 : 테스트는 빨리 돌아야한다.
    • Independent 독립적으로 : 각 테스트는 서로 의존하면 안된다.
    • Repeatable 반복가능하게 : 테스트는 어떤 환경에서도 반복 가능해야한다.
    • Self-Validating 자가검증하는 : 테스트는 성공아니면 실패라고 결과를 내야한다. (성공여부루를 알려고 로그를 읽게 만들어선 안된다.)
    • Timely 적시에 : 테스트는 적시에 작성해야한다.

10장 클래스

  • 클래스 체계 : 표준 자바 관례에 따르면, 가장 먼저 변수 목록이 나온다. static public 상수가 있다면 맨 처음에 나온다. 다음으로 정적 private 변수가 나오며, 이어서 비공개 인스턴스 변수가 나온다. 변수 목록 다음에는 공개 함수가 나온다. 비공개 함수는 자신을 호출하는 공개 함수 직후에 넣는다. 즉, 추상화 단계가 순차적으로 내려간다. 그래서 프로그래램은 신문기사처럼 읽힌다.
  • 단일 책임 원칙(SRP) : 클래스는 책임, 즉 변경할 이유가 하나여야 한다.
  • 규모가 어느 수준에 이르는 시스템은 논리가 많고도 복잡합하다. 이런 복잡성을 다루려면 체계적인 정리가 필수다. 그래야 변경을 가할 때 직접 영향이 미치는 컴포넌트만 이해해도 충분하다.
  • 큰 클래스 몇 개가 아니라 작은 클래스 여럿으로 이뤄진 시스템이 더 바람직하다.
  • 시스템의 결합도를 낮추면 유연성과 재사용성도 더 높아진다. 결합도가 낮다는 소리는 각 시스템 요소가 다른 요소로부터 그리고 변경으로부터 잘 격리되어 있다는 의미다.

11장 시스템

  • 의존성 주입 : 사용과 제작을 분리하는 강력한 메커니즘. 의존성 주입은 제어의 역전 기법을 의존성관리에 적용한 메커니즘이다. 제어 역전에서는 한 객체가 맡은 보조 책임을 새로운 객체에게 전적으로 떠넘긴다. 새로운 객체는 넘겨받은 책임만 맡으므로 딘일 첵임 원칙을 지키게 된다. 의존성 관리 맥락에서는 객체는 의존성 자체를 인스턴스로 만드는 책임을 지지 않는다. 대신에 이런 책임을 다른 '전담' 메커니즘에 넘겨야만 한다. 그렇게 함으로 써 제어를 역전한다.
  • AOP에서 관점이라는 모듈 구성 개념은 "특정 관심사를 지원하려면 시스템에서 특정 지점들이 동작하는 방식을 일관성 있게 바꿔야한다" 라고 명시한다. 프로그래머는 영속석으로 저장할 객체와 속성을 선언한 후 영속성 책임을 영속성 프레임워크에 위임한다. 그러면 AOP 프레임워크는 대상 코드에 영향을 미치지 않는 상태로 동작방식을 변경한다.
  • 프로그래머는 설정파일이나 API를 사용해 피룻적인 애플리케이션 기반구조를 구현한다. 여기에는 영속성, 트랜잭션, 보안, 캐시, 장애조치 등과 같은 횡단관심사도 포함된다.
  • 시스템을 설계하든 개별 모듈을 설계하든, 실제로는 돌아가는 가장 단순한 수단을 사용해야 한다는 사실을 명심하자.

12장 창발성

  • 단순한 설계 규칙 네 가지
    • 모든 테스트를 실행한다.
    • 중복을 없앤디.
    • 프로그래머 의도를 표현한다.
    • 클래스와 메서드 수를 최소로 줄인다.

13장 동시성

  • 동시성 코드가 일으키는 문제로부터 시스템을 방어하는 원칙과 기술
    • 단일 책임 원칙 : 동시성 코드는 다른 코드와 분리하라
    • 자료범위를 제한하라 : 자료를 캡슐화하라. 공유 자료를 최대한 줄여라.
    • 자료 사본을 사용하라
    • 스레드는 가능한 독립적으로 구현하라 : 독자적인 스레드로, 가능하면 다른 프로세서에서, 돌려도 괜찮도록 자료를 독립적인 단위로 분할하라.
    • 자바에서 synchronized 키워드를 사용하면 락을 설정한다. 락은 스레드를 지연시키고 부하를 가중시킨다. 그로므로 synchronized 문을 남발하는 코드를 바람하지 않다. 반면, 임계영역은 반드시 보호해야한다. : 동기화하는 부분을 최대한 작게 만들어라
    • 스레드 코드 테스트하기 : 문제를 노출하는 테스트 케이스를 작성하라. 프로그램 설정과 시스템 설정과 부하를 바꿔가며 자주 돌려리. 테스트가 실패하면 원인을 추적하라. 다시 돌렸더니 통과하더라는 이유로 그냥 넘어가면 절대 안된다.

14장 점진적인 개선

  • 깨끗한 코드를 짜려면 먼저 지저분한 코드를 짠 뒤에 정리해야 한다.

15장 JUnit 들여다보기

16장 SerialDate 리팩터링

17장 냄새와 휴리스틱

  • 저자가 코드를 짜면서 사용하는 기교와 휴리스틱을 나열해놓았다. 꼭 다시 한번 볼 것!!
  • 주석
    • 부적절한 정보
    • 쓸모 없는 주석
    • 중복된 주석
    • 성의 없는 주석
    • 주석 처리 된 코드
  • 환경
    • 여러 단계로 빌드해야 한다
    • 여러 단계로 테스트해야 한다
  • 함수
    • 너무 많은 인수
    • 출력 인수
    • 플래그 인수
    • 죽은 함수
  • 일반
    • 힌 소스 파일에 여러 언어를 사용한다
    • 당연한 동작을 구현하지 않는다
    • 경계를 올바로 처리하지 않는다
    • 안전 절차 무시
    • 중복
    • 추상화 수준이 올바르지 못하다
    • 기초 클래스가 파생클래스에 의존한다
    • 과도한 정보
    • 죽은 코드
    • 수직 분리
    • 일관성 부족
    • 잡동사니
    • 인위적 결합
    • 기능 욕심
    • 선택자 인수
    • 모호한 의도
    • 잘못 지운 책임
    • 부적절한 static 함수
    • 서술적 변수
    • 알고리즘을 이해하라
    • If/Else 혹은 Switch/Case 문보다 다형성을 사용하라
    • 표준 표기법을 따르라
    • 매직 숫자는 명명된 상수로 교체하라
    • 정확하라
    • 관례보다 구조를 사용해라
    • 조건을 캡슐화하라
    • 부정 조건을 피하라
    • 함수는 한 가지만 해야한다
    • 일관성을 유지하라
    • 경계조건을 캡슐화하라
    • 설정 정보는 최상위 단계에 둬라
    • 추이적 탐색을 피하라
  • 자바
    • 긴 Import 목록을 피하고 와일드 카드를 사용하라
    • 상수는 상속하지 않는다
    • 상수 대신 Enum
  • 이름
    • 서술적인 이름을 사용하라
    • 적절한 추상화 수준에서 일므을 선택하라
    • 가능하다면 표준 명명법을 사용하라
    • 긴 범위는 긴 이름을 사용하라
    • 인코딩을 피하라
    • 이름으로 부수 효과를 설명하라
  • 테스트
    • 불충분한 테스트
    • 커버리지 도구를 사용하라
    • 사소한 테스트를 건너뛰지 마라
    • 무시한 테스트는 모호함을 뜻한다
    • 경계조건을 테스트하라
    • 버그 주변은 철저히 테스트하라
    • 실패 패턴을 살펴라
    • 테스트 커버리지 패턴을 살펴라
    • 테스트는 빨라야 한다

2020년 3월 7일 토요일

나는 LINE 개발자입니다 책 메모

나는 LINE 개발자 입니다

여러 LINE 개발자들의 일기 같은 책
라인의 기업문화나 라인 개발자는 어떻게 일하나? 에 대해서 소개하는 책같아서 구입을 하였지만, 해당 내용들은 아주 조금씩 있었다...
요즘 우아한형제들 기술블로그나, 비슷한 책들을 많이 읽다보니 엄청 새로운 내용은 없었고, 라인 또한 개발자에게 좋은 회사 같다.
상당히 가볍게 읽기 좋은 책 (어려운 내용이 없어서 후루룩 읽혔다.)

  • 코드 리뷰를 통해 단순히 버그를 발견하고 수정하는 수준을 넘어 가독성과 확장성이 뛰어난 코드, 일관된 스타일의 코드, 유지보수하기 편리한 코드를 작성하려고 노력한다.
  • 개발을 가장 빨리배우는 방법은 내게 익숙한 소프트웨어를 따라 만들어보는 것이라고 생각한다.
  • 새로운 기술을 접할 때 책을 먼저 한번 보고, 기술 문서를 보고나 코드에 접근하면 내가 지금 파보고 있는 코드가 어ㄷ느 영역에 해당하는 것인지, 그리고 고민해야 하는 영역이 어떤 것인지 쉽게 알 수 있다.
  • 기술문서의 경우 용어 번역 등의 문제로 의도치 않은 오역이 발생하는 경우가 많다. 가능하면 원문으로 좀 더 정확하게 이해하기를 추천한다.
  • 어떻게 질문해야 할까? : 내 생황을 정확하게 알리자
  • 기술공유를 통해 가장 많이 배우는 사람은 역시 발표자 혹은 글을 쓰는 본인이다. 가르치는 것이 가장 좋은 배우는 방법이라는 말이 있듯이, 내가 안다고 생각해서 글로 정리하기 시작하면 더 많은 것을 정확하게 공부하게 된다.

2020년 2월 26일 수요일

엔터프라이즈 자바 마이크로서비스 책 메모

엔터프라이즈 자바 마이크로서비스

마이크로서비스의 개요와 모노리스를 마이크로서비스로 변경하는 간단한 실습이 있다.
엔터프라이즈서비스를 구현할 때 도움되는 프레임워크나 라이브러리 소개, 서비스발견개념, 히스트릭스, 도커 등 엄청 다양하고 얇게 예제를 통해 소개하고 있다.
필요한공부는 각자 깊게 해야함!
실습은 나중에 따라 해볼만할 듯. 소스원본도 있는 듯
엄청가볍게 개념만 읽으려고 본책이지만 깊게 설명한내용이 많아 그냥 넘어간내용도 많다.
실습과 함께 다시 읽어볼 필요도 있음
필요한 부분 참조해서 보면 좋을듯

  • 모노리스는 한 전개 단위 안에 모든 컴포넌트가 들어 있는 애플리케이션
  • 애플리케이션을 아주 조금 변경헀다고 해도 그 애플리케이션에 들어 있는 다른 부분들이 제대로 작동하는지 알기 위해 아주 큰 회귀 테스트를 돌려봐야한다. 자동화 했다고해도 그런 재귀 테스트는 여전히 거대한 작업이다.
  • 모노리스를 계속 유지해야 할지 어떻게 알 수 있을까?
    • 회사에 활발하게 개발과 유지보수가 이뤄지는 애플리케이션이 몇 가지밖에 없다.
    • 현재 개발팀의 인원이 십여명이라면, 두세 사람으로 구성된 마이크로서비스 팀으로 개발팀을 나누느 것은 아무 이득 없다. (12명이 좋은 예)
    • 주중에 여러 번 릴리스할 필요가 있나?
  • 애플리케이션의 필요를 충족시키기 위해 서로 통신하는 다수의 마이크로서비스가 존재할 때 마이크로서비스 아키텍쳐가 유용해진다.
  • 분산에 신경을 써야하는 이유?
    • 서비스가 위치와 무관해진다.
    • 서비스가 언어와 무관해진다.
    • 서비스 전개 규모가 작고 한 가지 목적을 위해 전개가 이뤄진다.
      • 이를 통해 기업은 더 쉽게, 거의 실시간에 준하는 방식으로 비즈니스에 대응할 수 있다.
    • 새로운 서비스는 기존 서비스 기능을 재조합하는 방식으로 정의된다.
  • JeAS는 애플리케이션 서버와 애플리케이션의 관계를 뒤집어서 애플리케이션 서버의 구성 요소 중 애플리케이션 실행을 위해 필요한 부분만을 패키징한 것
    • 꼭 필요한 만큼의 애플리케이션 서버 (Just Enough Application Service)
    • ex_ 드롭위자드, 파야라 마이크로, 스프링부트, 손테일 등
    • JeAS를 사용하면 마이크로서비스와 함께 사용하기에 꼭 필요한 런타임만을 패키징할 수 있다.
    • JuAS 런타임은 RESTFul 마이크로서비스를 전재할 때 최고의 전개방법이다.
  • JeAS 런타임을 사용한 이점
    • 패키지 크기 감소
    • 할당된 메모리 감소
    • 보안 풋프린트 감소
    • 애플리케이션 분리 증대
    • 업그레이드 단순화
  • 마이크로서비스 테스트의 핵심은 마이크로서비스가 정의하는 계약, 즉 마이크로서비스가 노출하는 API를 검증하되 마이크로 서비스가 API를 노출하는 의도에 대해서가 아니라 클라이언트가 어떤 요청을 보내고 어떤 응답을 받을 것으로 예상하는지에 대해서 검증하는 것이다.
  • IaaS, 인프라 제공서비스 (Infra as a Service)
    • 보통 가상 머신을 게스트로 실행할 수 있는 하이퍼바이저를 포함한다.
  • PaaS, 플랫폼 제공서비스 (Platform as a Service)
    • Iaas 위에서 운영체제, 다양한 프로그래밍 언어에 대한 실행환경, 데이터베이스, 웹 서버를 제공하는 계층
  • SaaS, 소프트웨어 제공서비스 (Software as a Service)
    • 애플리케이션의 일부분이나 전체 애플리케이션을 사용자의 필요나 요청에 따라 제공
  • 컨테이너를 사용하면 애플리케이션이나 서비스를 사용할 운영체제와 함께 패키지로 만들 수 있다. 이때 필요한 소프트웨어 설정도 컨테이너에 들어가는 운영체제에 포함시킬 수 있고, 전통적인 가상머신에 비해 만들어지는 이미지의 크기도 작아질 수 있다.
  • 클라우트 네이티브 개발은 클라우드 환경에서 전개할 것을 전제로 서비스나 애플리케이션을 개발하는 것을 뜻한다.
  • 미니시프트는 로컬 컴퓨터에서 오픈시프트를 사용하는 클라우드 환경을 제공한다. 따라서 여러 기계를 관리할 필요 없이 마이크로서비스를 실행하고 테스트하는 과정을 단순화할 수 있다.
  • JAX-RS 클라이언트 라이브러리를 사용하면 RESTful 마이크로서비스에 연결할 때 필요한 저수준 HTTP 연결에 대해 신경쓰지 않고 꼭 필요한 메타데이터에 집중할 수 있다.
  • 클라이언트측 부하 균일화 : 클라이언트가 어떤 마이크로서비스를 소비할지 결정하는 책임을 지는 경우
  • 서비스 발견 : 실행 시점에 한 마이크로서비스가 소비할 것을 목적으로 다른 마이크로서비의 물리적 위치를 얻을 수 있는 수단을 뜻한다.
    • 소비할 마이크로서비스의 위치를 포함하는 코드는 인스턴스가 새로 시작되거나 끝나면 잘못될 가능성이 있다. 마이크로서비스의 위치가 바뀐 경우 코드나 설정을 변경해야하고, 그런 변경의 영향이 미치는 여러 환경에 다시 전개해야하는 코드에서도 실패가 일어날 수 있다. 서비스 발견을 통해 마이크로서비스가 직접 IP환경을 다루지 않고도 축소나 확장을 할 수 있도록 다른 마이크로서비스의 위치를 코드와 분리할 수 있다.
  • 히스트릭스 : 지연시간과 내고장성을 위한 라이브러리로 원격 시스템, 서비스, 라이브러리에 대한 접근 지점을 격리시키고, 연쇄적인 샐패를 중단시키면, 분산시스템에 탄력성을 부여하려는 목적으로 만들어졌다.
  • 분산 아키텍처에 마이크로서비스를 전개할 때 지연시간이나 고장을 견딜 수 있는 내고장성을 갖추는 것이 중요하다.
  • 마이크로서비스를 소비하는 코드를 히스트릭스로 감싸서 폴백, 요청캐시, 벌크헤드와 같은 내고장성 기능을 추가할 수 있다.
  • 마이크로서비스의 보안 측면에서 인증과 권한부여가 가장 중요한 부분이다.
  • 아파치 카프카 : 분산 스트리밍 플랫폼. 카프카는 단일데이터 스트림에 속하는 데이터를 클러스터상의 여러서버에 분할해 처리할 수 있다. 추가로 내고장성을 위해 분할된 각 부분을 서버 사이에 복제할 수 있다.

2020년 2월 15일 토요일

[인프런] 스프링 기반 REST API 개발 수강 후기

벌써 인프런 백기선님의 강의 3번째 완강이다.
회사에서 REST 관련소스를 본적 있는데, 제대로 구현이 되어있지않은 것 같았다.
구글에서 본 REST API의 장점이나 특징들이 없었다.
그러던 도중 인프런 쿠폰이생겨서 재미있을 것 같은 백기선님의 스프링 기반 REST API 개발 강의를 구매하였다. (88000원)
https://www.inflearn.com/course/spring_rest-api
이 강의에서는 실습을 통해 REST의 특징을 잘 살려 코딩하는 방법을 알려준다.
API 중 다음을 만족하지 않는 API가 많으니 두 가지를 만족할 수 있게 하자
  - self-descriptive message
  - hypermisa as the engine of application state (HATEOAS)

강의는 프로젝트 생성 - 이벤트 관련 API 개발 - 보안 적용 으로 구성되며,
모든 실습은 TDD로 진행되어 TDD를 어떻게 해야할까? 의 나의 고민을 조금 해결해주었다. 
프로젝트 기본설정 구성부터 테스트 환경구성, 인텔리제이 단축키 활용, 코드 중복 줄이기, 스프링부트가 제공하는 설정, 간단한 JPA 설명 등 전반적으로 효율적인 개발에 엄청 도움이 되는 내용이 많았다.
중간에는 도커를 이용하여 DB도 사용해봤는데, 이것도 흥미있었다. 아직 잘모르겠지만 공부해보고싶다!
'프로젝트 구성할 때 과연 혼자서 이런 설정들을 찾아가면서 만들 수 있을까?'
'이런 유용한 방식들이 많구나'
'스프링 시큐리티는 저렇게 쓰는거구나'
등 의 생각도 나고...
아무튼 엄청 재미있으면서 감탄하면서 본 강의다!!!
내가 과연 잘 활용할 수 있을지는 모르겠지만, 지금 진행하고있는 토이프로젝트에 좀 적용시켜보면서 연습 해야겠다.

2019년 12월 29일 일요일

커리어 스킬 책 메모

커리어 스킬 책 메모

전자책으로 완독한 두번째 책이다. 책 소개로는 개발자 인생 로드맵이라고 소개하고 있다.
책 소개답게 개발자가 되려면 부터 회사 생활까지 다양하게 설명해주는 책이다.
개발자를 꿈을 갖고 공부하고 있는 상황이라면 가볍게 읽기 좋을 것 같다!
필요한 내용은 직접 검색해서 찾아봐야한다. 이 책은 여러가지를 소개하는 책이라 엄청 깊게는 설명하지는 않는다.

  • 코드 구조화란 주석을 줄줄이 달지 않고도 이해하기 쉽도록 코드를 잘 작성하는 것을 가리킨다. 원래는 코드만으로도 의사 전달이 가능해야 한다.
  • 코딩 인터뷰 완전 분석은 알고리즘과 데이터구조에 대한 최고의 참고 도서다. 이 책은 알고리즘과 데이터 구조에 대해 알아야할 거의 모든 것을 다른다.
  • 구글에서 '자신이 선택한 기술 + 면접 질문'을 검색해 나온 상위 세 가지 검색 결과에 해당하는 모든 질문에 대답할 수 있도록 준비하라.
  • 단위테스트의 이점 or 하는 이유
    • 코드 설계가 개선된다. 단위 테스트를 제대로 작성하려면 코드를 가능 한 작은 단위로 고립시켜야 한다. 과정에서 코드 설계의 문제점을 알게된다. 단위 테스트 작성 원칙을 엄격히 지키기 위해 코드를 고립된 상태로 가능한한 작게 만들다보면 그 코드와 단위 설계에 존재하는 온갖 문제가 드러난다.
    • 자동화된 회귀테스트를 만드는 것. 이렇게 작성한 테스트는 소프트웨어의 동작이 저수준에서 반드시 지켜야할 명세가 되기도 한다.
  • TDD의 기본 개념은 코드를 작성하기 전에 테스트부터 작성해서 그 코드가 해야할 일을 명확하게 정의하는 명세로 쓰는 것이다.
  • TDD의 가장 큰 가치는 테스트를 명세로 쓸 수 있게 해주는 것이다.
  • 테스트는 특정환경에서 정확히 어떤 일이 일어나야 하는지 명시한다. 그래서 TDD를 쓰려면 무언가 구현하기 전에 무엇을 구현할생각인지부터 제대로 이해하는 과정ㅇ이 선행되어야 한다.
  • 모의 객체는 미리 설정한 값을 써서 의존성이 있는 기능을 흉내 내어 테스트하고자 하는 개별 클래스를 고립시킬 수 있게 도와준다.
  • 지속적 통합을 활용하는 작업 흐름 샘플
    • 코드 체크인
    • 새 빌드 시작
    • 코드 체크아웃
    • 코드 컴파일
    • 정적 분석기 실행
    • 단위 테스트 실행
    • 결과 보고
    • 소프트웨어 패키징
    • 코드의 선택적 배포(지속적배포)
    • 완료
  • 유지 보수하기 쉬운 코드를 작성하고 자신이 작성하지 않은 기존코드를 유지 보수하는 데 도움을 주는 자료
    • 로버트 마틴의 Clean Code
    • 스티브 맥코넥의 Code Complete
    • 마이클 페더스의 레코시 코드 활용 전략
    • 마틴 파울러의 리팩토링
  • 자리를 지키기 위해 정치적 게임을 하면서 어느 말에 걸어야 안정성이 보장될까 전전긍긍하기보다 고용 보장이나 안정성의 필요를 느끼지 못할 정도로 자신의 실력을 키우는 건 어떨까?
  • 사이드 프로젝트 진행을 위한 체계와 일정이 필요하다.
    • 그 프로젝트를 위해 매일 혹은 매주 얼마의 시간을 쓸 것인지 명확히 정의한다.
    • 정의한 시간이 정확히 언제인가를 정의한다.
    • 작업 진도와 해야 할 일을 추적할 수 있는 절차를 정의한다.
  • 저자의 책 추천 목록
    • 훌륭한 코드 작성하기
      • 코들 컴플리트 2: 더 나은 소프트웨어 구현을 위한 실무 지침서
      • 클린 코드: 애자일 소프트웨어 장인 정신
      • 클린 소프트웨어
    • 개발 기본 소양 갖추기
      • GoF의 디자인 패턴
      • Testing Computer Software
      • Introduction to Algorithms
        • 앤터프라이즈 애플리케이션 아키텍쳐 패턴
    • 기존 코드 다루기
      • 리팩토링
      • 래거시 코드 활용 전략
      • 패턴을 활용한 리팩토링
    • 더 훌륭한 개발자 되기
      • 소프트 스킬
      • 실용주의 프로그래머
      • 프로그래머, 열정을 말하다.

2019년 12월 1일 일요일

김영한님의 JPA프로그래밍 기본기 다지기 메모

김영한님의 JPA 프로그래밍 기본기 강의


  • 회사에 입사한 지 얼마 안됬을 때 사수가 ORM에 대해 한번 훑어보라며, 책을 추천해준 적이 있었다.
    그 때는 정신도 없어서 나중에 봐야겠다... 라고만 생각했는데, 인프런 인강과 다른 블로그에 있는 스프링부트 실습을 따라하면서 JPA 간단하게 경험해볼 수 있었다. 공부해보고 싶기도하고, 토이프로젝트에 적용시켜보고 싶기도 해서 찾아보니 사수가 추천해준 책의 저자께서 직접 설명하는 기본 강의가 유튜브에 있었다!!
    (19.12.01 인프런에 JPA강의도 있다.)
    실습을 통해 이해할 수 있는 좋은 강의였고, 책이나 인프런강의를 통해 더 자세히 공부도 해보고 싶다!

https://www.youtube.com/watch?v=WfrSN9Z7MiA&list=PL9mhQYIlKEhfpMVndI23RwWTL9-VL-B7U

1강 - JPA 소개

  • JPA 기본기 교육임.
  • 애플리케이션은 객체지향언어로 짬. but 데이터베이스는 관계형DB을 사용하고 있음.
    • 객체를 관계형 DB에 관리 -> SQL 필요
  • SQL 중심적인 개발이 이루어짐 -> 무한 반복, 지루한 코드
  • 객체에 필드가 추가될 때? -> 모든 쿼리의 수정이 필요하게 됨
  • 앤티티 신뢰 문제 -> DAO 에서 우리가 필요한 것들을 가져오는게 맞는 지 확인해야함
  • 진정한 의미의 계층 분할이 어렵다
  • SQL에 의존적인개발을 피하기 어렵다
  • 객체를 저장할 때 ?? -> 현실적인 대안 관계형 DB
    • 객체 -> SQL -> RDB
  • 객체와 관계형 데이버베이스의 차이
    • 상속
    • 연관관계
    • 데이터 타입
    • 데이터 식별 방법
-> 객체답게 모델링할 수록 매핑작업이 늘어남(코드가 늘어난다)
  • Java Persistence API : 자바 진영의 ORM 기술 표준
  • ORM
    • Object-relational mapping(객체 관계 매핑)
    • 객체는 객체대로 설계
    • 관계형 데이터베이스는 관계형 데이터베이스대로 설계
    • ORM프레임워크가 중간에서 매핑
    • 대중적인 언어에는 대부분 ORM기술이 존재함
  • JPA를 왜 사용해야 하는가?
    • SQL 중심적인 개발에서 객체 중심으로 개발
    • 생산성 : 간단한 사용가능
    • 유지보수 : 컬러 변동 시 모든 sql 수정 -> 필드만 추가하면됨(sql은 jpa가 처리해줌)
    • 패러다임의 불일치 해결
    • 성능 : 최적화기능(캐시,동일성보장 / 트랜잭션을 지원하는 쓰기 지연 / 지연 로딩)
    • 데이터 접근 추상화와 벤더 독립성
    • 표준
  • ORM은 객체와 RDB 두 기둥 위에 있는 기술

2강 - JPA 기초와 매핑

  • 이번 강의는 실습 위주
  • JPA에서는 크게 중요한 것 두 가지
    1. 객체와 관계형DB와 매핑하는 과정(설계)
    2. 실제 JPA가 어떻게 동작하는지 (영속성 컨텍스 트)
  • H2 데이터 베이스
    • 최고의 실습용 DB
    • 가볍다 (1.5M) (자바에 올려서 배포하기도 한다고 함)
    • 웹용 쿼리 툴 제공
    • MySQL, Oracle 데이터베이스 시뮬레이션 기능
    • 시퀀스, AUTO INCREMENT 기능 지원
  • 메이븐
    • 자바 라이브러리, 빌드 관리
    • 라이브러리 자동 다운로드 및 의존성 관리

객체 매핑하기

  • @Entity : JPA가 관리할 객체 - 엔티티라 한다. (DB랑 매핑할 클래스)
  • @Id : DB PK와 매핑 할 필드
  • persistence.xml
    • JPA 설정 파일
    • /META_INF/persistence.xml 위치
    • javax.persistence로 시작 : JPA 표준 속성
    • hibernate로 시작 : 하이버네이트 전용 속성
  • 데이터베이스 방언
    • JPA는 특정 데이터베이스에 종속적이지 않은 기술
    • 각각의 데이터베이스가 제공하는 SQL 문법과 함수는 조금씩 다르다.
      • 가변문자 : mysql은 varchar, oracle은 varchar2
      • 문자열을 자르는 함수 : SQL 표준은 SUBSTRING(), oracle은 SUBSTR()
      • 페이징 : mysqldms limit , oracle ROWNUM
    • 방언: SQL 표준을 지키지 않거나 특정 데이터베이스만의 고유한 기능
    • Dialect 를 통해 (MySQLDialect, OracleDialect, H2Dialect 등)으로 각 DB용 SQL 생성
    • hibernate.dialect 속성에 지정
      • H2: org.hibernate.dialect.H2Dialect
      • Oracle 10g : org.hibernate.dialect.Oracle10gDialect
      • Mysql : org.hibernate.dialect.MySQL5InnoDBDialect
    • 하이버네이트는 45가지 방언 지원
  • 어플리케이션 개발
    • 준비
    • pom.xml dependency 입력
    • hibernate-entitymanager : 관련 라이브러리 포함되어있음. hibernate core, jpa 2.1 등등 가져옴
    • persistence.xml : jpa이 실행할 때 이파일을 읽어서 DB에 붙고 등등 (부트에선 이 설정파일 없이 알아서 해줌)
    • 앤티티 매니저 팩토리 설정
    • 앤티티 매니저 설정
    • 트랜잭션
    • 비즈니스 로직(CRUD)
// persistence.xml 에 명시된 persistence-unit name정보를 가져와서 로딩하기
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
  • 주의
    • 이 EntityManagerFactory 는 어플리케이션 띄울 때 한번 로딩해야함. 사용자가 실제 비즈니스로직을 태울 때마다 팩토리에서 앤티티매니저를 꺼내서 써야함. 앤티티매니저가 JPA라고 보면됨
    • 앤티티 매니저는 쓰레드간에 공유하면 안된다(사용하고 버려야한다) (데이터베이스 커넥션이 공유될 수 있음.)
    • JPA의 모든 데이터 변경은 트랜잭션 안에서 실행

3강 - 필드와 컬럼 매핑

  • jpa를 통해 테이블을 직접 만들수가 있음.
  • 데이터베이스 스키마 자동 생성하기
    • DDL을 애플리케이션 실행 시점에 자동 생성
    • 테이블 중심 -> 객체중심
    • DB에 맞는 적잘한 DDL 생성
    • 이렇게 생성된 DDL은 개 장비에서만 사용
    • 생성된 DDL은 운영서버에서는 사용하지 않거나, 적절히 다듬은 후 사용
  • hibernate.hbm2ddl.auto
    • create : 기존테이블 삭제 후 다시 생(DROP + CREATE)
    • create-drop : create 와 같으나 종료시점에 테이블 DROP
    • update : 변경분만 반영 (운영 DB에는 사용하면 안됨)
    • validate : 엔티티와 테이블이 정상 매핑되었는지 확인
    • none : 사용하지 않음
    • 운영장비에는 절대 create, create-drop, update 사용하면 안된다.
      • 개발초기단계 create or update
      • 테스트서버 update or validate
      • 스테이징과 운영 validate or none
  • 매핑 어노테이션
    • @Column (DB의 컬럼이름)
      • 가장많이 사용됨
      • name : 필드와 매핑할 테이블의 컬럼이름
      • insertalbe, updatalbe : 읽기전용
      • nullalbe : null 허용여부 결정 , DDL 생성 시 사용
      • unique : 유니크 제약조건, DDL 생성 시 사용
      • columnDefinition, length, precision, scale(DDL)
    • @Temporal (시간관련)
      • 날짜 타입 매핑
      • @Temporal(TemporalType.DATE)
      • localDateTime 써도됨
    • @Enumerated
      • enum타입.
      • 현업에서는 꼭 String을 써야함 (EnumType.STRING). 기본은 ORDINAL(순서임))
    • @Lob
      • CLOB, BLOB 매핑
      • CLOB : String, char[], java.sql.CLOB
      • BLOB : byte[], java.sql.BLOB
      • 이 어노테이션을 String에 쓰면 CLOB, byte에 쓰면 BLOB이 됨
    • @Transient
      • 이 필드는 매핑하지 않는다.
      • 애플리케이션에서 DB에 저장하지 않는 필드
  • 식별자 매핑 어노테이션
    • @Id (직접)
      • IDENTITY : 데이터베이스에 위임. MYSQL
      • SEQUENCE : 데이터베이스 스퀀스 오브젝트 사용. ORACLE
        • @SequenceGenerator
      • TABLE : 키 생성용 테이블 사용, 모든 DB에서 사용
        • @TableGenerator 필요
      • AUTO : 방언에 따라 자동 지정, 기본 값
    • @GeneratedValue
    • 권장하는 식별자
      • 기본 키 제약조건 : null 아님, 유일, 변하면 안된다.
      • 미래까지 이 조건을 만족하는 자연키는 찾기 어렵다. 대리키(대체키)를 사용하자.
      • 예를 들어 주민등록번호도 기본 키로 적절하지 않다.
      • 권장 : Long + 대체키 + 키 생성전략 사용

4강 - 연관관계 매핑

  • '객체지향 설계의 목표는 자율적인 객체들의 협력 공동체 를 만드는 것이다.'
  • 객체를 테이블에 맞추어 데이터 중심으로 모델링하면, 협력 관계 만들 수 없다.
    • 테이블은 외래키로 조인을 사용해서 연관된 테이블을 찾는다.
    • 객체는 참조를 사용해서 연관된 객체를 찾는다.
    • 테이블과 객체 사이에는 이런 큰 간격이 있다.
  • 연관관계 매핑 이론
    • 단반향 매핑
    • 양방향 매핑

5강 - 양방향 매핑

  • 연관관계의 주인과 mappedBy
    • mappedBy : JPA의 멘붕클래스1
    • mappedBy는 처음에는 이해하기 어렵다.
    • 객체와 테이블간에 연관관계를 맺는 차이를 이해해야 한다.
  • 객체와 테이블이 관계를 맺는 차이
    • 객체 연관관계
      • 회원 -> 팀 연관관계 1개 (단방향)
      • 팀 -> 회원 연관관계 1개 (단방향)
    • 테이블 연관관계
      • 회원 <-> 팀 의 연관관계 1개 (양방향)
  • 객체의 양방향 관계
    • 객체의 양방향관계는 사실 양방향관계가 아니라 서로 다른 단방향 관계 2개이다.
    • 객체를 양방향으로 참조하려면 단방향 연관관계를 2개 만들어야 한다.
  • 테이블의 양방향 연관관계
    • 테이블은 외래 키 하나로 두 테이블의 연관관계를 관리
    • MEMBER.TEAM_ID 외래 키 하나로 양방향 연관관계 가짐 (양쪽으로 조인할 수 있다.)
  • 연관관계의 주인 (Owner)
    • 양방향 매핑 규칙
      • 객체의 두 관계중 하나를 연관관계의 주인으로 지정
      • 연관관계의 주인만이 외래 키를 관리(등록,수정)
      • 주인이 아닌 쪽은 읽기만 가능
      • 주인은 mappedBy 속성 X
      • 주인이 아니면 mappedBy 속성으로 주인 지정
  • 누구를 주인으로?
    • 외래 키가 있는 곳을 주인으로 정해라
    • 여기서는 Member.team 연관관계의 주인
  • 양방향 매핑 시 연관관계의 주인에 값을 입력해야 한다.
  • 양방향 매핑의 장점
    • 단방향 매핑만으로도 이미 연관관계 매핑은 완료
    • 양방향 매핑은 반대 방향으로 조회 (객체 그래프 탐색) 기능이 추가 된 것 뿐
    • JPQL에서 역방향으로 탐색할 일이 많음
    • 단방향 매핑을 잘 하고 양방향은 필요할 때 추가해도 됨 (테이블에 영향을 주지않음)
  • 연관관계 매핑 어노테이션
    • 다대일(@ManyToOne)
    • 일대다(@OneToMany)
    • 일대일(@OneToOne)
    • 다대다(@ManyToMany) (현업애선 잘 안씀)
    • @JoinColumn, @JoinTable
  • 상속 관계 매핑 어노테이션 (설명은 책 참조..)
    • @Inheritance
    • @DiscriminatorColumn
    • @DiscriminatorValue
    • @MappedSuperclass (매핑 속성만 상속)
  • 복합키 어노테이션
    • @IdClass
    • @EmbeddedId
    • @Embeddalbe
    • @Mapsld

6강 - JPA 내부 구조

  • 영속성 컨텍스트
    • JPA를 이해하는데 가장 중요한 용어
    • "엔티티를 영구 저장하는 환경" 이라는 뜻
    • EntityManager.persist(entity);
  • 앤티티 매니저 팩토리와 앤티티 매니저
  • 앤티티 매니저? 영속성 컨테스트?
    • 영속성 컨텍스트는 논리적인 개념
    • 눈에 보이지 않는다
    • 앤티티 매니저를 통해서 영속성 컨텍스트에 접근
  • J2SE 환경 : 엔티티 매니저와 영속성 컨텍스트가 1:1
  • J2EE, 스프링 프레임워크 같은 컨테이너 환경 : 앤티티 매니저와 영속성 컨텍스트가 N:1
  • 앤티티의 생명주기
    • 비영속(new/transient) : 영속성 컨텍스트와 전혀 관계가 없는 상태 (객체를 생성만 한 상태)
    • 영속(managed) : 영속성 컨텍스트에 저장된 상태 (객체를 저장한 상태 em.persist(member) )
    • 준영속(detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태 (em.detach)
    • 삭제(removed) : 삭제된 상태 (em.remove(member) )
  • 영속성 컨텍스트의 이점
    • 1차 캐시 (DB가기 전 캐시에서 조회)
    • 동일성(identity) 보장 (1차 캐시때문)
    • 트랜잭션을 지원하는 쓰기 지연 (transactional write-behind)
    • 변경감지(Dirty Checking) (스냅샷과 비교하여 감지)
    • 지연 로딩(Lazy Loading)
  • 플러시 : 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영
  • 플러시 발생
    • 변경 감지
    • 수정된 엔티티 쓰기 지연 SQL 저장소에 등록
    • 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송( 등록, 수정, 삭제 쿼리)
  • 영속성 컨텍스트를 플러시하는 방법
    • em.flush() : 직접호출
    • 트랜잭션 커밋 : 플러시 자동 호출
    • JPQL 쿼리 실행 : 플러시 자동 호출(mybatis 나 스프링 jdbc 를 사용할 경우 flush 를 써야줘야 함)
  • 플러시는!
    • 영속성 컨텍스트를 비우지 않음 (clear가 비움)
    • 영속성 컨텍스트의 변경내용을 데이터베이스에 동기화
    • 트랜잭션이라는 작업 단위가 중요 -> 커밋 직전에만 동기화 하면 됨
  • 준영속 상태
    • 영속 -> 준영속
    • 영속 상태의 엔티티가 영속성 컨텍스트에서 분리(detached)
    • 영속성 컨텍스트가 제공하는 기능을 사용 못함
  • 준영속 상태로 만드는 방법
    • em.detach(entity) : 특정 엔티티만 준영속 상태로 전환
    • em.celar() : 영속성 컨텍스트를 완전히 초기화
    • em.close() : 영속성 컨텍스트를 종료
  • 프록시와 즉시로딩, 지연로딩
    • Member를 조회할 때 Team도 함께 조회해야 할까? : 지연로딩 LAZY을 사용해서 프록시(가짜객체)로 조회
      • 실제 team을 사용하는 시점에 초기화(DB조회)
    • Member와 Team을 자주 함께 사용한다면? : 즉시 로딩 EAGER를 사용해서 함계 조회 (현업에선 보통 LAZY.)
  • 프록시와 즉시로딩 주의
    • 가급적 지연 로딩을 사용
    • 즉시 로딩을 적용하면 예상하지 못한 SQL이 발생
    • 즉시 로딩은 JPQL에서 N+1 문제를 일으킨다.
    • @ManyToOne, @OneToOne은 기본이 즉시로딩 -> LAZY로 설정
    • @OneToMany, @ManyToMany는 기본이 지연로딩

7강 - JPA와 객체지향 쿼리

  • JPA는 다양한 쿼리방법을 지원
    • JPQL
    • JPA Criteria
    • QueryDSL
    • 네이티브 SQL
    • JDBC API 직접 사용, MyBaits, SpringJdbcTemplate 함께 사용
  • JPQL 소개 (객체 대상으로 조회)
    • 가장 단순한 조회 방법
      • EntityManager.find()
      • 객체 그래프 탐색(a.getB().getC())
    • JPA를 사용하면 앤티티 객체 중심으로 개발
    • 문제는 검색쿼리
    • 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색
    • 모든 DB데이터를 객체로 변환해서 검색하는 것은 불가능
    • 애플리케이션이 필요한 데이터만 DB에서 불러오려면 결국 검색 조건이 포함된 SQL이 필요
    • JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어 제공
    • SQL과 문법 유사 SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 지원
    • JPQL은 엔티티 객체를 대상으로 쿼리 vs SQL은 데이터베이스 테이블을 대상으로 쿼리
    • 테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리
    • SQL을 추상화해서 특정 데이터베이스 SQL에 의존 X
    • JPQL을 한마디로 정의하면 객체지향 SQL
  • JPQL 문법
    • select m from Member m where m.age > 18
    • 엔티티와 속성은 대문자 구문 (Member, username)
    • JPQL 키워드는 대문자 구분안함 (SELECT, FROM , where)
    • 엔티티 이름을 사용, 테이블 이름이 아님(Member)
    • 별칭은 필수 (m)
    • 결과 조회 API
      • query.getResultList() : 결과가 하나 이상, 리스트 반환
      • query.getSingleResult() : 결과가 정확히 하나, 단일 객체 반환 (정확히 하나가 아니면 예외 발생)
    • 파라미터 바인딩 - 이름기준, 위치 기준
      • where m.username=:username
      • query.setParameter("username", usernameParam);
      • where m.username=?1
      • query.setParameter(1, usernameParam);
    • 프로젝션
      • SEELCT m FROM Member m -> 엔티티 프로젝션
      • SELECT m.team FROM Member m -> 엔티티 프로젝션
      • SELECT username,age FROM Member m -> 단순 값 프로젝션
      • new 명령어 : 단순 값을 DTO로 바로 조회
        • SELECT new jpabook.jpql.UserDTO(m.username, m.age) FROM Member m
      • DISTINCT는 중복제거
    • 페이징 API
      • JPA는 페이징을 다음 두 API로 추상화
      • setFirstResult(int startPosition) : 조회 시작 위치(0부터 시작)
      • setMaxResults(int maxResult) : 조회할 데이터 수
      • 집합과 정렬 (COUNT, SUM, AVG, MAX, MIN, GROUP BY, HAVING, ORDER BY)
    • 조인
      • 내부조인 : SELECT m FROM Member m [INNER] JOIN m.team t
      • 외부조인 : SELECT m FROM Member m LEFT [OUTER] JOIN m.team t
      • 세타조인 : SELECT count(m) FROM Member m, Team t WHERE m.username = t.name
      • 페치조인 (많이 씀. LAZY일 경우 필요한경우 이걸로 한번에 조회가능) (List같은거 뿌릴때 안하면 lazy로딩 계속 나감->성능저하)
        • 인티티 객체 그래프를 한번에 조회하는 방법
        • 별칭을 사용할 수 없다.
        • JPQL : SELECT m FROM Member m join fetch m.team
        • SQL : SELECT M.* , T.* , FROM MEMBER T INNER JOIN TEAM t ON M.TEAM_ID = T.ID
    • JPQL 기타
      • 서브쿼리 지원
      • EXISTS, IN
      • BETWEEN, LIKE, IS NULL
    • JPQL 기본함수
      • CONCAT
      • SUBSTRING
      • TRIM
      • LOWER, UPPER
      • LENGTH
      • LOCATE
      • ABS, SQRT, MOD
      • SIZE, INDEX(JPA용도)
      • CASE
    • 사용자 정의 함수 호출
      • 하이버네이트는 사용전 방언에 추가해야한다.
    • Named 쿼리 - 정적 쿼리
      • 미리 정의해서 이름을 부여해두고 사용하는 JPQL
      • 어노테이션, XML에 정의 (요즘엔 어노테이션으로 많이 씀 )
      • 애플리케이션 로딩 시점에 초기화 후 재사용
      • 애플리케이션 로딩 시점에 쿼리를 검증 (오타 등 문법을 애플리케이션 로딩 시 검증가능)

8강 - Spring Data JPA와 QueryDSL의 이해

  • JPA 기반 프로젝트
    • Spring Data JPA
      • 반복되는 CRUD 문제를 세련된 방법을 해결
      • 개발자는 인터페이스만 작성
      • 스프링 데이터 JPA가 구현 객체를 동적으로 생성해서 주입
      • JpaRepository 인터페이스 (공통 CRUD 제공, 제네릭 <엔티티, 식별자> 로 설정)
      • 메서드 이름만으로 JPQL 쿼리 생성 (ㅁㅊ), 정렬, 페이징
        Pagable page = new PageRequest(1,20,new Sort...); Page<Member> result = memeberRepository.findMyName("hello", page);
        
        
        int total = result.getTotalElements(); // 전체 수
        List<Member> members = result.getContent(); // 데이터
        
      • @Query, JPQL 정의 (직접 정의)
      • Web 페이징과 정렬기능
        • 컨트롤러에서 페이징 처리 객체를 바로 받을 수 있음
      • Web 도메인 클래스 컨버터 기능
        • 컨트롤러에서 식별자로 도메인 클래스 찾음
    • QueryDSL
      • SQL, JPQL을 코드로 작성할 수 있도록 도와주는 빌더 API
      • JPA 클리테리아에 비해서 편리하고 실용적임
      • 오픈소스
      • SQL, JPQL의 문제점
        • SQL, JPQL은 문자, Type-check 불가능
        • 해당 로직 실행 전까지 작동여부 확인 불가
      • QueryDSL 장점
        • 문자가 아닌 코드로 작성
        • 컴파일 시점에 문법 오류 발견
        • 코드 자동완성 (IDE 도움)
        • 단순하고 쉬움: 코드모양이 JPQL과 거의 비슷
        • 동적 쿼리
      • QueryDSL 사용 (조인,페이징,동적쿼리 등 다 됌, 자바임!! 자주쓰는 쿼리구문 메서드로 뽑을 수 있음)
        // JPQL
        // select m from Member m where m.age > 18
        
        
        JPAFactoryQuery query = new JPAQueryFactory(em);
        QMember m = QMember.member;
        
        
        List<Member> list = query.selectFrom(m).where(m.age.gt(18)).orderBy(m.name.desc()).fetch();
        
    • Spring JPA, QueryDSL 배민에서 쓰고있음. 저자가 추천함
  • 실무 경험 공유
    • 주문,결제,정상 모두 JPA로 개발됨
    • 테이블 중심에서 객체 중심으로 개발 패러다임이 변화
    • 유연한 데이터베이스 변경의 장점과 테스트
      • Junit 통합 테스트 시에 H2 DB 메모리 로드
      • 로컬 PC에는 H2 DB 서버모드로 실행
      • 개발 운영은 MySQL, Orcle
    • 데이터베이스 변경 경험(개발 도중 MySQL > Oracle 바뀐적도 있다.)
    • 테스트, 통합 테스트시에는 CRUD는 믿고 간다.
    • 빠른 오류 발견
      • 컴파일 시점!
      • 늦어도 애플리케이션 로딩 시점
    • 최소환 쿼리 문법 실수나 오류는 거의 발생하지 않는다.
    • 대분 비즈니스 로직 오류
  • 실무 경험 성능
    • JPA 자체로 인한 성능 저하 이슈는 거의 없음
    • 성능 이슈 대부분은 JPA를 잘 이해하지 못해서 발생
      • 즉시 로딩 : 쿼리가 튐 > 지연로딩으로 변경
      • N+1 문제 > 대부분 페치 조인으로 해결
    • 내부 파서 문제: 2000줄 짜리 동적 쿼리 생성 1초
      • 정적쿼리로 변경(하이버네이트는 파싱된 결과 재사용)
  • 실무 경험 생산성
    • 단순 코딩 시간 줄어듬 > 개발 생성상 향상 > 잉여시간 발생
    • 비즈니스 로직 작성 시 흐름이 끊기지 않음
    • 남는 시간에 더많은 테스트 작성
    • 남는 시간에 기술 공부
    • 남는 시간에 코드 금칠...
    • 팀원 대부분 다시는 과거로 돌아가고 싶어하지 않음
  • 많이 하는 질문
    • ORM 프레임워크를 사용하면 SQL과 데이터베이스는 잘 몰라도 되나요? (둘다 잘해야함 )
    • 성능이 느리진 않나요? (잘쓰면 최적화할 수 있는 부분 많음)
    • 통계쿼리 처럼 매우 복잡한 SQL은 어떻게 하나요? (QueryDSL, 네이티브 쿼리)
    • MyBatis와 어떤 차이가 있나요? (쿼리를 직접 짜야한다)
    • 하이버네이트 프레임워크를 신뢰할 수 있나요? (쿠팡 등 많이 씀)
    • 제 주위에는 MyBatis(iBatis, myBatis)만 사용하는데요?
    • 학습곡선이 높다고 하던데요? (빡세게 공부하고 편하게 살자)
  • 팀 서버 기술 스택
    • Java8
    • Spring Framework(boot)
    • JPA, Hibernate
    • Spring Data JPA
    • QueryDSL
    • Juint, Spock(Test)