-
패스트캠퍼스 챌린지 3일차JAVA/Spring 2021. 11. 3. 19:48
1. Null Safety
Null Safety는 Null 연관성을 높이는 법이다.
- 아래와 같은 코드를 만들지 않는 방법
- 혹은 아래와 같은 널 체크를 하지 않아서 발생하는 NPE(Null Pointer Exception)을 방지하는 방법
- 완벽한 방법은 아니지만 IDE에서 경고를 표시함으로써 1차적인 문제를 방지하고, 정확한 에러 위치를 확인할 수 있도록 도움
public void method(String request) { if(request == null) return; // normal process System.out.println(request.toUpperCase()); }
@NonNull Annotation
- 해당 값이나 함수 등이 Null이 아님을 나타내는 어노테이션
- org.springframework.lang.NonNull 사용
- 메서드 파라미터에 붙이는 경우 : null이라는 데이터가 들어오는 것을 사전에 방지함
public void method(@NonNull String request) { // 이 부분에 Condition "request == null" is always "false" 라는 경고가 뜬다. if(request == null) return; // normal process System.out.println(request.toUpperCase()); }
- 프로퍼티에 붙이는 경우 : null을 저장하는 경우 경고
@NonNull public String request = "REQUEST"; public void method() { // normal process System.out.println(request.toUpperCase()); // "null" is assigned to a variable that is annotated with @NotNull 이라는 경고 메시지 뜸 request = null; }
- 메서드에 붙이는 경우 : null을 리턴하는 경우 경고, 응답값을 저장하거나 활용하는 쪽도 NonNull이라고 신뢰하고 사용한다.
@NonNull public void method() { // normal process System.out.println(request.toUpperCase()); // 'null' is returnd by the method declared as @NonNull 이라는 경고가 뜸 return null; }
@Nullable Annotation
- @NonNull과 반대로 해당 데이터가 null일 수 있음을 명시함
- 해당 어노테이션이 붙은 값을 사용하는 경우 null check를 항상 수행하도록 경고
@Nullable public String request = "REQUEST"; public void method() { // normal process // Method invocation 'toUppserCase' may produce 'NullPointerException' 이라는 경고가 뜸 System.out.println(request.toUpperCase()); }
2. 롬복 (lombok)
롬복은 보일러 플레이트 코드들(프로젝트 생성 시 반복적으로 작성해야 하는 코드들)을 간편하게 자동으로 생성해주는 라이브러리이다.
@Getter, @Setter
아래 코드를 보면 클래스에 정의된 프로퍼티들에 대해 getter와 setter가 정의되어 있다.
public class DevDto { String name; Integer age; LocalDateTime startAt; public String getName() { return this.name; } public Integer getAge() { return this.age; } public LocalDateTime getStartAt() { return this.startAt; } public void setName(String name) { this.name = name; } public void setAge(Integer age) { this.age = age; } public void setStartAt(LocalDateTime startAt) { this.startAt = startAt; } }
그러나 롬복을 이용하면 아래와 같이 반복적으로 getter와 setter를 정의하는 수고를 들이지 않아도 된다.
@Setter @Getter public class DevDto { String name; Integer age; LocalDateTime startAt; }
@ToString
setter와 getter 외에도 toString 어노테이션을 붙여서 해당 클래스의 프로퍼티 값들을 String화할 수 있다.
@ToString public class DevDto { String firstName; Integer age; LocalDateTime startAt; } // JUnit을 통한 Test class DevDtoTest { @Test void test() { DevDto devDto = new DevDto(); devDto.setFirstName("Harry"); System.out.println(devDto.getFirstName()); devDto.setAge(21); devDto.setStartAt(LocalDateTime.now()); // 통상적으로 devDto에 toString()을 붙여줘야함 // 하지만 ToString 어노테이션을 붙이면서 생략 가능 System.out.println(devDto); // DevDto(firstName=Harry, age=21, startAt=2021-11-03T17:36:57.201) } }
@NoArgsConstructor, @AllArgsConstructor, @RequiredArgsConstructor
생성자의 arguments를 제어하는 어노테이션도 존재한다.
// arguments가 없는 생성자를 만든다. @NoArgsConstructor // 모든 arguments를 포함하는 생성자를 만든다. @AllArgsConstructor // 요구되는 arguments(final 혹은 @NonNull이 붙은 프로퍼티)를 포함하는 생성자를 만든다. @RequiredArgsConstructor public class DevDto { String firstName; Integer age; LocalDateTime startAt; }
@Data
위에서 언급한 어노테이션들 대부분을 포함하는 어노테이션인 @Data도 존재한다.
// @Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode를 붙인 것과 동일. @Data public class DevDto { String firstName; Integer age; LocalDateTime startAt; }
그러나 @Dadta 어노테이션의 사용은 왠만해서는 피하는 것이 좋다. @ToString 어노테이션을 포함하고 있기에 원치 않는 경우에도 class가 String화되는 경우가 발생하기 때문이다.
@Builder
@Setter와 @Getter 어노테이션 대신 @Builder 어노테이션을 사용하는 방법도 있다. @Builder를 사용할 경우 코드의 응집력을 높여주고 변동성을 줄여주기 때문에 @Builder 사용을 권장한다고 한다.
// Lombok 덕분에 Builder를 손쉽게 사용할 수 있게 되었다. @Builder public class DevDto { String firstName; Integer age; LocalDateTime startAt; } ======================================== // JUnit 테스트 코드 class DevDtoTest { @Test void test() { // setFirstName, setAge 등으로 정의할 필요 없이 선언 시 정의가 가능 final DevDto devDto = DevDto.builder() .firstName("Harry") .age(31) .startAt(LocalDateTime.now()) .build(); System.out.println(devDto); } }
@Slf4j
@Slf4j 어노테이션을 이용하여 쉽게 로그를 출력하는 것도 가능하다.
@Slf4j public class DevDto { String firstName; Integer age; LocalDateTime startAt; public void printLog() { log.debug(getFirstName()); } } ================================== // JUnit 테스트 코드 class DevDtoTest { @Test void test() { final DevDto devDto = DevDto.builder() .firstName("Harry") .age(31) .startAt(LocalDateTime.now()) .build(); devDto.printLog(); // [Test worker] DEBUG com.example.devmaker.devmaker.dto.DevDto - Harry } }
@UtilityClass
개발에 쓰이는 여러 Utility적인 성격을 가지는 (포맷 변환, 계산 등) 메소드들을 모아둔 클래스를 정적으로 만들어주는 어노테이션
-> 상속을 못 받게 하고 private으로 쓰이게끔
@UtilityClass public class DevUtil { public static void printLog() { System.out.println(LocalDateTime.of(2021, 11, 3, 3, 15)); } public static void printNow() { System.out.println(LocalDateTime.now()); } }
3. HTTP 스펙
- 그냥 문자가 아닌 HyperText를 전송하는 데에 활용하는 프로토콜
HTTP Request 메시지 스펙
- 첫째 줄 : 요청라인 (HTTP 메서드 : GET, PUT, POST, DELETE 등)
- 두번째 줄부터 줄바꿈이 나오기 전까지 : Header (User-Agent, Accept 등)
- Header에서 줄바꿈 이후 : Request Body
POST / create-developer HTTP/1.1 Content-Type: application/json Accept: application/json { "developerLevel": "JUNIOR", "developerSkillType": "FULL_STACK", "experienceYears": 2, "memberId": "sunny.flower", "name": "sun", "age": 36 } // GET 요청일 때는 Request Body를 넣지 않고 POST 요청일 때는 QueryString을 통해 값들을 전달하기로 약속됨 // (넣어도 상관은 없음)
HTTP Response 메시지 스펙
- 첫째줄 : 상태라인 (200, 500 등)
- 두번째 줄부터 줄바꿈 나오기 전까지 : Header
- 헤더에서 줄바꿈 이후 : Response Body
HTTP/1.1 200 OK Content-Type: application/json Transfer-Encoding: chunked Date: Sat, 17 Jul 2021 15:33:34 GMT Keep-Alive: timeout=60 Connection: keep-alive { "developerLevel": "JUNIOR", "developerSkillType": "FULL_STACK", "experienceYears": 2, "memberId": "sunny.flower", "name": "sun", "age": 36 }
4. 1 Layer 구조의 어플리케이션
오직 Controller만을 생성해 동작하는 Application 예시이다.
com.fastcampus.programming.dmaker.controller.DMakerController
// 해당 class를 RestController라는 Bean으로 등록! // 가장 기본이 되는 Controller는 그냥 @Controller이지만 REST타입의 요청을 받을 수 있도록 @RestController를 준다. // (DmakerApplication이라는 레고 판에 Bean들을 하나씩 조립시키는 것인데 RestController 타입의 Bean을 조립시키는 것) @Slf4j @RestController public class DMakerController { @GetMapping("/developers") public List<String> getAllDeveleopers() { // GET /developers HTTP/1.1 log.info("GET /developers HTTP/1.1"); return Arrays.asList("Harry", "Paul", "Ashe"); } }
해당 Controller를 생성 후 Application을 실행시킨 다음 localhost:8080/developers로 접속하면
아래와 같은 화면을 볼 수 있다.
본 포스팅은 패스트 캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.
https://bit.ly/3FVdhDa'JAVA > Spring' 카테고리의 다른 글
패스트캠퍼스 챌린지 8일차 (0) 2021.11.08 패스트캠퍼스 챌린지 7일차 (0) 2021.11.07 패스트캠퍼스 챌린지 6일차 (0) 2021.11.06 패스트캠퍼스 챌린지 5일차 (0) 2021.11.05 패스트캠퍼스 챌린지 4일차 (0) 2021.11.04