OpenInView = true
C - S - R
(o) (o) (o)
(o) (o) (o)
OpenInView = false
C - S - R
(o) (o) (o)
(x) (o) (o)
3. User(Package 변경 및 수정)
1. UserRequest
1. loginDTO 만들기
@Data
public staticclassloginDTO{
private String username;
private String password;
}
2.joinDTO 만들기
@Data
public staticclassjoinDTO{
private String username;
private String password;
private String email;
//DTO를 -> UserObject로 바꿔준다.
public UsertoEntity(){
returnUser.builder().username(username).password(password).email(email).build();
}
2. UserRepository
loginDTO
@RequiredArgsConstructor// final이 붙은 애들의 생성자를 만들어준다,.
@PostMapping("/login")
public Stringlogin(UserRequest.loginDTO loginDTO) {
User sessionUser = userRepository.findByUsernameAndPassword(loginDTO.getUsername(),loginDTO.getPassword());
session.setAttribute("sessionUser", sessionUser);
return"redirect:/board";
}
login(UserRequest.loginDTO loginDTO: 메소드는 ‘loginDTO’라는 객체를 인자로 받고 객체에는 사용자가 입력한 ‘username’ 과 ‘password’가 들어있다.
joinDTO
//회원가입 하고 난 후
@PostMapping("/join")
public Stringjoin(UserRequest.joinDTO joinDTO) {
//insert 하는 모든 것들은 toEntitiy로 하면 된다.
userRepository.save(joinDTO.toEntity());
return"redirect:/login-form";
‘joinDTO.toEntity()’는 ‘joinDTO’ 객체를 ‘Entity’ 객체로 변환하고 데이터베이스에 저장될 실제 데이터 구조를 의미한다.
userRepository.save(joinDTO.toEntity())’는 변환된 ‘Entity’ 객체를 데이터베이스에 저장한다. 즉 새로운 사용자를 데이터베이스에 추가한다.
4.Board(Package 변경 및 수정)
1. BoardController
// subtitle=제목1&postContent=내용1//board/save 를 붙이 이유는 https 1.0버전으로 하려고 그리고 자바스크립트 등 라이브러리 X ,순순한 스프링 프로그램으로만 만들려고
@PostMapping("/board/save")
public Stringsave(BoardRequest.saveDTO saveDTO) { // 스프링 기본전략 = x-www-form-urlencoded 파싱User sessionUser = (User) session.getAttribute("sessionUser");
// 인증 체크 필요함if(sessionUser == null) {
thrownewRuntimeException("로그인이 필요합니다.");
}
boardRepository.save(saveDTO.toEntity(sessionUser));
return"redirect:/board";
}
‘User sessionUser = (User) session.getAttribute(”sessionUser”)는 현재 로그인한 사용자의 정보를 세션에서 가져온다
‘boardRepository.save(saveDTO.toEntity(sessionUser)) 는 ‘SaveDTO’ 객체를 엔티티로 변환한 후, 현재 로그인한 사용자 정보와 함께 데이터베이스에 게시글을 저장한다.
2. BoardRepository
// insert 하기
@Transactional
public voidsave(Board board) {
em.persist(board);
}
em.persist(board): ‘EntityManager’ 객체(’em’)를 사용하여 ‘board’ 객체를 데이터베이스에 영구 저장(persist)한다. 데이터베이스에서 새로운 레코드를 추가 한 것이다.
메소드는 트랜잭션을 적용하여 ‘board’객체를 데이터베이스에 안전하게 저장하는 기능을 수행합니다.
3. BoardRequest
package shop.mtcoding.blog.board;
import lombok.Data;
import shop.mtcoding.blog.user.User;
public classBoardRequest {
@Data
public staticclasssaveDTO{
private String title;
private String contnet;
public BoardtoEntity(User sessionUser){
returnBoard.builder().
title(title)
.content(contnet)
.user(sessionUser)
.build();
}
}
}
BoardRequest 클래스는 게시글 저장 요청과 관련된 데이터를 담고 있는 내부 클래스를 포함한다.
Board.builder(): 빌더 패턴을 사용하여 ‘board’ 객체를 생성하고, ‘title’, ‘content’, ‘user’ 정보를 이용해 ‘board’객체를 초기화한다.
4. BoardResponse
package shop.mtcoding.blog.board;
import lombok.Data;
import shop.mtcoding.blog.user.User;
public classBoardResponse {
//응답 DTO//화면에 필요한 데이터를 만든 것.
@Data
public staticclassDtailDTO{
private Integer boardId;
private String title;
private String content;
private boolean isOwner;
private Integer userId;
private String username;
public DtailDTO(Board board, User sessionUser) {
this.boardId = board.getId();
this.title = board.getTitle();
this.content = board.getContent();
this.isOwner = false;
if(board.getUser().getId() == sessionUser.getId()) {
isOwner = true; // 권한 체크
}
this.userId = board.getUser().getId();
this.username = board.getUser().getUsername();
}
}
}
DtailDTO(Board board, User sessionUser) 생성자: 이 생성자는 ‘board’객체와 현재 로그인한 사용자 정보(’sessionUser’)를 인자로 받아, DTO 객체를 초기화합니다.’boardId”, ‘title’, ‘content’는 각각 ‘board’객체의 ID, 제목, 내용에서 가져옵니다.
‘isOwner’필드는 현재 로그인한 사용자가 해당 게시글의 작성자인지 여부를 판단합니다. 만약 ‘board’ 객체의 ‘user’ID와 ‘sessionUser의 ID가 같다면, ‘isOwner’를 ‘true’로 설정하여 사용자가 게시글의 작성자임을 표시합니다.
‘userId'와 ‘username’은 게시글 작성자의 정보를 담습니다.
비즈니스 로직
💡
비즈니스 로직은 애플리케이션이 특정한 비즈니스 문제를 해결하기 위해 수행하는 핵심 작업을 의미합니다. 즉, 비즈니스 로직은 사용자가 기대하는 기능을 구현하는 규칙, 절차, 데이터 처리 방법 등을 정의합니다. 서비스 계층(Service Layer)이 이러한 비즈니스 로직을 담당하며, 컨트롤러(Controller)나 데이터 접근 계층(Repository)과 구분됩니다.
비즈니스 로직의 주요 역할
도메인 규칙 적용: 비즈니스 로직은 애플리케이션의 도메인(비즈니스 영역)에 대한 규칙을 적용합니다. 예를 들어, 쇼핑몰에서는 "상품 재고가 없으면 구매할 수 없다"는 규칙이 있을 수 있습니다.
데이터 처리: 비즈니스 로직은 데이터의 생성, 수정, 삭제, 조회를 담당합니다. 여기에는 여러 데이터를 조합하여 계산하거나, 특정 조건에 따라 데이터를 필터링하는 작업 등이 포함됩니다.
결과 반환: 비즈니스 로직은 최종적으로 결과를 반환합니다. 이 결과는 일반적으로 컨트롤러로 전달되어 사용자가 볼 수 있는 형태로 제공됩니다.
트랜잭션 관리: 비즈니스 로직에서는 여러 데이터베이스 작업이 원자적으로 처리되도록 트랜잭션 관리를 수행합니다. 즉, 하나의 작업이 실패하면 전체 작업을 롤백하여 데이터의 일관성을 유지합니다.
비즈니스 로직의 예시
위에서 설명한 BoardService 클래스의 상세보기 메서드는 비즈니스 로직의 좋은 예시입니다.
java코드 복사
public BoardResponse.DtailDTO 상세보기(int id, User sessionUser) {
// 게시글을 ID로 조회하고, 해당 게시글이 존재하는지 확인Boardboard= boardRepository.findById(id); // 조인(Board - User) 포함, 절대 null 일수 가 없다.// 게시글과 사용자 정보를 바탕으로 DTO를 생성하여 반환returnnewBoardResponse.DtailDTO(board, sessionUser);
}
이 메서드가 수행하는 주요 비즈니스 로직:
데이터 조회: 특정 ID를 가진 게시글을 데이터베이스에서 조회합니다.
권한 확인: DtailDTO 객체를 생성할 때, 현재 사용자가 해당 게시글의 작성자인지 확인합니다.
결과 반환: 게시글의 상세 정보를 담은 DTO를 반환하여, 컨트롤러가 이를 사용자에게 전달할 수 있도록 합니다.
왜 비즈니스 로직이 중요한가?
유지보수성: 비즈니스 로직을 서비스 계층으로 분리하면, 코드의 변경이 필요한 경우 이를 한 곳에서 관리할 수 있어 유지보수가 쉬워집니다.
재사용성: 동일한 비즈니스 로직을 여러 곳에서 재사용할 수 있습니다. 예를 들어, 게시글 조회 로직은 여러 컨트롤러에서 사용할 수 있습니다.
책임 분리: 컨트롤러는 요청과 응답을 처리하는 데 집중하고, 비즈니스 로직은 서비스 계층에서 처리하도록 하면 코드가 더 명확해집니다.
비즈니스 로직을 올바르게 관리하고 구현하는 것은 애플리케이션의 성공적인 운영에 매우 중요합니다.
5. BoardService
package shop.mtcoding.blog.board;
//C -> S -> Rimport lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import shop.mtcoding.blog.user.User;
@RequiredArgsConstructor
@Service
public classBoardService {
private final BoardRepository boardRepository; //DI 끝//2개 리턴을 못한다.//비즈니스 로직에는 Controller가 해줄 필요가 없다.
public BoardResponse.DtailDTO 상세보기(int id, User sessionUser) {
Board board = boardRepository.findById(id); // 조인(Board - User) 포함, 절대 null 일수 가 없다.returnnewBoardResponse.DtailDTO(board, sessionUser);
}
}
@Service: 이 클래스가 서비스 계층의 역활을 한다는 것을 나타내고 서비스 계층은 비즈니스 로직을 처리하는 곳이다.
DI(Dependency Injection: ‘private final BoardRepository boardRepository’는 의존성 주입(DI)으로, 스프링이 ‘BoardRepository’를 자동으로 주입하여 사용한다.
Board board = boardRepository.findById(id): 주어진 ID로 게시글을 조회합니다. 이 과정에서 ‘board’와 ‘user’ 간의 조인이 포함되어 있으면, 결과는 null이 될 수 없다.