📢 요청 처리와 매핑
👉 @RequestParam
- URL 파라미터로 전달받은 value를 메서드의 파리마터로 받을 수 있게 해주는 어노테이션
- 주로 쿼리 매개변수에서 값을 가져오는 데 사용
@GetMapping("/greet")
public String greet(@RequestParam(name = "name", required = false, defaultValue = "Guest") String name) {
return "Hello, " + name + "!";
}
👉 @PathVariable
- 변하는 값을 얻을 때 사용하는데, 매개변수와 Mapping URL 쪽에서 사용한 이름이 동일해야 함
- URL 경로에서 값을 추출하여 메서드의 인자로 전달할 때 사용
@GetMapping("/greet/{name}")
public String greetPath(@PathVariable String name) {
return "Hello, " + name + "!";
}
👉 @RequestBody
- 클라이언트가 보낸 JSON이나 XML 등의 HTTP 요청 본문(body)을 자바 객체로 변환시키기 위해 컨트롤러의 메서드 파라미터 앞에 사용
@RestController
public class MyController {
@PostMapping("/persons")
public ResponseEntity<String> addPerson(@RequestBody Person person) {
return ResponseEntity.ok("Person added successfully");
}
}
class Person {
private String name;
private int age;
}
👉 @RequestMapping
- 중복되는 URL 부분을 해당 어노테이션에 넣은 후 Mapping 부분에서 생략할 수 있음
@RequestMapping("/question")
👉 @GetMapping
- HTTP GET 요청을 특정 메소드에 매핑하기 위해 사용
- GET 요청
- GET은 서버의 리소스에서 데이터를 요청할 때 사용(DB로 따지면 GET은 SELECT에 가깝고, 멱등(연산을 여러 번 적용해도 결과가 달라지지 않음 = 리소스를 조회하는 것이라))
- GET은 요청을 전송할 때, 힐요한 데이터를 Body에 담지 않고, 쿼리스트링(URL 끝에 ?와 함께 이름과 값으로 쌍울 이루는 요청 파라미터)을 통해 전송
- GET 요청은 캐시가 가능(GET을 통해 서버에 리소스를 요청할 때, 웹 캐시가 요청을 가로채 리소스를 다시 다운로드 하는 대신 리소스의 복사본 반환)함
- GET 요청은 브라우저 히스토리에 남으며, 길이에 제한이 있고, 보안 상의 문제로 중요한 정보를 다루지 않는 것이 좋음
👉 @PostMapping
- 매핑을 담당하는 역할로, HTTP POST 요청만 받아들일 경우에 사용
- POST 요청
- POST 요청은 서버의 리소스를 새로 생성하거나 업데이트할 때 사용(DB로 따지면 Create에 가깝고, 멱등X(리소스를 생성/업데이트에 사용해서 POST 요청 발생 시 서버가 변경될 수 있음))
- POST는 리소스를 생성/변경하기 위해 설계되었기 때문에, HTTP 메세지의 Body에 담아 전송
- POST 요청은 캐시되지 않고, 브라우저 히스토리에 남지 않으며, 데이터 길이에 제한이 없음
- 메서드의 매개변수 이름과 템플릿의 항목 이름이 같아야 함
- @GetMapping과 매개변수가 다른 경우 같은 메서드 이름을 사용할 수 있음(메서드 오버로딩)
- 보안 등을 생각한다면 조회 빼고는 POST 처리하는 게 좋을 수도 있음
- GET과 POST를 제외한 요청은 HTML에서 적용이 안 됨 -> hiddenmethod를 키면 실제는 POST지만 요청을 이식해서 자동 변환(PATCH : 수정, DELETE : 삭제)
📢 검증과 상태 코드
👉 @Valid
- 매개변수 앞에 @Valid 어노테이션을 적용해야 Form 클래스에 어노테이션으로 설정한 검증 기능이 작동(바인딩)
BindingResult
- 항상 @Valid 뒤에 위치해야 하며, 어노테이션으로 인해 검증이 수행된 결과를 의미하는 객체
@PreAuthorize("isAuthenticated()")
@PostMapping("/create/{id}")
public String creatAnswer(Model model, @PathVariable("id") Integer id, @Valid AnswerForm answerForm, BindingResult bindingResult, Principal principal) {
}
👉 @NotEmpty
- Null 또는 빈 문자열("")을 허용하지 않음
@NotEmpty(message = "내용은 필수항목입니다.")
- message : 검증이 실패할 경우 화면에 표시할 오류 메세지
👉 @Email
- 주어진 문자열이 유효한 이메일 주소 형식인지 검사하는 역할
👉 @Size
- 문자열, 컬렉션, 배열 등이 특정 크기 조건을 만족하는지 검증하기 위해 사용
- 필드, 메서드 파라미터, 메서드 반환 값 등에 적용될 수 있으며, 주로 JPA 엔터티 클래스나 DTO(Data Transfer Object), Form Object 등에서 사용
@Size(min = 3, max = 24)
- 글자의 길이가 3바이트보다 작을 수 없고, 24바이트보다 클 수 없음
👉 @ResponseStatus
- HTTP 상태 코드와 선택적으로 이유(Reason)를 정의할 수 있음
- 특정 메서드나 예외 클래스에 붙여 사용하며, 해당 메서드가 호출되거나 예외가 발생했을 때 반환할 HTTP 상태 코드를 지정
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "entity not found")
- DataNotFoundException이 발생하면 @ResponseStatus 어노테이션에 의해 404오류(HttpStatus.NOT_FOUND)가 나타날 것
📢 데이터베이스와 JPA
👉 @Column
- 컬럼 명과 일치, 컬럼의 세부 설정을 위해 사용
- Entity의 속성은 @Column을 사용하지 않아도 테이블 컬럼으로 인식
- 인식하고 싶지 않다면
@Transient
사용
- 카멜 표기법이 DB 컬럼으로 전환될 때는 createDate -> create_date로 전환
@Column(columnDefinition = "TEXT")
- columnDefinition : 컬럼의 속성 정의
👉 @EntityListeners
- 엔터티 클래스에 적용되며, 특정 엔터티 리스너 클래스를 연결하는 역할
- 리스너 클래스는 엔터티의 생명주기 이벤트(예: 생성, 수정, 삭제 등)에 따라 특정 로직을 실행할 수 있음
@EntityListeners(AuditingEntityListener.class)
- AuditingEntityListener를 이용해 생성일과 수정일 등을 자동으로 관리
- 필드 레벨에는
@CreatedDate
와 @LastModifiedDate
등의 어노테이션을 사용하여 어떤 필드가 자동으로 관리되어야 하는지 지정
👉 @GeneratedValue
- 엔티티의 기본 키 필드가 어떻게 자동 생성되는지 지정
- 이 어노테이션은 보통 @Id 어노테이션이 붙은 필드와 함께 사용되어, 해당 필드의 값이 어떤 전략을 통해 생성될 것인지를 명시
@GeneratedValue(strategy = GenerationType.IDENTITY)
- strategy : 고유 번호 생성하는 옵션
- GenerationType.IDENTITY : 해당 컬럼에 독립적인 시퀀스를 생성하여 번호를 증가시킬 때 사용 == Auto_increment
👉 @ManyToOne, @OneToMany
- 관계 설정 : 엔티티에 서로 연결된 속성이라는 것을 명시해야 함
- 관계 설정할 때 사용하는 어노테이션 : @ManyToMany(N:N관계) @ManyToOne(N:1관계) @OneToMany(1:N관계) 등
@OneToMany(mappedBy = "question", cascade = CascadeType.REMOVE)
- mappedBy : 참조 엔티티의 속성명 -> Answer에서 Question이라고 선언했으니 question이라고 매핑
- cascade : OneToMany, ManyToOne 일 때(parent-child 관계), 엔티티의 상태가 변화하면 관계가 있는 엔티티에도 상태 변화를 전파시키는 옵션
- CascadeType.REMOVE : 질문 하나에 답변이 여러 개일 수 있는데, 질문을 삭제하면 답변들도 전부 삭제될 수 있게 작성한 속성(부모 엔티티가 삭제되면 자식 엔티티도 삭제되는 속성)
👉 @JoinColumn
- 두 엔티티 간의 관계를 데이터베이스 테이블의 컬럼에 매핑하는 역할
- 주로
@ManyToOne
, @OneToOne
, @OneToMany
, @ManyToMany
와 같은 엔터티 관계 매핑 어노테이션과 함께 사용
@JoinColumn
은 외래 키(foreign key) 관계를 설정할 때 사용되며, 해당 엔터티가 소유하고 있는 (즉, 외래 키가 있는) 테이블의 컬럼을 지정
- 이 어노테이션을 명시적으로 사용하는 것은 기본 동작(JPA의 기본 전략에 따라 FK 생성)을 덮어쓰거나, 추가적인 외래 키 제약 조건(예: nullable, unique 등)을 설정할 때 유용
@Entity
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "customer_id")
private Customer customer;
}
📢 스프링 컨테이너와 설정
👉 @Component
- 스프링 컨테이너에 등록하여 해당 클래스의 인스턴스를 스프링에서 직접 관리할 수 있게 됨 → 개발자가 직접 작성한 클래스를 Bean으로 등록하는 어노테이션
- 타임리프에서 @로 접근 가능
- 다른 클래스에서 해당 클래스의 인스턴스를 생성하고 사용할 때에도 스프링의 의존성 주입 기능을 활용하여 쉽게 관리할 수 있음
👉 @Configuration
- 스프링의 환경설정 파일임을 의미하는 어노테이션
👉 @EnableWebSecurity
- Security 구성 클래스에서 다양한 보안 구성을 수행할 수 있으며, 인증 및 권한 부여 매커니즘을 사용하여 웹 애플리케이션 보안을 확보
- 모든 요청 URL이 스프링 시큐리티의 제어를 받도록 만드는 어노테이션
- 어노테이션을 사용하여 Security 활성화하고, 이를 통해 Security를 구성하는데 필요한 설정 클래스를 자동으로 등록
- 해당 어노테이션을 사용하면 내부적으로 SpringSecurityFilterChain이 동작하여 URL 필터가 적용
👉 @Bean
- 메서드에 이 어노테이션을 붙이면 해당 메서드가 반환하는 객체가 Spring IoC(Inversion of Control) 컨테이너에 등록됨
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
👉 @ConfigurationProperties
- application.properties나 application.yml과 같은 외부 설정 파일에 정의된 속성들을 자바 객체에 자동으로 바인딩해줌
- 설정값들을 프로그램에서 쉽게 사용할 수 있게 됨
@ConfigurationProperties(prefix = "app.database")
- 아래처럼 사용할 수 있음
app:
database:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: secret
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "app.database")
public class DatabaseProperties {
private String url;
private String username;
private String password;
}
import org.springframework.beans.factory.annotation.Autowired;
public class SomeService {
@Autowired
private DatabaseProperties databaseProperties;
public void doSomething() {
String url = databaseProperties.getUrl();
String username = databaseProperties.getUsername();
}
}
📢 트랜잭션 관리
👉 @Transactional
- 메서드나 클래스에 적용하여 해당 부분이 트랜잭션의 범위에 포함되도록 지정
- 트랜잭션(Transaction)은 데이터베이스에서 데이터를 안전하게 처리하기 위한 작업의 단위
- 이 어노테이션을 사용하면 메서드의 실행이 하나의 트랜잭션으로 처리되며, 예외가 발생하면 자동으로 롤백됨
@Service
public class MyService {
@Transactional
public void doSomething() {
}
}
📢 접근 제어
👉 @PreAuthorize
- 메서드 호출 전에 검사
- "isAuthenticated()" : 요청에 대해 인증된 사용자만 접근할 수 있도록 설정하는 메서드 -> 로그인한 상태
@PreAuthorize("isAuthenticated()")
📢 생성자와 빌더
👉 @NoArgsConstructor
- 클래스에 기본 생성자를 자동으로 추가
- “기본 생성자"라는 것은 모든 필드를 초기화하지 않는 생성자를 의미
👉 @AllArgsConstructor
- 클래스에 모든 필드를 인자로 가지는 생성자를 추가
👉 @RequiredArgsConstructor
- 초기화되지 않은 final 필드 또는 @NonNull로 어노테이트 필드에 대해 생성자를 생성
- 즉, final 필드와 @NonNull로 표시된 필드 모두를 포함하는 생성자를 생성
👉 @Builder
- 빌더 패턴을 적용한 클래스를 생성
- 빌더 패턴은 객체 생성을 더 유연하고 코드 가독성을 높이는 패턴
👉 @SuperBuilder
- 빌더 패턴을 구현한 클래스를 자동으로 생성
- @Builder의 확장된 버전으로, 상속된 클래스 구조에서 Builder 패턴을 사용하고자 할 때 유용
- @SuperBuilder를 사용할 때는 상속 구조 내에서 모든 관련 클래스에 @SuperBuilder를 적용해야 함