[JPA 프로젝트 회고 - 5] JPA에서 DTO를 사용하는 이유 (feat. 코드 보안을 위해 수정)

2024. 8. 19. 14:21· 웹 개발 공부 : Back-end/JPA
목차
  1. 1. 보안
  2. 2. 유연성
  3. 3. 검증 및 가공
  4. 4. 예시코드
  5. 4-1. Entity를 직접 사용했을 경우
  6. 4-2. DTO를 사용했을 경우
  7. 5. 마무리
반응형

JPA 초기 구현 시, API 요청 JSON 데이터를 바로 엔티티에 적용하여 개발했다.
하지만, 이렇게 코드를 구현하면서 문득 든 생각이 있었으니...

 

 

'만약 API 스펙이 변경되면 엔티티와 매핑이 되는건가...?'


나의 의심은 역시나.. 실무에서 엔티티를 외부에 노출시키거나, 파라미터로 받으면 절대 절대!! 안된다!
그 이유를 한번 살펴보겠다.


1. 보안

회사 및 서비스 데이터베이스 정보는 굉장히 민감한 정보이다. 엔티티를 직접 파라미터로 받거나 노출시킨다면, API를 호출하는 과정에서 엔티티에 대한 정보가 모두 노출될 수 있다. 이는 곧 서비스의 민감한 정보가 노출될 수 있음을 의미한다.

 

 

2. 유연성

API 요청 스펙이 변경되면, 엔티티의 구조도 같이 변경해야할 수도 있다. 예를 들어, User라는 엔티티에 uuid라는 컬럼이 있고, API 요청 스펙중 uuid라는 key가 있는 상황에서 uuid -> uuids 로 변경된다면, User 엔티티의 uuid 컬럼도 변경되어야한다. 데이터베이스 구조가 수시로 변경되면... 생각만해도 아찔하다..

 

하지만, DTO를 사용한다면, DTO의 멤버 변수명만 변경해주면 된다. 어처피 getter를 사용하여 엔티티에 값을 넣어주기 때문에 유연성이 보장된다!

 

 

3. 검증 및 가공

API 요청 데이터를 엔티티에 넣어주기 전에 데이터를 검증할 수 있다. 예를들어 @Vaild를 사용하여 DTO에 @NotNull, @Email 등을 사용하여 요청 데이터의 유효성을 검증할 수 있다. 또한 getter로 데이터를 받아오기 때문에 데이터를 필요한 형태로 가공할 수 있다.

 

 

4. 예시코드

4-1. Entity를 직접 사용했을 경우

// Entity
@Entity
public class User{
    @Id
    private String uuid;
    private String username;
    private String email;
}

// Controller
@RestController
@RequestMapping("/user")
public class UserContoller{
	
    private UserSevice userSerivce;
    
    @Autowired
    public UserContoller(UserSevice userSerivce){
    	this.userSerivce = userSerivce;
    }
    
    @PostMapping("/v1/createuser")
    public String userCreate(@RequestBody User user){
    	return userSerivce.createUser(user).getBody();
    }
}

 

4-2. DTO를 사용했을 경우

// DTO
@Data
public class UserDto{
    // 해당 컬럼 데이터에 맞는 유효성 검증 제공
    @NotNull
    private String uuid;
    @NotNull
    private String username;
    @Email
    private String email;
}

// Entity
@Entity
public class User{
    @Id
    private String uuid;
    private String username;
    private String email;
    
    @Builder
    public User(String uuid, String username, String email){
        this.uuid = uuid;
        this.username = username;
        this.email = email;
    }
}

// Controller
@RestController
public class UserContoller{
	
    private UserSevice userSerivce;
    
    @Autowired
    public UserContoller(UserSevice userSerivce){
    	this.userSerivce = userSerivce;
    }
    
    // DTO를 통해 API 요청데이터를 받아옴 -> @Vaild를 통해 데이터 유효성 검증
    @PostMapping("/v1/createuser")
    public String userCreate(@RequestBody @Vaild UserDto userDto){
    	return userSerivce.createUser(userDto).getBody();
    }
}

// ServiceImpl
@Service
@Transactional
public class UserServiceImpl implements UserService{
    private final UserRepository userRepository;

    @Autowired
    public UserServiceImpl(UserRepository userRepository){
        this.userRepository = userRepository;
    }

    public ResponseEntity<String> createUser(UserDto userDto){
        try{
            User user = User.builder()
                            .uuid(userDto.getUuid())
                            .username(userDto.getUsername())
                            .email(userDto.getEmail())
                            .build();
            userRepository.save(user);
            return new ResponseEntity<String>("200", HttpStatus.OK);
        }catch(Exception e){
            e.printStackTrace();
            return new ResponseEntity<String>("400", HttpStatus.BAD_REQUEST);
        }
    }
}

 

5. 마무리

위와 같은 이슈는 실무에서 더욱 중요시되는 부분인 것 같다. 단순 기능 구현에만 치중하여 개발해선 안되며, 유연성, 확장성, 보안성 등 개발하는데에 있어 얼마나 중요한 요소인지 다시 한번 깨닫게 되었다.

반응형

'웹 개발 공부 : Back-end > JPA' 카테고리의 다른 글

[JPA 프로젝트 회고 - 7] org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type ~ 에러 해결  (0) 2024.10.11
[JPA 프로젝트 회고 - 6] 지연로딩  (0) 2024.09.09
[JPA 프로젝트 회고 - 4] java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for ~ 에러  (0) 2024.08.10
[JPA 프로젝트 회고 - 3] 영속성 컨텍스트 (Persistence Context)  (0) 2024.08.09
[JPA 프로젝트 회고 - 2] 레포지토리 (Repository)  (0) 2024.07.27
  1. 1. 보안
  2. 2. 유연성
  3. 3. 검증 및 가공
  4. 4. 예시코드
  5. 4-1. Entity를 직접 사용했을 경우
  6. 4-2. DTO를 사용했을 경우
  7. 5. 마무리
'웹 개발 공부 : Back-end/JPA' 카테고리의 다른 글
  • [JPA 프로젝트 회고 - 7] org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type ~ 에러 해결
  • [JPA 프로젝트 회고 - 6] 지연로딩
  • [JPA 프로젝트 회고 - 4] java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for ~ 에러
  • [JPA 프로젝트 회고 - 3] 영속성 컨텍스트 (Persistence Context)
Developer KTU
Developer KTU
Developer KTU
KTU 개발 블로그
Developer KTU
전체
오늘
어제
  • 분류 전체보기
    • 웹 개발 공부 : Back-end
      • JAVA
      • JPA
      • JAVA - Spring
      • MySQL
      • Docker
      • Redis
      • JSP
      • DevOps
      • 파이썬 - 장고
      • 운영체제
      • WEB
    • 블록체인
    • 웹 개발 공부 : Front-end
      • React
      • Javascript
      • JQuery
      • Ajax
    • 알고리즘 공부
    • 나의 커리어

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 백준
  • Algorithm
  • JavaScript
  • 파이썬
  • Python
  • Back-end
  • 알고리즘
  • 백엔드개발자
  • 알고리즘공부
  • 백엔드
  • 웹개발
  • 컴퓨터공학
  • Java
  • 스프링부트
  • 자바스크립트
  • BOJ
  • 알고리즘공부기
  • SpringBoot
  • 자바
  • 코딩테스트

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
Developer KTU
[JPA 프로젝트 회고 - 5] JPA에서 DTO를 사용하는 이유 (feat. 코드 보안을 위해 수정)
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.