Group Study (2020-2021)/ReactJS + Spring Boot ToyProject

[웹 2팀] 2. 웹 토이프로젝트에서 사용한 어노테이션 의미 알기

Leenk 2020. 12. 4. 22:58

웹 토이프로젝트의 Backe-end 코드를 되짚으며 Annotation과 의미를 정리하려고 한다. 본 토이프로젝트는 ReactJS + Spring Boot + MySQL을 사용하여 CRUD를 구현하였다. 참고한 튜토리얼은 다음과 같다.

www.youtube.com/playlist?list=PLGRDMO4rOGcNLnW1L2vgsExTBg-VPoZHr

 

ReactJS + Spring Boot CRUD Full Stack Application

This course designed for beginners to learn how to develop a full-stack CRUD application using React as frontend and spring boot as backend.

www.youtube.com

JPA Entity - Employee.java

@Entity
@Table(name = "employees")
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    @Column(name = "email_id")
    private String emailId;

1. @Entity : 영구 자바클래스 표시하여 Entity 클래스임을 명시한다. 테이블과 연결될 클래스임을 나타내는 것이다.

2. @Table(name="테이블명") : 매핑할 테이블명을 지정하여 엔티티가 매핑될 테이블의 세부정보 제공한다.

3. @Id : 기본키를 정의하며 모든 Entity클래스는 @Id설정이 필수이다.

4. @GeneratedValue(strategy = GenerationType.IDENTITY) : JPA가 생성하는 기본키의 전략을 정의한다. GenerationType.IDENTITY는 JPA가 기본키를 생성하도록 한다.

5. @Column(name = "데이터베이스의 컬럼명") : 해당 주석이 달린 필드에 매핑될 열의 속성을 정의한다. Entity클래스의 모든 필드는 데이터베이스의 컬럼과 매핑되어 따로 명시하지 않아도 되지만, 컬럼명이 다르거나 기본값이 다른 경우 표기를 위해 사용한다.

 

Spring Data Repository - EmployeeRepository.java

@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long>{

}

1. @Repository : Class-level의 어노테이션으로 데이터베이스에 접근하는 자바 클래스를 표시한다. Repository는 데이터베이스에 접근할 수 있는 DAO(Data Access Object)를 의미한다. 데이터베이스와 관련된 모든 오퍼레이션을 수행한다.

 

Custom Business Exception - ResourceNotFoundException.java

@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {

    private static final long serialVersionUID = 1L;

    public ResourceNotFoundException(String message) {
        super(message);
    }
}

1. @ResponseStatus : 이 주석은 method 혹은 exception class에 사용한다. 반환하길 원하는 상태 코드는 value에 이유는 reason으로 명시한다.

 

Spring Rest Controller - EmployeeController.java

@CrossOrigin(origins = "http://localhost:3000")
@RestController
@RequestMapping("/api/v1/")
public class EmployeeController {

    @Autowired
    private EmployeeRepository employeeRepository;

    // get all employees
    @GetMapping("/employees")
    public List < Employee > getAllEmployees() {
        return employeeRepository.findAll();
    }

    // create employee rest api
    @PostMapping("/employees")
    public Employee createEmployee(@RequestBody Employee employee) {
        return employeeRepository.save(employee);
    }

    // get employee by id rest api
    @GetMapping("/employees/{id}")
    public ResponseEntity < Employee > getEmployeeById(@PathVariable Long id) {
        Employee employee = employeeRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Employee not exist with id :" + id));
        return ResponseEntity.ok(employee);
    }

    // update employee rest api

    @PutMapping("/employees/{id}")
    public ResponseEntity < Employee > updateEmployee(@PathVariable Long id, @RequestBody Employee employeeDetails) {
        Employee employee = employeeRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Employee not exist with id :" + id));

        employee.setFirstName(employeeDetails.getFirstName());
        employee.setLastName(employeeDetails.getLastName());
        employee.setEmailId(employeeDetails.getEmailId());

        Employee updatedEmployee = employeeRepository.save(employee);
        return ResponseEntity.ok(updatedEmployee);
    }

    // delete employee rest api
    @DeleteMapping("/employees/{id}")
    public ResponseEntity <Map< String, Boolean >> deleteEmployee(@PathVariable Long id) {
        Employee employee = employeeRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Employee not exist with id :" + id));

        employeeRepository.delete(employee);
        Map< String, Boolean > response = new HashMap< >();
        response.put("deleted", Boolean.TRUE);
        return ResponseEntity.ok(response);
    }
}

1. @CrossOrigin : class와 method-level에서 cross origin requests가 가능하게 만드는 주석이다. 호스트가 다를 경우 CORS(Cross Origin Resource Sharing)는 도메인 간 통신을 가능하게 만든다. 도메인을 명시하지 않을 경우 모든 도메인에 대한 통신을 허용한다.

2. @RestController : class-level에서 사용되는 주석이며 @Controller와 @ResponseBody가 합쳐진 형태이다. @RestController는 클래스를 컨트롤러로 표기하는데, 이 때 컨트롤러는 모든 method가 뷰 대신 도메인 객체를 return한다. 이 주석을 class에 달면 클래스 속 모든 method에  @ResponseBody를 적용한 것과 같은 기능을 한다. JSON과 같이 클라이언트가 이해할 수 있는 형태로 도메인 개체를 HTTP response로 보낸다.

 +)@ResponseBody : 이는 request handler method에 사용된다. JSON 혹은 XML과 같은 형식으로 response body에 result type을 직접 작성해야 함을 나타낸다.

 +)@Controller : 해당 클래스가 Spring Controller임을 나타내는데 사용한다. 이 주석으로 인해 Spring MVC나 Spring WebFlux의 컨트롤러를 식별할 수 있다.

3. @RequestMapping : class와 method-level annotation이다. 웹 요청을 특정한 handler class나 handler method에 매핑하는데 사용한다. class에 사용하면 컨트롤러가 사용될 기본 URI가 생성되고 method에 사용하면 method가 실행될 URI를 제공한다.

4. @Autowired : 이 어노테이션을 통해 주석 기반 자동 연결 기능을 제공한다. setter method, field, constructor에 사용가능하다. 위 예시처럼 filed에 사용하고 값을 전달하면 Spring은 전달받은 값을 사용해 자동으로 field를 할당한다.

5. @GetMapping : 특정 handler method에 대한 HTTP GET 요청을 매핑한다. fetch를 위한 웹서비스 endpoint를 만드는데 사용된다.

6. @PostMapping : 특정 handler method에 대한 HTTP POST 요청을 매핑한다. 생성을 위한 웹서비스 endpoint를 만드는데 사용된다.

7. @PutMapping : 특정 handler method에 대한 HTTP PUT 요청을 매핑한다. 생성 또는 업데이트를 위한 웹서비스의 end point 생성에 사용된다.

8. @DeleteMapping : 특정 handler method에 대한 HTTP DELETE 요청을 매핑한다. 리소스를 삭제하는 웹 서비스의 end point를 만드는데 사용된다.

9. @PathVariable : 이 주석은 request handler method의 인수에 사용된다. HTTP 요청에 매핑되는 파라미터 값이 자동으로 들어간다.(매개변수인 URI의 동적 변경을 처리한다.) 정규식을 사용하여 해당 매개 변수를 지정할 수 있다.

10. @RequestBody : 이 주석도 request handler method의 인수에 사용된다. 해당 method의 매개변수가 HTTP response body의 값에 바인딩되어야함을 나타낸다. 그러면 HttpMessageConverter가 해당 HTTP 요청 메시지를 객체로 변환한다.

 

springframework.guru/spring-framework-annotations/

www.javatpoint.com/spring-boot-annotations