Java Spring Boot(3) 프로젝트 시작

제이 용·2025년 11월 11일

오늘은 강의를 마저 들은 다음 과제에 돌입하기 시작한 날이다. 연관관계에 대한 매핑에 대해 들었고 기준을 정하는 것을 확실히 이해한 날이었다.

또한 현업이나 프로젝트를 만들 때 단방향을 선호하는 이유 또한 알게 되었다.


방향에 대한 기준

  • 우선적으로 여러 Entity들의 관계들에 대해 생각을 해보자면, 여러 Entity들을 생성할 시 대부분에는 생성되는 개수의 차이가 분명히 존재한다.

  • 지금하고 있는 프로젝트로 예를 들자면, 만들어야되는 Entity는 user와 schedule, comment 총 3가지로 볼 수 있다.

  • 여기서부터 중요한 것은 이들의 생성원리에 대해서 생각을 해볼 필요가 있다.

  • 누가먼저 생성되는지를 생각해보면 쉽게 답을 찾을 수 있다.

  • user가 있기에 schedule을 생성할 수 있다, schedule이 있기에 comment를 달 수가 있다.

  • 따라서 comment -> schedule(N:1)관계, schedule -> user(N:1) 관계라고 볼 수 있다.

  • 여러개의 댓글이 일정에 달리고 여러 일정들이 유저들에 의해 생성된다. 따라서 위 와 같은 관계와 방향이 이뤄질 수 있는 것이다.

강의를 통해 관계와 방향성을 찾는 법을 익힐 수 있었고, 프로젝트에 들어감에 앞서 관계매핑에 대한 이해가 되었기에 쉽게 틀을 짤 수 있게 되었다.

  • Comment Entity에는 Schedule에 관련된 필드를 갖고 이에 ManyToOne 어노테이션이 붙을 것이며, Schedule Entity에는 User에 관련된 필드를 갖으며 ManyToOne 어노테이션이 붙을 것이다.

  • 이를 참고해서 ERD를 짤 수 있을 것이고, 몇 단계를 더 짚고 넘어갈 수 있다.


CRUD를 작성하며 파악하기

  • 우선 전에 했던 프로젝트와 비슷한 구조가 상당히 많아 이번에는 강의를 참고하지 않고서, 타이핑하는 과정을 밟아보려고 하였다.

  • 결과적으로는 뜨문뜨문 기억이 났기에 중간중간 코드에 구멍이 생기는 일이 발생하였다.

  • 따라서 이 과정을 지속적으로 반복 타이핑하며, 어노테이션이나 구문들, 구상이 자연스럽게 떠오르도록 차근차근 다시 타이핑을 해보려고 하였다.


패키지 파일 미리 생성하기

  • 우선 프로젝트를 생성하고 그에 맞는 세팅을 실시한다.

  • 생성간에는 롬복,JPA,MySQL,Spring framework web 이 4가지를 설정에 챙겨가는 것을 잊지말자.

  • 이후 resources -> application.properties에 마저 세팅을 해줘야한다.


spring.datasource.url=jdbc:mysql://localhost:****/test
url → MySQL 서버 주소
localhost:****/test → 내 PC의 **** 포트에 있는 test라는 DB에 연결

spring.datasource.username=root
username → DB 접속 계정 (root)

spring.datasource.password=****
password → 계정 비밀번호 (****)

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
driver-class-name → MySQL용 JDBC 드라이버 클래스

spring.jpa.hibernate.ddl-auto=create
JPA가 **엔티티(Entity)**를 기준으로 DB 테이블을 어떻게 생성할지 정하는 옵션
create → 실행할 때마다 기존 테이블을 삭제 후 새로 생성

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLBDialect
Hibernate가 SQL을 생성할 때 사용하는 **DB 방언(Dialect)**
MySQLBDialectMySQL 전용 SQL 문법을 쓰겠다는 뜻

spring.jpa.show-sql=true
show-sql=true → 콘솔에 실행되는 SQL 쿼리를 출력

spring.jpa.properties.hibernate.format_sql=true
format_sql=true → SQL 문을 보기 좋게 줄바꿈/들여쓰기해서 출력

  • 명세 확인
  • 일정을 생성, 조회, 수정, 삭제할 수 있습니다.
  • 일정은 아래 필드를 가집니다.
    • 작성 유저명, 할일 제목, 할일 내용, 작성일, 수정일 필드
    • 작성일, 수정일 필드는 JPA Auditing을 활용합니다.
  • CRUD를 모두 작성해야하고, Entity의 필드들이 설명되어있다. 먼저 일정에 관련된 패키지들을 작성한다.

  • 패키지가 완료되었으면 데이터와 관련된 entity와 repository를 먼저 설정한다.

Entity생성

필요 어노테이션

  • @Entity
  • Table(name ="names")
  • @Getter
  • @NoArgsConstructor(access = AccessLevel.PROTECTED)
  • @Id
  • @GeneratedValue(strategy = GenerationType.IDENTITY)
  • @CreatedDate
  • @LastModifiedDate
  • 날짜계산을 위해 Application에 @EnaleJpaAuditing추가

이후 명세에 맞게 필드를 작성하고, id를 제외한 생성자를 추가한다.


Repository생성

  • 꼭 인터페이스로 만들어줘야하며, extends 를 통해 JpaRespository를 추가한다.

Controller

필요 어노테이션

  • @RestController
  • @RequiredArgsConstructor

하위 계층인 서비스를 필드로 갖는다.(의존성 주입)


Service

필요 어노테이션

  • @Service
  • @RequiredArgsConstructor

하위 계층인 레퍼지토리를 피드로 갖는다.(의존성 주입)


CRUD 작성

  • C - 생성(Controller) :
@PostMapping("/names")
public ResponseEntity<생성 응답 DTO> create (@RequestBody 생성 요청 DTO dto) {
    return ResponseEntity.status(HttpStatus.OK).body(서비스.save(dto);
    }
  • save 메서드 생성(Service) :
@Transactional
    public 생성 응답 DTO save(생성 요청 DTO dto) {
        Entity entity = new Entity(dto.get생성요청dto 필드값들());
        Entity saveSchedule = 레퍼지토리.save(entity);
        return new 생성응답 DTO(
                saveSchedule.생성응답dto 필드값들()
        );
    }

  • R - 조회(전체)(Controller) :
@GetMapping("/names")
    public ResponseEntity<List<전체 조회 응답 DTO>> getSchedules() {
        return ResponseEntity.status(HttpStatus.OK).body(서비스.getAll());
    }
  • getAll메서드 생성(Service) :
@Transactional(readOnly = true)//조회
    public List<전체 조회 응답 DTO> getAll() {
        List<Entity> schedules = 레퍼지토리.findAll();
        List<전체 조회 응답 DTO> dtos = new ArrayList<>();
        for (Entity entity : schedules) {
            전체 조회 응답 DTO dto = new 전체 조회 응답 DTO(
                    schedule.전체 조회 응답 DTO 필드값들()
            );
            dtos.add(dto);
        }
        return dtos;
    }
  • R - 조회(선택)(Controller) :
    @GetMapping("/schedules/{scheduleId}")
    public ResponseEntity<선택 조회 응답 DTO> getSchedule(@PathVariable Long scheduleId) {
        return ResponseEntity.status(HttpStatus.OK).body(서비스.getOne(scheduleId));
    }
  • getOne메서드 생성(Service)
@Transactional(readOnly = true)//조회
    public 선택 조회 응답DTO getOne(Long scheduleId) {
        Entity entity = 레퍼지토리.findById(scheduleId).orElseThrow(
                () -> new IllegalArgumentException("없는 일정입니다.")
        );
        return new 선택 조회 응답 DTO(
                schedule.get선택 조회 응답 DTO 필드값들()
        );
    }

  • U - 수정(Controller) :
 @PutMapping("/schedule/{scheduleId}")
    public ResponseEntity<수정 응답 DTO> update(@PathVariable Long scheduleId, @RequestBody 수정 요청 DTO dto){
        return ResponseEntity.status(HttpStatus.OK).body(서비스.update(scheduleId, dto));
    }
  • update 메서드 생성(Service) :
@Transactional
    public 수정 응답 DTO update(Long scheduleId, 수정 요청 DTO dto) {
        Entity entity = 레퍼지토리.findById(scheduleId).orElseThrow(
                () -> new IllegalArgumentException("없는 일정입니다.")
        );

        entity.update(dto.update 생성자에 맞게);
        return new 수정 응답 DTO(
                schedule.수정 응답 DTO 필드값들()
                );
    }
  • 서비스 내 update 생성(더티채킹)(Entity) :
public void update(String title, String content) {
        this.title = title;
        this.content = content;
    }

  • D - 삭제(Controller) :
@DeleteMapping("/schedule/{scheduleId}")
    public ResponseEntity<Void> delete(@PathVariable Long scheduleId){
        서비스.delete(scheduleId);
        return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
    }
  • delete 메서드 생성(Service)
@Transactional
    public void delete(Long scheduleId) {
        boolean existence = 레퍼지토리.existsById(scheduleId);
        if (!existence) {
            throw new IllegalArgumentException("없는 일정입니다.");
        }
        레퍼지토리.deleteById(scheduleId);
    }

각 CRUD별 코드 작성함에 있어 순서들을 정리하였고 구멍없이 매꾸기 위해 반복숙달할 예정이다. 각 기능별로 특징들이 잡혀있는 것들을 볼 수 있고 위 내용들이 헷갈리기 때문에 체득을 해야만 한다고 생각한다. 앞으로 프로젝트 뿐만아니라 가장 기본적인 요소이기에 중요하니 손가락에 익혀야만한다고 생각한다. 잊을만 하면 다시 찾아보기 위해 정리해본다.

2개의 댓글

comment-user-thumbnail
2025년 11월 12일

반성하고 갑니다.

1개의 답글