그렇다면 기존에 했던 것을 내가 직접 원하는 기술을 활용하여 리펙토링하는 것은 어떨까??
- AS IS
소스: https://github.com/cotgyu/NoN
- 개발환경
- 이클립스로 개발하였음.
- 스프링부트 1.5(이 당시 스터디원분께서 환경구축을 거의 하였음)
- mybatis(mysql)
- maven
- 서버엔 띄워보진 않았음
- git (처음으로 git 브랜치 사용해봄)
- 주요기능
- 소셜로그인
- 강좌 기능
- 강의 추천알고리즘
- 머하웃 (엑셀파일을 통한 수동갱신)
- 개발환경
- 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를 적용할 수 있는 곳이 있을까?
- 주요기능에 대한 예상 개선방안
- 소셜로그인 정리
- 팀원이 개발하였지만, 어디에 적용되어있는 것을 그대로 가져와서 사용한 느낌이었다. 보기편하고, 로그인기능을 제대로할 수 있도록 뜯어고치자.
- 강좌 기능
- 소스 스타일 개선할 것, 사용자가 본 강의 등을 표시할 수 있도록하자.
- 강의 추천알고리즘
- 현재 엑셀파일을 통해서 추천알고리즘을 적용하는데, 수동으로 진행하고있다. 이 엑셀파일로하는 방식 교체, 수동이 아닌 배치 등을 통해 자동화된 추천순위 갱신을 해보자.
- 소셜로그인 정리
- 개발환경
- 진행 순서
- 모든 과정은 정리&메모를 바탕으로 진행한다. 큰 틀마다 브랜치를 생성하고, 각 정리한 메모 또한 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
- gradle / gralde.bat : gradle 빌드 스크립트 파일(wrapper을 이용하여 gradle이나 java 설치 없이 빌드할 수 있게 도와준다)
- gradle-wrapper : 새로운 환경에 설치할 때 별도의 설치 없이 곧 바로 빌드할 수 있게 도와줌.
- build.gradle : 의존성, 플러그인 설정 등을 위한 스크립트 파일 (build.gradle의 의존성 설정이나 플로그인 설정 등은 공부를 따로 해야할 것 같다.
- settings.gradle : 프로젝트 정보
- 참조 :
gradle 특장점(블로그) https://medium.com/@goinhacker/운영-자동화-1-빌드-자동화-by-gradle-7630c0993d09
gradle(공식?) https://docs.gradle.org/current/userguide/userguide.html
gradle로 가자(블로그) : http://egloos.zum.com/kwon37xi/v/4747016
gralde 간단 가이드(블로그 내 자료많음) : http://kwonnam.pe.kr/wiki/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테스트 부분을 개념없이 막하니깐 많이 막히고 '왜 쓰는가?' 에 대해서도 모르고 막하는 것 같았다.)
자바 ORM 표준 JPA 프로그래밍 책을 사려고하였지만, 저자의 직강이 유튜브에 올라와있다. 해당 강의를 먼저 보자! - 강의: https://www.youtube.com/watch?v=WfrSN9Z7MiA&list=PL9mhQYIlKEhfpMVndI23RwWTL9-VL-B7U
- 책 : https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=194881362
JPA 테스트
- 저번에 사용한 JPA를 활용해서 JPA테스트를 해보자
- 일단 저번에 블로그 따라했을 때는 service나 repository 등을 미리 생성한 다음 테스트코드에서 해당 클래스들을 autowired를 통해 테스트하였음. (존재하는 소스들에 대한 테스트)
- JPA에 필요한 설정을 적용해보고 작동하는 지 확인해보자!!
- 일단 test패키지에 JPA용 테스트코드를 작성하고 동작하는 지 확인해보자
- 일단 저번에 블로그에서 보고 따라한 구조를 기준으로 따라하였음.
- 펫클리닉 구조를 참조해도 좋을 듯 함. https://github.com/spring-petclinic/spring-framework-petclinic
- /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")); } }
- 일단 test패키지에 JPA용 테스트코드를 작성하고 동작하는 지 확인해보자
발생했던 오류
- 잉.. save가 안됨 왜? select는 되는 거 보니 DB연결은 된 것 같음
- delete도 안됨. mysql 이랑 jpa 설정이 필요할 것 같음 -> 무슨설정? -> 음 Application에 설정된 어노테이션들이랑 연관이 있을까? -> DB 관련 설정 문제였음!!!
- 오류 메모
Caused by: java.sql.SQLException: Can not issue data manipulation statements with executeQuery().
- insert, update, delete 등은 select와 같은 executeQuery가 아닌듯 해당 쿼리에 @Modifying 붙여주니 해당오류는 없어졌음.
- 참고: https://anshulgnit.blogspot.com/2018/03/java-sql-exception-can-not-issue-data-manipulation-statements-with-executeQuery.html
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 시 ??? 입력되는 현상
- 해당 오류는 저번에도 발생했던 것으로 기억하는데, 역시 메모안해놓으니 또 발생했을 때 또 삽질함.
- my.cnf 설정바꾸기 (난 my.cnf가 없던데 새로 추가해야하는건가 아니면 다른 위치에 있는 것일까?)
- 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();
- 매개변수 개수가 많아지면 클라이언트 코드를 작성하거나 읽기 어렵다.
- 이펙티브자바 : 아이템2-생성자에 매개변수가 많다면 빌더를 고려하라
- 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
- 형식은 비슷한듯싶음. 토큰보내서 들어오는 정보 json으로 받아서 멤버에 받아서 처리하는 듯 싶다.
- 일단 세션에 멤버객체, id 저장해놓고, 기존에 id가 등록되었는 지 확인하고, 중복된사용자면 바로 홈화면, 중복된 사용자가 아니면 사용자정보를 insert하고 있음.
TODO : 구글로그인도 자세하게보다는 내가 한 방향을 기록만해놓기. JPA강의 계속~ , 로그설정 찾아보기
7월 1주차~3주차 기록
- 개인적인 사정으로 공부를 못하고 있음(병원)
7월 4주차 기록
- 구글로그인
- HOW : 기존 프로젝트에는 구글로그인이 아닌 네이버로그인이 되어있는데, 이를 생략하고 구글로그인으로 진행해보았다.
이전 스터디에서 해본 구글로그인 코드를 그대로 가져왔지만, root-context에 등록된 빈 사용문제, 코드 노출문제가 발생하여, 이를 개선해야한다. 일단 로그인 및 회원가입 기능은 동작
- 외부 프로퍼티를 써서 인증에 사용되는 값들은 깃에 안올라가게 설정함
- 카카오와 비슷한 방식으로 진행함... 너무 허접함.
이건 정말 정보 보내고, 받아서 회원가입, 로그인 등만 억지로 하는 느낌?
(구글에 나온 시큐리티와 OAuth 연동하여 계정 권한 관리하는 소스들이 많은데, 일단 나는 그냥 처음에 검색했던 소셜 로그인만 딱 되도록 한 느낌.. 전체적인 이해와 개선의 필요성이 있다. 예제나 레퍼런스같은게 있을까?)
- HOW : 기존 프로젝트에는 구글로그인이 아닌 네이버로그인이 되어있는데, 이를 생략하고 구글로그인으로 진행해보았다.
이전 스터디에서 해본 구글로그인 코드를 그대로 가져왔지만, root-context에 등록된 빈 사용문제, 코드 노출문제가 발생하여, 이를 개선해야한다. 일단 로그인 및 회원가입 기능은 동작 - 외부 프로퍼티를 써서 인증에 사용되는 값들은 깃에 안올라가게 설정함
- 카카오와 비슷한 방식으로 진행함... 너무 허접함.
이건 정말 정보 보내고, 받아서 회원가입, 로그인 등만 억지로 하는 느낌?
TODO : JPA 강의 계속듣기, 회원가입 시 닉네임입력할 수있게, 로그인 팝업으로, 회원 수정 창 만들기
+ 부트 설정 공부필요함. 프로퍼티 하나 추가하려고했다가 엄청 삽질함(이 프로젝트에선 AppConfig.java 에서함)
+ 팝업로그인, 회원 수정 등이 끝나면 JPA 적용할 것
8월 4주차 기록
- 로그인창은 팝업으로
- 되도록이면 모달창이 낫겠징? 흠 매우 귀찮네; 음.... 카카오,구글인증창만 새창에서하는 것도 나쁘지는않을텐디 흠..
- 새로운 페이지 띄워서 해당 페이지 접속 시 자동으로 카카오 url 타도록??
- 회원가입 시 닉네임 입력할 수 있도록
- 되도록이면 모달창이 낫겠징? 흠 매우 귀찮네; 음.... 카카오,구글인증창만 새창에서하는 것도 나쁘지는않을텐디 흠..
- 새로운 페이지 띄워서 해당 페이지 접속 시 자동으로 카카오 url 타도록??
11월 1주차 기록
- 교육기간을 활용하여, 프로젝트를 진행해보자
- 로그인창 모달창으로 만들기 O
- 소셜 회원가입할때 닉네임입력할 수 있게할지?? X
- 그냥 자동회원가입되도록 O
- 로그인, 회원정보 수정 등 로그인에 필요한 로직 구현
- 로그인 : ajax를 통해 로그인처리하기 O
- 회원수정 : 되는지만 확인하고 수정 할 것 O
- 비밀번호 찾기 : 인프런은 입력한 이메일로 비밀번호 수정 url을 보내주는듯
- 그냥 초기화된 비밀번호를 메일로 전송하도록 O
- 회원기능은 일단 마무리...
- JPA를 바로 회원에 적용해볼지..
- 모두 개선해보고나서 JPA로 전환할지..
- 그냥 자동회원가입되도록 O
- 로그인 : ajax를 통해 로그인처리하기 O
- 회원수정 : 되는지만 확인하고 수정 할 것 O
- 비밀번호 찾기 : 인프런은 입력한 이메일로 비밀번호 수정 url을 보내주는듯
- 그냥 초기화된 비밀번호를 메일로 전송하도록 O
- JPA를 바로 회원에 적용해볼지..
- 모두 개선해보고나서 JPA로 전환할지..
TODO : JPA 적용하면서 간소화된 테이블로 교체할 것, 암호화 등 시큐리티 활용
1월 2주차 기록
- 강좌를 리펙토링해보자
- 해야할 것
- 수강평부분
- 수강한 강좌 체크(어디까지 수강했는지)
- 강좌 추천부분 동작할 수 있도록(현재는 특정 로컬경로를 지정...)
- 엄청 완성도 높은 것보다는 의도한 기능이 정확하게 돌아가는가..
- 수강하는 강좌 볼 수 있는 페이지 (있음 강의 진척률 표시할 것 )
- 수강평 부분(다른팀원이 개발한 영역)
- html을 제이쿼리로 통제하여 생성하는 방식..
- 동작만 할 수 있게 수정함. (화면이 보기좋은 형태는 아님..)
- 수강한 강좌 체크 (어디까지 수강했는지)
- 어케할지...
- 인프런에서는 완강하면 체크표시되면서 강좌 열었을때 시작할 강좌부터 열어줌
- 필요한 것
- 해당 강의 체크 방법
- 일단 테이블에 저장 필요. (데이터 중복은 불가피한데 어디까지?)
- 사용자/수강강좌/강좌 수 1,2,3,4,5
- 사용자/수강강좌/강좌 1 / 2/ 3 4 (데이터 중복..)
- userid, cosno, lecno, indt, delyn
- 완강인지 어케 파악?
- 동영상 종료시점 알아야함. (거기에 맞춰서 해당 강좌번호 체크 )
- 만약 사용자가 체크한다고한다면? > TDD를 할 수있지 않을까? REST인강 실습기회!!
- 테이블읽어서 가장 최신 강의
- 체크하면 ajax 로 바로 해당 강의 insert
- 해제하면 delflag 처리
- 현재 강의 표시.
- 수강평부분
- 수강한 강좌 체크(어디까지 수강했는지)
- 강좌 추천부분 동작할 수 있도록(현재는 특정 로컬경로를 지정...)
- 엄청 완성도 높은 것보다는 의도한 기능이 정확하게 돌아가는가..
- 수강하는 강좌 볼 수 있는 페이지 (있음 강의 진척률 표시할 것 )
- html을 제이쿼리로 통제하여 생성하는 방식..
- 동작만 할 수 있게 수정함. (화면이 보기좋은 형태는 아님..)
- 어케할지...
- 인프런에서는 완강하면 체크표시되면서 강좌 열었을때 시작할 강좌부터 열어줌
- 필요한 것
- 해당 강의 체크 방법
- 일단 테이블에 저장 필요. (데이터 중복은 불가피한데 어디까지?)
- 사용자/수강강좌/강좌 수 1,2,3,4,5
- 사용자/수강강좌/강좌 1 / 2/ 3 4 (데이터 중복..)
- userid, cosno, lecno, indt, delyn
- 일단 테이블에 저장 필요. (데이터 중복은 불가피한데 어디까지?)
- 완강인지 어케 파악?
- 동영상 종료시점 알아야함. (거기에 맞춰서 해당 강좌번호 체크 )
- 만약 사용자가 체크한다고한다면? > TDD를 할 수있지 않을까? REST인강 실습기회!!
- 테이블읽어서 가장 최신 강의
- 체크하면 ajax 로 바로 해당 강의 insert
- 해제하면 delflag 처리
- 현재 강의 표시.
- 해당 강의 체크 방법
TODO 수강한 강좌 체크 진행, 코스 이미지 분리, 테이블 데이터 delFlag, regDate
2월 4주차 기록
- 테스트환경 구축
- 테스트에는 h2 , 운영은 mysql 쓰도록 구성
- 일단 mysql만..
- 필요 테이블 생성
- TDD 실습
- 최신강의 체크
- 체크한 강의 불러오기
- 체크하기
- 체크해제하기
- 테스트에는 h2 , 운영은 mysql 쓰도록 구성
- 일단 mysql만..
- 필요 테이블 생성
- TDD 실습
- 최신강의 체크
- 체크한 강의 불러오기
- 체크하기
- 체크해제하기
3월 1주차 기록
- 필요 테이블 생성함
- TDD 실습
- 최신강의, 체크한 강의 가져오기
- 없는 사용자에 대한 error 테스트
- 테스트 시 응답 json에 대해 좀 더 자세한 검증 필요 https://github.com/json-path/JsonPath 참조
- 최신강의, 체크한 강의 가져오기
- 없는 사용자에 대한 error 테스트
- 테스트 시 응답 json에 대해 좀 더 자세한 검증 필요 https://github.com/json-path/JsonPath 참조
3월 4주차 기록
- 강의정보로 최신강의로 불러오기 (체크 이후가 제일 최신일지? 클릭할떄마다 뭔가를 남겨야할지?)
- 강의 해제 ajax 추가
- 강의기능은 이정도까지만 하고 마무리?
- 체크한 값 받아서 체크표시하기 o
- 체크 및 해제 할때마다 ajax 날리기 o
- 테이블에 체크된 강의 있는 지 확인
- 테이블에 없으면 insert
- 체크한 값 받아서 체크표시하기 o
- 체크 및 해제 할때마다 ajax 날리기 o
- 테이블에 체크된 강의 있는 지 확인
- 테이블에 없으면 insert
TODO 알고리즘 적용, 예외처리, 에러페이지 생성, 이미지 등 파일관리, 테스트 디비 생성
4월 2주차
- 에러페이지, 예외처리 진행
- 컨트롤러어드바이스 찿아보기
TODO 에러 처리 더 다듬기, 에러페이지 사진넣기, 404 등 상태코드 시 페이지 설정, 알고리즘적용, 파일관리, 테스트 디비 생성(필요할까?)
4월 3주차
- 예외처리 핸들러를 통해 처리 시 exception 페이지로 이동, 로그 남기기
- 회사 소스에서는 로그만 남기도록 되어있던데, 일부러 그런걸까?
- 상태코드에 대한 설정 추가
- 회사 소스에서는 로그만 남기도록 되어있던데, 일부러 그런걸까?
TODO 알고리즘 적용(머하웃 다시 정리?), 파일관리
4월 4주차 & 5월 1주차
- 수강평 없는 경우 예외 처리 할 걳
- 일단 화면에서만 문구 변경으로 처리
- 머하웃 로직 분석
- 강좌를 클릭하였을 때 해당 강좌에 대한 추천강좌를 보여줄 것이기 때문에 아이템 기반 알고리즘을 사용하였음.
- 사용자 기반 추천 : 사용자의 유사도를 비교. 선호 이력이 비슷한 다른 사용자의 선호 아이템 추천
- 아이템 기반 추천 : 아이템의 유사도를 비교. 해당 아이템과 유사한 아이템 추천
인터넷 예제를 통해 Tanimoto 유서도를 사용했지만, 검색해보니 tanimoto와 loglikeihood 는 선호도 상관 없이 사용자의 아이템 겹침을 통해 추천을 하는 것 같아 유클리드 거리 기반 유사도로 변경하였다.
- 책도 있음! : 머하웃 완벽 가이드
- 머하웃아이템 추천에는 유사도를 고를 수 있다. (유사도에 따라 추천아이템이 달라진다!!)
- EuclideanDistanceSimilarity
- 두 점 사이의 거리 계산
- 사람들이 공통적으로 점수를 매긴 항목의 거리를 통해 유사도를 판단 (짧은수록 유사)
- PearsonCorrelationSimilarity
- 두 개의 연속적인 숫자열의 일대일 비교를 통해 경향성을 측정
- 한 숫자열의 각 숫자가 다른 숫자열의 대응되는 값보다 얼마나 상대적으로 큰지 측정
- LogLikelihoodSimilarity
- 두 사용자의 공통 아이템 수에 대비해서 얼마나 두 사용자가 겹치지 않는지 표현
- 타니모토 보다 성능이 좋다고 함
- TanimotoCoefficientSimilarity
- 선호값 전체를 무시하도록 구현된 유사도 측정 방식
- 사용자의 선호 표현 여부만 확인. 아이템에 대한 선호도가 높은지 낮은지
- 머하웃 참고
- http://blog.chapagain.com.np/recommender-system-using-java-apache-mahout/
- https://over153cm.tistory.com/entry/실습-머하웃-recommender실습2
- 머하웃 튜토리얼(포트폴리오에 정리할 때 해당 슬라이드 참고하면 좋을듯 함) : https://www.slideshare.net/Cataldo/tutoria-mahout-recommendation
- https://www.programcreek.com/java-api-examples/?api=org.apache.mahout.cf.taste.neighborhood.UserNeighborhood
- https://www.slideshare.net/springloops/collaborative-filtering-23732558
- 일단 화면에서만 문구 변경으로 처리
- 강좌를 클릭하였을 때 해당 강좌에 대한 추천강좌를 보여줄 것이기 때문에 아이템 기반 알고리즘을 사용하였음.
- 사용자 기반 추천 : 사용자의 유사도를 비교. 선호 이력이 비슷한 다른 사용자의 선호 아이템 추천
- 아이템 기반 추천 : 아이템의 유사도를 비교. 해당 아이템과 유사한 아이템 추천
인터넷 예제를 통해 Tanimoto 유서도를 사용했지만, 검색해보니 tanimoto와 loglikeihood 는 선호도 상관 없이 사용자의 아이템 겹침을 통해 추천을 하는 것 같아 유클리드 거리 기반 유사도로 변경하였다.
- 책도 있음! : 머하웃 완벽 가이드
- 머하웃아이템 추천에는 유사도를 고를 수 있다. (유사도에 따라 추천아이템이 달라진다!!)
- EuclideanDistanceSimilarity
- 두 점 사이의 거리 계산
- 사람들이 공통적으로 점수를 매긴 항목의 거리를 통해 유사도를 판단 (짧은수록 유사)
- PearsonCorrelationSimilarity
- 두 개의 연속적인 숫자열의 일대일 비교를 통해 경향성을 측정
- 한 숫자열의 각 숫자가 다른 숫자열의 대응되는 값보다 얼마나 상대적으로 큰지 측정
- LogLikelihoodSimilarity
- 두 사용자의 공통 아이템 수에 대비해서 얼마나 두 사용자가 겹치지 않는지 표현
- 타니모토 보다 성능이 좋다고 함
- TanimotoCoefficientSimilarity
- 선호값 전체를 무시하도록 구현된 유사도 측정 방식
- 사용자의 선호 표현 여부만 확인. 아이템에 대한 선호도가 높은지 낮은지
- EuclideanDistanceSimilarity
- http://blog.chapagain.com.np/recommender-system-using-java-apache-mahout/
- https://over153cm.tistory.com/entry/실습-머하웃-recommender실습2
- 머하웃 튜토리얼(포트폴리오에 정리할 때 해당 슬라이드 참고하면 좋을듯 함) : https://www.slideshare.net/Cataldo/tutoria-mahout-recommendation
- https://www.programcreek.com/java-api-examples/?api=org.apache.mahout.cf.taste.neighborhood.UserNeighborhood
- https://www.slideshare.net/springloops/collaborative-filtering-23732558
TODO 데이터소스 부분 뜯어고치기 (좀 더 표준적인 mybatis 로?, 책 참조해볼것 ), 파일관리 필요
5월 2주차
데이터 접근 부분 리펙토링
- 너무 복잡한 형식으로 되어있는 것 같다.
- 표준적인 mybatis - mapper 형식으로 변환해보자.
- databaseConfig 부분 정리하기
@Mapper 는 어떻게 스프링 빈으로 와이어될 수 있을까?
MyBatis 장점
- 자동적으로 Connection close() 가능
- Mybatis 내부적으로 PreparedStatement 처리
- #{prop}와 같이 속성을 지정하면 내부적으로 자동 처리
- 리턴 타입을 지정하는 경우 자동으로 객체 생성 및 ResultSet 처리
데이터 접근 부분 리펙토링
- 너무 복잡한 형식으로 되어있는 것 같다.
- 표준적인 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 사용해서 처리할 것 !!
이번주까지 변환 완료할 것 !
테이블 연관관계 학습필요!
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 만들것
파일관리를 보통 어떻게하는가?
로켓마켓 : FileUtils
- 파일 전용테이블 있음
- 특정 경로에 저장하도록 하였음 (환경설정 파일에 명시)
스프링부트 책 :
유효성 검사
rest api 에 대해 유효값 검증을 하자 !! (백기선님 강의 참고)
ResponseEntity 변경
rocketmarket에 있는 전송방법 참고하여서 dto 만들것
TODO 파일 관리, 시큐리티, 보안취약, 테이블 연관관계 학습필요! (JPA책 공부하자), CI 적용
7월 1주차
스프링 시큐리티 적용
백기선님 강의 듣고 정리하기
강의랑 로켓마켓 참조하여 내 프로젝트에 적용해보기
집가서 책에 있는 시큐리티는 어떻게 구현되어있는 지 확인할 것
시큐리티 참조
CI 장단점 비교하기
CI란?
Travis VS Jenkins
도커 장점
- 가상의 공간을 이미지로 만들어 저장할 수 있다. 이 이미지를 통해 컨테이너를 생성할 수 있다.
스프링 시큐리티 적용
백기선님 강의 듣고 정리하기
강의랑 로켓마켓 참조하여 내 프로젝트에 적용해보기
집가서 책에 있는 시큐리티는 어떻게 구현되어있는 지 확인할 것
시큐리티 참조
CI 장단점 비교하기
CI란?
Travis VS Jenkins
도커 장점
- 가상의 공간을 이미지로 만들어 저장할 수 있다. 이 이미지를 통해 컨테이너를 생성할 수 있다.
TODO 시큐리티 인증절차 제대로 구현필요, 테이블 연관관계 학습필요! (JPA책 공부하자), CI 적용
7월 2주차
시큐리티 심화 적용
로켓마켓은 어떻게 활용하고 있는가?
- 이상함.. 비번체크하는부분이 없음..? -> 시큐리티에서 다해줌!!!!
나의 방식 : 로그인 시 권한체크 성공하면 패스워드 인코더를 통한 비밀번호 체크해서 세션에 로그인 정보 담는 방식임 , 소셜부분은?
- 아.. 시큐리티를 태우는 순간 DaoAuthenticationProvider에서 비번체크까지 해줌 ;;
try {
preAuthenticationChecks.check(user);
additionalAuthenticationChecks(user,
(UsernamePasswordAuthenticationToken) authentication);
}
- 시큐리티와 소셜로그인 연동은 개선할 것이 많고 어렵당 ㅠㅠㅠ 다시해보자
시큐리티 개선할떄 참고할 것
시큐리티 심화 적용
로켓마켓은 어떻게 활용하고 있는가?
- 이상함.. 비번체크하는부분이 없음..? -> 시큐리티에서 다해줌!!!!
나의 방식 : 로그인 시 권한체크 성공하면 패스워드 인코더를 통한 비밀번호 체크해서 세션에 로그인 정보 담는 방식임 , 소셜부분은?
- 아.. 시큐리티를 태우는 순간 DaoAuthenticationProvider에서 비번체크까지 해줌 ;;
try { preAuthenticationChecks.check(user); additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication); }
- 시큐리티와 소셜로그인 연동은 개선할 것이 많고 어렵당 ㅠㅠㅠ 다시해보자
시큐리티 개선할떄 참고할 것
TODO 소셜로그인에 시큐리티 로그인 연동하기 , 테이블 연관관계 학습필요! (JPA책 공부하자), CI 적용
7월 3주차
프로젝트 좀 정리하는 시간 갖고, 다음에 뭐 개선할지 정하기
테이블 연관관계 or 소셜 연동 하는 것이 좋아보임.
네이버클라우드에 젠킨스 깔자 (ㅋㅋ거기꺼 써도될듯)
- 회사 선배계정에 젠킨스 설치함!! github README.md 파일에 build status 표시 중
프로젝트 좀 정리하는 시간 갖고, 다음에 뭐 개선할지 정하기
테이블 연관관계 or 소셜 연동 하는 것이 좋아보임.
네이버클라우드에 젠킨스 깔자 (ㅋㅋ거기꺼 써도될듯)
- 회사 선배계정에 젠킨스 설치함!! github README.md 파일에 build status 표시 중
TODO 소셜로그인에 시큐리티 로그인 연동하기 , 테이블 연관관계 학습필요! (JPA책 공부하자), CI 적용
7월 4주차
시큐리티 + OAuth 구현해보기
이제 어떻게 연결시키느냐? principal 이랑? 7
세션관리;; 다시? principal로 하니 문제가 많음;;
- 세션에 다시 저장할 것!!
필터추가하기 : https://parkhyeokjin.github.io/spring/2019/11/19/Spring-OAuth.html
카카오oauth 필터적용: https://hojak99.tistory.com/563
시큐리티 + OAuth 구현해보기
이제 어떻게 연결시키느냐? principal 이랑? 7
세션관리;; 다시? principal로 하니 문제가 많음;;
- 세션에 다시 저장할 것!!
필터추가하기 : https://parkhyeokjin.github.io/spring/2019/11/19/Spring-OAuth.html
카카오oauth 필터적용: https://hojak99.tistory.com/563
다중 구현 가능할듯!!
TODO 테이블 연관관계 학습필요! (JPA책 공부하자), build.Gradle 정리
8월 1주차
build.gradle 정리
- 필요없는 부분 지우기
- io.spring.gradle:dependency-management-plugin 으로 자동으로 버전이 설정됨. 필요없는 건 버전을 지우자
- 로컷마켓 task 분석해보기
- test : Junit5 을 사용하기 위함으로 보임
- jooq : jooq 관련 설정
- 나머지는 비슷...?
테이블 연관관계 공부 하기
- 책을 인쇄해서 가야할까? or 사야할까..흠
테이블 연관관계는 책이나, 인강으로 학습이 필요해보인다. 나중에 새로운 프로젝트할 때 제대로 적용하자
build.gradle 정리
- 필요없는 부분 지우기
- io.spring.gradle:dependency-management-plugin 으로 자동으로 버전이 설정됨. 필요없는 건 버전을 지우자
- 로컷마켓 task 분석해보기
- test : Junit5 을 사용하기 위함으로 보임
- jooq : jooq 관련 설정
- 나머지는 비슷...?
테이블 연관관계 공부 하기
- 책을 인쇄해서 가야할까? or 사야할까..흠
테이블 연관관계는 책이나, 인강으로 학습이 필요해보인다. 나중에 새로운 프로젝트할 때 제대로 적용하자