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)

2019년 11월 18일 월요일

소프트웨어 장인 책 메모

소프트웨어 장인

첫 전자책으로 구매한 책이다. 출퇴근 시간 지하철에서 읽었으며, 가볍게 읽기 좋았다.
책은 개발자의 태도에 대해서 써있다. 애자일,TDD, 페어프로그래밍의 도입과 적용에 대해 강조하고 있다. (실제 직접 사용,적용하려면 해당 주제에 대한 책을 구매해야할 것 같다.)
팀을 이끌 때 도움이 될 만한 글이 많은 것 같다.

  • 일을 어떻게 했느냐는 일을 해낸 것만큼이 중요하다.
  • 소프트웨어 장인정신은 소프트웨어 개발자가 스스로가 선택한 커리에 책임을 가지고, 지속적으로 새로 운 도구와 기술을 익히며 발전겠다는 마음가짐이다.
  • 코드도 처음 발견했을 때보다 더 깨끗하게 관리해야한다.
  • 시간이 없다는 말 은 더 이상 변명이 될 수 없다. 우리는 항상 시간이 있다. 우리는 모두 정히 같은 시간 만큼의 시간이 주어진다. 차이점은 우리가 그 시간을 어떻게 쓰느냐일 뿐이다.
  • 의도한 대로 동작할 수 없거나, 실행 불가능한 무리한 일정에 대해서 "아니오" 라고 답하는 것은 우리의 의무다.
  • 자동화된 테스를 만들고 활용하는 데 능숙한 개발라면 코드 디버깅을 해야 하는 상황이 매우 드물다.
  • 유지보수가 쉬운 깨끗한 코드는 개발속도를 높이고 버그가 만들어질 가능을 낮춘다. 이것이 리펙토링 의 비즈니스적인 가치다.
  • Git에 익숙한지? Git이 이미 설치되어 있는지? 컴퓨터 설정이 어떻게 되어 있는지? 어떤 도구를 선호하는지? 프로젝트를 금방 시작할 수 있는지? 테스팅/목업 프레임워크가 이미 모두 가지고 있고 사용할 수 있게 설정되어 있는지? 업무 외 시간에도 코딩을 하는 개발자라면 이러한 것들이 항상 준비되어 있어야한다.
  • (그룹코드리뷰하기) 특정 코드 부분이 개선의 여지가 많은지 아니면 모범사례로 공표할만큼 훌륭한지를 놓고서 동료들간에 논쟁한다.
  • 펫프로젝트에서는 자기 자신이 상사이고 다음 피처가 뭐가 될지, 그 피처를 어떻게 만들지 마음대로 결정할 수 있다. 더욱 중요한 것은 일정 데드라인이 없다.
  • 당신의 열정과 변화 의지에 모두 관심을 가질 것으로 기대하긴 어렵다. 변화를 수용하는 사람들에게 집중하자.
  • 단순한 설계를 위한 네가지 원칙
    • 모든 테스트의 통과
    • 중복의 최소화
    • 명료성의 최대화
    • 구성요소의 최소화

2019년 6월 9일 일요일

기존프로젝트 개선 기록

스프링 스터디가 파토가 났다. 특정 시점부터는 깨질 것을 예상하고 있었다.
나의 문제도 컸지만, 과정을 진행하면서 정하다보니 별로 좋지 않았고, 뭔가 예전에 혼자 스프링 프로젝트를 만들었던 것과 별반 다를게 없는 듯한 느낌이 있었다. (제대로 코딩도 못하고 끝났지만...)
그래서 내가 공부하고싶은 것을 토이프로젝트를 통해 진행하는 것이 좋다고 판단하였는데 새로운 주제를 정하거나, 기존의 스프링 프로젝트를 시작하는 것은 매우 시작하기 귀찮았다.
그렇다면 기존에 했던 것을 내가 직접 원하는 기술을 활용하여 리펙토링하는 것은 어떨까??
지금도 그때와 별반 다를거없는 실력이지만, 에전에 한 코드를 다시보면 고치고 싶은 것들이 상당히 많이 있다. 그래서 취업직전 스터디프로젝트를 했던 인프런 모방 프로젝트를 리펙토링 하기로하였다.
거의 모든코드를 뜯어 고친다는 생각으로 해보자.

  1. AS IS
    소스: https://github.com/cotgyu/NoN
    • 개발환경
      • 이클립스로 개발하였음.
      • 스프링부트 1.5(이 당시 스터디원분께서 환경구축을 거의 하였음)
      • mybatis(mysql)
      • maven
      • 서버엔 띄워보진 않았음
      • git (처음으로 git 브랜치 사용해봄)
    • 주요기능
      • 소셜로그인
      • 강좌 기능
      • 강의 추천알고리즘
        • 머하웃 (엑셀파일을 통한 수동갱신)
  2. TO DO
    소스: https://github.com/cotgyu/NoN_ver2
    • 개발환경
      • IntelliJ
      • 스프링부트 1.5 (부트 설정에 대해 찾아보자)
      • JPA(mybatis) (aws서버에있는 mybatis 쓰자)
      • gradle(maven과 차이점과 학습해야할 이유 찾아보자)
      • GCP (구글클라우드 플랫폼)에 띄우기, CI로 마스터 빌드 시 배포될 수 있도록 구축하기
      • git (브랜치 활용해보자_개선할 기능마다 브랜치따서 관리해보기)
      • 각 기능 개선하면서 모든코드에 대해 테스트 케이스를 작성할 것
        https://www.slideshare.net/OKJSP/okkycon-tdd
      • REST API를 적용할 수 있는 곳이 있을까?
    • 주요기능에 대한 예상 개선방안
      • 소셜로그인 정리
        • 팀원이 개발하였지만, 어디에 적용되어있는 것을 그대로 가져와서 사용한 느낌이었다. 보기편하고, 로그인기능을 제대로할 수 있도록 뜯어고치자.
      • 강좌 기능
        • 소스 스타일 개선할 것, 사용자가 본 강의 등을 표시할 수 있도록하자.
      • 강의 추천알고리즘
        • 현재 엑셀파일을 통해서 추천알고리즘을 적용하는데, 수동으로 진행하고있다. 이 엑셀파일로하는 방식 교체, 수동이 아닌 배치 등을 통해 자동화된 추천순위 갱신을 해보자.
  3. 진행 순서
    • 모든 과정은 정리&메모를 바탕으로 진행한다. 큰 틀마다 브랜치를 생성하고, 각 정리한 메모 또한 git에 등록하자.
    • 사용환경 지식 정리
      • ORM - JPA란?, 왜 씀?
      • gradle 이란?, 왜 씀?
    • 기존 프로젝트 실행
      • github에 새로운 저장소를 파서 기존프로젝트 등록
    • 환경 변경
      • 기존 설정파일 분석
      • gradle 프로젝트로 변경? vs gradle 프로젝트로 생성하여 모든 소스들을 직접 등록?
      • JPA 설정 후 작동 테스트(쿼리변경은 각 기능마다 따로 따로진행할 것)
    • 기능 리펙토링
      • 소셜로그인
      • 강좌 기능 (이 쯤에 배포환경을 구성해보자)
      • 강의 추천 알고리즘

6월 1주차 기록

커밋 로그 구분해서 알아보기 쉽게하기

  feat (feature)
  fix (bug fix)
  docs (documentation)
  style (formatting, missing semi colons, …)
  refactor
  test (when adding missing tests)
  chore (maintain)

ORM ? JPA?

  • Object-Relational Mapping
  • 객체와 관계형 DB를 매핑해주는 것으로, '객체-테이블' 을 매핑시킬 수 있게 도와준다. ORM을 통해 객체와 데이터베이스의 변형에 유연하게 대처할 수 있고, 관계형 데이터베이스에 제약을 최대한 받지 않으면서, 관계형 데이터베이스를 객체처럼 표현 가능하게 할 수 있다.
  • SQL이 아닌 메서드로 데이터 조작 가능
  • 객체 간의 관계를 바탕으로 SQL이 자동으로 생성됨
  • DB변경과 같은 변화에 쉽게 대처가능?
  • JPA : ORM을 위한 표준기술 (JPA을 통해 ORM을 쓸 수 있다? 더 정리가 필요해보이는뎅...)
  • 백기선님 JPA강의소개 중 왜 JPA를 학습해야하는가?
    왜 JPA를 학습해야 하는가?
    1) 도메인 주도 개발이 가능합니다.
    2) 애플리케이션의 코드가 SQL 데이터베이스 관련 코드에 잠식 당하는 것을 방지하고 도메인 기반의 프로그래밍으로 비즈니스 로직을 구현하는데 집중할 수 있습니다.
    3) 그리고 개발 생산성에 좋으며, 데이터베이스에 독립적인 프로그래밍이 가능하고, 타입 세이프한 쿼리 작성 그리고 Persistent Context가 제공하는 캐시 기능으로 성능 최적화까지 가능합니다.
    

gradle이란??

  • 빌드배포툴로 ANT와 MAVEN의 단점을 보완했다고 한다. 안드로이드 스튜디오 공식 빌드 시스템이.
  • XML이 아닌 Groovy 언어를 활용한 DSL(도메인특화언어?)을 스크립트로 사용. 때문에 다양한 기능을 스크립트안에서 직접 구현가능.
  • 상속구조를 이용하여 멀티모듈 구현이 가능하다.
  • Maven의 길고 떨어지는 가독성 개선(xml 사용안함)
  • 성능향상을 위해 다양한 기능 제공 (증분빌드, 작업결과 캐싱, 병렬 실행 등이 가능하다고 함.)

기본 gradle 구조

 gradlew
 gradlew.bat
 gradle/wrapper/gradle-wrapper.jar
               /gradle-wrapper.propeties
 build.gradle
 settings.gradle   

그래들 변환 과정 기록

  • brew 설치 (맥에서 gradle 자동설치를 위해)
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
  • gradle 설치
  brew install gradle
  • 메이븐 gradle 로 자동 변환 프로젝트 pom 파일위치에서
  gradle init --type pom
  • 프로젝트에서 메이븐관련 파일 삭제
  • import 모듈 -> gradle -> build.gradle 선택
  • gradle init --type pom 을 통해 자동으로 생성되는 build.gradle
(상당히 복잡해여서 좀 더 간단하게 개선하고 싶음. 근데 뭘보고 개선해야할까? 일단 그대로?)
  plugins {
      id 'java'
      id 'maven-publish'
  }

  repositories {
      mavenLocal()
      maven {
          url = 'http://repo.maven.apache.org/maven2'
      }
  }

  dependencies {
      compile 'org.springframework.boot:spring-boot-starter-integration:1.5.10.RELEASE'
      compile 'org.springframework.boot:spring-boot-starter-jdbc:1.5.10.RELEASE'
      ...
      compileOnly 'org.apache.tomcat.embed:tomcat-embed-jasper:8.5.27'
  }

  group = 'com.Library'
  version = '0.0.1-SNAPSHOT'
  description = 'NoN_ver2'
  sourceCompatibility = '1.8'

  publishing {
      publications {
          maven(MavenPublication) {
              from(components.java)
          }
      }
  }

  tasks.withType(JavaCompile) {
      options.encoding = 'UTF-8'
  }

TODO : build.gralde 수정해보기


6월 2주차 기록

JPA 학습하기

JPA 테스트

  • 저번에 사용한 JPA를 활용해서 JPA테스트를 해보자
    • 일단 저번에 블로그 따라했을 때는 service나 repository 등을 미리 생성한 다음 테스트코드에서 해당 클래스들을 autowired를 통해 테스트하였음. (존재하는 소스들에 대한 테스트)
    • JPA에 필요한 설정을 적용해보고 작동하는 지 확인해보자!!
      • 일단 test패키지에 JPA용 테스트코드를 작성하고 동작하는 지 확인해보자
      • /src/main/java/com/Edu/Domain/JPADomain.java
        @NoArgsConstructor(access = AccessLevel.PROTECTED) // 기본생성자 자동 추가 (protected Posts(){} 와 같음)
        @Getter //클래스 내 모든 필드의 getter 메소드 자동생성
        @Entity //테이블과 링크될 클래스임을 나타냄
        public class JPADomain {
            @Id // PK
            @GeneratedValue(strategy = GenerationType.IDENTITY )
            private Long id;
        
        
            @Column(length = 500, nullable = false) //테이블의 컬럼 ()와 같이 컬럼특징 설정 가능
            private String title;
        
        
            @Column
            private String content;
        
        
            @Builder // Builder란 ?
            public JPADomain(String title, String content){
                this.title  = title;
                this.content = content;
            }
        }
        
      • src/main/java/com/Edu/Domain/JPADomainRepository.java
        //DB Layer 접근자(DAO), JpaRepository<Entity, PK타입 > 을 상속하면 기본적인 CRUD 메소드가 자동 생성됨.
        public interface PostsRepository extends JpaRepository<Posts, Long> {
        
        
            //@Query 를 통해 JPA에서 제공하지 않는 메소드는 쿼리로 작성 가능
            @Query("SELECT p " +
                    "FROM Posts p " +
                    "ORDER BY p.id DESC")
            Stream<Posts> findAllDesc();
        }
        
      • src/test/java/com/Edu/Domain/TestJPADomainRepository.java
        @RunWith(SpringRunner.class)
        @SpringBootTest //기존 스프링test의 @ContextConfiguration 의 발전된 기능 ? 다양한 기능이 있으니 찾아볼 것
        public class TestJPADomainRepository {
        
        
            @Autowired
            JPADomainRepository jpaDomainRepository;
        
        
            @After
            public void cleanup(){
                jpaDomainRepository.deleteAll();
            }
        
        
            @Test
            public void saveTest(){
        
        
                //테스트 환경 구축
                jpaDomainRepository.save(JPADomain.builder()
                        .title("테스트title")
                        .content("테스트content")
                        .build());
        
        
                //테스트 행위
                List<JPADomain> postsList = jpaDomainRepository.findAll();
        
        
                //테스트 검증
                JPADomain posts = postsList.get(0);
                assertThat(posts.getTitle(), is("테스트title"));
                assertThat(posts.getContent(), is("테스트content"));
        
        
            }
        
        
            @Test
            public void insertTest(){
        
        
                //insert @Query 테스트
                jpaDomainRepository.insertQueryTest();
        
        
                //테스트 행위
                List<JPADomain> postsList = jpaDomainRepository.findAll();
        
        
                //테스트 검증
                JPADomain posts = postsList.get(0);
                assertThat(posts.getTitle(), is("2"));
                assertThat(posts.getContent(), is("2"));
            }
        
        
        }
        

발생했던 오류

  • 잉.. save가 안됨 왜? select는 되는 거 보니 DB연결은 된 것 같음
  • delete도 안됨. mysql 이랑 jpa 설정이 필요할 것 같음 -> 무슨설정? -> 음 Application에 설정된 어노테이션들이랑 연관이 있을까? -> DB 관련 설정 문제였음!!!
  • 오류 메모
    Caused by: java.sql.SQLException: Can not issue data manipulation statements with executeQuery().


    org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query
    • -> 구글링해보니 class에 적용되어있는 @Transactional 확인해보고 javax.transaction.Transactional 을 org.springframework.transaction.annotation 으로 바꿔라인데 난 그래도안되는데?
    • -> update나 insert할 때 트랜잭션이 필요한 것 같음. 어떤 설정떄문에 트랜잭션이 적용되지않는 것이 아닐까?
    • -> 기존프로젝트에 존재하는 dataconfig 에 트잭잭션매니저 설정(DataConfig.java)이 있었고, 해당 설정을 주석처리 하니 됨!!
    • 약간 여기때문에 설정이 꼬여서 모든 insert, update, 등이 안되었던 것 같음. 해당 트랜잭션 매니저부분 주석처리하니 됨!!!


    mysql 한글 insert 시 ??? 입력되는 현상
    • 해당 오류는 저번에도 발생했던 것으로 기억하는데, 역시 메모안해놓으니 또 발생했을 때 또 삽질함.
        1. my.cnf 설정바꾸기 (난 my.cnf가 없던데 새로 추가해야하는건가 아니면 다른 위치에 있는 것일까?)
        1. my.cnf 위치도 모르겠고 커넥션할 때 &useUnicode=true&characterEncoding=utf8 해당 옵션 추가해줌

TODO builder란? , 기존에 사용했던 설정들 분석 필요


6월 3주차 기록

JPA 개념 익히기

  • 강의 들으면서 정리 중

builder 란?

  • @Builder : 해당클래스의 빌더패턴 클래스 생성
  • 빌더 패턴 : 객체를 생성할 때 사용하는 패턴
    • 이펙티브자바 : 아이템2-생성자에 매개변수가 많다면 빌더를 고려하라
      책에서는 점층적 생성자 패턴 -> 자바빈즈 패턴 -> 이 둘의 장점을 살린 빌더 패턴을 설명하고 있다. (자세한건 책으로...)
      • 매개변수 개수가 많아지면 클라이언트 코드를 작성하거나 읽기 어렵다.
        // 각 값의 의미 파악 어려움. 매개변수가 몇개인지도 세야함.
        Ex ex = new Ex(100, 10, 1, 2, 1, 2, 3 ,4);
        
      • 빌더 패턴을 통해 쓰기 쉽고, 읽기 쉽게 만들자. (인 것 같다. 또한 빌더패턴을 통해 객체가 완전히 생성되기 전까지는 일관성이 무너진 상태에 놓여지는 단점을 해결해주는 것 같다.)
        Ex ex = new Ex.Builder(100,10).name(1).age(2).number(1).code(2).name2(3).number2(4).code2();
        
  • Lombok 의 @Builder 어노테이션을 통해 빌더패턴코드를 간단하게 사용할 수 있는 듯하다. (Lombok 라이브러리가 여러가지 자동으로 생성해주는 것 같다!!)

회원기능 개선하기

  • 소셜 로그인
    • 현재 구현되어있는 기능 : 회원가입(수정 등), 카카오로그인, 네이버로그인
    • 수정할 기능들? : 회원가입 간소화, 소셜로그인 정리 및 소스정리 (or 방식 수정)
      • 회원 가입 간소화
        • 기존의 member 테이블에서 최소한의 정보만 있는 user테이블 생성
        • 아마 완성된 기능에서 회원기능을 아예 다 가져와서 동작하게끔 수정한 것으로 보임.(이것저것 많음...) 필요없는 건 다 없애는 방향으로 진행할 것. 음 이메일인증기능도 쓰나본데..? 이메일 인증기능은 일단 간단한 회원가입을 위해 없애자 나중에 방식 한번 살펴보기
        • todo 회원가입창 모달창에서 할수 있게하고 소셜로그인 등 같이할수있게
          • 로그인창 하나만 만들고 회원가입은 그창에서 모달로 보여주기
    • 추가 기능 : 구글 로그인
    • 마지막에는 JPA 적용하도록 수정 (이 때 테이블도 바꾸자 )
TODO 회원기능 개선 후에는 기존 설정 한번 더 살펴보기. JPA 강의 계속보기. 로그 적용하기. 테스트까먹음..소셜로그인 개선시 에는 테스트 하기

6월 4주차 기록

  • 로그 설정하기
    • 스프링부트는 기본으로 logback을 지원하고 있으며, 기타 xml으로도 로그설정들을 조정할 수 있지만, application.properties 에서도 설정 가능한듯 싶다. 일단 레벨만 간단하게 조정하고, 기타 로그 저장위치 설정할 수있게 xml 등을 생성해보자(펫클리닉에서는 logback.xml 을 사용하고 있다.)
    logging.level.root=info
    
  • 카카오로그인
    • HOW? : 이전의 내가 적용했던 방식이랑 비교하고, 현재 어떤방식인 지 어떻게 사용하고 있는 지 기록하고 어떻게 바꿀껀지?? 적용하기. 이번엔 테스트 코드를 짜면서 해보자
    • AS IS
      1. 형식은 비슷한듯싶음. 토큰보내서 들어오는 정보 json으로 받아서 멤버에 받아서 처리하는 듯 싶다.
      2. 일단 세션에 멤버객체, id 저장해놓고, 기존에 id가 등록되었는 지 확인하고, 중복된사용자면 바로 홈화면, 중복된 사용자가 아니면 사용자정보를 insert하고 있음.
TODO : 구글로그인도 자세하게보다는 내가 한 방향을 기록만해놓기. JPA강의 계속~ , 로그설정 찾아보기

7월 1주차~3주차 기록

  • 개인적인 사정으로 공부를 못하고 있음(병원)

7월 4주차 기록

  • 구글로그인
    • HOW : 기존 프로젝트에는 구글로그인이 아닌 네이버로그인이 되어있는데, 이를 생략하고 구글로그인으로 진행해보았다.
      이전 스터디에서 해본 구글로그인 코드를 그대로 가져왔지만, root-context에 등록된 빈 사용문제, 코드 노출문제가 발생하여, 이를 개선해야한다. 일단 로그인 및 회원가입 기능은 동작
    • 외부 프로퍼티를 써서 인증에 사용되는 값들은 깃에 안올라가게 설정함
    • 카카오와 비슷한 방식으로 진행함... 너무 허접함.
      이건 정말 정보 보내고, 받아서 회원가입, 로그인 등만 억지로 하는 느낌?
    (구글에 나온 시큐리티와 OAuth 연동하여 계정 권한 관리하는 소스들이 많은데, 일단 나는 그냥 처음에 검색했던 소셜 로그인만 딱 되도록 한 느낌.. 전체적인 이해와 개선의 필요성이 있다. 예제나 레퍼런스같은게 있을까?)

TODO : JPA 강의 계속듣기, 회원가입 시 닉네임입력할 수있게, 로그인 팝업으로, 회원 수정 창 만들기
+ 부트 설정 공부필요함. 프로퍼티 하나 추가하려고했다가 엄청 삽질함(이 프로젝트에선 AppConfig.java 에서함)
+ 팝업로그인, 회원 수정 등이 끝나면 JPA 적용할 것


8월 4주차 기록

  • 로그인창은 팝업으로
    • 되도록이면 모달창이 낫겠징? 흠 매우 귀찮네; 음.... 카카오,구글인증창만 새창에서하는 것도 나쁘지는않을텐디 흠..
    • 새로운 페이지 띄워서 해당 페이지 접속 시 자동으로 카카오 url 타도록??
  • 회원가입 시 닉네임 입력할 수 있도록

11월 1주차 기록

  • 교육기간을 활용하여, 프로젝트를 진행해보자
  • 로그인창 모달창으로 만들기 O
  • 소셜 회원가입할때 닉네임입력할 수 있게할지?? X
    • 그냥 자동회원가입되도록 O
  • 로그인, 회원정보 수정 등 로그인에 필요한 로직 구현
    • 로그인 : ajax를 통해 로그인처리하기 O
    • 회원수정 : 되는지만 확인하고 수정 할 것 O
    • 비밀번호 찾기 : 인프런은 입력한 이메일로 비밀번호 수정 url을 보내주는듯
      • 그냥 초기화된 비밀번호를 메일로 전송하도록 O
  • 회원기능은 일단 마무리...
    • JPA를 바로 회원에 적용해볼지..
    • 모두 개선해보고나서 JPA로 전환할지..

TODO : JPA 적용하면서 간소화된 테이블로 교체할 것, 암호화 등 시큐리티 활용

1월 2주차 기록

  • 강좌를 리펙토링해보자
  • 해야할 것
    • 수강평부분
    • 수강한 강좌 체크(어디까지 수강했는지)
    • 강좌 추천부분 동작할 수 있도록(현재는 특정 로컬경로를 지정...)
    • 엄청 완성도 높은 것보다는 의도한 기능이 정확하게 돌아가는가..
    • 수강하는 강좌 볼 수 있는 페이지 (있음 강의 진척률 표시할 것 )
  • 수강평 부분(다른팀원이 개발한 영역)
    • html을 제이쿼리로 통제하여 생성하는 방식..
    • 동작만 할 수 있게 수정함. (화면이 보기좋은 형태는 아님..)
  • 수강한 강좌 체크 (어디까지 수강했는지)
    • 어케할지...
      • 인프런에서는 완강하면 체크표시되면서 강좌 열었을때 시작할 강좌부터 열어줌
    • 필요한 것
      • 해당 강의 체크 방법
        • 일단 테이블에 저장 필요. (데이터 중복은 불가피한데 어디까지?)
            1. 사용자/수강강좌/강좌 수 1,2,3,4,5
            1. 사용자/수강강좌/강좌 1 / 2/ 3 4 (데이터 중복..)
          • userid, cosno, lecno, indt, delyn
      • 완강인지 어케 파악?
        • 동영상 종료시점 알아야함. (거기에 맞춰서 해당 강좌번호 체크 )
      • 만약 사용자가 체크한다고한다면? > TDD를 할 수있지 않을까? REST인강 실습기회!!
        • 테이블읽어서 가장 최신 강의
        • 체크하면 ajax 로 바로 해당 강의 insert
        • 해제하면 delflag 처리
        • 현재 강의 표시.
TODO 수강한 강좌 체크 진행, 코스 이미지 분리, 테이블 데이터 delFlag, regDate

2월 4주차 기록

  • 테스트환경 구축
    • 테스트에는 h2 , 운영은 mysql 쓰도록 구성
      • 일단 mysql만..
    • 필요 테이블 생성
    • TDD 실습
      • 최신강의 체크
      • 체크한 강의 불러오기
      • 체크하기
      • 체크해제하기

3월 1주차 기록

  • 필요 테이블 생성함
  • TDD 실습
    • 최신강의, 체크한 강의 가져오기
    • 없는 사용자에 대한 error 테스트
    • 테스트 시 응답 json에 대해 좀 더 자세한 검증 필요 https://github.com/json-path/JsonPath 참조

3월 4주차 기록

  • 강의정보로 최신강의로 불러오기 (체크 이후가 제일 최신일지? 클릭할떄마다 뭔가를 남겨야할지?)
  • 강의 해제 ajax 추가
  • 강의기능은 이정도까지만 하고 마무리?
    • 체크한 값 받아서 체크표시하기 o
    • 체크 및 해제 할때마다 ajax 날리기 o
      • 테이블에 체크된 강의 있는 지 확인
      • 테이블에 없으면 insert
TODO 알고리즘 적용, 예외처리, 에러페이지 생성, 이미지 등 파일관리, 테스트 디비 생성

4월 2주차

  • 에러페이지, 예외처리 진행
  • 컨트롤러어드바이스 찿아보기
TODO 에러 처리 더 다듬기, 에러페이지 사진넣기, 404 등 상태코드 시 페이지 설정, 알고리즘적용, 파일관리, 테스트 디비 생성(필요할까?)

4월 3주차

  • 예외처리 핸들러를 통해 처리 시 exception 페이지로 이동, 로그 남기기
    • 회사 소스에서는 로그만 남기도록 되어있던데, 일부러 그런걸까?
  • 상태코드에 대한 설정 추가
TODO 알고리즘 적용(머하웃 다시 정리?), 파일관리

4월 4주차 & 5월 1주차

  • 수강평 없는 경우 예외 처리 할 걳
    • 일단 화면에서만 문구 변경으로 처리
  • 머하웃 로직 분석
    • 강좌를 클릭하였을 때 해당 강좌에 대한 추천강좌를 보여줄 것이기 때문에 아이템 기반 알고리즘을 사용하였음.
      • 사용자 기반 추천 : 사용자의 유사도를 비교. 선호 이력이 비슷한 다른 사용자의 선호 아이템 추천
      • 아이템 기반 추천 : 아이템의 유사도를 비교. 해당 아이템과 유사한 아이템 추천
      인터넷 예제를 통해 Tanimoto 유서도를 사용했지만, 검색해보니 tanimoto와 loglikeihood 는 선호도 상관 없이 사용자의 아이템 겹침을 통해 추천을 하는 것 같아 유클리드 거리 기반 유사도로 변경하였다.
    • 책도 있음! : 머하웃 완벽 가이드
    • 머하웃아이템 추천에는 유사도를 고를 수 있다. (유사도에 따라 추천아이템이 달라진다!!)
      • EuclideanDistanceSimilarity
        • 두 점 사이의 거리 계산
        • 사람들이 공통적으로 점수를 매긴 항목의 거리를 통해 유사도를 판단 (짧은수록 유사)
      • PearsonCorrelationSimilarity
        • 두 개의 연속적인 숫자열의 일대일 비교를 통해 경향성을 측정
        • 한 숫자열의 각 숫자가 다른 숫자열의 대응되는 값보다 얼마나 상대적으로 큰지 측정
      • LogLikelihoodSimilarity
        • 두 사용자의 공통 아이템 수에 대비해서 얼마나 두 사용자가 겹치지 않는지 표현
        • 타니모토 보다 성능이 좋다고 함
      • TanimotoCoefficientSimilarity
        • 선호값 전체를 무시하도록 구현된 유사도 측정 방식
        • 사용자의 선호 표현 여부만 확인. 아이템에 대한 선호도가 높은지 낮은지
  • 머하웃 참고
TODO 데이터소스 부분 뜯어고치기 (좀 더 표준적인 mybatis 로?, 책 참조해볼것 ), 파일관리 필요

5월 2주차

  • 데이터 접근 부분 리펙토링

    • 너무 복잡한 형식으로 되어있는 것 같다.
    • 표준적인 mybatis - mapper 형식으로 변환해보자.
    • databaseConfig 부분 정리하기
  • @Mapper 는 어떻게 스프링 빈으로 와이어될 수 있을까?

  • MyBatis 장점

    • 자동적으로 Connection close() 가능
    • Mybatis 내부적으로 PreparedStatement 처리
    • #{prop}와 같이 속성을 지정하면 내부적으로 자동 처리
    • 리턴 타입을 지정하는 경우 자동으로 객체 생성 및 ResultSet 처리

@Configuration
@MapperScan(basePackages = { "com.Edu.Dao" })
@EnableTransactionManagement
public class DataSourceConfig {

    @Autowired
	private ApplicationContext applicationContext;

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception{
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();

        sqlSessionFactoryBean.setDataSource(dataSource());
		sqlSessionFactoryBean.setConfigLocation(applicationContext.getResource("classpath:static/mybatis/mybatis-config.xml"));
		sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources("classpath:static/mybatis/mappers/mysql-*.xml"));

        return sqlSessionFactoryBean.getObject();
    }

    @Bean(destroyMethod = "close")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        DataSource dataSource = new DataSource();

        return dataSource;
    }
}

TODO 파일 관리, JPA, 시큐리티, 보안취약 , 유효값 검증?

5월 3주차 ~ 4주차

  • JPA 적용 준비

    • JPA + QueryDSL 조합하여 많이 쓰는 것 같음

    • QueryDSL 이란?

      • Jooq와 함께 가장 유명한 조회 프레임워크
      • 타입에 안전한 방식으로 HQL 쿼리를 실행하기 위한 목적으로 만들어짐
      • 쿼리 작성과정에서 코드 자동완성 기능을 통해 쿼리를 더 안전하고 빠르게 생성할 수 있음
  • Querydsl 참조

  • compilequerydsl 실행 시 @Entity 어노테이션 있는 클래스들만 generated 들에 Q~~.java 로 자동 생성됨 (후에 쓰임)

  • insert, update는 JPA로 ??

  • 어려운 쿼리만 querydsl 사용하고 일반적인 쿼리는 jpa 사용해서 처리할 것 !!

  • 이번주까지 변환 완료할 것 !

  • 테이블 연관관계 학습필요!

TODO 파일 관리, 시큐리티, 보안취약 , 유효값 검증?, 테이블 연관관계 학습필요! (JPA책 공부하자)

6월 2주차

  • 파일관리를 보통 어떻게하는가?

    • 로켓마켓 : FileUtils

      • 파일 전용테이블 있음
      • 특정 경로에 저장하도록 하였음 (환경설정 파일에 명시)
    • 스프링부트 책 :

  • 유효성 검사

    • rest api 에 대해 유효값 검증을 하자 !! (백기선님 강의 참고)

    • ResponseEntity 변경

    • rocketmarket에 있는 전송방법 참고하여서 dto 만들것

TODO 파일 관리, 시큐리티, 보안취약, 테이블 연관관계 학습필요! (JPA책 공부하자), CI 적용

7월 1주차

  • 스프링 시큐리티 적용

  • CI 장단점 비교하기

    • CI란?

    • Travis VS Jenkins

  • 도커 장점

    • 가상의 공간을 이미지로 만들어 저장할 수 있다. 이 이미지를 통해 컨테이너를 생성할 수 있다.

TODO 시큐리티 인증절차 제대로 구현필요, 테이블 연관관계 학습필요! (JPA책 공부하자), CI 적용

7월 2주차

  • 시큐리티 심화 적용

    • 로켓마켓은 어떻게 활용하고 있는가?

      • 이상함.. 비번체크하는부분이 없음..? -> 시큐리티에서 다해줌!!!!
    • 나의 방식 : 로그인 시 권한체크 성공하면 패스워드 인코더를 통한 비밀번호 체크해서 세션에 로그인 정보 담는 방식임 , 소셜부분은?

      • 아.. 시큐리티를 태우는 순간 DaoAuthenticationProvider에서 비번체크까지 해줌 ;;
      try {
          preAuthenticationChecks.check(user);
          additionalAuthenticationChecks(user,
                  (UsernamePasswordAuthenticationToken) authentication);
      }
      
      • 시큐리티와 소셜로그인 연동은 개선할 것이 많고 어렵당 ㅠㅠㅠ 다시해보자
  • 시큐리티 개선할떄 참고할 것

TODO 소셜로그인에 시큐리티 로그인 연동하기 , 테이블 연관관계 학습필요! (JPA책 공부하자), CI 적용

7월 3주차

  • 프로젝트 좀 정리하는 시간 갖고, 다음에 뭐 개선할지 정하기

  • 테이블 연관관계 or 소셜 연동 하는 것이 좋아보임.

  • 네이버클라우드에 젠킨스 깔자 (ㅋㅋ거기꺼 써도될듯)

    • 회사 선배계정에 젠킨스 설치함!! github README.md 파일에 build status 표시 중

TODO 소셜로그인에 시큐리티 로그인 연동하기 , 테이블 연관관계 학습필요! (JPA책 공부하자), CI 적용

7월 4주차

다중 구현 가능할듯!!

TODO 테이블 연관관계 학습필요! (JPA책 공부하자), build.Gradle 정리

8월 1주차

  • build.gradle 정리

    • 필요없는 부분 지우기
      • io.spring.gradle:dependency-management-plugin 으로 자동으로 버전이 설정됨. 필요없는 건 버전을 지우자
    • 로컷마켓 task 분석해보기
      • test : Junit5 을 사용하기 위함으로 보임
      • jooq : jooq 관련 설정
      • 나머지는 비슷...?
  • 테이블 연관관계 공부 하기

    • 책을 인쇄해서 가야할까? or 사야할까..흠
  • 테이블 연관관계는 책이나, 인강으로 학습이 필요해보인다. 나중에 새로운 프로젝트할 때 제대로 적용하자

끝. 부족한건 다음 프로젝트에서 ...