설치
spring.io 접속
projects > spring initializr > 설정 후 Generate 를 눌러 다운로드
아래 경로의 파일을 열고 실행해 본다.
다음 주소를 입력한다. > http://localhost:8080/
프론트엔드 vs 백엔드
Java는 Node.js 를 쓰기 위해 사용하는 게 일반적임.
REST API 란?
- 클라이언트와 서버가 데이터를 주고 받는 약속된 방식
- HTTP 요청방식:
- GET(받기), POST(보내기), PUT(수정하기), DELETE(삭제하기)
- JSON 데이터를 주고받음
Main 파일
main > java 경로 바로 아래에 프로젝트명으로 생성한 파일
SpringRestApplication.java
어노테이션
- Controller - 요청을 받아 처리
- Service - 계산 및 조건 처리
- Repostitory - 데이터 연결
Bean 빈
- 빈(Bean) = 스프링 프레임워크에서 스프링 컨테이너가 관리하는 자바 객체.
- 컨테이너 = 빈이 만들어지고 관리되는 상자
- 개발자가 직접 new로 만들지 않고, 스프링이 대신 생성·관리.
- 어노테이션이나 설정 파일로 등록.
- 객체 생성, 의존성 주입, 생명주기 관리 등 다양한 역할을 담당.
@SpringBootApplication
- 설정 클래스 등록: 해당 클래스를 스프링 설정 파일로 인식해서, @Bean 메서드로 직접 빈을 등록할 수 있습니다.
- 자동 설정: Spring Boot가 프로젝트에 추가된 라이브러리(JAR)와 설정을 바탕으로 필요한 환경설정을 자동으로 해줍니다. 예를 들어, spring-boot-starter-web이 있으면 Spring MVC가 자동 구성됩니다.
- 컴포넌트 스캔: 메인 클래스가 위치한 패키지와 그 하위 패키지에서 @Component, @Service, @Repository, @Controller가 붙은 클래스를 자동으로 스프링 빈으로 등록합니다
@Controller - 가장 먼저 작동되는 부분
@Controller
public class ExampleController {
@GetMapping("/hello")
@ResponseBody
public String hello() {
return "안녕하세요!";
}
}
// RestController = Controller + ResponseBody
@RestController
public class HelloController {
private final HelloService helloService;
public HelloController(HelloService helloService) {
this.helloService = helloService;
}
@GetMapping("/hello")
public String sayHello() {
return helloService.getHello();
}
}
public class HelloController {
private final HelloService helloService;
public HelloController(HelloService helloService) {
this.helloService = helloService;
}
@GetMapping("/hello")
public String sayHello() {
return helloService.getHello();
}
}
@GetMapping
get 방식으로 넘어온 주소가 맞으면 작동
@PostMapping
post 방식으로 넘어온 주소가 맞으면 작동
return의 차이
@Autowired
private JoinService joinService;
아래 내용을 자동으로 지원해 준다.
private HelloService helloService;
// 가져온 메서드를 해당 인스턴스에 전달처리
public HelloController(HelloService helloService){
this.helloService = helloService;
}
@Service
@Service
public class HelloService {
public String getHello() {
return "Hello from Service!";
}
}
public class HelloService {
public String getHello() {
return "Hello from Service!";
}
}
@Repository
@Repository
public interface HelloRepository extends JpaRepository<User, Long> {
// 기본 CRUD 메서드는 자동 구현됨
}
// 기본 CRUD 메서드는 자동 구현됨
}
작동방식 정리
1. controller - 각 페이지이별 컨트롤러 파일 확인
2. 각 컨트롤러 파일안쪽에서 GetMapping, PostMapping으로 어떤 URL요청이 들어오는지 확인
3. 각 URL 요청에 따라 실행되는 메서드가 어떤 문자를 반환하는지 확인
4. resources폴더 안쪽에서 매칭 파일명의 html이 어떤 UI 렌더링 하는지 확인
5. layout.html과 각 페이지별.html이 어떤식으로 연결되어 있는지 확인
실습
HelloController.java
HelloService 클래스는 내부 코드를 숨기기 위해, 객체를 생성해서 private로 담아 사용한다.
package com.example.spring_rest.controller;
import com.example.spring_rest.service.HelloService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
//rest api를 간단히 구현하게 해주는 어노테이션
@RestController
public class HelloController {
// HelloService 클래스 서비스 패키지에서 private으로 가져옴 (보안이슈)
private HelloService helloService;
// 가져온 메서드를 해당 인스턴스에 전달처리
public HelloController(HelloService helloService){
this.helloService = helloService;
}
// "/hello" url 접속시 sayHello함수 호출
// sayHello함수 안쪽에는 은닉화 해놓은 서비스 계층 함수 실행
// controller(요청) + service(실행 로직)을 분리해서 관리
@GetMapping("/hello")
public String sayHello(){
return helloService.getHello();
}
}
HelloService.java
package com.example.spring_rest.service;
import org.springframework.stereotype.Service;
@Service
public class HelloService {
public String getHello(){
return "Hello from Service";
}
}
빌드 설정 파일에 thymeleaf 의존성 주입
src / build.gradle
dependencies항목 제일 아래쪽에 tymeleaf를 의존성 추가
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:3.1.0'
}
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:3.1.0'
}
공통의 레이아웃 템플릿 생성
src / main /resource / template / layout.html 파일 추가 (공통의 템플릿 레이아웃 추가)
layout:fragment="a" : a를 제외한 모두를 점령한다. fragment = 'a' 부분만 남겨 놓는다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--공통 헤더 영역-->
<header>
<h1><a href="/">Logo</a></h1>
<nav>
<a href="/join">Join Member</a>
</nav>
</header>
<!-- 각 페이지 내용이 삽입될 위치 -->
<main layout:fragment="body"> </main>
<!--공통 푸터 영역-->
<footer>
2025 alpaco © All rights reserved.
</footer>
</body>
</html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--공통 헤더 영역-->
<header>
<h1><a href="/">Logo</a></h1>
<nav>
<a href="/join">Join Member</a>
</nav>
</header>
<!-- 각 페이지 내용이 삽입될 위치 -->
<main layout:fragment="body"> </main>
<!--공통 푸터 영역-->
<footer>
2025 alpaco © All rights reserved.
</footer>
</body>
</html>
메인 페이지에 레이아웃 템플릿 연결
src / main /resources / template / index.html
layout:fragment="a" : a의 layout을 그대로 사용하되, 남겨진 해당 부분만 사용할 수 있다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout}">
<head>
<meta charset="UTF-8">
<title>Join</title>
</head>
<body>
<section layout:fragment="body">
<h1>Main Page</h1>
</section>
</body>
</html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout}">
<head>
<meta charset="UTF-8">
<title>Join</title>
</head>
<body>
<section layout:fragment="body">
<h1>Main Page</h1>
</section>
</body>
</html>
html로 값을 java로 전달받아 다시 html로 출력
JoinController
/join 에서 작동
package com.example.basic.controller;
import com.example.basic.service.JoinService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
//Model: 컨트롤러에서 템플릿에 데이터를 전달시 필요한 스프링 내장 객체
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@Controller
public class JoinController {
@Autowired
private JoinService joinService;
@GetMapping("/join")
public String join() {
return "join";
}
@PostMapping("/join/create")
public String create(
@RequestParam("uname") String uname,
@RequestParam("email") String email,
@RequestParam("colors") String colors,
Model model // Model 타입의 파라미터 추가
) {
// 서비스 메서드로 부터 전달받은 문자열을 전달 받음
String msg = joinService.processJoin(uname, email, colors);
//추가한 파라미터로 자동 전달된 인스턴스의 addAttribute라는 메서드를 통해
// {"data":전달할 문자열} 형식의 데이터를 index 템플릿에 전달
model.addAttribute("data", msg);
return "index";
}
}
join.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout}">
<head>
<meta charset="UTF-8">
<title>Join</title>
</head>
<body>
<section layout:fragment="body">
<h1>Join Member</h1>
<form action="/join/create" method="post">
<h2><label for="uname">User Name</label></h2>
<input type="text" name="uname" id="uname" placeholder="사용자 이름을 입력하세요.">
<h2><label for="email">Email</label></h2>
<input type="email" name="email" id="email" placeholder="이메일 주소를 입력하세요.">
<h2>Favorait Color</h2>
<div>
<label for="red">red</label>
<input type="radio" name="colors" id="red" value="red" checked>
<label for="green">green</label>
<input type="radio" name="colors" id="green" value="green">
<label for="blue">red</label>
<input type="radio" name="colors" id="blue" value="blue">
</div>
<div>
<input type="reset" value="cancel">
<input type="submit" value="send">
</div>
</form>
</section>
</body>
</html>
JoinService.java
package com.example.basic.service;
import org.springframework.stereotype.Service;
@Service
public class JoinService {
public String processJoin(String uname, String email, String colors) {
// 컨트롤러를 통해 실제 템플릿에 전달된 데이터가 매핑된 태그 문자열 반환
String result = "name: " + uname + "<br/>"
+ "email: " + email + "<br/>"
+ "my color: " + colors;
return result;
}
}
index.html
/join/create 에서 작동'
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout}">
<head>
<meta charset="UTF-8">
<title>Main</title>
</head>
<body>
<section layout:fragment="body">
<h1>Main Page</h1>
<div th:utext="${data}"></div>
</section>
</body>
</html>
낱개 파리미터 전달 방식이 아닌 객체 전달 방식
As-is: @RequestParam("uname") String uname,
To-be: @ModelAttribute JoinDTO formDTO
JoinDTO 객체 생성
package com.example.basic.dto;
public class JoinDTO {
private String uname;
private String email;
private String colors;
// 인스턴스 복사하는 성성자 함수
public JoinDTO(){}
// 각 폼의 항목별로 getter, setter 등록
public String getUname(){
return uname;
}
public void setUname(String uname){
this.uname = uname;
}
public String getEmail(){
return email;
}
public void setEmail(String email){
this.email = email;
}
public String getColors(){
return colors;
}
public void setColors(String colors){
this.colors = colors;
}
}
JoinController.java
@PostMapping("/join/create")
public String create(
// 매개변수 용도의 객체
@ModelAttribute JoinDTO formDTO,
// return에 사용하는 라이브러리 객체
Model model
) {
// 서비스 메서드로 부터 전달받은 문자열을 전달 받음
String msg = joinService.processJoin(formDTO);
model.addAttribute("data", msg);
return "index";
}
- model을 선언할 때,
- {joinDTO=com.example.basic.dto.JoinDTO@18ca2bfc, org.springframework.validation.BindingResult.joinDTO=org.springframework.validation.BeanPropertyBindingResult: 0 errors}
- model.addAttribute 를 사용할 때,
- {joinDTO=com.example.basic.dto.JoinDTO@18ca2bfc, org.springframework.validation.BindingResult.joinDTO=org.springframework.validation.BeanPropertyBindingResult: 0 errors, data=</br><ul><li>name: 남상도</li><li>email: sangdo@hanmail.net</li><li>my color: green</li></ul></br>}
JoinService.java
public class JoinService {
public String processJoin(JoinDTO dto) {
// 컨트롤러를 통해 실제 템플릿에 전달된 데이터가 매핑된 태그 문자열 반환
String result = "</br><ul><li>name: " + dto.getUname() + "</li>"
+ "<li>email: " + dto.getEmail() + "</li>"
+ "<li>my color: " + dto.getColors() + "</li></ul></br>";
return result;
}
}
Tags:
웹개발_교육