12주차. SpringBoot와 MVC 패턴(1)

박서영·2025년 11월 20일

Spring과 SpringBoot

스프링(Spring)

  • 자바 기반의 강력한 웹 애플리케이션 개발을 위한 오픈소스 프레임워크
  • 설정이 복잡함 -> 그래서 등장한 것이 스프링부트(SpringBoot)

스프링부트(SpringBoot)

  • 복잡한 설정 없이 간편하게 시작할 수 있는 스프링 프로젝트 템플리
  • 스프링 프레임워크를 기반으로 하지만 복잡한 XML 설정 없이 어노테이션(Annotaion) 기반으로 더 빠르고 직관적인 개발이 가능함
  • 스프링부트를 통해 Rest API 구현

+) XML: 데이터를 저장하고 전송하기 위한 확장 가능한 마크업 언어
(현재는 XML이 아니라 JSON을 통해 더 편하게? 데이터 전송이 가능한듯)
어노테이션(Annotation): @Service, @RequestParam

REST API

  • REST: 웹에서 데이터를 주고받기 위한 표준화된 아키텍쳐 스타일, HTTP 프로토콜을 기반으로 하며, 자원을 기반으로 데이터를 교환하는 방식
    => GET, POST 같은 HTTP 메소드 + URL을 규칙대로 잘 쓰자는 느낌..?
  • REST API: REST 원칙에 따라 설계된 웹 기반의 API

스프링부트 개발환경 세팅하기

스프링부트 프로젝트 생성

이클립스에서는 Eclipse Marketplace에서 스프링 관련 툴(STS4 SpringToolSuit)를 설치해서 IDE에서 스프링부트 프로젝트를 생성할 수 있는 것 같지만, IntelliJ IDE를 사용하고 있기에 Spring Initializer를 써서 스프링부트 프로젝트를 만들어주었다. (IntelliJ Ultimate을 쓰면 아래 사진처럼 IDE에서 바로 스프링 프로젝트를 만들 수 있긴 하다...)


우선 Spring Initializer는 아래처럼 생겼다.

해당 화면에서 아래 처럼 선택해서 세팅을 해줬다.

타입: Gradle-Groovy
언어: Java
Packaging: Jar
Configuration: properties
SpringBoot Version: 4.0.0(SNAPSHOT)
Group: kr.ac.ewha.java2
Package name: kr.ac.ewha.java2


의존성은 일단 Spring Web을 선택.

Generate을 누르면 파일을 받을 수 있다.

해당 파일을 인텔리제이 IDE에서 열어주면 우선 스프링부트 프로젝트 생성이 끝난다.

스프링부트 프로젝트 구조

src 디렉토리: 일반 자바에서 쓰던 소스코드? 위치하는 곳

  • 안에 maintest 디렉토리 존재
  • test는 웹 페이지 테스트?(코드로 작성한 화면 테스트 등등..)할 때 사용
  • kr.ac.ewha.java2.demo: 앞에 spring initializer에서 설정한 group/package명.
    => google.com 이면 com.google 인것처럼 도메인을 역순으로 표기하는 것..

resources 디렉토리: 웹페이지의 프론트엔드 관련 요소 존재

  • css/html 등의 파일 존재
  • application.properties 파일(설정 파일) 존재

build.gradle: 기억하는바에 따르면 여기에서 의존성 추가하거나, initializer에서 설정한 설정을 보고, 수정할 수 있다.


SpringBoot 기본 어노테이션(Annotation)

  1. @SpringBootApplication: 애플리케이션의 시작점.
  2. @RestController: JSON 등 REST API 응답을 반환하는 컨트롤러로 선언
  3. @GetMapping, @PostMapping: HTTP 메소드 중 각각 GET, POST 요청을 처리하는 메소드에 사용
  4. @PathVariable: URL 경로 내에 있는 변수를 가져올 때 사용한다
  5. @Autowired: 스프링이 자동으로 빈(Bean)을 주입해주는 의존성 주입(DI) 어노테이션
  6. @RequestParam: 쿼리 파라미터나 폼데이터를 받아올 때 사용
  7. @Component: 스프링의 빈(Bean) 등록의 기본형태로, 다른 어노테이션의 상위 개념
  8. @Service: 서비스 계층을 나타내는 component

+) 빈(Bean): 스프링 컨테이너에서 관리하는 자바 객체...
+) 스프링에서 컴포넌트/빈/ 이런식으로 어노테이션을 쓰면 다 스프링 컨테이너에서 관리하는 객체로 들어가고, 필요한데에서 알아서 주입(autowired) 되는...? 느낌으로..우선 이해했다...

REST API 컨트롤러

REST 핵심 원칙

1. 클라이언트-서버 구조: 클라이언트와 서버는 명확히 역할에 따라 분리됨
2. 무상태성(Stateless): 서버는 요청 간의 상태를 저장하지 않음. 즉, 각 요청은 독립적 - 이전 요청의 영향을 받지 않음
3. 캐시 가능(Cacheable): 서버 응답은 캐시될 수 있어야함 => 불필요한 요청 감소
4. 계층화된 시스템: 클라이언트가 여러 계층의 서버를 거칠 수 있으나, 서버 내부의 구조, 존재유무를 몰라도됨.
5. 일관된 인터페이스: 모든 리소스는 일관된 방식으로 접근함
예) HTTP 메소드(GET, POST, PUT, DELETE)

SpringBoot의 핵심원리

의존성 주입(DI)

  • 외부(프레임워크)에서 의존 객체를 전달(주입) 받는 방식으로 의존성 관리를 프레임워크가 대신해주는 방식
  • @Autowired 어노테이션을 통해 주입, 생성자에서 주입, Setter를 통해 주입 등

제어의 역전(IoC)

  • 객체의 생성부터 생명 주기 관리까지 모든 것을 개발자가 아닌 프레임워크가 대신하는 원리
    - 개발자는 필요 기능만 정의 -> 나머지는 스프링에 맡김
    • DI는 IoC의 구현방식 중 하나

자동구성(Auto Configuration)

  • 어플리케이션 설정을 자동으로 구성함
  • @SpringBootApplication 안에 자동구성을 활성화하는 EnableAutoConfiguration이 있음
  • 클래스 경로와 Bean 설정, 속성들을 기반으로 적절한 설정을 자동으로 적용
    -Spring Bean: 스프링 컨테이너가 관리하는 객체로 기본적으로 싱글톤
    - @Component, @Service, @Repository, @Controller 등으로 등록

실습하기

웹 어플리케이션 실행하기(1): 데이터 웹페이지에 띄우기

스프링부트는 @SpringBootApplication 이 어노테이션을 먼저 찾아서 실행시킨다.

위와 같은 형태이고, 위치는 아까 본 src->main->java->kr.ac.ewha.java2.demo에 있다. 이를 실행하면 아래의 화면처럼 콘솔이 뜬다.

RestController 어노테이션 사용하기
MVC의 컨트롤러를 사용해 JSON 파일(?)같은 데이터를 반환해 웹 페이지에 띄울 수 있다.

package kr.ac.ewha.java2.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @RequestMapping("/web")
    public String hello() {
        return "/web 페이지 테스트";
    }
}

코드는 위와 같은데 @RequestMapping 어노테이션은 ~/web이라는 URL의 요청이 들어왔을 때, 아래와 같은 메소드를 실행시키겠다..?는 의미인 듯 했다. 여기서는 로컬 호스트 주소인 127.0.0.1:8080/web을 치게되면 의도한대로 반환한 "/web 페이지 테스트"라는 문자가 보여야한다.

다행히 생각한대로 나왔다. :D
+) Request가 HTTP의 메소드 GET, POST를 둘 다 포함하는 느낌인 것 같았다..

웹 어플리케이션 실행하기(2): 웹페이지에 html(정적 웹페이지) 띄우기

우선 스프링부트 프로젝트에서는 html 파일이 놓여지는 위치가 정해져있다. 지금 만드는 html 파일은 resources 디렉토리의 statics 디렉토리 내에 만들어준다. (html 파일 이름은 index.html, 보통? 이게 메인/홈의 페이지 이름이 되는 것 같았다...)

여기에 두면, 딱히 아무 코드를 작성하지 않아도 스프링부트가 알아서 index.html을 해당 위치에서 찾아서 메인?(=URL에서 주소, 포트만 적고 아무것도 적지 않은 페이지), 즉, '/'의 URL이 요청될 때 띄워준다.)

<!DOCTYPE html>
<html lang="kr">
<head>
    <meta charset="UTF-8">
    <title>홈페이지</title>
</head>
<body>
    <h2>테스트용 홈페이지</h2>
</body>
</html>

HTML 코드는 위에처럼 대충 테스트용으로 적어줬고, 그 결과 아래처럼 페이지가 나왔다.

웹 어플리케이션 실행하기(3): URL에서 데이터 받아오기

@PathVariable을 사용해 URL에서 데이터를 받아와보는 내용으로 코드를 작성하고 테스트했다.

HelloController.java 파일의 코드

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class HelloController {
	...

    @GetMapping("/user/{name}")
    public String getUserName(@PathVariable("name") String name) {
        return "어서오세요 "+ name+"님!";
    }
}

@PathVariable은 URL 경로에 들어온 {name}의 값과 매칭되고, 변수에 저장된다.
@ReqeustMapping은 클래스 단위에도 적용될 수 있으며, 이 경우 HelloController 내에서 매핑되는 URL들은 앞에 /api가 붙는 느낌이다.
예) .../api/user/{name}

웹 어플리케이션 실행하기(4): 웹페이지에서 데이터 받오기

GreetingService.java 파일

@Service
public class GreetingService {
    public String getGreeting(String name) {
        return "어서오세요! "+name+"님. 좋은 하루 보내세요 :D";
    }
}

GreetingController.java 파일

@RestController
public class GreetingController {

    @Autowired
    private GreetingService greetingService;
    
    @PostMapping("/hello")
    public String sayHello(@RequestParam(name="name") String name){
        return greetingService.getGreeting(name);
    }
}

GreetingService를 개발자가 직접 주입(생성자/Setter로)할 필요없이 스프링 컨테이너에서 해당 서비스를 관리할 수 있게 @Service 어노테이션을 적어주었으니, 자동으로 주입해준다.
=> 의존성 역전 (IoC): GreetingService 객체를 새로 만들지 않고 스프링에서 제어함

@Autowired: 객체를 직접 주입할 필요없이 자동으로 주입됨
=> 의존성 주입(DI): GreetingService를 자동으로 주입해줌



복습: MVC 패턴 & Spring MVC

사용목적

  • 사용자 인터페이스와 데이터, 처리 로직을 명확히 구분할 때
  • 화면, 로직, 제어흐름에 따라 역할별로 협업할 때

Spring MVC

  • 핵심: DispatcherServlet: 프론트 컨트롤러 역할. 모든 클라이언트의 요청을 가장 먼저 받아서, 어플리케이션 내부의 적절한 컨트롤러에게 작업을 분배해줌 (=총괄 지휘)
  • 컨트롤러(Controller) <-> 서비스(Service) <-> 레포지토리(Repository) <-> DB(데이터베이스)

프로젝트 구조 예시

  • controller: 요청 처리 (@RestController)
  • service: 비즈니스 로직 (@Service)
  • dto: 모델. 요청/응답용 데이터 객체
  • repository: DB 접근 (@Repostiory)
  • domain: JPA Entity(@Entity)
  • config/: 설정 클래스 (@Configuration)

의존 방향

예)

  • Controller가 Service에 의존: 컨트롤러 안에 서비스를 필드로 가지고, 이를 사용함.

소감
이전에 스프링 조금 해보면서 잘 이해가 안가던 내용이 이해가 되어서 좋다...
이전에는 잘 이해가 안돼도 일단 책 내용 따라 치기만한 느낌이라면 현재는 어노테이션 쓰는 이유? 목적?을 알 것 같아서 사실 외울 필요없이 뭔가 이해가는 느낌이라..? 좋은 것 같다.
구조나 어노테이션은 조금..? 감이 오는 것 같고, 의외로 매핑하는게 재밌는 것 같다. 데이터 주고받는건 익숙해지려면 몇 번 더 해봐야할 것 같지만, 그래도 이전보다 훨씬 잘 이해한 것..? 같다...ㅎㅎ
그래도 아직 약간 각 부분 간의 관계나 의존성은 헷갈리는 것 같다. 이건 프로젝트하면서도 느낀건데 약간 어떤걸 필드로 가지고 있어도 될 지 이런 의존성 설정?하는 게 헷갈리는 것 같다.

profile
이불 밖은 위험해.

0개의 댓글