📚 필수 과제
- th:field, th:text 등의 문법을 통해 HTML 폼을 구성하고 서버에 데이터를 전송할 수 있음
- Model을 통해 사용자 입력값을 View에 출력할 수 있음
- 프로젝트의 구성도
Practical2_starter/
├── src/
│ └── main/
│ └── java/
│ └── kr.practical2_starter
│ ├── IntroController.java
│ ├── MbtiEmojiService.java
│ ├── Person.java
│ └── Practical2StarterApplication.java
│
├── resources
│ └── templates
│ ├── form.html
│ └── result.html
1. HTML 입력 폼 구성
- Thymeleaf의 th:field를 사용해 이름, 나이, MBTI, 좋아하는 음식, 좋아하는 색상 항목을 입력받는 <form>을 만들어보세요.
- 데이터는 POST 방식으로 전송되어야 합니다.
파일 구조는 기본적으로 제공된 예시 폴더 구조를 유지하여 진행 (추가 파일 생성 / 삭제는 없이 진행해야 함)
작업 방식은 Java 파일을 우선적으로 작업을 진행하고, HTML 작업을 진행하는 방향으로 작업해야 함
그 이유로는 Thymeleaf 템플릿은 자바코드에서 내려준 Model 데이터가 있어야 렌더링 가능하기 때문
1. Java (모델/컨트롤러) → HTML
- Person 클래스 (폼 데이터 DTO) → IntroController (GET에서 new person()을 model에 넣어주기)
- 이렇게 하면 form.html에서 th:object="${person}"로 안전하게 시작 가능
+. DTO란? (Data Transfer Object)
ㄴ 데이터를 옮기기 위한 객체를 의미
ㄴ 데이터를 주고받을 때 쓰는 단순한 바구니 역할 클래스
2. 그 다음에 form.html에서 th:field 붙이고 action="@{/intro}" 지정
3. 마지막으로 result.html에서 th:text, th:style로 모델 값 출력
//Person.java
package kr.sparta.practical2_starter;
/*
model
*/
public class Person { //클래스 선언
private String name;
private Integer age;
private String mbti;
private String favoriteFood;
private String favoriteColor;
public Person() {} //클래스 선언 이후 생성자 선언(초기화 방법에 대한 선언)
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public Integer getAge() {return age;}
public void setAge(Integer age) {this.age = age;}
public String getMbti() {return mbti;}
public void setMbti(String mbti) {this.mbti = mbti;}
public String getFavoriteFood() {return favoriteFood;}
public void setFavoriteFood(String favoriteFood) {this.favoriteFood = favoriteFood;}
public String getFavoriteColor() {return favoriteColor;}
public void setFavoriteColor(String favoriteColor) {this.favoriteColor = favoriteColor;}
}
//form.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>자기소개 입력</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css">
<style>
body {
font-family: 'Noto Sans KR', sans-serif;
}
</style>
</head>
<body>
<h1> 📝나를 소개합니다. </h1>
//form 형태로 도메인/intro 요청이 서버로 진행됨, 전송방식을 POST로 지정하고 입력된 값들을 person이라는 모델 객체와 바인딩 시킴
<form th:action="@{/intro}" method="post" th:object="${person}">
<label>이름: <input type="text" th:field="*{name}" /></label><br>
<label>나이: <input type="number" th:field="*{age}"></label><br>
<label>MBTI: <input type="text" th:field="*{mbti}"></label><br>
<label>좋아하는 음식: <input type="text" th:field="*{favoriteFood}"></label><br>
<label>좋아하는 색상: <input type="text" th:field="*{favoriteColor}"></label><br>
<button type="submit">제출</button>
</form>
</body>
</html>
2. 서버에서 입력값 처리 및 모델 전달
//IntroController.java
package kr.sparta.practical2_starter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
/*
Controller ?
사용자의 요청을 처음으로 받아서
어떤 작업을 해야 할지 판단하고** 그 작업을 Service에게 시키는 역할을 해요.
*/
@Controller
public class IntroController {
@Autowired
private MbtiEmojiService mbtiEmojiService;
// 폼 보여주기
@GetMapping("/")
public String form(Model model) {
model.addAttribute("person", new Person());
return "form";
}
// 제출 처리
@PostMapping("/intro")
public String submit(@ModelAttribute("person") Person person, Model model) {
String emoji = mbtiEmojiService.emojiFor(person.getMbti());
model.addAttribute("emoji", emoji);
return "result";
}
}
3. 한 줄 자기소개 출력
//result.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>자기소개 결과 화면</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css">
<style>
body {
font-family: 'Noto Sans KR', sans-serif;
}
</style>
</head>
// th:text로 사용, th:style은 도전과제 진행을 위함
<body th:style="'background:'+ ${person.favoriteColor}">
<p th:text="|안녕하세요 저는 ${person.age}살이고 ${person.mbti} ${emoji}인 ${person.name}이에요. ${person.favoriteFood}를 좋아하고, ${person.favoriteColor} 색을 좋아해요!|"></p> <a th:href="@{/}"> 다시 작성하기</a>
</body>
</html>
❤️🔥 도전 과제
1. 좋아하는 색상에 따라 배경색 적용하기
- 입력 폼에서 사용자가 좋아하는 색상을 고르면, 결과 페이지의 <body> 배경색으로 적용되도록 구현해보세요.
- th:style 을 사용해 CSS 스타일을 동적으로 적용해보세요.
form 형태로 제출하게 될 경우 정확한 색상의 고유값을 입력하거나, 선택하게 진행했어야 했음
이에 따라 select-option 형태로 입력받는 값을 한정지어 받게 진행하였고 그에 대한 value 값들을 적용시켜 body문에 색을 변화시켰음
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>자기소개 입력</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css">
<style>
body {
font-family: 'Noto Sans KR', sans-serif;
}
</style>
</head>
<body>
<h1> 📝나를 소개합니다. </h1>
<form th:action="@{/intro}" method="post" th:object="${person}">
<label>이름: <input type="text" th:field="*{name}" /></label><br>
<label>나이: <input type="number" th:field="*{age}"></label><br>
<label>MBTI: <input type="text" th:field="*{mbti}"></label><br>
<label>좋아하는 음식: <input type="text" th:field="*{favoriteFood}"></label><br>
<label>좋아하는 색상:
<select th:field="*{favoriteColor}">
<option value="red">빨강</option>
<option value="citrus">주황</option>
<option value="lightyellow">노랑</option>
<option value="lightgreen">초록</option>
<option value="lightblue">파랑</option>
<option value="purple">보라</option>
<option value="pink">분홍</option>
</select>
</label><br>
<button type="submit" >제출</button>
</form>
</body>
</html>
2. MBTI에 따라 이모지 출력하기
- MBTI 입력값에 따라 대표 이모지를 매핑해서 결과 페이지에 함께 출력해보세요.
- 아래 예시 Java 코드로 Map<String, String>을 만들어서 MBTI에 따른 이모지 매핑을 해보세요.
// 아래 코드를 그대로 MbtiEmojiService.java에 붙여넣어 사용하세요
public static final Map<String, String> MBTI_EMOJI_MAP = Map.ofEntries(
Map.entry("ISTJ", "📘"), // 신중한 관리자 – 책
Map.entry("ISFJ", "🛡️"), // 헌신적인 수호자 – 방패
Map.entry("INFJ", "🔮"), // 통찰력 있는 조언자 – 수정구슬
Map.entry("INTJ", "♟️"), // 전략적인 사색가 – 체스말
Map.entry("ISTP", "🛠️"), // 논리적인 장인 – 공구
Map.entry("ISFP", "🎨"), // 예술적인 예민가 – 팔레트
Map.entry("INFP", "🌸"), // 감성적인 중재자 – 벚꽃
Map.entry("INTP", "💡"), // 논리적인 사색가 – 전구
Map.entry("ESTP", "🏍️"), // 모험적인 활동가 – 오토바이
Map.entry("ESFP", "🎉"), // 자유로운 연예인 – 폭죽
Map.entry("ENFP", "🔥"), // 열정적인 외교관 – 불꽃
Map.entry("ENTP", "⚡"), // 재기발랄한 발명가 – 번개
Map.entry("ESTJ", "📋"), // 현실적인 관리자 – 체크리스트
Map.entry("ESFJ", "🤝"), // 친화력 좋은 사회자 – 악수
Map.entry("ENFJ", "🌟"), // 정의로운 주도자 – 별
Map.entry("ENTJ", "👑") // 당당한 리더 – 왕관
);
☠️ 트러블 슈팅
- 발생한 Issue
- 타임리프 속성 및 의미에 대해 다시 복습하고 세부내용 살펴볼 필요가 있었음. (왜 사용되고 어떤 방식으로 연결해야 하는지에 대한 이해도 부족)
- Getter / Setter 개념 복습 필요
- 해결방법 / 찾아본 내용
- 🔑 th:field, th:text 의 개념은?
- 타임리프(Thymeleaf)에서 제일 기본적인 속성
- th:field
- 폼 입력 요소(input, textarea, select 등)를 객체의 필드와 연결(bind)하는 속성
th:object="${person}" → 컨트롤러에서 모델에 넣어준 Person 객체를 바인딩 대상으로 지정
th:filed="*{name}" → person.name 필드와 이 input을 연결
- 폼 입력 요소(input, textarea, select 등)를 객체의 필드와 연결(bind)하는 속성
- th:text
- HTML 태그 안에 텍스트를 동적으로 출력하는 속성
- 단순한 ${변수} 출력과 달리, th:text는 XSS 방지를 위해 HTML 이스케이프 처리를 해줌
예:<script> 같은 값이 들어와도 그냥 텍스트로 보이게 함
<p th:text="${person.name}">기본값</p> → <p>홍길동</p>
- th:field
- 이에 따라 입력 폼에서는 필드를 연결하는 th:field를 사용하여 연결하고, 결과문에서는 값들을 조합하는 th:text를 활용한 최종 문장 출력에 이용하게 되었음
- 타임리프(Thymeleaf)에서 제일 기본적인 속성
- 🔑 Getter / Setter의 개념에 대해 복습 필요
- Getter (읽기)
- 필드(변수)의 값을 가져올 때 사용하는 메서드
- 이름 규칙 : get + 필드명 (대문자로 시작)
- 반환 타입은 필드 타입과 동일해야 함
- Setter (쓰기)
- 필드(변수)의 값을 변경할 때 사용하는 메서드
- 이름 규칙 : set + 필드명(대문자로 시작)
- 매개변수 타입은 필드의 타입과 동일, 리턴은 보통 void
- 목적 : 캡슐화 + 제어 가능성 확보
- 사용 위치 : 클래스 블록 안, 생성자 밖
- Getter (읽기)
- 🔑 th:field, th:text 의 개념은?
> ❗️ Getter,Setter / th:field, th:text 유사해보이는데 비슷한 과정을 거치는 것 아닌가?
- 값을 주고받는 것에서는 비슷해 보이지만, 실제로는 역할과 위치가 다름
- Getter / Setter
- 자바 클래스 내부에서 정의 하는 메서드
- 목적 : 객체의 필드를 읽고 변경하기
- th:field / th:text
- 템플릿(HTML, 뷰) 에서 쓰이는 속성
- 목적 : HTML 입력값 ↔︎ 자바 객체 필드를 자동 매핑 / 객체의 값을 화면에 출력
💬 Q. Controller가 뭔가요?
A. Controller 는 사용자의 요청을 처음으로 받아서, 어떤 작업을 해야 할지 판단하고 그 작업을
Service에게 시키는 역할을 해요.
Q. Service는 뭔가요?
A. Service는 **실제로 처리해야 할 일(기능)**을 담아두는 클래스예요.
'JAVA > Java 실습' 카테고리의 다른 글
| [JAVA] 계산기 과제 개념 추가 정리 (0) | 2025.09.16 |
|---|---|
| 점메추 SPA 에디션 (0) | 2025.09.10 |
| MVC 기반 점심 메뉴 추천기 (0) | 2025.09.10 |
| JSP 자기소개 버전 만들기 (0) | 2025.09.09 |
| JSP / Servlet 실습 (0) | 2025.09.05 |