Self Code Review/(sparta) Spring 기초 - CRUD API

[Spring] Spring 구조와 API 흐름 이해하기1 (스파르타코딩클럽 - 웹개발의 봄, Spring 2주차)

밍굥잉 2022. 5. 25. 21:41

{ ⭐ 더 정리된 노션 버전 ⭐}

 

week 2 숙제 코드 흐름 이해하기

숙제 설명

fair-cheetah-80d.notion.site


Spring의 구조

1.Controller : 가장 바깥 부분, 요청/응답을 처리함.
2. Service : 중간 부분, 실제 중요한 작동이 많이 일어나는 부분
3. Repo : 가장 안쪽 부분, DB와 맞닿아 있음. (Repository, Entity) - 강의에서는 models

models - person.java

  1. lombok (import도 해주기)
    • person 클래스에 @Getter 적용 (기존 getName, getJob…을 대체함)
  2. 생성자 만들기
public Person(PersonRequestDto requestDto) {
        this.name = requestDto.getName();
        this.job = requestDto.getJob();
        this.age = requestDto.getAge();
        this.address = requestDto.getAddress();
    }

 

 

models - PersonRequestDto.java

  1. PersonRequestDto.java 클래스 생성
import lombok.Getter;

@Getter
public class PersonRequestDto {
    private String name;
    private String job;
    private int age;
    private String address;
}

API

POST - 생성

  1. controller - PersonController.java
@PostMapping("/api/persons")
//포스트 요청이 올 때 항상 실행되는 메소드 
    public Person createPerson(@RequestBody PersonRequestDto requestDto) {
        Person person = new Person(requestDto);
        return **personRepository**.save(person);
    }
  • PersonRequestDto requestDto : 데이터를 가져오는 소재(파라미터)
  • @RequestBody : Request의 body 영역에 있는 게 제대로 전달되기 위해 사용
  • personRepository의 save를 사용해서 person 값을 저장해야함.
    • (😋) But! personRepository 아직 생성 안됨

 

2. models - PersonRepository.java 인터페이스 생성

  • JPA를 사용하기 위해서 JpaRepository 상속을 해주는데 (extends JpaRepository)
  • person에 대한 것이고 Long이 빠져있다. (<Person, Long>)
public interface PersonRepository extends JpaRepository<Person, Long> {
}

 

 

3. models - person.java 파일

  • @Entity (테이블임을 알려줌), @NoArgsConstructor (기본 생성자 생성해주는 것) 을 Person 클래스에 추가
  • private key를 생성해주기 위해서 Long 타입의 Id 만들기
@GeneratedValue(strategy = GenerationType.AUTO)
// 생성 전략이 자동으로 증가 부여
@Id
private Long id;
// 각각의 컬럼에 대해서 지정하기
// 없으면 안된다 nullable = false

@Column(nullable = false)
private String name;

@Column(nullable = false)
private String job;

@Column(nullable = false)
private int age;

@Column(nullable = false)
private String address;

 

4. 다시 controller - PersonController.java

@RequiredArgsConstructor
//권한을 줄테니까 스프링에게 알아서 생성자를 생성해주라고 하는 것
@RestController
public class PersonController {
    private final PersonRepository personRepository;
		// PersonController 할 때 꼭 필요한거야 (final)
}
  • @RequiredArgsConstructor : ‘니가 PersonController 갖다 쓰려고 할 때, 멤버로 선언된 것 중에 final로 된 거 있으면 알아서 생성해줘’ 라고 권한을 넘겨줌
  • (😋) 이렇게 personRepository 생성 해줬음!!

 

5. controller - PersonController.java 에서 api 완성하기

@PostMapping("/api/persons")
// 포스트 요청이 올 때 항상 실행되는 메소드 
    public Person createPerson(@RequestBody PersonRequestDto requestDto) {
        Person person = new Person(requestDto);
        return personRepository.save(person);
    }
  • personRepository를 return 해주면 생성하는 POST API가 완성됨 !

 

GET - 조회

  1. controller - PersonController.java
@GetMapping("/api/persons")
    public List<Person> readPersons() {
        return personRepository.findAll();
    }
  • personRepository를 이용해 findAll을 해서 모든 사용자의 목록을 돌려줌
  • 도메인이 같아도 요청 방식에 따라 다른 결과를 보여줌. 최고 ..

 

PUT - 수정

  1. controller - PersonController.java
@PutMapping("/api/persons/{id}")
    public Long updatePerson(@PathVariable Long id, @RequestBody PersonRequestDto requestDto) {
    }
  • api 도메인에 {id}를 추가해 어떤 id의 값을 수정할지 알려줘야함
  • 파라미터 중요 !
    • (Long id, PersonRequestDto requestDto) 만 작성하면 도메인의 {id}와 매칭이 되는지, 요청을 보내는 body와 requestDto가 매칭이 되는지 스프링이 알 수 없음!
    • 각 파라미터에 @PathVariable (주소), @RequestBody 로 알려줘야함! 필수!
    • Long id : 어떤 id의 값을 수정하는지 주는 파라미터
    • PersonRequestDto requestDto : 데이터를 가져오는 파라미터
  • 수정을 하기 위해서는 (1) id에 해당하는 person 값을 찾아서, (2) 그것을 업데이트 시켜줘야함

(1) id에 해당하는 person 값 찾기 (personService에 적용할거야)

Person person = personRepository.findById(id).orElseThrow(
				() -> new IllegalArgumentException("아이디가 존재하지 않습니다.")
);
  • orElseThrow( ) : 없을 때는 이런 오류를 일으켜서 나한테 알려줘.
  • (❗) 하지만, 이 코드를 controller의 PUT에서 처리하면, service와 controller의 영역이 겹치게 됨.

(2) 업데이트 하기

@PutMapping("/api/persons/{id}")
    public Long updatePerson(@PathVariable Long id, @RequestBody PersonRequestDto requestDto) {
        return personService.update(id, requestDto);
    }
  • personService의 update 메소드에서 id를 반환하는 return 코드 작성.
    • (🤩) But! personService 아직 생성 안됨.

 

2. service - personService.java 클래스 생성

  • (🤩) personService 생성해줬음!
@RequiredArgsConstructor
@Service //서비스라고 알려줘야 함. 
public class PersonService {
    private final PersonRepository personRepository;

    @Transactional //이 메소드의 결과가 반드시 반영 돼야 해
    public Long update(Long id, PersonRequestDto requestDto) {
        Person person = personRepository.findById(id).orElseThrow(
                () -> new IllegalArgumentException("해당 id가 존재하지 않습니다.")
        ); 
    }
}
  • update 메소드를 만드는데 id를 돌려줄 거니까 Long 타입
  • (❗) PUT 1 - (1) 코드를 붙여주기
  • 즉, id 값으로 해당하는 person 값 찾는 과정을 붙여줌.
  • personRepository를 멤버 변수로 선언하고 (private final PersonRepository personRepository;)
  • 권한 주기 (@RequiredArgsConstructor)

 

3. models - person.java 에서 update 메소드 만들기

public void update(PersonRequestDto requestDto) {
        this.name = requestDto.getName();
        this.job = requestDto.getJob();
        this.age = requestDto.getAge();
        this.address = requestDto.getAddress();
    }
  • Person 메소드와 가져오는 데이터(파라미터)와 하는 일도 똑같음
  • requestDto에서 name, job, age, address 데이터를 받아서 내가 갖고 있는 person을 업데이트 함.

 

4. service - personService.java

  • service의 update 메소드 안에 update 해서 return 하는 코드를 추가해야 함.
person.update(requestDto);
return person.getId();

 

 

5. controller - PersonController.java

@RequiredArgsConstructor
//권한을 줄테니까 스프링에게 알아서 생성자를 생성해주라고 하는 것
@RestController
public class PersonController {
    private final PersonRepository personRepository;
		private final PersonService personService;
		//필요하면 언제든지 personService 써먹어~
}
  • personService를 멤버 변수로 선언하고 personService에 사용 권한을 줌.

 

DELETE - 삭제

  1. controller - PersonController.java
@DeleteMapping("/api/persons/{id}")
    public Long deletePerson(@PathVariable Long id) {
        personRepository.deleteById(id);
        return id;
    }
  • api 도메인에 {id}를 추가해 어떤 id의 값을 삭제할지 알려줘야함, Id의 타입은 Long
  • id값을 찾기 위해서 @PathVariable (주소)

 


프로그램 run

  1. 프로젝트 파일에 있는 HwkWeek01.Application.java
@EnableJpaAuditing
@SpringBootApplication
public class HwkWeek01Application {

    public static void main(String[] args) {
        SpringApplication.run(HwkWeek01Application.class, args);
    }
}
  • @EnableJpaAuditing : JPA를 자유롭게 쓸 수 있게 해줌