
1.스프링부트의 백엔드는 구성하는 요소는 다음 그림과 같다.

다른 그림도 많지만, 이 그림이 필자가 설명하고자 하는 논리의 흐름에 맞
는 그림이라서 이 그림을 가져왔다.
2.각 부분들을 간단하게 설명하겠다.
출처: https://pink1016.tistory.com/153 [괴발개발 성장기:티스토리]
1.controller
사용자 요청이 진입하는 곳
사용자 요청을 처리하는 곳
처리 후 서비스로 넘어간다
2.service
repository와 controller 사이의 미들웨어
controller에서 받은 데이터를 가공해서 db를 보내거나 db에서 가져온 데이터를 가공해서 사용자에게 보내준다.
사용자 요구사항을 처리하는 곳이다.
3.repository
CRUD 명령어를 작성하는 곳이다.
4.dto
Data Transfer Object이다.
데이터 저장을 담당하는 클래스이며,
계층 간에 데이터를 교환할 때 주로 사용한다.
이 클래스가 없으면, 계층 간에 데이터를 교환하기 어렵다.
5.entity
DB에 접근하는 객체이다.
entity와 dto를 분리하는 이유는, 하나로 쓰면 변경된 값이 db에 들어갈 수 있기 때문이다.
3.controller 코드
controller는 사용자 요청이 진입하거나, 사용자 요청을 처리하는 곳이다.
이를 처리 한 뒤 서비스로 넘어간다.
다음은 프로젝트의 controller 코드이다.
controllerclass.java
각 페이지 간을 이동할 때의 동작에 대한 코드이다.
package com.example.finalproject.finalproject.controller;
import java.util.Optional;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.example.finalproject.finalproject.dto.memberDTO;
import com.example.finalproject.finalproject.entity.MemberEntity;
import com.example.finalproject.finalproject.service.RoadDamageService;
import com.example.finalproject.finalproject.service.memberservice;
import lombok.RequiredArgsConstructor;
@Controller
@RequiredArgsConstructor
public class controllerclass {
// memeberservice 객체를 정의한다.
private memberservice memberService;
// roadDamageService정의
private RoadDamageService roadDamageService;
@Autowired
public void MemberController(memberservice memberService) {
this.memberService = memberService;
}
@GetMapping("/main") // 메인 페이지로 이동하는 컨트롤러.
public String gomain(Model model, HttpSession session) {
// 세션에 저장된 memberId를 모델에 추가
model.addAttribute("loggedInUser", session.getAttribute("loggedInUser"));
return "main";
}
// officer.js에 아이디를 전달하는 controller 코드.
@GetMapping("/getLoggedInUser")
@ResponseBody
public String getLoggedInUser(HttpSession session) {
return (String) session.getAttribute("loggedInUser");
}
@GetMapping("/goofficer") // 지자체 페이지로 이동하는 컨트롤러.
public String goOfficer(Model model, HttpSession session) {
// 세션에 저장된 memberId를 모델에 추가
model.addAttribute("loggedInUser", session.getAttribute("loggedInUser"));
return "goofficer";
}
@GetMapping("/detail") // 디테일 페이지로 이동하는 컨트롤러.
public String godetail() {
return "detail";
}
@GetMapping("/login") // 로그인 페이지로 이동하는 컨트롤러.
public String gologin() {
return "login";
}
@PostMapping("/login")
public String login(@RequestParam("memberId") String memberId,
@RequestParam("password") String password,
HttpSession session, RedirectAttributes attributes) {
try {
// 실제로는 데이터베이스나 다른 인증 로직을 통해 사용자를 검증하는 작업이 필요
memberDTO result = memberService.login(new memberDTO(memberId, password));
if (result != null) {
// 로그인 성공 시 세션에 정보 저장
session.setAttribute("loggedInUser", result.getMemberId());
// 리다이렉트 URL과 함께 성공 메시지 전달
attributes.addFlashAttribute("successMessage", "로그인에 성공했습니다.");
return "redirect:/goofficer";
} else {
// 로그인 실패 시 리다이렉트 URL과 함께 실패 메시지 전달
attributes.addFlashAttribute("errorMessage", "아이디 또는 비밀번호가 올바르지 않습니다.");
return "redirect:/login";
}
} catch (Exception e) {
// 로그인 중 오류 발생 시 리다이렉트 URL과 함께 오류 메시지 전달
attributes.addFlashAttribute("errorMessage", "로그인 중 오류가 발생했습니다.");
return "redirect:/login";
}
}
// 로그아웃에 관한 get매핑이다.
@GetMapping("/logout")
public String logout(HttpServletRequest request) {
// 세션에서 사용자 정보 삭제
request.getSession().invalidate();// 로그아웃은 이거 한줄이면 뚝딱이다.
return "redirect:/main";
}
@GetMapping("/signup") // 회원가입 페이지로 이동하는 컨트롤러.
public String gosignup() {
return "signup";
}
// 회원가입 페이지에서 요청을 받아옴.
// ResponseEntity:Spring Framework에서 제공하는 클래스. http 응답을 나타낸다.
@PostMapping("/signup")
public ResponseEntity<String> signup(@RequestBody memberDTO memberDTO) {
try {
memberService.save(memberDTO);
// 회원가입이 완료되었다는 신호를 보낸다.
return ResponseEntity.ok("회원가입이 완료되었습니다.");
} catch (Exception e) {
// 오류 신호를 보낸다.
return ResponseEntity.status(500).body("회원가입 중 오류가 발생했습니다.");
}
}
// 회원가입 페이지에서, 중복 check에 관한 요청을 받아옴.
@PostMapping("/checkDuplicateId")
public ResponseEntity<Boolean> checkDuplicateId(@RequestBody String memberId) {
try {
// 중복되지 않은 경우에 true.
boolean isDuplicate = memberService.idCheck(memberId) != null;
return ResponseEntity.ok(isDuplicate);
} catch (Exception e) {
return ResponseEntity.status(500).body(false);
}
}
@GetMapping("/findpassword") // 비밀번호 찾기 페이지로 이동하는 컨트롤러.
public String gofindpassword() {
return "findpassword";
}
// id중복 체크를 하기 위한 controller 코드.
// service의 idCheck을 통해 중복된 id check을 한다.
// 데이터를 requestparam을 통해 받아온다.
@PostMapping("/member/idcheck")
@ResponseBody
public String idCheck(@RequestParam("memberId") String memberId) {
// 아이디를 디비에서 체크하기 위해 memberservice에서 함수를 만든다.
String checkResult = memberService.idCheck(memberId);
return checkResult;
}
// 이메일 중복 체크를 하기 위한 controller 코드이다.
@PostMapping("member/emailcheck")
@ResponseBody
public String emailCheck(@RequestParam("email") String email) {
// 이메일을 디비에서 체크하기 위해 memberservice에서 함수를 만든다.
String emailResult = memberService.emailCheck(email);
return emailResult;
}
// 이메일로 아이디 찾기 요청 처리
@PostMapping("/findIdByEmail")
public ResponseEntity<MemberEntity> findIdByEmail(@RequestParam String email) {
Optional<MemberEntity> memberEntityOptional = memberService.findIdByEmail(email);
return memberEntityOptional.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
}
// 아이디로 비밀번호 찾기 요청 처리
@PostMapping("/findPasswordById")
public ResponseEntity<MemberEntity> findPasswordById(@RequestParam String memberId) {
Optional<MemberEntity> memberEntityOptional = memberService.findPasswordById(memberId);
return memberEntityOptional.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
}
}
RoadDamageController.java
데이터베이스 데이터의 수정,불러오기 등을 처리하는 코드이다.
package com.example.finalproject.finalproject.controller;
import java.util.List;
import javax.persistence.EntityNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.finalproject.finalproject.dto.RoadDamageDto;
import com.example.finalproject.finalproject.repository.RoadDamageRepository;
import com.example.finalproject.finalproject.service.RoadDamageService;
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "http://localhost:8090")
public class RoadDamageController {
// dto에 저장된 데이터를 엔드포인터로 연결시켜주는 controller이다.
@Autowired
private RoadDamageService roadDamageService;
private RoadDamageRepository roadDamageRepository;
@GetMapping(value = "/getMarkers", produces = "application/json")
public List<RoadDamageDto> getMarkers() {
return roadDamageService.getAllRoadDamages();
}
@PutMapping("/updateMarker/{id1}")
public ResponseEntity<String> updateRoadDamage(@PathVariable Integer id1,
@RequestBody RoadDamageDto updateDto) {
try {
roadDamageService.updateRoadDamage(id1, updateDto);
return ResponseEntity.ok("도로 위험물이 성공적으로 업데이트되었습니다.");
} catch (EntityNotFoundException e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("도로 위험물을 찾을 수 없습니다.");
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("도로 위험물 업데이트 중 오류 발생: " + e.getMessage());
}
}
}
자, 이제 코드를 자세히 뜯어보면서 개념을 알아보도록 하자.
4.controller 개념 설명
우선, 가장 대표적인 코드 하나를 불러와서 개념을 알아보자.
@GetMapping("/main") // 메인 페이지로 이동하는 컨트롤러.
public String gomain(Model model, HttpSession session) {
// 세션에 저장된 memberId를 모델에 추가
model.addAttribute("loggedInUser", session.getAttribute("loggedInUser"));
return "main";
}
1.getmapping/postmapping
getmapping은 HTTP Get method에 해당하는 단축 표현으로 서버의 리소스를 조회할 때 사용된다.
postmapping은 HTTP Post mapping에 해당하는 단축 표현으로 서버에 리소스를 등록할 때 사용한다.
이외에도 서버의 리소스를 삭제하는 DeleteMapping이 있다.
2.함수 부분
return에 html 파일의 이름을 적는다. 즉, 이 함수는 main.html로 이동하고, 서버의 리소스를 조회하는 것이다.
보통 "main"과 같이 return 하기 때문에, 함수의 자료형은 String을 쓴다.
postmapping에 관해서도 설명을 해보자. 아래는 postmapping의 대표적인
코드를 따 온것이다.
@PostMapping("/login")
public String login(@RequestParam("memberId") String memberId,
@RequestParam("password") String password,
HttpSession session, RedirectAttributes attributes) {
try {
// 실제로는 데이터베이스나 다른 인증 로직을 통해 사용자를 검증하는 작업이 필요
memberDTO result = memberService.login(new memberDTO(memberId, password));
if (result != null) {
// 로그인 성공 시 세션에 정보 저장
session.setAttribute("loggedInUser", result.getMemberId());
// 리다이렉트 URL과 함께 성공 메시지 전달
attributes.addFlashAttribute("successMessage", "로그인에 성공했습니다.");
return "redirect:/goofficer";
} else {
// 로그인 실패 시 리다이렉트 URL과 함께 실패 메시지 전달
attributes.addFlashAttribute("errorMessage", "아이디 또는 비밀번호가 올바르지 않습니다.");
return "redirect:/login";
}
} catch (Exception e) {
// 로그인 중 오류 발생 시 리다이렉트 URL과 함께 오류 메시지 전달
attributes.addFlashAttribute("errorMessage", "로그인 중 오류가 발생했습니다.");
return "redirect:/login";
}
}
다음은 위의 코드에 대한 설명이다.
1.postmapping
login 페이지에서 서버에 리소스를 보내는 것이다.
로그인 페이지이므로, 사용자가 적은 로그인 정보를 보내는 것이라고 생각하면 된다.
2.RequestParam
값을 받아오는 기능이다. 우리는 로그인 페이지에서 정보(memberId,password)를 받아온 것이다.
3.HttpSession
클라이언트를 식별하고, 해당 클라이언트 정보를 저장하는 방법을 제공한다.
4.RedirectAttributes
리디렉션을 수행할 때 쓰이는 것이다.
5.application 설명
application은 간단히 말해서, 대빵이라고 보면 된다.
자세히 말하면, 어플리케이션을 실행할 때, 이 페이지에서 controller,dto,entity등 모든 코드들을 스캔하고, 어플을 실행시킨다.
@SpringBootApplication 어노테이션으로 쓴다.
package com;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class FinalprojectApplication {
public static void main(String[] args) {
SpringApplication.run(FinalprojectApplication.class, args);
}
}
각 부분에서는 각자의 기능에 맞는 어노테이션을 잘 추가하는 것이 중요하다.
그래야 이 코드에서 '아,이놈이 우리 어플리케이션에 포함되는 놈이구나... 이놈의 기능은.... 그래! controller구나!'
라는 깃으로 인식을 할 수 있기 때문이다.
application은 코드의 길이나 난이도는 가장 낮지만, 기능상으로는 가장
중요한 부분이라고 할 수 있다.