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 사야할까..흠
  • 테이블 연관관계는 책이나, 인강으로 학습이 필요해보인다. 나중에 새로운 프로젝트할 때 제대로 적용하자

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



무엇을 해야할지 생각&정리 먼저하자

목적의식이 필요해

(뭘 해야하는 지 생각하고 실행하자)

(5월 12일 작성)

  • 또 공부를 안하고 있다. 항상 머리로는 공부해야하는데... 라는 생각만 하면서 침대에서 빈둥거리고 잘 시간이 또 안했네 라고 혼자 스트레스를 준다.
    이 얼마나 쓸데없는 정신소모인가ㅋㅋㅋ 하더라도 강의 몇개 들어놓고 끝난다.
    의지가 약해졌다.
    2019년 계획을 짜면서 보람찼던 때가 어제같은데 벌써 5월이 되었다. 다시 의지를 씨게 잡아야될 때가 왔다.

  • 우아한형제들 기술블로그에서 박재성님의 글 중 '목적의식 있는 연습'에 대한 내용인데, 밑의 문장이 참 좋은 것 같아서 한번 써봤다.
    내가 현재 수준에 만족하고 더 이상의 의식적인 노력을 하지 않는다면 그 순간 성장이 멈추는 단계이다.
    무작정 반복하고 경력을 쌓는다고 해서 성장하지 않는다.
    20년 경력의 의사가 5년 경력의 의사보다 환자의 병을 잘 진단한다고 볼 수 없다.
    경력을 쌓는 과정에서 의식적인 노력을 통해 다음 단계로 성장하기 위해 노력했느냐에 따라 달라지는 것이다.
    http://woowabros.github.io/woowabros/2019/05/02/techcourse.html

물론 난 일단 노력부터 해야하지만, 이왕 할꺼 나도 효율적으로 해보자!

지금 진행중인 것들(현재 상태 체크)

  1. 자바의 정석 애매한 부분 복습
    • 3월 말 이후부터 멈춤
    • 9, 11, 12, 14, 15, 16 챕터 남음
  2. 백기선님의 웹 MVC 강의 (완료)
    • 3월에 시작하였으나 아직도 진행중
    • 현재 12개 정도 남은 상태 (3~4시간 분량)
  3. 블로그
    • 3월 10일 이후부터 멈춤
    • 재료고갈, 기록할만한 공부를 안헸음
  4. 백준 알고리즘
    • 3월 중순부터 멈춤
    • 단계별 코스를 진행하려하였으나, 기초적인 1~3단계 후 4단계에서 멈춤 (이 때, 스프링 강의에 정신에 쏠림)
  5. 스프링 스터디 (파토ㅋㅋ)
    • 4월부터 시작
    • 스프링프레임워크를 사용하여 여행계획 사이트 만들 계획
    • 내가 원하는 방향으로 진행하기가 어려움 (새로운 것을 해보고 싶은데... 너무 기존의 했던 방식의 방향임..ㅠ)
  6. 독서 - 이펙티브 자바 (완료. 하지만 한번 더 읽어야할 것 같음)
    • 2월부터 읽기 시작하였으나 아직도 진행 중
    • 65% 정도 읽음
    • 어려움 + 아침에만 살짝 읽다보니 속도가 엄청나게 느려짐

나에게 필요한 것

(상세 계획은 구글 스프레드시트에서 관리하도록 하자!)
  1. 언어
    • 자바(기초&심화)
      • 자바의 정석 읽던 거 마무리 하기.
        HOW?
        현재 6개 챕터 정도 남음. 아는 내용은 빠르게 넘어가도록 하자.
        
      • 이펙티브 자바를 통해 심화학습으로 이어질 수 있도록 하기.
        HOW?
        책을 눈으로만 읽고 넘기지말고, 직접 실습을 통해 머리로 이해하고 넘어가기(물론, 기록도 해서 나중에 또 볼 수 있도록 남기기)
        
    • 자바스크립트(기초)
      • 자바스크립트 공부는 어떤방식으로 해야하는 걸까?
        HOW?
        책으로 보는게 제일 좋을 듯함. 인사이드 자바스크립트 책이 괜찮아보임.
        
    • 다른 언어 학습(후보: Node.js, Python, .Net, Scala, Golang)
      • Node.js 재미있어보이는데..
        HOW?
        제일좋은 방법은 nodejs 사용해서 무엇을 만들어보는 것
        (책 따라하는 것 vs 인터넷자료보고 따라해보는 방법)
        
  2. CS 지식
    • 네트워크
      • 학교의 지식이 거의 없으니, 기초지식을 학습하자! (HTTP, 네트워크)
        HOW?
        인터넷 강의 or 간단한 네트워크 지식책 읽기
        
  3. 알고리즘 테스트 준비
    • 알고리즘에 필요한 자료구조 공부
      • 학교에서 수업한 자료구조 지식이 전혀 없다. 기초지식을 학습하자!
        HOW?
        일단 Hello Coding 알고리즘 책을 통해 기본 알고리즘에 대해선 학습했지만, 머리에 남는 것이 없는 듯하다..
        인프런 알고리즘 강좌, T아카데미에 기초 알고리즘 강좌가 있는 듯 함.
        
    • 알고리즘 문제
      • 직접 알고리즘을 풀면서 코딩테스트에 대비하자 (코테는 꾸준해야한다.)
        백준
        or 코딜리티
        or else?
        하나 선택해서 계획 짜야해
        
  4. 배포 & 운영환경 지식
    • 뭘 해야하지..?ㅋㅋ
    • 회사들은 CI/CD 를 어떻게 사용하는데?
      • 우형,카카오 등 운영업체에서 어떻게 쓰고있는지 찾아보기
      • 스터디에 CI 적용시켜보기
        지금 진행 중인 스프링 프로젝트에 젠킨스를 통해 CI/CD를 적용시켜도 좋을 듯 한데...팀원들은 별로 관심이 없는 듯 함..
        
    • MSA(마이크로서비스 환경? )가 뭔데?
      • 어디서 본 건 있지만, 확 와닿고 이해하진 못함
      • 실습해보는 것이 가장 좋은 방법인데 어떻게해야할까?
    • 도커가 뭔데?
      • 진짜 모름. 찾아봐야함.
      • 실습해보는 것이 가장 좋은 방법인데 어떻게해야할까?
        HOW?
        블로그에 정리해보는 것도 좋을듯 (간단한 실습과 함께)
        
  5. 코딩 챡챡
    • 타자 (현재 개느림. 특히 영타)
      • 의식적으로 다른손가락 연습해야함. 오른손을 너무 안쓰고 있음.
    • 객체지향 코딩
      • 객체지향 코딩은 어떻게해야하지?
        How?
        스터디에서 코딩하는 것은 나만의 코딩이므로 내 마음대로 코딩할 수 있음.
        하지만 객체지향적인 코딩은 어떻게 해야하는 건데??
        
    • 테스트 연습
      • 단위테스트 , TDD
        HOW?
        지금 당장 TDD는 어려움이 있으니, 의식적으로 단위테스트를 해보자.  
        (best는 스프링 스터디코딩할 때 연습. )
        
  6. 개발 지식
    • 기술지식
    • 새로운 학습?
      HOW?
      nodejs 나 도커, msa 등 실습해보면서 정리한 기록에 대해 이야기해보면될 듯?
      Node가 제일 재미있을 것같음.

2019년 3월 10일 일요일

[인프런] 스프링 프레임 워크 핵심 기술 수강 후기

스프링 프레임 워크 핵심 기술 수강 후기

사수님의 지식 공유로 백기선님에 대해 알게되었다. 처음에는 유튜브에 있는 영상만 보다가 인프런에서 직접 강의를 올리시는 것을 알게 되었고, 그 중 나에게 도움이 되면서 비교적 저렴한 강의를 찾다 '스프링 프레임워크 핵심 기술' 이라는 강의를 구매하였다.
이 강의에서는 스프링의 핵심기술을 이해하여, 스프링이 제공하는 다른 기능(JDBC, 테스트, MVC, 스프링부트 등)을 더 쉽고 정확하게 이해할 수 있게할 수 있는 베이스지식을 제공한다.
스프링하면 떠오르는 IoCAOP 에 대한 내용이 강의의 대부분을 차지하며, 이것이 무엇 이며 어떻게 제공되는지 설명하고 있다.
코드를 따라하면서 진행하는 강의는 아니었지만, 테스트 예제코드를 통해 설명을 해주셔서 이해하기 더 편했고, 재미있었다. 내 머리속에 애매하게 있던 지식들이 조금씩 정리가 되는 느낌이여서 매우 좋았다.
하지만, 엄청 깊게 설명하는 방향보다는 소개와 이해 중심의 강의여서 직접 써보면서 찾아봐야 확실하게 이해가 될 것 같은 느낌이었다. 모든 강의가 그렇겠지만 보는 것으로 끝나면 남는게 없다.
직접 해보고 내 머리속에 저장하자!
완강 후에는 바로 백기선님의 스프링 웹 MVC 강의도 구매하였다.
처음에는 '구글에 자료도 많고 잘 정리된 블로그도 많은데 왜 돈 주고 강의를 사야하지' 라는 생각이 있었는데, 생각을 조금만 해보면 고작 책 몇권 가격으로 내 소중한 시간을 아끼면서 좋은 지식을 습득할 수 있다면 구매할 가치가 충분하다. 매우
이것이 시간을 돈으로 살 수 있는 것이 아닐까?? 물론 내 것으로 만든다는 가정하에...




인프런 - 스프링 프레임워크 핵심기술
https://www.inflearn.com/course/spring-framework_core/

2019년 2월 24일 일요일

AWS 탄력적IP 간단 사용

AWS 탄력적 IP 사용하기

  • 저번 젠킨스 설정을 해보면서 인스턴스가 자꾸 뻗은 적이 있었다. 그럴 때 마다, 재기동을 해주었는데, ip가 변경되는 바람에 소스에 설정해놓은 DB주소들을 같이 변경해주었고, 터미널로 접속할 때도 IP와 키파일 경로를 복붙해서 쓰고 있었는데, 그 부분도 변경을 같이 해주는 바람에 매우 귀찮았었다.
하지만, AWS는 탄력적IP 라는 기능을 통해 고정IP를 제공해주고 있다고한다.
  • 설정방법
    • EC2 대시보드 > 네트워크 및 보안 > 탄력적 IP 
    • 새 주소 할당
    • 원하는 인스턴스 선택, 프라이빗IP에는 해당 탄력적주소IP를 입력
    • 인스턴스 메뉴 > 선택한 인스턴스 클릭 > 인스턴스 설명을 보면 방금 설정한 탄력적IP가 나와있는 것을 확인할 수 있음.
참고사항 - 탄력적IP를 할당받고 인스턴스에 연결을 안하면 요금이 발생되는 것 같다. 좀 이상한듯....왜 안쓰냐 이건가ㅋㅋ 탄력적IP 메뉴에서 안쓰는 IP는 주소릴리즈 하면 되는 것 같다.[해당내용 링크] https://aws.amazon.com/ko/premiumsupport/knowledge-center/elastic-ip-charges/

탄력적 IP를 사용한 인스턴스 쉽게 접속하기

  • AWS에서 알려준 예시 연결방법말고 직접 등록하여 쉽게 접속해보자
(연결방법 예시) ssh -i "cot.pem" ubuntu@ec2-{퍼블릭 IP}.ap-northeast-2.compute.amazonaws.com
  • 설정 방법
    • 인스턴스 생성 시 받은 키 파일을 해당 경로로 복사한다.
  cp {key.pem} ~./ssh/
  • ./ssh 경로에 config 파일을 생성한다.
  vi config

  다음의 내용 입력 후 저장 종료 (wq)
  ---

  Host {접속할 이름}
      HostName {AWS 탄력적IP}
      User ec2-user
      IdentityFile ~/.ssh/{key.pem}
  • 접속 확인
  ssh {접속할 이름}

2019년 1월 28일 월요일

실용주의 프로그래머 책 메모

실용주의 프로그래머 

드디어 실용주의 프로그래머를 다 읽었다.
영어공부에 대해 이야기하다가 사수에게 한글로 책을 읽고 원서로 한번 더 읽는 방법을 추천받아 이 책까지 빌리게 되었는데 1챕터 읽고 멈췄었다...
하지만, 2019년 읽을 도서 목록으로
실용주의 프로그래머 -> 이펙티브 자바 -> 클린코드 -> ...more
으로 정하여서 2019년 1월 - 약 1달에 걸쳐서 다 읽게 되었다.
사실..1월말 까지 책을 돌려줘야해서 살짝 급하게 읽었다. 중간에 대충 읽은 부분도 많다.
이 책은 어디선가 보고 들은 개발자가 가져야할 생각이나 명심해야할 것들을 모아놓은 책 느낌이었다. 그래서 더 읽는데 속도가 붙을 수 있었던 것 같았다. 책을 사서 다시 읽어봐도 좋을 듯 하다.
그땐 또 다른 느낌점들과 깨닫는 것들이 생길 것 같다.

인상깊은 문장 메모
  • 자신의 일에 대해 생각하면서 일해라!
  • 깨진 창문(나쁜설계, 잘못된 결정, 혹은 형편없는 코드)을 고치지 않은 채로 내버려 두지 마라.
  • 큰 그림에 늘 주의를 기울여라. 개인적을 무엇을 하고 있는가에만 정신을 쏟지 말고, 주변에서 무슨일이 벌어지는지 지속적으로 살펴보라.
  • DRY - Don't Repeat Yourself
  • 관련 없는 것들 간에 서로 영향이 없도록 하라. (직교성 강조하고 있음)
  • 최종 결정이란 없다. (유연성강조)
  • 언제나 소스코드 관리 시스템을 사용하라.
  • 가장 속이기 쉬운 사람은 자기 자신이다.
  • 가정하지 마라. 증명하라.
  • 단정문을 사용해서 불가능한 상황을 예방하라.
  • 시작한 것은 끝내라.
  • 모듈간의 결합도를 최소화하라.
  • 통합하지 말고 설정하라.
  • 코드에는 추상화를, 메타데이터에는 세부 내용을.
  • <의도적으로 프로그래밍하기>
    • 정말로 제대로 돌아가는 것이 아닐지도 모른다. 우리에게만 그런 것처럼 보일 수도 있다.
    • 신뢰할 수 있는 것에만 기대라. 우연한 일이나 가정에 의존하지 말라.
    • 기존 코드가 아픙로 짤 코드를 지배하도록 놓아두지 말라. 더 이상 적절한 코드가 아니라고 생각되면, 어떤 코드라도 교체할 수 있다.
    • 어떤 것이 잘돌아가는 것처럼 보이기는 하는데 그 이유를 모를 경우, 그것이 우연은 아닌지 반드시 확인하라.
  • 일찍 리팩터링하고, 자주 리팩터링 하라.
    • 리팩터링과 새로운 기능 추가를 동시에 하지마라.
    • 리팩터링 전 테스트 집합이 있는지 먼저 확인하라.
    • 단계를 작게 나누어서 신중하게 작업하라. 단계가 끝날 때마다 테스트를 돌려라.
  • 테스트 코드를 쉽게 접근할 수 있게 해놓는 것은 앞으로 코드를 사용할지 모르는 개발자들에게 매우 귀중한 자원 2가지를 제공하는 것이다.
    • 모듈의 모든 기능을 어떻게 이용하야 하는지 보여주는 예제
    • 후일 코드 변경 시 검증하기 위한 희귀 테스트를 구축할 수 있는 수단
  • 주석에 나오지 말아야 할 것들의 목록
    • 파일 내의 코드가 export하는 함수들의 목록
    • 리비전 기록
    • 이 파일이 사용하는 파일 목록

2019년 1월 13일 일요일

스프링에서 선언식 트랜잭션 간단하게 실습해보기

트랜잭션이란??

정보처리기사에 정말 많이 나오는 개념으로 all or nothing 이라고 생각하면 된다.
'모두 처리 아니면 모두 X'
예를 들면, 트랜잭션이 적용된 어떠한 행동이 3가지의 insert , update, insert의 쿼리를 수행하는 행동일 때,
insert 성공
update 성공
insert 실패
가 되었을 때 앞의 insert와 update 쿼리가 성공이 되었을 지라도 마지막 insert가 실패되었기 때문에 모두 롤백이 되어야하는 개념이다.
스프링에서 트랜잭션은 선언식 트랜잭션과 프로그램에 의한 트랜잭션을 통해 사용할 수 있는 것 같다.
선언식 트랜잭션 중 어노테이션방법을 게시판의 예제로 간단하게 살펴보자
사용자가 게시물을 클릭한다고 생각하면 다음의 순서로 진행된다. 
1. 조회수가 오른다. (update)
2. 게시물의 데이터를 가져온다. (select)
만약 이때 2. select 과정에서 오류가 발생한다고 가정한다면, 게시물의 데이터를 못가져왔으므로 조회가 되지않는다. 그렇다면 조회수도 오르지 말아야한다.
(예시가 좀 이상하다. 적절한 예시를 찾아서 수정해야할듯...)
이 행동에 대해서 트랜잭션을 적용해보겠다.

root-context.xml
...

    <!-- transactionManager -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

...
servlet-context.xml
...

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

...
serviceImpl
package com.wpp.service;
...
import org.springframework.transaction.annotation.Transactional;
...

@Service
public class BoardServiceImpl implements BoardService{
...


@Transactional
public Object read(int bnum) throws Exception {
    Object object = null;

    //조회수 올리기
    boardDao.uphit(bnum);

    //게시물 내용
    object = boardDao.read(bnum);

    //트랜잭션 테스트를 위한 Exception 발생
    if( object == null) {
        throw new RuntimeException();
    }

    return object;
}


...
}
아까 만든 가정대로 테스트를 하기위해
다음과 같이 object가 null이면 RuntimeException 을 발생시켜보았다.
breakpoint를 잡고 object = freeboardDao.read(bnum); 부분에 bum의 값을 DB에 없는 값을 줘서 object를 null이 나오도록 하였다.
@Transactional 어노테이션이 없을 때는 해당 Exception이 발생하더라도 그 전의 조회수가 올라가는 것을 볼 수 있지만, 어노테이션을 추가한 후에는 조회수 부분이 rollback 된 것을 볼 수 있다.

@Transactional 에는 다양한 속성을 지정해줄 수 있다.
ex_) @Transactional(isolation=Isolation.DEFAULT, timeout=10)
- 격리레벨 : 데이터에 대한 격리
  - ex_) 커밋된 데이터 읽기 허용, 커밋되지 않는 데이터 읽기 허용 등)
- 전파 : 트랜잭션 중 다른 트랜잭션 호출할 때의 경우
  - ex_) 기존에 실행되고 있는 트랜잭션이 있으면 참여 아니면 새로 생성, 무조건 트랜잭션 새로 생성
- readonly : 트랜잭션을 읽기전용으로 적용
  - ex_) 쓰기작업 발생 시 예외발생(기본설정은 false)
- rollbackFor : 특정 예외가 발생할 경우 롤백 처리 설정
  - ex_) : 스프링의 데이터엑세스 예외는 RuntimeException 이므로, 런타임예외만 롤백대상이므로 다른예외도 추가하는 방식...인가????
- timeout : timeout발생 시 롤백 처리(초단위같음)
  - ex_) : 지정된 시간안에 수행이 되지 않으면 롤백

어노테이션 외에도 aop를 이용해 service단의 모든 메소드에 트랜잭션을 적용시킬 수 있다.

게시판에 트랜잭션을 적용하려고 다시 소스를 보았는데.....
정말 개판이다..

물론 이 때는 게시판을 만들어보는 것에 목적으로 두고 생성하였지만,
참...ㅋㅋㅋ 이 구조는 왜 이런식이며...service단은 그냥 쿼리를 호출하는 거랑 뭐가 다르게 만들어졌으며..

너무 못짰다. 이게 뭐야ㅠㅠㅠㅠㅠㅠㅠㅠ
얘를 개선할 수 있을까?
todo
aop 예제도 해보자.

2019년 1월 2일 수요일

그림과 실습으로 git branch 연습하기

개발자 커뮤니티 페이지를 돌아다니다가 git이 어렵다면 branch가 어려운 일 겁니다. 라는 제목을 보았다.
이 글에서 git branch 관련해서 연습을 하는 사이트를 추천해주셨는데

아주 직관적이고 그림으로 움직이면서 설명을 해줘서 브랜치에 대해 이해하기 쉽게 만들어져있었다.
마침 매번 사용할 때마다 찾아보고, 이클립스 안에서만 간단하게 commit, push만 하는 나에게 유익하다고 생각되었다.
commit, branch, checkout, cherry-pick, reset, revert, rebase, merge
의 명령어를 사용할 수 있고, 다음과 같은 단계별로 진행된다.

각 단계마다 명령어횟수를 측정하는데 모범답안 횟수에 도달하거나 하지 못할 때 메시지를 보여준다.

하단부에서 답안을 확인할 수 있으며, 초기화(Reset)이나 되돌리기(Undo)가 가능하다.

단계별로 되어있어 복습하기 쉽고, 답안까지 친절하게 제공해주고 있어 학습하기 좋은 것 같다. 



나도 언젠가 누군가에게 쉽고 간단하게 설명해줄 수 있는 날이 올까....?