[Spring boot] Bank App - 회원가입

2025. 2. 15. 10:50·Spring
728x90

1. dto 설계 하기 및 개념 확인(사전 기반 지식)

🔹DTO 설계 및 개념 이해

 

Spring Boot 애플리케이션에서 DTO(Data Transfer Object)와 Model을 분리하는 것은 유지보수성과 가독성을 높이기 위해 중요한 설계 원칙 중 하나입니다.

 

✅ DTO와 Model의 차이점

구분 DTO (Data Transfer Object) Model (Entity, Domain Model)
역할 클라이언트와 서버 간 데이터 전달 DB 테이블과 매핑되는 비즈니스 객체
사용 목적 View-Controller 간의 데이터 교환 데이터베이스 저장 및 조회
설계 방식 주로 @Getter와 @Setter만 포함 JPA Entity, @Entity, @Table 사용

✅ DTO와 Model을 분리하는 이유

  1. 가독성과 유지보수성 향상:
    • Model 클래스에는 비즈니스 로직이 포함될 수 있으므로, 이를 DTO와 분리하여 클라이언트와 데이터베이스를 각각 다룰 수 있습니다.
    • 유지보수가 쉬워지고, Model이 변경될 때 API 요청 및 응답 데이터 구조를 변경하지 않아도 됩니다.
  2. 객체의 역할 구분:
    • Model(Entity)은 데이터베이스 테이블과 매핑되는 객체이며, 데이터 저장을 위한 ORM 객체입니다.
    • DTO는 API 응답 및 요청 데이터를 위한 데이터 전달용 객체입니다.
  3. 유연한 변경 가능:
    • Model을 직접 노출하면 보안 이슈(불필요한 필드 포함)가 발생할 수 있음.
    • API 요구사항이 변해도 Model을 변경할 필요 없이 DTO만 수정하면 됨.

🔹Spring Boot Web MVC 구조

Spring Boot 애플리케이션은 일반적으로 3-Tier Layered Architecture를 따릅니다.

✅ 레이어별 역할

  • Web Layer (Controller)
    • 클라이언트 요청을 받고 응답을 반환하는 역할.
    • @RestController 또는 @Controller 사용.
    • @RequestMapping을 활용하여 API 엔드포인트를 정의.
  • Business Layer (Service)
    • 내부 비즈니스 로직을 처리하는 계층.
    • @Service 어노테이션 사용.
    • 데이터 검증, 로직 처리, 트랜잭션 관리 수행.
  • Data Layer (Repository, DAO)
    • 데이터베이스와 직접 통신하는 계층.
    • @Repository와 JPA, MyBatis 등을 사용하여 데이터 CRUD 처리.
    • 외부 API와 연동할 경우, API Client를 정의하여 데이터를 가져옴.

📌 핵심 개념:
서비스(Service) 레이어를 활용하면 컨트롤러에서 비즈니스 로직을 분리할 수 있어 유지보수성이 향상됩니다.
또한, 컨트롤러가 단순히 요청을 처리하는 역할만 하도록 설계하면 **SRP(단일 책임 원칙)**을 준수할 수 있습니다.


🔹트랜잭션 개념과 ACID 원칙

트랜잭션(Transaction)은 데이터베이스에서 수행되는 일련의 작업 단위를 의미합니다.
즉, 하나의 트랜잭션 내에서 여러 SQL 작업이 실행되더라도 모두 성공해야 하고, 하나라도 실패하면 전체 작업이 롤백(rollback)되어야 합니다.

✅ ACID 원칙이란?

ACID는 데이터의 무결성과 안정성을 보장하기 위한 트랜잭션의 4가지 핵심 속성입니다.

  1. 원자성 (Atomicity)
    • 트랜잭션은 All or Nothing 방식으로 실행됩니다.
    • 예: 계좌 이체 시, 출금과 입금이 하나의 트랜잭션으로 실행되며 둘 중 하나라도 실패하면 전체가 롤백됩니다.
  2. 일관성 (Consistency)
    • 트랜잭션이 실행되기 전과 후에 데이터가 항상 일관된 상태를 유지해야 합니다.
    • 예: 은행 잔고 합계가 변경되면 안 됨.
  3. 고립성 (Isolation)
    • 여러 트랜잭션이 동시에 실행될 때 서로 간섭하지 않도록 보장해야 합니다.
    • 트랜잭션 격리 수준에 따라 성능과 일관성이 조정될 수 있습니다.
  4. 지속성 (Durability)
    • 트랜잭션이 완료된 후에는 데이터가 영구적으로 저장됩니다.
    • 서버가 다운되거나 장애가 발생해도 데이터가 손실되지 않음.

✅ Spring Boot에서 트랜잭션 관리

Spring Boot에서는 @Transactional 어노테이션을 활용하여 트랜잭션을 관리할 수 있습니다.

@Service
public class UserService {
    
    @Transactional
    public void registerUser(UserDTO userDTO) {
        userRepository.save(userDTO.toEntity()); // 사용자 저장
        sendWelcomeEmail(userDTO.getEmail()); // 환영 이메일 발송
    }
}

 

📌 @Transactional을 적용하면 모든 작업이 성공적으로 완료될 때만 커밋(Commit)되고, 실패하면 자동으로 롤백(Rollback) 됩니다.


2. UserController, UserService 설계 및 유효성 검사, 예외 처리

SignUpDTO 클래스 설계
package com.tenco.bank.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

// SignUpFormDTO
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class SignUpDTO {
	
	private String username;
	private String password; 
	private String fullname; 

//  ToDo 추후 진행 예정 	
//	private MultipartFile customFile; // name 속성과 일치 시켜야 함
//	private String originFileName; 
//	private String uploadFileName; 
//	private String eMail;
}

🔹SignUpDTO 설계

DTO는 클라이언트와 서버 간 데이터를 주고받기 위한 객체이며, 회원 가입 시 필요한 데이터를 담고 있습니다.

  • @Data: Getter, Setter, toString 등을 자동 생성
  • @NoArgsConstructor, @AllArgsConstructor: 기본 생성자 및 전체 필드 포함 생성자 자동 생성
  • @Builder: 객체를 유연하게 생성할 수 있도록 지원

 UserController 클래스 생성 및 구현
package com.tenco.bank.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.tenco.bank.dto.SignUpDTO;
import com.tenco.bank.handler.exception.DataDeliveryException;
import com.tenco.bank.service.UserService;

@Controller
@RequestMapping("/user") // 대문 처리 
public class UserController {
	
	// 1단계 
	@Autowired // DI 처리 
	private UserService userService;
	// 2단계 
	//private final UserService userService;
	
	// 2단계
	// private final UserService userService
	// final 처리를 하는 이유는 (성능향상)
	// @Autowired 함께 표시 가능, 표시 하는 이유는 (가독성 향상)
	public UserController(UserService userService) {
		this.userService = userService;
	}
	
	/**
	 * 회원 가입 페이지 요청 
	 * 주소 설계 http://localhost:8080/user/sign-up
	 * @return signUp.jsp 파일 리턴
	 */
	@GetMapping("/sign-up")
	public String signUpPage() {
	   //   prefix: /WEB-INF/view/
	   //   suffix: .jsp
		return "user/signUp";
	}
	
	
	// 회원 가입 요청 처리 
	// 주소 설계 http://localhost:8800/user/sign-up
	// Get, Post -> sign-up 같은 도메인이라도 구분이 가능하다. 
	// REST API 를 사용하는 이유에 대해한번 더 살펴 보세요  
	@PostMapping("/sign-up")
	public String signProc(SignUpDTO dto) {
		
		// 1. 인증검사 x 
		// 2. 유효성 검사 
		if(dto.getUsername() == null || dto.getUsername().isEmpty()) {
			throw new DataDeliveryException("username을 입력 하세요", 
					HttpStatus.BAD_REQUEST);
		}
		
		if(dto.getPassword() == null || dto.getPassword().isEmpty()) {
			throw new DataDeliveryException("password을 입력 하세요", 
					HttpStatus.BAD_REQUEST);
		}
		
		if(dto.getFullname() == null || dto.getFullname().isEmpty()) {
			throw new DataDeliveryException("fullname을 입력 하세요", 
					HttpStatus.BAD_REQUEST);
		}		
		userService.createUser(dto);
		
		// todo 로그인 페이지로 변경 예정
		return "redirect:/user/sign-up"; 
	}
	
	
}

🔹 UserController 설계

UserController는 회원 가입 관련 요청을 처리하는 컨트롤러입니다.

2.1 의존성 주입

  • @Autowired를 사용하여 UserService를 주입할 수도 있지만,
  • **생성자 주입 방식(권장됨)**을 사용하면 불변성을 보장하고 테스트가 용이합니다.

2.2 회원 가입 페이지 요청

  • URL: GET /user/sign-up
  • 처리: 회원 가입 페이지 (signUp.jsp) 반환

UserService 클래스 생성 및 구현
package com.tenco.bank.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.tenco.bank.dto.SignUpDTO;
import com.tenco.bank.handler.exception.DataDeliveryException;
import com.tenco.bank.handler.exception.RedirectException;
import com.tenco.bank.repository.interfaces.UserRepository;

@Service // IoC 대상(싱글톤으로 해당 객체를 관리) 
public class UserService {

	@Autowired
	private final UserRepository userRepository;

	// 생성자 의존 주입 DI
	public UserService(UserRepository userRepository) {
		this.userRepository = userRepository;
	}

	// 회원 가입 처리 
	// 예외 처리 
	// DB 에서 연결이나 쿼리 실행, 제약 사항 위한 같은
	// 예외는 RuntimeException 으로 예외를 잡을 수 없습니다. 
	@Transactional // 트랜 잭션 처리 습관
	public void createUser(SignUpDTO dto) {
		// Http 응답으로 클라이언트에게 전달할 오류 메시지는 최소한으로 유지하고,
		// 보안 및 사용자 경험 측면에서 민감한 정보를 노출하지 않도록 합니다.
		int result = 0; 
		try {
			result = userRepository.insert(dto.toUser());
			// 여기서 예외 처리를 하면 상위 catch 블록에서 예외를 잡는다. 
		} catch (DataAccessException e) {
			// DataAccessException는 Spring의 데이터 액세스 예외 클래스로,
			// 데이터베이스 연결이나 쿼리 실행과 관련된 문제를 처리합니다.
			throw new DataDeliveryException("잘못된 처리 입니다",HttpStatus.INTERNAL_SERVER_ERROR);
		} catch (Exception e) {
			// 그 외 예외 처리 - 페이지 이동 처리 
			throw new RedirectException("알 수 없는 오류" , HttpStatus.SERVICE_UNAVAILABLE);
		}
		// 예외 클래스가 발생이 안되지만 프로세스 입장에서 예외 상황으로 바라 봄 
		if (result != 1) {
			// 삽입된 행의 수가 1이 아닌 경우 예외 발생
			throw new DataDeliveryException("회원 가입 실패", HttpStatus.INTERNAL_SERVER_ERROR);
		}
	}

}

UserService 설계

UserService는 회원 가입 로직을 처리하는 서비스 계층입니다.

 

📌 의존성 주입

  • UserRepository를 생성자 주입 방식으로 주입

📌 회원 가입 처리

    • 트랜잭션 보장: @Transactional을 사용하여 모든 작업이 성공적으로 수행될 때만 DB에 반영
    • 예외 처리:
      • DataAccessException: DB 연결 및 쿼리 실행 중 발생하는 예외 처리
      • Exception: 알 수 없는 오류 처리 후 리다이렉트 예외 발생

📌 트랜잭션 처리 (@Transactional)

  • 회원 생성이 완료되지 않으면 자동으로 롤백
  • DB 관련 예외(DataAccessException)가 발생하면 500 (INTERNAL_SERVER_ERROR) 반환
  •  

user.xml 파일 (MyBatis 쿼리 정의)

회원 정보를 user_tb 테이블에 삽입하는 SQL 문

 

<insert id="insert">
	insert into user_tb	(username, password, fullname, created_at)
	values( #{username}, #{password}, #{fullname}, now())
</insert>

 

📌 #{}를 사용하여 MyBatis가 DTO 값을 동적으로 바인딩

 

 

테스트 시나리오

케이스입력 데이터예상 결과

✅ 정상 회원 가입 username=hong, password=1234, fullname=홍길동 회원 가입 성공 및 로그인 페이지 리다이렉트
❌ username 누락 password=1234, fullname=홍길동 400 BAD_REQUEST - username 입력 요청
❌ password 누락 username=hong, fullname=홍길동 400 BAD_REQUEST - password 입력 요청
❌ fullname 누락 username=hong, password=1234 400 BAD_REQUEST - fullname 입력 요청

 

📌 검증 도구:

  • Postman을 사용하여 HTTP 요청을 보내고 응답을 확인
  • Talend API Tester를 사용하여 API를 테스트

✅ 정리

1️⃣ 회원 가입 요청을 처리하는 DTO, Controller, Service 설계
2️⃣ 회원 정보 유효성 검사 및 예외 처리 (DataDeliveryException)
3️⃣ 트랜잭션 보장을 위한 @Transactional 사용
4️⃣ MyBatis user.xml을 활용한 회원 가입 SQL 작성
5️⃣ Postman 및 Talend API를 활용한 테스트 시나리오 검증


🚀 h2 스키마 및 초기 데이터 셋팅과 회원 가입 화면 구현 다음 포스팅에서!

'Spring' 카테고리의 다른 글

[Spring boot] Bank App - 로그인 처리  (0) 2025.02.17
Spring[Spring boot] Bank App - 회원가입(화면구현)  (2) 2025.02.15
[Spring boot] Bank App - MyBatis 설정 (DB 접근 기술)  (0) 2025.02.14
[Spring boot] Bank App - Exception Handler  (0) 2025.02.13
[Spring boot] Bank App - MainController, mainPage.jsp 구현  (2) 2025.01.15
'Spring' 카테고리의 다른 글
  • [Spring boot] Bank App - 로그인 처리
  • Spring[Spring boot] Bank App - 회원가입(화면구현)
  • [Spring boot] Bank App - MyBatis 설정 (DB 접근 기술)
  • [Spring boot] Bank App - Exception Handler
공돌이 출신 개발자
공돌이 출신 개발자
공돌이 출신 개발자입니다
  • 공돌이 출신 개발자
    공돌이 출신 개발자
    공돌이 출신 개발자
  • 전체
    오늘
    어제
    • 분류 전체보기 (124)
      • Database (0)
        • SQL (0)
        • 1일 1쿼리 (9)
      • Flutter (40)
        • Dart 언어 (18)
        • App (22)
      • Git (0)
      • Http 기초 지식 (14)
      • HTML5 & CSS3 (0)
      • Java (33)
      • JSP (0)
      • JavaScript (0)
      • Linux (0)
      • MSA (0)
      • Project (0)
      • React (0)
      • Spring (19)
      • 설치 메뉴얼 (1)
      • [Flutter] 프로젝트 (눈길) (8)
        • 작업일지 (8)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • GitHub
  • 공지사항

  • 인기 글

  • 태그

    spring boot
    데이터
    블로그 만들기
    jsp
    개발
    1일1쿼리
    클래스
    안드로이드
    객체지향
    dart
    Android
    회원가입
    메서드
    코딩
    HTTP
    앱개발
    앱 개발
    프로젝트
    JAVA 기초
    로그인
    프로그래밍
    플러터
    Java
    SQL
    flutter
    객체
    SQLD
    android studio
    안드로이드 앱 개발
    공부
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
공돌이 출신 개발자
[Spring boot] Bank App - 회원가입
상단으로

티스토리툴바