1. 계층형 댓글을 구현한 간단한 게시판 만들기
(웹 개발자에겐 누워서 떡먹기?? 아..아닌데..)

  

게시판을 만들기위해 필요한 조건을 PPT로 만들어 주셨고, 필수 스펙은 다음과 같았습니다.

  
  •    
  • Java8
  •    
  • STS (intellij)
  •    
  • Spring 4.0 MVC
  •    
  • Spring Security
  •    
  • ORM(Hibernate)
  •    
  • Git
  •    
  • MySQL
  •    
  • Log4j
  •    
  • Springboot
  •    
  • Gradle
  •    
  • jQuery
  •  
  

선택기술은 다음과 같았습니다.

  
  •    
  • Freemarker
  •    
  • Ajax
  •    
  • JUnit
  •    
  • Node.js
  •    
  • Backbone.js
  •    
  • BootStrap
  •    
  • 빌드 시스템(grunt)
  •    
  • 다양한 Spring Annotation
  •    
  • 다양한 Design Pattern
  •    
  • 다양한 opensource, framework
  •  
  

필수 사항은 반드시 사용해야하는 기술이였고, 선택사항은 추가적인 기술스펙이였습니다.
 필수 스펙을 보면 아시겠지만, java8, Spring 4.*버전, SpringBoot 등 최신 버전(제가 쫌 올드한 것 같다는 느낌이 많이 들었습니다.)으로 개발을 진행하였습니다.

  이전에 3.0 버전과 전자정부프레임워크, Maven만을 사용해봐서 SpringBoot, Gradle을 사용하며 신세계를 맛(쓰면 쓸수록 스프링개발이 편한 맛??)보았습니다.

  그 밖에 처음 사용해 보았던 hibernate(책만 사놓고 안써봄, 결국 처음엔 개발에 급급해서 myBatis, iBatis처럼 개발), MySQL(오라클만 써보았습니다.), Git(뭔지 궁금해서 한번해보고 SVN만 써봄), Security(한번 써봤습니다.) ,Log4j(로그찍는 것은 실서비스에서 꼭 필요한 기능임을 알게 됬습니다..로그 레벨도 있습니다.) 등을 사용하였습니다.

  

**굵은 글씨**는 제가 선택했던 선택기술입니다.(나머지는? 잘 모르는 것들..)

  

Freemarker는 처음 들어 봤는데(알고 보니.. JSP탬플릿은 몇 해 전 부터 개발이 중단되었고, 그 뒤를 이어가는 자바진영의 서버 탬플릿 -그 밖에 대표적인 서버 탬플릿 Velocity, Thymeleaf) 이란 것을 알게 되었습니다.

   Node나 Backbone, grunt, npm와 같은 프론트 기술들을 잘 사용해 보지 않은 저 였기에 2주라는 기간 동안에 개발이 힘들 것이라 판단하고 과감히 포기하였습니다..(기술 스펙트럼이 좁다는 것을 다시 한번 느끼게 되었습니다.)

  망한건가?

  

필수 구현 기능

  

필수 구현해야 했던 기능들 입니다.

  

회원 기능

  
  •    
  • id, password, email 을 계정 정보로 가짐
  •    
  • 회원가입, 로그인, 개인정보수정,탈퇴     
    •        
    • 개인 정보 암호화, BCryptPasswordEncoder(bcrypt 해시알고리즘)를 사용
    •      
  • Spring Security 레퍼런스에 다음과 같이 쓰여있습니다. "bcrypt is a good choice for most cases"

          
    •        
    • 비밀번호의 단방향 암호화
    •      
  • 사용자의 정보를 encryption하여 저장하고, 사용자의 접속 요청 때 요청된 비밀번호와 DB에 저장된 암호를 비교하는 방법.

        선택한 이유? 해킹에 의한 사용자의 DB 정보 탈취나 관리자의 정보 악용을 최대한 막을 수 있습니다.
        양방향의 경우 decryption하는 추가적인 작업이 발생합니다.

          
    •        
    • 회원탈퇴시 이전에 남겼던 글에 대한 권한 문제
    •      
  •  탈퇴를 하게 되면 이전에 사용했던 글들은 남아있습니다. 그리고 같은 아이디로 사용자가 로그인 하게 된다면?   이전에 남긴 글과 댓글에 대한 권한을 갖게 됩니다.
     
       나중에 알게 된 사실..일정기간 동안 해당 아이디를 사용하지 못하게 한 후, 기간이 지난 아이디에 대하여 남긴 글을 삭제 하는 방법이 있다고 합니다.

  •  
  

기본 게시판(요약)

  
  •    
  • 게시판은 하나 (여러 개의 게시판 X)
  •    
  • 게시판의 글에 답글은 달리지 않음
  •    
  • 게시글 글자수 제한(10000자), 댓글 글자수 제한(140자)     
    •        
    • textchange(MIT license) 모듈(js)을 사용하여 사용자의 입력에 이벤트를 걸어 글자수를 제한
    •      
  • 검증된 오픈소스를 사용해야 합니다.

  •    
  • 권한 처리(내가 쓴 글만 지울 수 있어야 함)     
    •        
    • spring security를 사용하여 사용자의 권한에 맞는 이벤트만 가능하도록 함
    •      
  • (순수 jdbc연동하는 방법 UserDetails, UserDetailsService을 상속받는 방법. 똑같은 걸 2번 개발했습니다.)

          
    •        
    • 유저 아이디와 session 속 로그인아이디를 비교하여 내가 쓴글만 수정가능하게 함.
    •      
  •    
  •    
  • 글은 [번호, 제목, 내용, 글쓴이, 시간, 조회수] 의 정보를 가짐
  •    
  • 새 글 등록/수정/삭제 기능 및 권한 처리     
    •        
    • hibernate의 criteria를 사용한 CRUD
    •      
  • 하이버네이트를 myBatis 처럼 사용한 것을 보고 당황해 하셧던 선임분들..

  •    
  • 페이징 기능     
    •        
    • 직접 paging만 처리하는 객체를 만들어서 구현.
    •      
  • JPA에 JpaRepository을 이용한 pageable이란 좋은게 있었습니다.

  •    
  • 보안(tag, script 입력 필터링)     
    •        
    • hibernate.Validator 어노테이션을 이용
    •      
  • 서버에서 Domain의 값을 제한하기 좋습니다.

          
    •        
    • taglib escapeXml
    •      
  • 스크립팅 공격, injection tag을 막을 수 있습니다.

  •    
  • 계층형 댓글 기능     
    •        
    • 재귀함수를 통해 부모의 자식을 찾아서 계층형을 만드는 방법
    •      
  •  가장 어려운 부분이엿습니다. 알맞은 로직을 찾아내는 것.
       개발 전 오라클 처럼 START WITH 쓰면 되겠지 했지만 (그건 저의 오산..)
       mysql에는 START WITH 같은 계층형을 지원하는 쿼리가 존재하지 않았습니다..

       그래서 저의 선택은 step을 만들어서..재귀함수까지.(성능 망함)
       결국, 시간이 부족해서 만들지 못했지만, 찾아낸 방법은 바로 소수점 계층형 게시판입니다.(괜찮을 걸 찾았다!!)

  •    
  • 이미지(jpg,png,gif) 업로드 기능

          

    1)파일과 이미지를 따로 전송하는 AJAX  방법
       2)enctype="multipartform-data"로 한번에 전송하는 방법. 똑같은 걸 또..2번 만들어 봤습니다. 

  •  
  

이상으로 필수 기능과 필수 기능을 구현하기 위해, 사용했던 기술 설명을 추가로 붙여 보았습니다.(궁금.. 하셧죠?)

  


 

  

1차 프로젝트 어려웠던 점.

  
  •    
  • 혼자서 모든 것을 판단하고, DB ~ QA까지 진행했던 점
  •  
  

학원이나 스터디에서 오로지 기능완성만을 위해서 개발을 진행했습니다.. 회사에서 서비스 관점에서도 본다면 훠~~~얼씬 고려해 봐야 할 것이 많다는 것을 알게 되었습니다.

  
  •    
  • 네이밍 규칙, 컨벤션
  •  
  

코드리뷰를 하며, 가장 많이 수정해야할 부분이 네이밍 규칙이였습니다.
 습관 처럼 마음대로 변수 이름을 정하고, 테이블을 만들어 내고 있었습니다..

  

*팀내에서 DB는 snake 표기법을 준수하고, 코드는 camelCase를 따릅니다.

 그 밖에.. 

  

*의미없는 String str; 같은 변수명은 피합니다. 
 *1,2,3 과 같은 매직넘버는 절대 피해야 합니다. (final, enum을 활용)
 *클래스명은 명사이고 대문자로 시작합니다.
 *패키지명은 소문자로 씁니다.
 *메소드명은 동사이고 소문자로 시작합니다.
 *변수명은 소문자로 시작합니다.
 등.. 많습니다.

  
  •    
  • Git
  •  
  

개발을 시작한지 3일만에 git을 잘 못 사용해서 프로젝트를 날려먹고 다시 처음부터 개발했습니다.
 그 만큼 저에게는 친숙하지 못했는데 쓰면 쓸수록 개발자에겐 필수 tool이라는 것을 느꼈습니다.

  
  •    
  • 그 밖에 수정했던 무수히 많은 내용들 중 일부는 다음과 같습니다.     
    •        
    • dynamic dom이용한 이벤트 등록
    •        
    • 회원 비밀번호 encoding
    •        
    • 자바스크립트 ‘==’ 보다 ‘===’를 사용.
    •        
    • 자바스크립트를 모듈화하여 사용.
    •        
    • 테이블에 idx를 추가
    •        
    • hibernate 영속성을 사용한 제대로된 사용
    •        
    • 운영체제(window/linux)에 종속하지 않는 파일 업로드
    •        
    • 로직은 service에서 구현
    •        
    • handlebars를 적용한 렌더링 속도개선
    •        
    • 패키지 관리툴 적용
    •        
    • system.out.println 삭제
    •        
    • 겸손한 자바스크립트 처리
    •        
    • exception 처리 등…  
       
    •      
  •    
  •  
  

1차 프로젝트를 마치며 느낀점.

  
  •    
  • 앞으로 수 많은 삽질이 남아 있음을 느꼈습니다.(앞으로 계속..쭉!)
  •    
  • 나는 노다지??

          

    1차, 2차, 3차까지 선임 분들 앞에서 코드리뷰를 진행하고, 수정을 반복하면서 들었던 생각입니다.
     캐고 캐도 계속 금이 나오는 노다지처럼 수정사항이 쏟아져 나왔습니다.
      프로그래머가 내길이 맞나? 한번이상 생각하게 만들어 줄 정도로 수정 해야할 사항이 너무 많았습니다.

  •    
  • 혼자서 진행해야 했기에 모든 것(10중 8? 7? 나머지 책..)을 구글링으로 알아 내면서, 정보를 찾아내는 능력도
      개발자에게는 정말 정말 중요한 기술이라는 것을 느꼈습니다.
  •    
  • 더불어 주변에 믿고 물어볼 선임 분들(정말 고마운 존재? 사랑합니다.)이 있다는 것은 정말 좋은 일이라는 것을 느꼈습니다.

          

    *1차 프로젝트에서는 다른 사람의 도움없이 오로지 혼자 프로젝트를 수행합니다.

  •  
  

*노다지 [명사]
  1. <광업>캐내려 하는 광물이 많이 묻혀 있는 광맥.
  2. 손쉽게 많은 이익을 얻을 수 있는 일감을 비유적으로 이르는 말. 

  

다음엔 더 잘 할 수 있을거야..
다음엔 더 잘 할거야..


  

2. 이글루스(php)를 자바로 포팅하기.

  

실서비스를 포팅해본다는 엄청난 경험이 나에게??

  

두근두근?

  

진행할 작업

  
  •    
  • www.egloos.com
  •    
  • valley.egloos.com
  •  
  

위 페이지를 자바로 포팅하는 작업.

  

작업 진행순서

  
  •    
  • 분석
  •  
  

실 서비스되고 있는 이글루스 로직과 사용 데이터를 분석합니다.
  php의 기본 문법을 찾아 보는 수준이여서 이글루스 분석을 진행하면서, phpschool에서 php를 어느정도(아주 조금?) 공부하였습니다.  로직상에 연결된 테이블과 배치성 데이터를 확인하고 분석하였습니다.
  (파악하고 나니.. 이미.. 1주일이란 시간이 지난 간 후 였습니다..)

  
  •    
  • 설계
  •  
  

이글루스 개발서버에서 사용되고 있는 배치성 파일들과 개발 DB를 활용하여 구조를 설계하였습니다.
  (보안 상 파일럿프로젝트 부분만 공개합니다!)  

  

시스템 구조도
  구조

 배치성 파일 parsing 로직
  배치성파일 parsing 로직 

  간략 설명 
  Spring 스케줄러가 배치성파일(인기글(테마별), 전체 인기글, 인기테마 등)을 파싱하고, 이를 EHcache에 담아 사용합니다.  또한, 내부 API를 호출하여, 실시간 검색 랭킹 데이터를 활용하였습니다.

  
  •    
  • 기술 

      사용 기술 
      *2차 프로젝트부터는 기술의 제한없이 기술을 선택하여 구현합니다.

      1차 프로젝트 때, 코드리뷰를 수정하며 추가했던 npm(패키지관리 모듈, package.json으로 관리)과 grunt(빌드 툴), handlebars, require.js를 적용 하였습니다.  JSP 대신 FreeMarker를 이용하였고, Backbone.js(MVC, model, view ,collection)를 사용해 보았습니다.

  •    
  • 개발   이글루스를 분석한 내용을 바탕으로 위에 기술된 기술을 가지고 SpringBoot로 개발을 진행하였습니다.

  •    
  • 개발 서버  개발 서버에 접속하여, 리눅스 기본명령어를 사용하였습니다.(저는 리눅스를 잘 못해서 조금 (많은) 도움을 받으며, 진행하였습니다.)

  •  
  

*배포 순서 
  war 파일 생성 -> 개발 서버로 복사 -> nohup을 이용한 백그라운드 실행 -> NginX 리로드(NginX 설정 파일을 생성은 미리)  (위 배포 방법은 실제 서비스 배포와 전혀 무관한 방식입니다.)


  

부딪혔던 문제

  

많은 문제가 있었지만, 기억에 남는 일부입니다. 

  
  •    
  • 이미지 LazyLoding이란?
  •  
  

문제는 아니였지만, 지금까지 생각해 보지 않았던 것이여서 추가해 보았습니다.(저에게는 신선한 충격..)

  

이미지를 LazyLoding하는 이유는 숨겨진 이미지를 미리 로딩하지 않고 이벤트가 발생했을 때, 이미지를 로딩하여   페이지 로딩 속도를 높이기 위해서 입니다.(저만 몰랐던것이죠..)

   처음에 제가 눈여겨 본것(당연히 구글링)은 jquery의 lazyload플러그인 이였습니다. 이벤트 발생했을 때 lazyload함수를 통해서 이미지를 로딩하는 방식입니다.   하지만, 페이지가 로딩될 때 jquery.load 플러그인을 추가로 로딩하기 보다는 아래와 같이 구현 하였습니다.(선임 님의 힌트를 덥석 받아 먹었습니다.)
 
    data-src에 이미지url를 저장

    이벤트가 발생했을 때, data-src의 주소를 src로 변경해주는 방법만으로 간단하게 구현 할 수 있었습니다.

  
  •    
  • 캐시냐? DB냐?

      캐시 : 반복적 && 고정적, (주기적으로 변하는) 배치성의 특징을 가지는 데이터, 결과값 계산이 오래걸리는 데이터
      DB : 자주 사용되지 않는 데이터, 최신 데이터(게시판)

  •    
  • 사고?치고 얻은 하이버네이트에서 POJO를 써야만하는 이유..

      하이버네이트를 사용하기 위해서는 테이블과 연결된 Domain이 존재해야 합니다.(저만 몰랐죠..)
      그리고 Domain에 담아온 데이터를 직접 가공하여 사용하다가 사고를 쳤습니다..(나중에.. 고해성사 했습니다.)
      Domain의 영속성 때문에 해당 객체와 연결된 테이블 값이 모두 변해 버린것이 문제였습니다.(복구함, 개발서버 DB여서 다행..실서버였으면..하하..끔찍)  사고를 친 이후 POJO를 이용해 Domain(다른 Domain과 Relation 관계를 맺고 있던)을 Transform하여 사용하였고, 영속성을 걱정할 필요없이 데이터를 마음껏 가공할 수 있었습니다.

  •    
  • static Util이냐? @Component냐?

      프로젝트를 진행하면서 Util성 클래스를 생성해야 했고, 어떻게 만드는 것이 좋은지 고민이 많이 되었습니다. 아래와 같이 정리 해보았습니다.

  •  
  

1) static Util      - 변함없는 단순 메소드로 사용할 경우     - JDK당? 하나를 만들어 공유할 경우

  

2) @Component(default : singleton)
      - 초기화가 필요한 경우(ex-@PostConstruct)     - DB 관련 작업이 있는 경우(@Autowired를 사용할 때)     - lazy 생성이 필요한 경우     - 좀 더 객체지향 구현을 원하는 경우     - IOC(스프링컨테이너) 당 하나를 공유할 경우

  

성능상 차이는 거의 없다고 합니다. 또한, 둘다 스레드 safe 입니다. static Util은 사용자가 객체를 생성하고, @Component는 IOC에 객체생성을 위임합니다(제어의 역전).  

  
  •    
  • 스프링 빈 초기화 문제
  •  
  

@PostConstruct를 여러 곳에서 사용하고, 서로를 참조했더니 IOC 빈 초기화 과정에서 의존성문제가 발생했습니다.
  처음에 접근 했던 방식은 순서를 지정해줘서 의존성 문제를 풀기 위해 노력했습니다.

  

제가 찾아낸 방법은 ‘@DependsOn’을 사용해 먼저 초기화 되야 하는 Bean을 명시해주는 방식이였습니다.

  하지만, 이렇게 명시적으로 순서를 정해주는 것을 남용하게 되면 또다시 의존성문제에 부딪힐 수 밖에 없기 때문에, 되도록이면 자연스러운 초기화 과정을 지키는 것이 좋다는 것을 알게 되었습니다.  
(결론적으로, 로직을 수정하여서 해결하였습니다.)

  

*@DependsOn : 해당 Bean 이전에 초기화되어야 하는 하나 이상의 Bean을 명시적으로 강제하기 위해서 사용.


  

마치며.

  

처음 시작하면서 말씀드린 것과 같이 3개월 동안 프로젝트를 진행하면서 저에겐 시간이 빛에 속도로 지나간 것 처럼 빠르게 지나갔습니다.

  프로젝트를 진행하면서 가장 크게 느낀점은 스스로 문제를 판단 할 수 있는 능력이 부족하다는 것이였습니다.
   앞으로 해나갈 프로젝트(삽질?)에서도 항상 왜? 라는 물음을 잊지 않고, 이를 통해 더 나은 개발자로 성장해 나가고 싶습니다.

  프로젝트 기간동안 소중한 시간(매우 소중한 2시간? 저 때문에 야근까지..)을 내어 코드를 리뷰해주시고 지도해주신 선임, 팀장 님께 감사드립니다.