About the Author

71 Posts By brientoh

  • Elbow fractures

    갑자기 낮에 첫째 아이 after school 에서 전화가 왔다. playground 에서 Kayla가 놀다가 철봉에서 떨어 졌다고… 헉. 정말 뒤도 돌아 보지 않고 달려 가니 주차장에서 아이들이 playground 에서 돌아와 하나 둘씩 내리고 있었다. 첫째가 날 보더니 울면서 걸어 왔다. 안아 주고 팔꿈치를 확인해 보니 다행이 심하게 다친것 같지는 않았다. 크게 부어 오르지도 않았고.

  • Daddy and Son Day

    오늘은 president day 로 첫째는 학교를 가지 않고 둘째는 preschool 을 가지 않는다. 대신 첫째는 after-school 에서 field trip을 가고 둘째는 오늘 아빠와 데이트 하기로 함! 그래서 도착한 곳이 Los Angeles County Museum of Natural History.

  • It’s a magic day!

    우리의 아침은 큰 변화가 없다. 엄마는 일찍일어나 큰 아이 점심 도시락과 아이들 아침에 간단히 먹을 것을 준비 한다. 그 동안 아빠는 아이들을 깨우고 씻기고 옷 입히고 학교 갈 준비를 한다. 아이들을 깨우는 일은 방에 불을 키고 음악을 트는 일로 시작한다. 처음엔 학교 갈 시간이라고 이야기 하며 잠을 깨우는데 이때 일어날 가능성은 정말 손 꼽을 정도. field trip을 가는 날이 아닌 이상 혼자 번쩍 일어 나거나 깨워서 바로 일어 나는 일은 드물다. 이때 부터 아빠의 아이들 깨우기 작전은 시작된다.

  • Raining day

    예전, 한때 나무 라는 인터넷 닉네임을 사용 하기 전 잿빛하늘 이라는 닉네임을 쓴 적이 있다. 우울해서 그런 이름을 사용 하였던 것은 아니었고 기억에 비가 내린 잿빛하늘 뒤맑게 개인 환한 하늘, 구름이 뭉게 뭉게 떠 있는 모습을 참 좋아했던 것 같다.

  • 바보 아빠

    얼마 전 딸아이를 after school 에서 픽업 하면서 차에서 있었던 일이다. 내가 무언가 실수를 해서 딸아이 한테 이렇게 이야기를 했었다.

    “아이구, 아빠가 바보 같이 깜빡 실수를 했네, 미안해 우리 딸, 아빠가 바본가 보다. 그런걸 잊어 버리고…”

    그랬더니 딸아이가 정색을 하면서 나에게 말을 했다.

  • Spring Boot – Using Logback

    Spring Boot 는 로그를 기록하는 의무적인 의존 관계가 없지만 Common Logging API, jcl-over-slf4j 을 기본적으로 가지고 있다. 여기서 알아 보려고 하는 Logback 의 경우 간단하게 spring-boot-starter-logging 을 maven 에 dependency 로 설정해 주면 된다. 하지만 이것 설정 없이도 web application 의 경우 spring-boot-starter-web 을 설정했을 경우 자동으로 Logback 을 사용할 수 있다.

    이렇게 하면 아래와 같이 Logback 관련 라이브러들이 classpasth에 들어 온것을 알 수 있다.

    이렇게 하고 간단하게  Spring Boot web application을 만들고 실행을 해 보자. 아래는 간단한 RESTFul 예 이다.

    이렇게만 하고 실행을 시키고 browser 를 통해 http://localhost:8080 을 실행해 보면 Hello World 가 뜰 것이고 Eclipse의 Console을 보면 아래와 같이 기본 로그가 출력이 될 것이다.

    아무 세팅도 하지 않고 단지 org.slf4j.Logger 을 이용하였는데도 로그 정보가 console 화면에 나타났다. 근데 debug를 제외 한 로그 정보들만 나왔다. 이유는 Spring Boot 어플리케이션을 실행 했을 경우에 Spring Boot JAR (내가 사용한 Spring Boot 1.4.2.RELEASE 버전에서는 spring-boot-1.4.2.RELEASE.jar) 파일 안에 있는 org.springframework.boot.logging.logback 안에 있는 base.xml 을 기본으로 사용 하고 있기 때문이다.

    위에서 보듯이 <root level=”INFO”> 로 하였기 때문에 INFO, WARN, ERROR 만 로그 정보로 출력이 되었다.

    이제 부터는 default 로그를 사용하지 않고 customized configuration 을 하는 방법을 알아 보자. 우선 먼저 application.properties 를 이용한 방법을 알아 보자. Spring Boot 을 사용할 때 application.properties 파일은 다양한 configuration 정보들을 설정하는데 유용하게 사용된다. 우선 resources 폴더 아래 application.properties 파일을 만들고 아래와 같이 간단히 log 설정을 해 보자.

    이렇게 하고 Spring boot 웹 어플리케이션을 다시 실행해 보면 console 에 아래와 같이 DEBUG 로그가 출력 된 것을 확인 할 수 있을 것이다.

    그리고 프로젝트 루트 폴더에 logs 가 생성된 것을 볼 수 있고 그 안에 spring-boot-logging.log 가 들어 있는 것을 볼 수 있을 것이다. 혹시 안보이면 포로젝트 루트 폴더를 Refresh 해 보면 된다. 그 안에 console 에서 보인 로그가 똑 같이 들어가 있음을 알 수 있다.

    대부분의 Spring Boot 어플리케이션의 경우 application.properties 에 logback 을 설정해 주는 것만으로도 문제가 없다. 하지만 규모가 큰 Application 에서 복잡한 logback 설정을 하기 위해서는 xml 파일을 이용한 설정을 해 준다. Spring Boot 에서는 class path 에 logback.xml 이나 logback-spring.xml 파일을 만들어 logback 설정을 하면 처음 로딩 될 때 해당파일을 읽어 로그 설정을 하게 된다.

    위와 같이 설정해 주면 application.properties 에서 해 주었던 설정의 결과와 같은 결과를 얻을 수 있다. 위에서는 appender 를 따로 설정 하지 않고 기존 base.xml 에 설정되어 있는 appender 인 CONSOLE 과 FILE 을 사용 하였다.

    자 이렇게 해 주었는데 사실 application.properties 에 logback file 을 어디에 저정할지 지정을 하지 않은 상태에서 위와 같이 logback-spring.xml 을 설정하게 되면 실제 파일이 어디에 저장되는지 알기가 쉽지 않다. 위의 설정은 logback 을 어떻게 이용하는 지 간단한 설명을 보여 주는 것이다. 이번에는 실제 production 에서 사용 할 수 있는 logback 설정을 해 보자.

    위에 쓰인 설정은 실제 production 에 사용 되어 지는 logback 설정과 같다. 단지 STDOUT appender는 실제 production 에서는 빼주면 된다. 여기서는 어떻게 로그가 기록되는지를 console 을 통해 보기 위해 설정을 했을 뿐이다.

    appender 를 사용하여 FILE 을 정의 하였다. FILE appender 의 경우 ch.qos.logback.core.rolling.RollingFileAppender class를 이용하여 30 일 동안 로그 history 를 가지고 있게 했다. 그리고 각각의 파일은 최고 10MB 를 넘지 못하게 하였고 이것을 넘을 경우 <timeBasedFileNamingAndTriggeringPolicy class=”ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP”> 와 <fileNamePath> 에서 _%i 를 써서 파일이 같은 이름일 경우 뒤에 숫자가 붙게 하였다. 즉 위의 로그를 이용하면 아래와 같은 로그 히스토리가 쌓이게 될 것이다.

    spring-boot-logging.log
    spring-boot-logging.2016-11-1.log
    spring-boot-logging.2016-11-1_0.log
    spring-boot-logging.2016-11-1_1.log
    spring-boot-logging.2016-11-1_2.log
    spring-boot-logging.2016-11-1_3.log
    spring-boot-logging.2016-11-2.log
    spring-boot-logging.2016-11-3.log

    지금 까지 Spring Boot의 logback 을 이용하여 Application log 를 기록 하는 방법에 대해 알아 보았다.

     

    *** Reference

    About Logback Appender: http://logback.qos.ch/manual/appenders.html

     

  • Spring Boot RESTFul Web Service Example – GET/POST/PUT/PATCH/DELETE

    예제에 앞서 REST 에 대한 정의는 Representational state transfer 이다. RESTFul을 이용하는 이유에 대해서는 굳이 설명을 하지 않아도 될 듯 하다. 간단히 내 생각을 이야기 하자면, 우선 cloud 가 아닌 단일 Web Application만 생각해 볼때 현재 개발 추세가 Back-end 의 중요성 보다는 Front-end 의 UI/UX 디자인의 비중이 좀더 커가고 있다. 예전에 그저 model을 던저 주고 JSP 에서 그 모델을 JSP 페이지 쪽에 던져 주어 content를 만드는 방법에서 이제는 Front-end 가 로딩 되어진 상태에서 asynchronous 방식으로 content를 서버쪽에서 받아와 보여주는 방식을 선호 하게 되었다. 이렇게 하여 우선 Front-end의 로딩 속도를 빨리 가져 갈수 있다. 머 사실 어찌 되었던 간에 Back-end 데이타 가져 오는 데 걸리는 시간은 같지만…. 그래도 페이지 전체가 먼저 보여 졌을 때랑, 그렇지 않고 back-end 데이타를 기다리는 동안 페이지르 볼 수 없는 것이랑은 느낌이 틀리니. 이런 이유로 RESTFul Web Service 의 비중도 커졌고 이에 대한 개발도 좀더 구체화 되었다.

    먼저 내가 사용한 개발 환경은:

    • Spring Boot 1.4.3.RELEASE (Spring Framework 4.3.5.RELEASE 가 사용 되어 진다.)
    • Java 1.7 version으로 세팅 (1.8로 해도 무난)
    • Postman – RESTFul 개발시 test 를 위해 사용 되어 지는 GUI 이다. Mac OS, Windows, Chrome browser 용으로 설치 하면 된다.
    • Eclipse

    자 그럼 시작에 앞서 아래 5가지의 HTTP request method type 들에 대해서 알아 보자.

    • GET – 데이타를 검색하여 해당 값을 받아 올때 사용한다. (CRUD 에서 Retrieve 할 때 사용)
    • POST – 새롭게 데이타를 생성 할 때 사용 한다. (CRUD 에서  Create 할 때 사용)
    • PUT – 데이타를 업데이트 할 때 사용 한다. (CRUD 에서  Update 할 때 사용)
    • PATCH – PUT 과 마찬가지로 데이타를 업데이트 할 때 사용하지만 PUT 과 달리 전체 Entity 데이타의 업데이트가 아닌 부분의 값을 업데이트 할 때 사용한다.
    • DELETE – 데이타를 삭제 할 때 사용한다. (CRUD 에서  Delete 할 떄 사용)

    이렇게 HTTP request method type 에 대해 Front-end 개발자와 Back-end 개발자 사이에 확실한 이해를 하고 넘어 가야 한다. 물론 Back-end 개발자의 경우 Front-end 개발자가 사용 할 수 있도록 정확한 문서를 제공해야 한다.

    먼저 아래와 같이 Eclipse 를 이용하여 sbrest 라고 하는 프로젝트를 만들고 pom.xml 을 설정하자.

    그러면 이제 Customer Entity 를 이용한 CRUD 를 하는 간단한 RESTFul 을 만들어 보자. 우선 아래와 같이 Customer entity를 만든다.

    Spring framework 4.0 이후 버전에서는 Entity class 에서 @Table annotation 을 사용 하지 않으면 기본적으로 class 이름과 같은 table 을 맵핑한다. 따라서 class 이름과 다른 table 이름을 사용 한다면 @Table(name = “tbl_customer”) 처럼 명시 하여 주어야 한다. 또 한 가지는 class의 property 들도 @Column annotation을 사용 하지 않는 다면 기본적으로 property 이름을 이용하여 table column 이름과 맵핑을 하게 된다. 위에서는 firstname과 lastname이 이 경우에 해당한다.

    다음으로 Spring Data JPA 를 이용하여 아래와 같이 간단하게 Repository 인터페이스와 Service 를 만들자.

     

     

    여기 까지 간단하게 Customer entity 에 대한 CRUD 오퍼레이션을 하는 Repository와 Service 를 만들어 보았다. 이제 RESTFul 을 만들어 보자. 개인적으로 @RestController 들을 따로 package를 만들어 관리를 하는 것을 선호 한다. 따라서 아래와 같이 rest package를  만들어 그곳에 Rest Controller 들을 정의 한다.

    위와 같이 RestCustomerConstroller.java 를 만들고 @RestController annotation을 설정 하여 Rest Controller를 만들었다. 먼저 GET/POST/PUT/PATCH/DELETE 를 이용한 Rest 코드 부터 하나 하나 알아 보겠다.

     

    GET – To retrieve data

    GET 을 이용 하는 경우는 Data를 검색할 때 사용 한다.

    위에서 보면 전체 customer list를 가져오거나 @PathVariable을 이용하여 customer ID 를 보내 특정 customer 를 검색하여 데이타를 받는 경우이다. method = RequestMethod.GET 을 @RequestMapping 에 정의 하면 된다. 리턴은 ReponseEntity<T> 클래스를 이용하여 검색이 되지 않았을 경우에는 HttpStatus.NOT_FOUND 를 넘겨 주고, 검색이 되었을 경우에는 검색한 결과 object을 HttpStatus.OK 와 함께 넘겨 준다. 이때 Spring 에서는 자동으로 jackson-databind 를 이용하여 JSON 포맷으 데이타를 넘겨 준다.

     

    POST – To create data

    POST 를 이용 하는 경우는 Data를 새롭게 만들 때 사용 한다.

    POST 는 새로운 Data를 생성 할 때 사용 하는 방법으로 method = RequestMethod.POST 로 설정을 해 준다. argument 들로 Customer 객체를 @RequestBody 를 이용하여 받아 왔다. Front-end 쪽에서 JSON 포맷으로 Customer 데이타를 보내 주면 된다. 이 떄 Front-end 개발자는 POST 이기 때문에 새로운 객체를 생성해야 하는 것으로 알고 데이타를 보내 주어야 한다. 두번 째 argument 로 UriComponentBuilder 를 설정 했다. 이유는 Customer를 생성하고 HttpHeaders 객체의 location 정보를 넣어 주기 위함이다. 이렇게 해 주면 Front-end 쪽 개발자는 새로운 데이타가 성공적으로 생성 (HttpStatus.CREATED) 되었을 경우 header 정보에서 location 값을 찾아 redirect 해 줄 수 있게 된다.

    위에서 보면 만약 새롭게 생성하려고 하는 데이타가 이미 존재 하는 경우라면 HttpStatus.CONFLICT를 ResponseEntity<Void> 를 통해 리턴해 준다.

     

    PUT –  To update data

    PUT 을 이용 하는 경우는 존재 하는 Data를 업데이트 할 때 사용 한다.

     

    PATCH – To update partial data

    PATCH 는 부분적이 Data를 업데이트 할 때 사용 한다. 즉 Front-end 쪽에서 객체 전체 업데이트가 아닌 부분만 업데이트 할 때 업데이트 하는 부분만 RESTFul 에 보내 준다. PUT 과 PATCH 는 공통적으로 update 할 때 사용 하지만 PATCH 가 부분 데이타를 업데이트 한다는 점에서 PUT 과 차이가 있다.

    위에서 method = RequestMethod.PATCH 를 설정해 주었고 업데이트 하려는 Customer의 ID와 Customer 객체를 받았다. 받은 Customer 객체의 경우 실제 업데이트 하려는 property 에만 값이 들어 있고 나머지는 null 이 들어 있게 된다. PATCH 가 성공적으로 되었으면 업데이트된 Customer 와 HttpStatus.OK 를 ResponseEntity<Customer> 에 넣어 보내 주고, 그렇지 않을 경우에는 HttpStatus.NOT_FOUND 를 넘겨준다. CustomerServiceImpl.java 의 patchCustomer 메소드를 참고 하기 바란다.

     

    DELETE – To delete data

    DELETE 를 이용 하는 경우는  Data를 삭제 할 때 사용 한다.

    method = RequestMethod.DELETE 를 이용 하고 성공했을 경우 ResponseEntity<Void> 에 HttpStatus.OK 를 넣어 주고 그렇지 않을 경우 HttpStatus.NOT_FOUND 를 넣어 넘겨주었다.

     

    지금 까지 RESTFul controller 를 개발 하는 방법을 설명 하였다. 아래는 최종 파일 이다.

    이렇게 하여 간단하게 Spring Boot 을 이용한 REST web application을 만들어 보았다.

     

    최종 프로젝트는 위와 같을 것이다. 자 그러면 이제 Postman 을 이용하여 위에서 만든 RESTFul web application을 테스트 해 보자. 아직 Postman을 설치 하지 않았다면 아래 사이트에 가서 각자의 환경에 맞게 다운 받아 설치를 하자.

    Postman

     

    TEST

    자 그러면 먼저 Spring Boot application을 실행 하자.

    그리고 이제 Postman을 실행 하자. 원하면 Sign up을 해서 자신이 test 한 것을 저장할 수 있다.

    먼저 Data 가 아무 것도 없으니 CREATE method 를 이용하여 생성 해 보자.

    위와 같이 POST 로 http://localhost:8080/customer 를 호출 하였다. 이때 Body 에는 javascript의 AJAX 를 이용하여 업데이트 한다는 가정으로 raw 와 JSON (application/json) 을 설정하고 JSON 데이타를 타입한 후에 Send 버튼을 눌러 호출 하면 된다. 이렇게 하면 아래 보는 것과 같이 Status: 201 Created 가 넘어 오는 것을 확인 할 수 있다. 다른 이름을 이용하여 하나 더 만들어 보자.

    그 다음으로 위에서 생성한 데이타를 검색해 보자.

    위에서는 http://localhost:8080/customer 를 GET 방식을 이용하여 Send 를 눌렀다. 그리고 나면 아래와 같이 Status: 200 OK 와 생성한 Customer 리스트를 볼 수 있다.

    위에서는 http://localhost:8080/customer/2 를 GET 방식을 이용하여 Send 를 눌렀다. 그리고 나면 아래와 같이 Status: 200 OK 와 id 값이 2 인 Customer 검색 결과가 리턴 된다.

    이번엔 PUT을 이용한 Update 이다.

    보는 것과 같이 Front-end 쪽에서는 객체 전체 데이타를 update 하기 위해 보내 주었다. 위와 같이 PUT으로 설정해서 Send 를 누르면 업데이트 된 결과 값이 Status: 200 OK 와 함께 넘어 온다.

    이제 PATCH 를 보자.

    위에서 보면 front-end 에서는 lastname 만 넣어 PATCH 를 이용하여 request를 보냈다. 이렇게 하면 back-end 쪽에서는 부분 업데이트로 알고 lastname 만 업데이트 해 주었다. 리턴된 결과를 보면 Status: 200 OK 와 lastname 이 업데이트된 JSON 데이타 결과 같이 넘어 왔다.

    마지막으로 아래 DELETE 를 해 보자.

    DELETE 를 이용 http://localhost:8080/customer/2 를 호출 하여보면 ID 가 2 인 Customer 가 삭제 되고 Status: 200 OK 가 넘어 왔다.

     

    이상 Spring Boot 을 이용한 RESTFul web service 를 만들어 보았다.

     

    ** DOWNLOAD this project

     

    ** Reference

     

  • [Angular2 – 8] Tour of Heroes – HTTP (final! – download final project)

    지금 까지는 HEROES 라는 mock data로 부터 heroes 를 받아 오는 구조였다. 이번 시간에는 HttpModule을 이용하여 직접 Web Service 를 호출 하는 방법에 대하여 알아 보겠다. 먼저 실제 어떻게 되는 지를 여기에서 확인해 볼 수 있다.

    아래와 같이 AppModule 에 HttpModule 을 사용 하기 위한 설정을 하자.

  • [Angular2 – 7] Tour of Heroes – Routing

    이번 포스팅은 Angular2의 Routing 이라는 것에 대해 알아 볼 예정이다. 아래는 Angular2에서 나온 Routing 에 대한 정의 이다.

    The Angular router is an external, optional Angular NgModule called RouterModule. The router is a combination of multiple provided services (RouterModule), multiple directives (RouterOutlet, RouterLink, RouterLinkActive), and a configuration (Routes).

    먼가 말이 좀 어렵긴 하지만 일단 그대로 해석해 보면

  • [Angular2 – 6] Tour of Heroes – Services

    지난 포스팅까지 여러 component 들을 사용 하는 것을 알아 보았다. Heroes 데이타를 직접 component 들에서 import 하여 사용 하였는데 실제 이런 방법은 효율성이 너무 적다. 물론 실제 PRODUCTION 개발에서도 일런 방법을 사용 하는 경우는 없다. 앞으로 Tour of Heroes 는 dashboard 를 만들고 메뉴도 만들고 하여 여러개의 다른 component 들이 존제를 하는데 이럴 때마다 data를 import 해서 쓰는것이 아닌 Service 를 통해 data 를 받아 사용할 것이다. 앞서에서 data를 import 해서 사용 한것은 어디 까지나 component 들의 사용을 설명하기 위한 것이 었다. 대부분의 실제 web application 의 경우에는 restful web service 를 이용하여 데이타를 주고 받는다.