일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 문제풀이
- 스프링
- MYSQL
- 백준
- CJ UNIT
- 알고리즘
- 파이썬
- 정보처리산업기사
- 백준알고리즘
- kotlin
- SW봉사
- python
- 소프티어
- 회고
- 공부일지
- 코딩봉사
- 자바
- 데이터베이스
- softeer
- 코틀린
- 프로그래머스
- java
- programmers
- 1과목
- 백준 알고리즘
- 시나공
- 코딩교육봉사
- BFS
- C++
- SQL
- Today
- Total
JIE0025
[Spring] Annotation 본문
개인적으로 공부하면서 정리한 내용입니다 : )
FLAG Project - BE Study
2022.11.10
Annotation
- Annotation
- Spring Annotation
- 주요 Annotation
- Spring boot Annotation
- Spring MVC Annotation
- JPA Annotation
- JUnit Annotation
✅ Annotation
⏺ 어노테이션 용도
- 컴파일러에게 코드 작성 문법 에러를 체크하도록 정보 제공
- SW개발 툴이 빌드/배치시 코드를 자동 생성할 수 있도록 정보 제공
- 런타임시 특정 기능을 실행하도록 정보 제공
스프링 주요 어노테이션
✅ 스프링 MVC Annotation
⬛️ Config
@Configuration
스프링 설정 정보로 인식
- 어노테이션 기반 환경 구성, 빈 설정을 담당하는 클래스가 됨
- 이 클래스 안에서 @Bean어노테이션 메서드 선언시 메서드를 통해 스프링 빈을 정의하고 생명주기를 설정하게 됨.
- 스프링 빈이 싱글톤을 유지하도록 추가 처리를 함(스프링 빈 스코프가 싱글톤이 아니면 추가처리 안함)
@Bean
컨테이너에 빈을 등록
개발자가 컨트롤이 불가능한 외부 라이브러리들을 빈으로 등록하고 싶을 때 사용함.
메소드/어노테이션 단위에 붙일 수 있다.
@Component
스프링 컨테이너에 빈을 알아서 등록하게 만듬
컴포넌트 스캔 : @Component를 명시해 빈을 추가하는 방법
컴포넌트 스캔 대상 : @Controller, @Service, @Repository, @Conficguration (@Component의 상속을 받고 있어서)
* @ComponentScan("com.sdoaod.web.controller")
--- 나중에 봐야지 https://oingdaddy.tistory.com/254
어노테이션은 아니지만 같이 보면 좋을것 같아 함께 추가
⬛️ DTO
DTO(Data Transfer Object)는 계층 간 데이터 교환을 하기 위해 사용하는 객체,
DTO는 로직을 가지지 않는 순수한 데이터 객체(getter & setter 만 가진 클래스)
- 유저가 자신의 브라우저에서 데이터를 입력하여 form에 있는 데이터를 DTO에 넣어서 전송한다.
- 해당 DTO를 받은 서버가 DAO를 이용하여 데이터베이스로 데이터를 집어넣는다.
https://melonicedlatte.com/2021/07/24/231500.html
⬛️ repository
@Repository
스프링 데이터 접근 계층으로 인식, 해당 계층에서 발생하는 예외는 모두 DataAccessException으로 변환함.
→ 나중에 ComponentScan으로 찾아서 Bean으로 등록됨
@Repository
public class UserRepoImpl implements UserRepository {
// ...
}
⬛️ Service
@Service
특별한 처리는 하지 않지만, 핵심 비지니스 계층 인식에 도움을 줌
Bean으로 관리되기 위해 명시
@Autowired
스프링 빈을 가져오는 가장 기본적인 방법
- IoC컨테이너안에 존재하는 Bean을 자동으로 주입한다.
- 필드, 메서드, 생성자에 추가 가능하다.
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepo;
// ..
}
빈으로 UserRepository가 있을 때, 자동적으로 가져와서 주입해 종속된다.
@Qualifier
동일한 타입의 Bean객체 두개가 있을 때 해당 Bean id값을 지정해 구분가능하게 한다.
@Qualifier("해당id") 를 설정, @Autowired와 함께 선언
⬛️ Controller
@Controller
스프링 MVC 컨트롤러 인식
Bean으로 관리되기 위해 명시
@RequestMapping()
method에 명시된 방식으로 value path를 요청하는 경우
- value : 요청받은 url 설정
- method : 어떤 방식으로 받을지 정의 (GET, POST, PUT, DELETE)
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
return "home"; // return : logical view name
}
불편하다.
@RestController
public class HelloController {
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String helloGet(...) { ... }
@RequestMapping(value = "/hello", method = RequestMethod.POST)
public String helloPost(...) { ... }
@RequestMapping(value = "/hello", method = RequestMethod.PUT)
public String helloPut(...) { ... }
@RequestMapping(value = "/hello", method = RequestMethod.DELETE)
public String helloDelete(...) { ... }
}
--------------개선
@RestController
@RequestMapping(value = "/hello")
public class HelloController {
@GetMapping()
public String helloGet(...) { ... }
@PostMapping()
public String helloPost(...) { ... }
@PutMapping()
public String helloPut(...) { ... }
@DeleteMapping()
public String helloDelete(...) { ... }
}
@RequestMapping을 클래스에 설정하고, 새로운 어노테이션 사용
추가 url을 붙히고 싶을 때 @GetMapping("/hihi")이런식으로 넣으면 됨.
* 당연한 말이지만
@RequestMapping 은 클래스, 메서드에 붙힐수있고
@GetMaping들은 메서드에만 붙힐수있다.
⬛️ 서버-클라이언트 통신 관련 (?비동기랑만 관련있는지 잘 모르겠음?)
@ResponseBody
비동기통신을 하는 상황에서
클라이언트에서 서버로 요청 메세지를 보낼 때, 본문에 데이터를 담아서 보내야 하고,
서버에서 클라이언트로 응답을 보낼때에도 본문에 데이터를 담아서 보내야 한다.
이 본문이 바로 body
즉, 요청본문 requestBody, 응답본문 responseBody 을 담아서 보내야 한다.
대표적으로 JSON형식으로 데이터를 주고받는다.
@RestController
@Controller와 다르게, @RestController는 리턴값에 자동으로 @ResponseBody가 붙게된다
별도 어노테이션을 명시해주지 않아도 HTTP 응답데이터(body)에 자바 객체가 매핑되어 전달 됨
*********
@Controller를 사용하면 바디를 자바 객체로 받기 위해서
@ResponseBody 어노테이션을 반드시 명시해주어야함.
*********
클라이언트에서 서버로 요청 메세지를 보낼 때 Json data를 요청 본문에 담아서 서버로 보내는데 다음과 같은 두 방식이 사용된다.
@RequestBody , @RequestParam
@RequestParam : url상에서 데이터를 전달하는 경우(form 태그 등)
@RequestBody : 그 외의 경우에 사용
@PathVairable
url경로에 변수를 넣어주는 것.
- @RequestMapping 어노테이션 값으로 {템플릿변수} 를 사용
- @PathVariable 어노테이션을 이용해서 {템플릿 변수} 와 동일한 이름을 갖는 파라미터를 추가하면 됨
- RequestMapping 어노테이션에 변수를 포함하고 있음!
@RequestMapping(value = "/user/email/{email}", method=RequestMethod.GET)
이 형식에서 아래처럼 쓸 수 있다. (사실 안써봐서 잘모르겠다 직접 써보면서 익혀야할것 같다.)
@RequestMapping(value = "user/email/{email:.+}", method = RequestMethod.GET)
public ModelAndView getUserByEmail(@PathVariable("email") String email) {
- null, 공백값 들어가는 파라미터는 적용하지 말기
- Spring 에서 @PathVariable 사용하여 값을 넘겨받을때 값에 . 가 포함되어 있으면 .포함하여 그뒤가 잘려서 들어온다는 것!
RequestParam | PathVariable |
http://192.168.0.1:8080?aaa=bbb&ccc=ddd | http://192.168.0.1:8080/bbb/ddd |
너무 많아서,ㅡ 아래는 나중에 할란다 ㅠㅠ
@PropertySource
@CookieValue
@Lazy
@Value
@Required
✅ JPA Annotation
javax.persistence 패키지 않의 수많은 어노테이션 인터페이스들이 존재
@Entity
클래스가 DB 테이블과 1:1 매칭
- 기본 생성자가 꼭 필요
- final, enum, interface, innter class에서는 사용 불가
- 필드(변수)를 final로 선언 불가
아래 예제는 user2 테이블이 생성된다.
@Entity(name = "user2")
public class User {}
@Table(name="??")
엔티티와 매핑할 테이블 지정
속성 | 기능 |
name | 매핑할 테이블 이름 생략시 엔티티 이름(@Entity(name="~") 사용 |
catalog | catalog 기능이 있는 DB에서 catalog 매핑 |
schema | schema기능이 있는 DB에서 schema 매핑 |
uniqueContraints | DDL 생성시 유니크 제약조건 생성 ※ 스키마 자동 생성 기능을 사용해 DDL을 만들 때만 사용 |
@Table(name= "user3")
name속성 추가시 테이블이름이 name값으로 설정, 생략시 Entity이름으로 테이블이 만들어짐
@Column
객체 필드를 테이블 컬럼과 매핑
//옵션 왕많아서 그냥 생략함 검색하면서 써야겠다.
@Id
멤버변수가 테이블의 Primary key가 됨
@GeneratedValue(stargety=GenerationType.AUTO)
옵션에 따라 JPA 구현체가 자동으로 생성 전략을 결정
- AUTO (default) : JPA 구현체가 자동으로 생성 전략을 결정한다.
- IDENTITY : 기본키 생성을 데이터베이스에 위임한다.
ex) MySQL- AUTOINCREMENT를 사용해 기본키를 생성함. - SEQUENCE : 데이터베이스의 특별한 오브젝트 시퀀스를 사용해 기본키를 생성한다.
- TABLE : 데이터베이스에 키 생성 전용 테이블을 하나 만들고 이를 사용해 기본키를 생성한다.
@Access
JPA가 엔티티 데이터에 접근하는 방식을 지정함.
접근 방식 | 기능 |
AccessType.FILED | 필드에 직접 접근 필드 접근 권한이 private여도 접근 가능 |
AccessType.PROPERTY | getter를 통해 접근 |
@Enumerated(EnumType.STRING)
자바 enum타입 매핑시 사용
value | EnumType.ORDINAL : enum 순서를 DB에 저장 EnumType.STRING : enum이름을 DB에 저장 |
@Temporal
날짜 타입 매핑시 사용
value | TemporalType.DATE : 날짜, DB date 타입과 매핑(예 : 2020-02-12) TemporalType.TIME : 시간, DB time 타입과 매핑(예: 12:12:12) TemporalType.TIMESTAMP : 날짜와 시간 DB timestamp타입과 매핑(예 : 2020-02-12 12:12:12) |
@Transient
DB에 저장도 조회도 안하고, 임시로 객체에 값을 보관할 때 사용
나..중..
@JoinColumn
Join할 컬럼 지정
@JoinTable
N:N 조인에 해당하는 테이블 선언
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@JsonNaming
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Transactional(readOnly = true)
@Modifying
@Query(value = "truncate table reply", nativeQuery = true)
@RequiredArgsConstructor
✅ JUnit Annotation
@SpringBootTest
- 통합 테스트를 위한 환경을 준비
- 모든 빈들을 스캔하고 애플리케이션 컨텍스트를 생성하여 테스트를 실행
@Transactional
Transaction을 begin하고 commit까지 시켜주는 어노테이션
Exception 발생시 Rollback까지 시켜줌
@AutoConfigureMockMvc
- Controller의 API를 테스트하는 용도인 MockMvc 객체를 주입 받음
- Perform()메소드를 활용하여 컨트롤러의 동작을 확인할 수있음
- andExpect(), andDo(), andReturn() 등의 메소드를 같이 활용함
@WithMockUser
spring security에서 제공하는 어노테이션- 인증이 된 상태로 테스트를 진행하도록 도와줌
*SecurityconotextHolder에 UsernamePasswordAuthenticationToken이 담긴 상태를 만들어준다.
[ @Autowired와 @MockBean, @SpyBean ]
스프링부트가 제공하는 테스트 어노테이션들은 실제 스프링 컨텍스트를 사용해 빈들을 등록한다. 그러므로 @Autowired로 등록된 빈을 주입받을 수 있다. 특정 객체를 모킹하고 싶은 경우에는 @MockBean과 @SpyBean를 사용하면 된다.
@MockBean: 해당 객체를 Mock된 빈으로 등록함@SpyBean: 해당 객체를 Spy된 빈으로 등록함
@Mock
Mock 객체에 대해 더더 알아보고 추가하자.
Mockito에서 Mock 객체를 제공해준다고 위에서 언급이 되었는데, Mock 객체란 다음과 같다. Mock 객체란 개발한 프로그램을 테스트할 때 테스트를 수행할 모듈과 연결되는 외부의 다른 모듈을 흉내 내는 가짜 모듈을 생성하여 테스트의 효율성을 높이는 데 사용하는 객체
@MockBean
- 테스트할 클래스에서 주입 받고 있는 객체에 대해 가짜 객체를 생성해주는 어노테이션
- 해당 객체는 실제 행위를 하지 않음
- given() 메소드를 활용하여 가짜 객체의 동작에 대해 정의하여 사용할 수 있음
@BeforeEach
각 테스트 함수가 불리기 전에 매번 호출
@Test
테스트 대상 메소드 지정
@Test(timeout=5000)
public void testSum(){
}
@DisplayName("이름!")
테스트 이름 표시해 가독성 높임
@Before
선언시 해당 메서드는 @Test 메소드가 실행되기 전 실행됨
@Test메서드에서 공통으로 사용하는 코드를 @Before 메서드에 선언하여 사용
@After
선언시 해당 메서드는 @Test 메소드가 실행된 후 실행됨
아래 어노테이션은 해당 테스트 클래스에서 전/후에, 딱 한번씩 수행되도록 지정된다.
@BeforeClass
@BeforeClass 어노테이션은 @Test 메소드보다 먼저 한번만 수행되어야 할 경우에 사용
@AfterClass
@AfterClass 어노테이션은 @Test 메소드 보다 나중에 한번만 수행되어야 할 경우에 사용
references
https://www.informit.com/articles/article.aspx?p=2027052&seqNum=6
https://www.happykoo.net/@happykoo/posts/256
https://www.charlezz.com/?p=1167
https://www.youtube.com/watch?v=o6-gRZfQqOE
https://cjw-awdsd.tistory.com/46
https://zepettoworld.tistory.com/4
1) form 태그를 이용해 요청메시지 전송시
@RequestBody → String 데이터로 전달됨
@RequestParam → 데이터를 저장하는 이름으로 메서드의 변수명을 설정
2) json 형식으로 데이터 전송시
//@RequestParam 은 url 상에서 데이터를 찾음
http://localhost:8080/receive?name=jun&age=13
우리가 위에서 <form> 태그를 이용하여 데이터를 입력하고 제출 버튼을 누르면 입력한 데이터들이 url을 통해서 전달된다.
json형식으로 전송시 url은 변함이 없고 body에 데이터를 포함해 전송하기 때문에 @RequestParam으론 받을 수 없음.
@Controller
public class UserController {
@PostMapping("/receive")
public String age(@RequestBody String req) {
System.out.println("통신 성공");
System.out.println(">>> " + req);
return "result";
}
}
//출력 결과
//통신 성공
//>>> name=jun&age=13
--------------------------
@Controller
public class UserController {
@PostMapping("/receive")
public String age(@RequestParam String name) {
System.out.println("통신 성공");
System.out.println(">>> " + name);
return "result";
}
}
//출력 결과
//통신 성공
//>>> jun
'백엔드 > 스프링, 스프링부트, JPA, Spring Webflux' 카테고리의 다른 글
[설계] Category ERD, Request URI, 임시데이터 생성 (0) | 2022.12.16 |
---|---|
[Spring] DI/ IOC (0) | 2022.12.08 |
[Spring] 스프링 빈(bean), 스프링 컨테이너, 빈 등록하는 방법 (0) | 2022.11.23 |
[Spring] QueryDSL (0) | 2022.11.13 |
[JPA] 3장 영속성 관리 (0) | 2022.11.05 |