토비의 스프링 부트 - 독립 실행형 스프링 애플리케이션-1

2023. 4. 17. 01:01·공부/Spring
반응형

출처 : 인프런

스프링 컨테이너 사용

기존 소스 코드 정리

  • FrontController의 로직 중 'else if~' 구문 삭제
  • HTTP Status Code 세팅 코드 삭제 (에러가 나지 않는 한 알아서 200 OK 코드가 붙어 나간다.) 즉, 생략가능
  • HTTP Header에 세팅한 Content-Type 부분 setContentType() 메서드로 변경. 이러면 header ID를 생략하고 값만 넣으면 됨
public class HellobootApplication {
   public static void main(String[] args) {
      TomcatServletWebServerFactory serverFactory = new TomcatServletWebServerFactory();
      // 다양한 서버 프로그램을 위한 추상화를 위해 WebServer
      WebServer webServer = serverFactory.getWebServer(servletContext -> {
         HelloController helloController = new HelloController();
         servletContext.addServlet("frontController", new HttpServlet() {
            @Override
            protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
               if(req.getRequestURI().equals("/hello") && req.getMethod().equals(HttpMethod.GET.name())) {
                  String name = req.getParameter("name");

                  String ret = helloController.hello(name);

                  resp.setContentType(MediaType.TEXT_PLAIN_VALUE);
                  resp.getWriter().println(ret);
               }
               else {
                  resp.setStatus(HttpStatus.NOT_FOUND.value());
               }
            }
         }).addMapping("/*");
      });
      webServer.start();
   }
}

 

스프링 컨테이너를 만들기 위해 helloController를 불러왔던 코드를 삭제하고 스프링 컨테이너를 사용한다.

public class HellobootApplication {
   public static void main(String[] args) {

      GenericApplicationContext applicationContext = new GenericApplicationContext();
      applicationContext.registerBean(HelloController.class); // bean 등록 끝
      applicationContext.refresh();

      ServletWebServerFactory serverFactory = new TomcatServletWebServerFactory();
      // 다양한 서버 프로그램을 위한 추상화를 위해 WebServer
      WebServer webServer = serverFactory.getWebServer(servletContext -> {
         servletContext.addServlet("frontController", new HttpServlet() {
            @Override
            protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
               if(req.getRequestURI().equals("/hello") && req.getMethod().equals(HttpMethod.GET.name())) {
                  String name = req.getParameter("name");

                  // 등록되어있는 bean을 가져와서 사용할 수 있음
                  HelloController helloController = applicationContext.getBean(HelloController.class);
                  String ret = helloController.hello(name);

                  resp.setContentType(MediaType.TEXT_PLAIN_VALUE);
                  resp.getWriter().println(ret);
               }
               else {
                  resp.setStatus(HttpStatus.NOT_FOUND.value());
               }
            }
         }).addMapping("/*");
      });
      webServer.start();
   }
}

 

서버 실행 후 테스트

 

 

 

의존 오브젝트 추가

스프링 컨테이너는 싱글톤 패턴과 유사하게 어떤 타입의 오브젝트를 한 번만 만들고 이를 계속 재사용하는 방식으로 동작한다. 그래서 스프링 컨테이너를 `싱글톤 레지스트리`라고도 한다.

SimpleHelloService.java 생성

public class SimpleHelloService {
    String sayHello(String name) {
        return "Hello " + name;
    }
}

 

HelloController.java 수정

public String hello(String name) {
    SimpleHelloService helloService = new SimpleHelloService();
    return helloService.sayHello(Objects.requireNonNull(name));
}

Objects.requireNonNull() 메서드의 경우 매개변수가 null인지 아닌지 판별해주며 Null일때는 NullPointException을 터트려주며, 아니면 예외 발생 없이 사용할 수 있는 메서드이다.

 

서버 재실행 후 테스트

 

 

 

의존 오브젝트 DI 적용

Refactor를 이용해 interface 생성

 

Interface name 변경 및 interface Member sayHello 선택 후 Refactor 버튼을 클릭하면 interface도 만들어지고 SimpleHelloService도 그에 맞게 소스 코드가 수정된다.

 

 

HelloService.interface 생성

public interface HelloService {
    String sayHello(String name);
}

 

 

SimpleHelloService.java 수정

public class SimpleHelloService implements HelloService {
    @Override
    public String sayHello(String name) {
        return "Hello " + name;
    }
}

 

 

HelloController.java 수정

public class HelloController {
    private final HelloService helloService;

    public HelloController(HelloService helloService) {
        this.helloService = helloService;
    }

    public String hello(String name) {
        return helloService.sayHello(Objects.requireNonNull(name));
    }
}

 

HelloService도 스프링 컨테이너에 Bean 등록을 해야한다.

HellobootApplication.java 수정

public static void main(String[] args) {

   GenericApplicationContext applicationContext = new GenericApplicationContext();
   applicationContext.registerBean(HelloController.class); // bean 등록 끝
   applicationContext.registerBean(SimpleHelloService.class);
   applicationContext.refresh();
   
   // ... 생략

 

서버 재실행 후 테스트

 

 

 

DispatcherServlet으로 전환

기존 서블릿 등록했던 코드 모두 삭제 후 DispatcherSerlvet 추가

public class HellobootApplication {
   public static void main(String[] args) {

      GenericWebApplicationContext applicationContext = new GenericWebApplicationContext();
      applicationContext.registerBean(HelloController.class); // bean 등록 끝
      applicationContext.registerBean(SimpleHelloService.class);
      applicationContext.refresh();

      ServletWebServerFactory serverFactory = new TomcatServletWebServerFactory();
      // 다양한 서버 프로그램을 위한 추상화를 위해 WebServer
      WebServer webServer = serverFactory.getWebServer(servletContext -> {
         servletContext.addServlet("dispatcherServlet",
               new DispatcherServlet(applicationContext)
               ).addMapping("/*");
      });
      webServer.start();
   }
}

 

서버 재실행 후 테스트하면 404 에러가 발생한다. DispatcherServlet 까지는 요청이 잘 들어오는데 그 이후에 알맞은 컨트롤러로 보내기엔 정보가 부족하기 때문이다. 

 

 

 

애노테이션 매핑 정보 사용

HelloController.java 수정

@RequestMapping("/hello")
public class HelloController {
    private final HelloService helloService;

    public HelloController(HelloService helloService) {
        this.helloService = helloService;
    }

    @GetMapping
    public String hello(String name) {
        return helloService.sayHello(Objects.requireNonNull(name));
    }
}

 

서버 재실행 후 테스트하면 404 에러가 여전히 발생한다. hello() 메서드도 잘 호출했고 helloService의 sayHello() 메서드도 잘 호출했을 것이다. 문제는 `return 타입`이다. DispatcherServlet은 return 타입이 String이면 `view`라고 불리는 HTML 템플릿을 찾아 view를 return해주라라는 기본 동작 방식 때문이다. 그렇기 때문에 String으로 리턴하려면 view가 아닌 text라는 걸 알려주기 위해 `@ResponseBody`라는 애노테이션을 추가로 붙여주면 된다.

@GetMapping
@ResponseBody
public String hello(String name) {
    return helloService.sayHello(Objects.requireNonNull(name));
}

 

서버 재실행 후 테스트

 

 

 


- 출처 : 인프런 토비의 스프링부트 - 이해와 원리 강의

반응형
저작자표시 비영리 변경금지 (새창열림)
'공부/Spring' 카테고리의 다른 글
  • 토비의 스프링 부트 - DI와 테스트, 디자인 패턴
  • 토비의 스프링 부트 - 독립 실행형 스프링 애플리케이션-2
  • 토비의 스프링 부트 - 독립 실행형 서블릿 애플리케이션
  • 토비의 스프링 부트 - 스프링 부트 시작하기
데부한
데부한
어차피 할 거면 긍정적으로 하고 싶은 개발자
    반응형
  • 데부한
    동동이개발바닥
    데부한
  • 전체
    오늘
    어제
    • 분류 전체보기 (307)
      • 방통대 컴퓨터과학과 (27)
        • 잡담 (9)
        • 3학년1학기 (17)
      • 프로젝트 및 컨퍼런스 회고 (1)
        • 프로젝트 (4)
        • 한이음 프로젝트 (0)
        • 회고 (3)
      • 공부 (165)
        • Spring (37)
        • JPA (71)
        • 인프런 워밍업 클럽_BE (10)
        • Java (6)
        • React.js (27)
        • 넥사크로 (11)
        • 기타 (3)
      • 알고리즘 (85)
        • 알고리즘 유형 (10)
        • 알고리즘 풀이 (57)
        • SQL 풀이 (18)
      • 에러 해결 (13)
      • 잡담 (7)
        • 국비교육 (2)
        • 구매후기 (5)
        • 진짜 잡담 (0)
  • 블로그 메뉴

    • Github
    • Linkedin
    • 홈
    • 방명록
    • 글쓰기
    • 관리
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    RESTful
    에러해결
    IT
    springboot
    JPA
    개발자
    토이프로젝트
    인프런
    Spring
    기출문제
    oracle
    프론트엔드
    백준
    react
    egov
    자바스크립트
    QueryDSL
    방통대
    프로그래머스
    Java
    SQL
    토비의스프링부트
    코딩테스트
    운영체제
    전자정부프레임워크
    스프링부트
    SpringBoot를 이용한 RESTful Web Service 개발
    알고리즘
    MSA
    넥사크로
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
데부한
토비의 스프링 부트 - 독립 실행형 스프링 애플리케이션-1
상단으로

티스토리툴바