Spring boot camp #2

JSP & Servlet

  • Spring MVC
    • 내부적으로는 Servlet, JSP를 사용
    • 따라서 Spring을 사용하기 위해서는 Servlet, JSP에 대한 이해를 해야 함
  • 응집도의 개념이란 관련된 기능을 하나의 class가 모아 지니고 있는 것
  • Spring Framework를 이용하는 spring boot
    • 따라서 Spring에 대한 이해를 하는 것이 좋음
    • Spring boot를 사용하면 설정해주지 않아도 되는 부분드리 많지만, 현업에서 이미 Spring으로 작성된 프로젝트를 관리해야 할 일들도 많이 있기 때문
  • Java 웹프로그래밍의 시작, Servlet & JSP

    • Servlet 3.0 이전에는 web.xml 설정을 해주어야 함
      • 하나의 path 설정하는 것이 하나의 servlet
      • 결국, 응집도가 떨어지는 결과 -> 문제
    • 3.0 이후부터는 annotation을 이용해서 path 설정
    • JSP는 HTML code와 Java code를 섞어서 작성하는 것
      • 서버에서 JSP가 java code로 바뀜
        • <h1>hello</h1>이라는 HTML line이 out.write("<h1>hello</h1>")로 변환되는 것
        • 즉, out이라는 Java 변수가 위에 선언되어야 하는 것 -> JSP 내장 객체
      • 근래에는 Java code 잘 사용 안하려고 함
        • 유지보수 어려워지기 때문
      • JSTL과 EL로 결과값만 출력하자! 는 것이 대세
  • Servlet의 구성

    class 'servlet_name' extends HttpServlet{
      doGet()
      doPost()
      Service
      ...
    }
    



After JEE Pattern

  • Java로 기업급에서 프로그래밍을 할 때는 이러한 패턴을 사용하자!
  • Front controller도 그 JEE Pattern 하나

    • browser가 하는 모든 요청을 이 놈이 받도록 함
    • Servlet으로 작성할 수도, JSP로 작성할 수도, ServletFilter로 작성할 수도 있음
  • Spring MVC는 Servlet으로 Front Controller 만듬

    • Spring MVC의 DispatcherServlet이 Front Controller의 역할 수행
    • 즉, Spring MVC의 life cycle이 궁금하다면 DispatcherServlet을 공부해야 함!
      • WAS가 DispatcherServlet을 메모리에 올려주는 역할 수행
        • 1) web.xml에 등록(143.p)
          • 배포를 1초라도 빨리하려면 web.xml에 DispatcherServlet 등록해주는 것이 좋음
          • 명시적인게 빠르기 때문
        • 2) 서블릿 3.0 이상에서는 ServletContainerInitializer 인터페이스 사용 -> WAS용 Java config
        • 3) but, Spring 쪽에서는 모든 객체를 Spring 쪽에서 관리해주고 싶어함
          • WebApplicationInitializer 인터페이스 구현해서 사용 -> Spring용 Java config
          • Servlet 인터페이스를 보고 Spring interface를 확인하기 때문에 배포 속도가 가장 느림
    • DispatcherServlet은 내부적으로 WebApplicationContext(Bean Container)를 지님
  • Front Controller는 관련된 url 요청들을 분배하는 역할을 수행하게 됨

    • 관련된 url을 처리하는 객체를 Spring MVC에서는 'xxx'Controller라고 부름
      • cf.명령을 처리한다는 개념에서 Command Pattern이라고 부르기도 함
    • 프로그래머가 만들고 Spring이 관리해주는 객체
    • @Controller 혹은 @RestController 라는 annotaion이 붙어있어야 함
    • Web에 종속적인 기술
      • UI에 따라 사용되지 않을 수도 있는 것
    • Spring containter가 Component scan을 통해 annotation 붙어있는 객체들 찾음
      • 다 Bean으로 등록해줌
      • Bean이란 Spring이 관리해주는 객체
    • 공통적으로 처리되는 부분들은 객체 하나를 사용해서 중복되게 사용되도록 사용할 수 있음
      • 'xxx'Service라 불리우는 객체 !
      • 즉, 하나의 Controller가 여러 개의 Service를 사용하도록 하는 것 ! (중복된 기능을 제공하기 위해서)
      • @Service annotation 사용
      • Service 안에서 또 중복된 기능을 사용
        • 대개, CRUD 기능이 중복된 코드일 가능성이 높음
        • 이러한 기능을 Repository 혹은 DAO라고 부름
        • @Repository annotation 사용
  • 이처럼 FrontController-'xxx'Controller-'xxx'Service의 계층으로 나뉘어져 구성되기 때문에 'Layered Architecter' 라고 부름

  • Service와 Repository는 별도의 ApplicationContext 필요 (Business Logic 관리하기 위해)

    • Service와 Repository에 해당하는 객체만 관리해줌
    • WebApplicationContext은 Service와 Repository 객체를 사용하기 위해 ApplicationContext를 부모로 가짐(141.p)
    • 자식 container는 부모 container로 부터 객체 먼저 찾음
      • 부모가 가지고 있는 Service를 자식의 Controller에 넣어주게 됨
    • 중요한 것은 Context 간에 부모-자식 관계가 있을 수 있다는 것
  • 경우에 따라서 DispatcherServlet을 여러 개 선언할 수도 있음

    • /board를 1번 Dispatcher가,
    • /users를 2번 Dispatcher가 관리하도록 함
    • 따라서 WebApplicationContext도 2개 생성됨
      • Container를 따로 사용하기 때문에 1번 Dispatcher에서의 객체를 2번 Dispatcher에서 사용 불가
        • 마치 한 서버에 있지만, 두 서버에 있는 듯한 느낌
        • 나중에 Micro service 단위로 분할하기 편하게 하기 위해 사용하는 경우가 있긴 하나 잘 사용되지는 않는 기법



Controller

  • Controller의 예
@Controller
@RequsetMapping("/board")
class test{
    @RequsetMapping("/list")
    static void testmethod(){
        ...
    }
}
  • Spring 4.3 버전 이후부터 RequestMapping 외 GetMapping, PostMapping, PutMapping 등도 등장
  • class의 mapping 정보와 method의 mapping 정보가 결합된 것이 실제 url 주소
  • Controller를 url을 처리해준다하여 Handler라고도 부름
  • HandlerMapping이라는 객체가 존재하여, url 관리
    • 어떤 Controller의 method와 관련이 있다는 정보들을 저장
    • 즉, 내부적으로 DispatcherServlet의 관리해주는 것
    • 유효한 요청을 받았을 시, HandlerAdapter로 보내 실행
      • Controller method는 보통 View 이름 return
        • ModelAndView 혹은 String 객체로 return
  • HTTP header에는 accept 정보 존재
    • browser가 원하는 data format(ex. html, json, xml...)
  • ViewResolver는 어떤 view를 보여줄지에 대한 전략을 세워줌
    • 경로 작성해주고, data format 찍어주어 view 생성하여 return
      • ex) WEB-IMF/views... + /list + .jsp
    • ViewResolver도 여러 개 존재해서, 요청한 data format에 따라 다르게 처리 가능
    • Java config에서 default 값들 설정해주면 됨
  • DispatcherServlet과 Controller 사이에 Interceptor 여러 개 존재할 수 있음
    • 모든 요청에 대해 공통으로 처리해줄 수 있음
    • Dispatcher 앞에 존재할 수 있는 ServletFilter와 유사한 역할 수행



실습

  • Lombok 적용: Preference -> Compiler -> annotation processor -> enable annotation processing
  • @Configuration 붙어있는 class들은 Java config
  • @ConditionalOn이 붙어있는 annotation은 중요한 annotation
    • ex) ConditionalOnMissingBean
      • 사용자가 AutoConfig 사용하지 않고 Bean 직접 생성했을 때 자동 설정을 사용하지 않겠다는 설정
  • spring.factories에서 기본 설정 확인 가능
    • dispathcer servlet 생성해줌
    • MultipartResolver는 file upload용
  • Spring 구버전의 @RequestMapping(method = RequestMethod.GET)가 GetMapping이 됨
  • Spring에서 JSP로 결과 출력하려면 JSTL 의존성 추가해주어야 함
    • tomcat에 기본적으로 포함된 것이 아니기 때문
    • pom.xml과 application.properties에 다음 설정 추가
// pom.xml
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>

// application.properties
spring.mvc.view.prefix= /WEB-INF/jsp/
spring.mvc.view.suffix= .jsp
  • http://www.inven.co.kr/board/{game name}/{board id}
    • 위 예에서 'game name'과 'board id'는 Path variable
  • http://www.inven.co.kr/board/{game name}/{board id}/?sort=PID&p=1

    • 위 예에서 ? 이하의 값은 Request Parameter
    • 이름=값&이름=값 의 형태로 전달
  • 내가 입력한 값들을 저장해야 하는 서버

  • 이전 입력 값들에 대한 parameter를 계속 가지고 다녀야 함
  • form 도 requestParam으로 읽어올 수 있음

  • redirect?

    • 요청을 하는 WebClient와 요청을 받는 WAS의 존재를 가정
      • form을 POST 방식으로 입력
      • HTTP message에는 POST /boards 방식 명시되고, header 정보 이후 body 부분에 user가 입력한 값이 실림
        • 1) @RequestParam으로 입력 값 읽어드릴 수 있고,
        • 2) form의 입력 값이 너무 많을 시, @ModelAttribute 사용
          • @ModelAttribute Board board와 같이 정의
          • set으로 값 채워넣음
          • +) 값을 validate하는 기능 필요
            • 값이 잘못되어있으면 다시 입력하라는 메시지와 함께 이전 정보들 재전송
            • hibernate에 검증 기능 구현
  • Forward vs. Redirect
    • viewname을 return하는 방식은 다 forward
      • forward와 밀접한 관련이 있는 것이 RequestScope
        • 요청 정보는 해당 정보와 관련있는 JSP까지 전달됨
        • SetAttribute로 Request에 값을 담고, GetAttribute로 값을 꺼냄
      • JSP는 RequestScope에서 정보를 꺼내서 결과 출력
    • redirect는 view를 생성하지 않고, browser에게 redirect하라는 명령 (status code: 302)
      • browser는 redirect하라는 주소로 다시 요청보냄
      • 최종적으로 redirect 주소 정보를 받아와 읽게 됨
    • redirect를 할 때도 정보 전달 가능 -> RequestParam을 통해
      • 그러나, header 길이의 한계로 큰 data는 redirect로 전송이 불가능함
      • Spring MVC의 FlashMap 객체 이용해 정보 저장 가능
      • 이후, distpatcherServlet이 FlashMap의 정보를 꺼내서 browser에 제공
      • 해당 FlashMap 정보는 1회용 !
  • @RequestBody와 @ModelAttribute 혼동하지 말자!

    • @RequestBody는 body에 JSON과 같은 데이터 넘어올 때 사용
      • 내가 보낸 정보를 저장해라!
    • body가 form data 형식으로 넘어오면 @ModelAttribute 사용
  • 반환할 객체에 값을 자동으로 채워넣어주는 ArgumentResolver

    • 먼저, 내가 지원하는 type인지를 검사
      • true이면, 해당 객체를 생성
    • Controller method에 객체를 반환해줌
  • Interceptor를 구현하여 값을 검사하거나, 삭제하거나, 검증하는 등의 기능을 구현할 수도 있음
    • 보안 관련된 기능을 구현할 때 용이
  • 작성한 ArgumentResolver와 Interceptor는 Java config에 등록을 해주어야 사용 가능
    • Spring MVC가 읽어들이는 설정에 ArgumentResolver와 Interceptor를 등록해주어야 함
    • ex) WebMvcConfigurer를 구현한 Config class에 두 객체를 모두 등록하여 사용



etc

  • 잘 만들어진 객체는 보는 것만으로도 공부가 됨
    • 내가 객체를 작성해야 할 때 참고하기도 좋음
  • 기술면접에서 화이트보드 면접이 잦아짐
    • 그림 그리면서 설명하는 것이 수월할 것
  • 모든 Web의 기본은 게시판!
  • 프로젝트 주제를 신중하게 정하자
    • 본인이 계속 운영하고 싶은 페이지를 만들어라!
    • open source로 만들어 계속 version up
    • 이후, 이직 과정에서 포트폴리오로 사용할 수 있음
    • Why? 내가 사용하지 않는 코드는 version up이 되지 않음
    • 또한 개발이 50%라면, 운영 역시 50% 만큼의 능력을 요함
  • Paper Prototyping을 하자!
    • 웹 페이지 어떻게 구성될 것인지 detail하게 그려가며 구상
  • 디자인에 신경을 쓰지 않더라도, 최소 bootstrap 정도는 이용하는 것이 좋음
  • 앞으로는 Java 8을 공부해야 함
    • Stream, lambda 등의 신규 문법 숙지!
  • 절대로 운영중인 서버에는 sysout 사용하지 마라
    • 성능이 엄청 떨어짐
    • 대신, logger 객체를 이용해야 함
  • 어느 한 interface가 있고, 다른 class에서 해당 interface를 구현해야 함
    • 이 인터페이스의 모든 기능을 구현하지 않고, 필요한 기능만 구현하고 싶다면?
    • ex) 사용자가 MyInterface만들었고, 해당 인터페이스가 메소드를 5개 가지고 있음
      class MyBean implements MyInterface{
      5개의 메소드 구현해야 함
      }
      
  • 이전에는 이러한 불편함 해결하기 위해 Myinterface를 구현한 MyAdapter라는 default 클래스 제공
    • 해당 interface의 method들을 구현하고 있지만, 내용은 없음
class MyAdapter implements Myinterface{
    ...
    ... 
}

class MyBean extends MyAdapter{
    필요한 것만 Override해서 사용!
}
  • jdk 8부터는 default method 기능 추가됨
    • 이제 interface도 method 구현이 가능해짐!
    • Why? Framework 측에서 제공하는 interface에 method 추가하고 싶은데,
    • 이미 framework를 사용하고 있는 수 많은 프로젝트들 때문에 함부로 추가하지 못함
    • 함부로 method의 갯수를 늘리면 모든 프로젝트가 에러나게 생김
    • default로 구현된 method를 추가하여 배포하면 문제없이 사용할 수 있게 될 것이라는 개념에서 비롯됨


+ Recent posts