Spring Boot를 활용한 첫 프로젝트를 완성했습니다.
아직 부족한 부분이 많지만 고치다 보면 완성이 계속 미뤄질 거 같더라고요😥
추후 리팩토링을 위해 프로젝트를 다시 보며 든 궁금증이 생겼습니다.
어떠한 구조가 최고의 프로젝트 구조일까?
controller, service, dto, dao, repository 등
spring boot 프로젝트를 위해 필요한 요소들은 꽤 다양합니다.
이 요소들에 대해 살펴보고 최고의 프로젝트 구조란 무엇일지
포스팅해보려 합니다🤩
MVC 패턴을 전제로 합니다.
잘못된 정보가 있다면 댓글로 꼭 알려주세요!
1. 필요한 요소들
1) Entity (Domain)
실제 DB 테이블과 매핑되는 요소이다.
하나의 객체가 DB의 하나의 Column처럼 작용한다.
// Entity 예시 코드
@Entity
@Getter
@Table(name = "COMMENT")
public class CommentEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
private String commentContents;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "board_id")
private BoardEntity boardEntity;
}
2) Repository
Entity에 의해 생성된 DB에 접근하기 위한 인터페이스이다.
직접 쿼리문을 작성하기도 하고 JPA를 사용하여 보다 쉽게 접근하기도 한다.
// Repository 예시 코드 - JPA 사용
public interface CommentRepository extends JpaRepository<CommentEntity, Long> {
// 해당 게시물에 댓글 오름차순 조회
List<CommentEntity> findAllByBoardEntityOrderByIdAsc(BoardEntity boardEntity);
}
3) DAO
실제로 DB에 접근하는 객체입니다.
Repositoy와 거의 같지만 동일한 것은 아니다.
- Repository는 Entity 객체를 보관하고 있는 저장소
- DAO는 데이터에 접근하도록 DB 접근 관련 로직을 모아둔 객체
개념은 엄연히 다르지만 개발할 때에는 비슷하게 사용된다.
출처) 인프런 김영한님 답변
domain과 repository 질문 - 인프런 | 질문 & 답변
안녕하세요, 강의 듣다 궁금증이 생겨 질문 남깁니다.질문 1.domain == vo, repository == dao이렇게 똑같이 봐도 괜찮은 건가요?같은 것이라면 왜 vo, dao가 아닌 다른 이름을 사용한 것인지,다른 것이라면
www.inflearn.com
4) Mapper
Repository에 포함되는 개념이다.
000.xml과 같이 SQL문을 정의해놓은 파일로 사용한다.
정의해놓은 SQL과 개발할 때 사용하는 메소드를 연결하여 나온 결과값을
정의해놓은 타입으로 mappig 시켜준다.
5) DTO
Controller, Service, Repository 등
계층 간 데이터 교환을 할 때의 Entity로 통신하는 것은
보안에 좋지 못하기 때문에 DTO를 사용한다.
// DTO 예시 코드
@Getter
@Setter
@ToString
public class CommentDTO {
private Long id;
private String commentWriter;
private String commentContents;
private Long boardId;
private LocalDateTime commentCreatedTime;
}
6) VO
DTO와의 차이점은 Read-Only라는 것이다.
DTO과 getter, setter가 있다면 VO는 getter만 있다.
7) Service
DAO 혹은 Repository에서 받아온 데이터를 받아 가공한다.
// Service 예시 코드
@Service
@Transactional
@RequiredArgsConstructor
public class CommentService {
private final UserRepository userRepository;
private final BoardRepository boardRepository;
private final CommentRepository commentRepository;
// 댓글 조회
public List<CommentDTO> findCommentAll(Long boardId) {
BoardEntity boardEntity = boardRepository.findById(boardId).get();
List<CommentEntity> commentEntityList = commentRepository.findAllByBoardEntityOrderByIdAsc(boardEntity);
List<CommentDTO> commentDTOList = new ArrayList<>();
for(CommentEntity commentEntity : commentEntityList){
CommentDTO commentDTO = CommentDTO.toCommentDTO(commentEntity);
commentDTOList.add(commentDTO);
}
return commentDTOList;
}
}
7) ServiceImpl
이 요소를 프로젝트에 둘 경우 Service는 인터페이스, ServiceImpl은 구현체가 된다.
다형성과 OCP를 지키는 구조가 되기 때문에 코드의 수정이 용이하다.
개인적으로 1:1로 매핑되는 인터페이스 - 구현체 구조가 과연 필요할까라는 의구심이 듭니다. 인터페이스의 존재 이유가 하나의 존재로 여러 역할을 내 입맛대로 쓰기 위한 것이니까요.
8) Controller
비즈니스 로직이 있는 서비스를 호출한다.
- Controller : 주로 View를 반환하기 위해 사용한다.
- RestController : @Controller + @ResponseBody가 합쳐진 것으로 Json형태의 데이터를 반환하기 위해 사용한다.
// Controller 예시 코드
@Controller
@RequiredArgsConstructor
public class UserController {
// 로그인
@GetMapping("/login")
public String loginForm(@RequestParam(value="error", required = false) String error,
@RequestParam(value = "exception", required = false) String exception,
Model model){
model.addAttribute("error", error);
model.addAttribute("exception", exception);
return "user/info/login";
}
}
2. 최고의 프로젝트 구조
전 controller - service - dto - repository - entity 구조를 사용했습니다.
repository 대신 dao를 사용할 수도 있고
service를 인터페이스로 두고 serviceImpl을 둘 수도 있고
restcontroller와 controller를 따로 둘수도 있고..정말 다양한 구조가 나올 수 있습니다.
최고의 프로젝트 구조..그런 건 없습니다
허무하시죠?
프로젝트의 상황과 규모 등에 따라 그에 맞는 프로젝트 구조를 만들 수 있는 것이 가장 중요한 것 같습니다.
확장 가능성이 있다면 service와 serviceImpl을 두고
restful api가 많다면 restcontroller와 controller로 나누는 등으로요.
또 기능에 따라 폴더를 나누고 controller, dto, entity 넣을 수도 있고
controller, dto, entity 안에 기능별로 나눌 수도 있겠죠.
상황에 따라 유동적으로 구조를 바꿀 수 있는 능력이 될 때까지 계속 공부하며 발전해나가봅시다!
출처) 인프런 김영한님 답변
프로젝트 폴더 구조와 강의 일정에 관하여 질문이 있습니다. - 인프런 | 질문 & 답변
1. 실무에서 프로젝트 구현시 보통 폴더 구조를 어떤식으로 하시나요?프로젝트를 하는데 폴더 구조를 어떻게 해야 좋을지 궁금합니다. 강의와 같이 api 패키지를 하나 만들고 Controller 클래스 안
www.inflearn.com
'JAVA' 카테고리의 다른 글
[JAVA] JDBC, JPA, Spring Data JPA 차이 그리고 Hibernate와 ORM (0) | 2023.10.13 |
---|---|
[Spring Security] 일반 로그인과 소셜 로그인 (oauth2) 그리고 JWT (0) | 2023.09.06 |
[Spring 외부 API 호출] RestTemplate, WebFlux (WebClient) 그리고 WebSocket (0) | 2023.09.02 |
[JAVA] Selenium으로 구글 로그인 자동화 만들기 (0) | 2023.07.29 |