250107 에이콘 아카데미 수업에 기반하여 작성되었음을 알립니다.
MongoDB - Spring Boot (빅데이터)
build.gradle
... 생략
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
// JSON 라이브러리 추가
implementation 'org.json:json:20210307'
}
tasks.named('test') {
useJUnitPlatform()
}
application.properties
spring.application.name=mongo5_boot_bigdata
# MongoDB 설정
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
KaData
@Data
@Document(collection = "katalkfiles")
public class KaData {
@Id
private String id;
private String req;
private String res;
}
KaDataController
@Controller
public class KaDataController {
@Autowired
private MongoClient mongoClient;
@GetMapping("/")
public String sijak() {
return "index";
}
// /show 경로에 요청이 오면 show.html을 반환
@GetMapping("/show")
public String showChatData(Model model) {
List<KaData> kaDataList = new ArrayList<>(); // 데이터를 저장할 리스트
// MongoDB의 GridFSBucket에서 파일을 가져온다.
GridFSBucket gridFSBucket = GridFSBuckets.create(mongoClient.getDatabase("katalkdb"), "katalkfiles");
try {
// GridFS에서 저장된 파일을 하나씩 가져온다.
for (GridFSFile gridFSFile : gridFSBucket.find()) {
ObjectId fileId = gridFSFile.getObjectId();
// 파일 다운로드
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
gridFSBucket.downloadToStream(fileId, outputStream);
String fileContent = new String(outputStream.toByteArray());
// JSON 파싱
if (fileContent.trim().startsWith("[")) {
JSONArray jsonArray = new JSONArray(fileContent);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
KaData kaData = new KaData();
kaData.setReq(jsonObject.getString("req"));
kaData.setRes(jsonObject.getString("res"));
kaDataList.add(kaData);
}
} else {
JSONObject jsonObject = new JSONObject(fileContent);
KaData kaData = new KaData();
kaData.setReq(jsonObject.getString("req"));
kaData.setRes(jsonObject.getString("res"));
kaDataList.add(kaData);
}
}
} catch (Exception e) {
e.printStackTrace();
}
model.addAttribute("dataList", kaDataList); // 데이터를 모델에 추가
return "show"; // show.html 파일을 반환
}
}
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="/show">몽고 데이터 보여 줘</a>
</body>
</html>
show.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<head>
<meta charset="UTF-8">
<title>Kakao Data</title>
<style>
table {
width: 100%;
border-collapse: collapse;
}
th, td {
border: 1px solid black;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
</style>
</head>
<body>
<h1>카카오 데이터</h1>
<table>
<thead>
<tr><th>질문</th><th>답변</th></tr>
</thead>
<tbody>
<tr th:each="kdata : ${dataList}">
<td th:text="${kdata.req}"></td>
<td th:text="${kdata.res}"></td>
</tr>
</tbody>
</table>
</body>
</html>
MongoDB - Spring Boot (Schedule CRUD)
application.properties
spring.application.name=mongo06_boot_schedule
spring.data.mongodb.uri=mongodb://localhost:27017/scheduledb
spring.data.mongodb.database=scheduledb
Schedule
@Data
@Document(collection = "schedules")
public class Schedule {
@Id
private String id;
private String title;
private String description;
private LocalDateTime startTime;
private LocalDateTime endTime;
}
ScheduleRepository
public interface ScheduleRepository extends MongoRepository<Schedule, String> {
}
ScheduleService
@Service
public class ScheduleService {
private final ScheduleRepository scheduleRepository;
public ScheduleService(ScheduleRepository scheduleRepository) {
this.scheduleRepository = scheduleRepository;
}
public List<Schedule> getAllSchedules() {
return scheduleRepository.findAll();
}
public Optional<Schedule> getScheduleById(String id) {
return scheduleRepository.findById(id);
}
public Schedule createSchedule(Schedule schedule) {
return scheduleRepository.save(schedule);
}
public Schedule updateSchedule(String id, Schedule schedule) {
schedule.setId(id);
return scheduleRepository.save(schedule);
}
public void deleteSchedule(String id) {
scheduleRepository.deleteById(id);
}
}
WebMvcConfig
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
// custom formatter나 변환기를 등록할 수 있다.
@Override
public void addFormatters(FormatterRegistry registry) {
// DateTimeFormatterRegistrar : 날짜와 시간에 대한 형식 설정을 관리
DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
// 날짜와 시간을 "YYYY-MM-DD'T HH:MM:SS 형식으로 변환하기 위한 ISO 표준값 중 하나
// 예) 2025-01-07T10:09:15
registrar.setDateTimeFormatter(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
registrar.registerFormatters(registry);
}
}
MainController
@Controller
public class MainController {
@GetMapping("/")
public String main() {
return "redirect:/schedules";
}
}
ScheculeController (읽기)
@Controller
@RequestMapping("/schedules")
public class ScheculeController {
private final ScheduleService scheduleService;
public ScheculeController(ScheduleService scheduleService) {
this.scheduleService = scheduleService;
}
@GetMapping
public String getAllSchedules(Model model) {
List<Schedule> schedules = scheduleService.getAllSchedules();
model.addAttribute("schedules", schedules);
return "schedule/list";
}
@GetMapping("/new")
public String createform(Model model) {
model.addAttribute("schedule", new Schedule());
return "schedule/create"; // create.html에서 Schedule 객체 접근 가능
}
// @ModelAttribute : 다른 어노테이션보다 먼저 수행된다.
@PostMapping
public String createSchedule(@ModelAttribute("schedule") Schedule schedule) {
scheduleService.createSchedule(schedule);
return "redirect:/schedules";
}
}
list.html
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>스케쥴 관리</title>
<link rel="stylesheet" th:href="@{/css/mystyles.css}">
<script th:inline="javascript">
function confirmDelete(event, id) {
event.preventDefault();
if(confirm("정말 삭제?")) {
window.location.href = "/schedules/delete/" + id;
}
}
</script>
</head>
<body>
<h2>일정 목록</h2>
<a href="/schedules/new" class="button primary">새 일정 추가</a>
<table class="styled-table">
<thead>
<tr>
<th>제목</th><th>설명</th><th>시작시간</th><th>종료시간</th><th>작업</th>
</tr>
</thead>
<tbody>
<tr th:each="schedule:${schedules}">
<td th:text="${schedule.title}">제목</td>
<td th:text="${schedule.description}">설명</td>
<td th:text="${#temporals.format(schedule.startTime, 'yyyy-MM-dd HH:mm')}">시작시간</td>
<td th:text="${#temporals.format(schedule.endTime, 'yyyy-MM-dd HH:mm')}">종료시간</td>
<td>
<a th:href="@{'/schedules/edit/' + ${schedule.id}}" class="button secondary">수정</a>
<a href="#" class="button danger" th:data-id="${schedule.id}"
onclick="confirmDelete(event, this.getAttribute('data-id'))">삭제</a>
</td>
</tr>
</tbody>
</table>
</body>
</html>
ScheculeController (추가)
@Controller
@RequestMapping("/schedules")
public class ScheculeController {
... 생략
@GetMapping("/new")
public String createform(Model model) {
model.addAttribute("schedule", new Schedule());
return "schedule/create"; // create.html에서 Schedule 객체 접근 가능
}
// @ModelAttribute : 다른 어노테이션보다 먼저 수행된다.
@PostMapping
public String createSchedule(@ModelAttribute("schedule") Schedule schedule) {
scheduleService.createSchedule(schedule);
return "redirect:/schedules";
}
}
create.html
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>새 일정 추가</title>
<link rel="stylesheet" th:href="@{/css/mystyles.css}">
</head>
<body>
<h2>새 일정 추가</h2>
<form th:action="@{/schedules}" th:object="${schedule}" method="post">
제목 : <input type="text" th:field="*{title}" /><br />
내용 : <textarea th:field="*{description}"></textarea><br />
시작 시간 : <input type="datetime-local" th:field="*{startTime}" /><br />
종료 시간 : <input type="datetime-local" th:field="*{endTime}" /><br />
<button type="submit">저장</button>
</form>
<br/>
<a href="/schedules">일정 목록</a>
</body>
</html>
ScheculeController (수정)
@Controller
@RequestMapping("/schedules")
public class ScheculeController {
... 생략
@GetMapping("/edit/{id}")
public String editform(@PathVariable(name = "id")String id, Model model) {
Schedule schedule = scheduleService.getScheduleById(id)
.orElseThrow(() -> new IllegalArgumentException("invalid id : " + id));
model.addAttribute("schedule", schedule);
return "schedule/edit";
}
@PostMapping("/update/{id}")
public String editschedule(@PathVariable(name = "id")String id, @ModelAttribute("schedule") Schedule schedule) {
scheduleService.updateSchedule(id, schedule);
return "redirect:/schedules";
}
}
edit.html
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>일정 수정</title>
<link rel="stylesheet" th:href="@{/css/mystyles.css}">
</head>
<body>
<h2>일정 수정</h2>
<form th:action="@{'/schedules/update/' + ${schedule.id}}" th:object="${schedule}" method="post">
제목 : <input type="text" th:field="*{title}" /><br />
내용 : <textarea th:field="*{description}"></textarea><br />
시작 시간 : <input type="datetime-local" th:field="*{startTime}" /><br />
종료 시간 : <input type="datetime-local" th:field="*{endTime}" /><br />
<button type="submit">저장</button>
</form>
<br/>
<a href="/schedules">일정 목록</a>
</body>
</html>
ScheculeController (삭제)
@Controller
@RequestMapping("/schedules")
public class ScheculeController {
... 생략
@GetMapping("/delete/{id}")
public String deleteschedule(@PathVariable(name = "id")String id) {
scheduleService.deleteSchedule(id);
return "redirect:/schedules";
}
}
mystyles.css
@charset "UTF-8";
body {
font-family: Arial, sans-serif;
margin: 20px;
}
h1 {
color: #333;
}
form {
max-width: 600px;
}
label {
display: block;
margin-top: 15px;
font-weight: bold;
}
input[type="text"],
input[type="datetime-local"],
textarea {
width: 100%;
padding: 8px;
box-sizing: border-box;
}
textarea {
height: 150px;
resize: vertical;
}
button {
margin-top: 20px;
padding: 10px 20px;
background-color: #4CAF50;
color: #fff;
border: none;
cursor: pointer;
}
button:hover {
background-color: #45a049;
}
a.button {
display: inline-block;
margin-bottom: 15px;
padding: 10px 20px;
background-color: #007BFF;
color: #fff;
text-decoration: none;
border-radius: 5px;
font-weight: bold;
}
a.button.primary {
background-color: #28a745;
}
a.button.secondary {
background-color: #007BFF;
}
a.button.danger {
background-color: #dc3545;
}
a {
display: inline-block;
margin-top: 20px;
color: #007BFF;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
table.styled-table {
width: 100%;
border-collapse: collapse;
margin-top: 15px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
table.styled-table thead tr {
background-color: #009879;
color: white;
text-align: left;
font-weight: bold;
}
table.styled-table th,
table.styled-table td {
padding: 12px 15px;
}
table.styled-table tbody tr {
border-bottom: 1px solid #dddddd;
}
table.styled-table tbody tr:nth-of-type(even) {
background-color: #f3f3f3;
}
table.styled-table tbody tr:last-of-type {
border-bottom: 2px solid #009879;
}
'Study > Acorn' 카테고리의 다른 글
250106 MongoDB (SpringBoot, 대용량 데이터 저장/읽기) (0) | 2025.01.06 |
---|---|
250103 MongoDB (Java - CRUD, 동적인 칼럼 처리) (0) | 2025.01.03 |
250102 MongoDB (개념, 설치, 기본 CRUD, Java 연동) (0) | 2025.01.02 |
241231 도커 (nodejs 웹서버, 우분투 자바 설치, 도커 허브 푸쉬) (0) | 2024.12.31 |
241230 도커 (설치, 기본명령어) (0) | 2024.12.30 |