Book
[ITEM 13] clone 재정의는 주의해서 진행해라
Cloneable 인터페이스 Cloneable은 복제해도 되는 클래스임을 명시하는 용도의 인터페이스다. public class Person implements Cloneable { //..... } 아쉽게도 Cloneable 인터페이스는 의도한 목적을 제대로 이루지 못했다. 왜냐하면 Cloneable 인터페이스에는 아무런 정의가 되지 않은 빈통 인터페이스다. public interface Cloneable { } clone 메서드가 정의 된 곳은 Object 클래스에 protected로 정의 되어 있다. @HotSpotIntrinsicCandidate protected native Object clone() throws CloneNotSupportedException; 그러면 Cloneable 인터페이스..
[ITEM 12] toString을 항상 재정의하라
Object의 기본 toString 메서드가 해당 클래스의 적합한 문자열을 반환하는 경우는 거의 없다. 이 메서드는 단순히 클래스이름@16진수로표현한해시코드 를 반환 할 뿐이다. toString의 일반 규약 ‘간결하면서 사람이 읽기 쉬운 형태의 유익한 정보' 를 반환해야 한다. ‘모든 하위 클래스에서 이 메서드를 재정의하라' 객체가 가지고 있는 주요 정보들을 모두 반환하는 것이 좋고 toString을 잘 구현한 클래스는 사용하기에 쉽고 디버깅하기 쉽다. toString을 구현할 때면 반환값의 포맷을 문서화할지 정해야 한다. 포맷을 명시하면 그 객체는 표준적이고, 명확하고, 사람이 읽을 수 있게 된다. 정적 팩터리나 생성자를 함께 제공하면 좋다. 단점 명확성을 얻을 수 있고 코드를 수정해야하는 유연성을 잃..
[ITEM 11] equals를 재정의하려거든 hashCode도 재정의하라
equals를 재정의한 클래스 모두에서 hashCode도 재정의해야 한다. 그렇지 않으면 equals 재정의 규약을 어기게 되어 문제를 일으킨다. 규약 equals 비교에서 사용되는 정보가 변경되지 않았다면, 애플리케이션이 실행되는 동안 그 객체의 hashCode 메서드는 몇 번을 호출해도 일관되게 항상 같은 값을 반환해야 한다. equals 메서드가 두 객체를 같다고 판단했다면, 두 객체의 hashCode는 똑같은 값을 반환해야 한다. equals 메서드가 두 객체를 다르다고 판단했더라도, 두 객체의 hashCode가 서로 다른 값을 반환할 필요는 없다. 단, 다른 객체에 대해서는 다른 값을 반환해야 해시테이블의 성능이 좋아진다. hashCode 재정의를 잘못했을 때 크게 문제가 되는것은 ‘논리적으로 ..
[ITEM 10] equals는 일반 규약을 지켜 재정의하라
equals() 메서드를 재정의 하지 않고 그냥 두면 해당 클래스의 인스턴스는 오직 자기 자신하고만 같게 된다. 재정의하지 않는 것을 권장 각 인스턴스가 본질적으로 고유 Thread 클래스의 equals() 가 좋은 예 인스턴스의 ‘논리적 동치성(logical equality)’을 검사할 일이 없다. 상위 클래스에서 재정의한 equals가 하위 클래스에도 맞는다. 예) 컬렉션 프레임워크의 구현체들은 추상클래스의 equals를 그대로 사용한다. equals() 를 호출할 일이 없다. 재정의해야 할 때는 언제일까? 상위 클래스의 equals가 논리적 동치성을 비교하도록 재정의 되지 않았을 때 값 클래스들이 해당됨 Integer String ….. 등 재정의를 하지 않아도 될 때 싱글톤이 보장되면 equals..
[Book] 18) 스프링 Security와 Oauth2.0으로 로그인 기능 구현하기! -1
👻 들어가기 앞서.. 스프링 시큐리티는 인증과 인가 기능을 가진 프레임워크입니다. 인터셉터, 필터 기반의 보안 기능을 구현하는 것보다 스프링 시큐리티를 통해 구현하는 것을 권장한다고 합니다. 확장성을 고려한 프레임워크여서 다양한 요구사항에 쉽게 추가하고 변경할 수 있습니다. 그리고 많은 서비스에서 로그인 기능을 소셜 로그인 기능으로 사용합니다. 왜 소셜 로그인 기능을 사용하나요? 로그인 기능을 직접 구현 하려면 보안, 인증, 찾기, 변경 같은 기능들을 전부 다 구현 해야합니다. 많은 시간 투자와 코드의 복잡성이 늘어나겠죠? 그러나 Oauth 로그인 구현시 로그인 기능을 대신 해주며 서비스 개발에 더욱더 집중 할 수 있도록 합니다. 이번장에서는 구글과 네이버 로그인을 연동하여 로그인 기능을 구현해보겠습니다..
[Book] 17) 수정 및 삭제 기능을 만들어보자!
😀 화면 구성해보기! {{>layout/header}} 게시글 수정 글 번호 제목 작성자 내용 {{posts.content}} 취소 수정 완료 삭제 {{>layout/footer}} 😀 Service 클래스에 수정 / 삭제 기능을 추가해보자! 수정 기능은 앞전에 만들어 놓았습니다. @Transactional public Long update(Long id, PostsUpdateRequestDto requestDto) { Posts entity = getEntity(id); entity.update(requestDto.getTitle(), requestDto.getContent()); return entity.getId(); } service 클래스에 삭제 기능을 추가해봅시다! @Transactional ..
[Book] 16) 전체 조회 화면 및 기능을 만들어보자!
🥢 전체 조회 화면 구성하기! 아래 코드는 앞전에 만든 index.mustache 파일에 있는 코드입니다. 게시글번호 제목 작성자 최종수정일 {{#posts}} {{id}} {{title}} {{author}} {{modifiedDate}} {{/posts}} 😀 Repository 에 전체 조회 기능 만들기!! PostsRepository 에 기능을 추가해봅시다. @Query("select p from Posts p order by p.id desc") List findAllDesc(); List 타입으로 Posts의 모든 데이터를 내림차순으로 받아옵니다. spring data jpa 의 기능으로 메서드 만으로 위와 같은 기능을 만들 수 있습니다. List** findAllByOrderByIdDesc*..
[Book] 15) 머스테치로 화면 구성을 해보자! -2
👻 인덱스 페이지 만들기! {{>layout/header}} Main Page 글 등록 {{#userName}} Logged in as:{{userName}} Logout {{/userName}} {{^userName}} Google Login Naver Login {{/userName}} 게시글번호 제목 작성자 최종수정일 {{#posts}} {{id}} {{title}} {{author}} {{modifiedDate}} {{/posts}} {{>layout/footer}} 👻 레이아웃 분리해보자! footer.mustahce header.mustache 👻 posts-save 페이지를 만들어보자! {{>layout/header}} 게시글 등록 제목 작성자 내용 취소 등록 {{>layout/footer}..
[Book] 14) 머스테치로 화면 구성을 해보자! -1
👻 머스테치 플러그인 설치! plugin 설정에 들어가서 handlebars/mustache 를 설치해 줍니다. 👻 머스테치 의존성 추가! build.gradle 파일에 implementation 'org.springframework.boot:spring-boot-starter-mustache' 의존성을 추가해 줍니다. 🕶 index 페이지를 만들어보자!. resources 파일의 templates 안에 index.mustache 파일을 생성해줍니다. 스프링 🕶 index 파일을 제어 하는 Controller 를 만들어야합니다. @Controller public class IndexController{ @GetMapping("/") public String index() { return "index"; ..
[Book] 13) JPA Auditing으로 생성시간/수정시간 자동화 하기!
👻 시간 엔티티 만들기! 매번 DB 에 생성시간과 수정시간을 삽입 하고 갱신 하는 것은 번거로운 일 입니다. 자동으로 생성시간과 수정시간을 관리해주는 JPA Auditing 을 사용합니다. 자 그러면 domain 패키지에 BaseTimeEntity 를 생성해봅시다. @Getter @MappedSuperclass // 해당 엔티티를 상속한 엔티티의 속성 값도 엔티티에 적용 @EntityListeners(AuditingEntityListener.class)// Auditing 기능을 적용 public class BaseTimeEntity { @CreatedDate // 엔티티가 생성되어 저장될 때 시간이 자동 저장 private LocalDateTime createdTime; @LastModifiedDate..
[Book] 12) H2 DB 웹 콘솔에서 직접 접근해보자!
👻 h2 db 웹 콘솔에서 직접 접근 하기! 지금까지 h2 db를 메모리에서 관리를 하였습니다. 지금은 db를 웹 콘솔에 직접 접근하여 관리를 해보겠습니다. application.properties 파일에 spring.h2.console.enabled=true 을 추가 해줍시다!. http://localhost:8080/h2-console 를 접속합니다. jdbc url 을 jdbc:h2:mem:testdb 으로 지정 해줍니다. 다음으로 concat 버튼을 눌러 접속 해줍니다. 접속한 db에 console 창에 select * from posts; 입력하여 db를 확인합니다.
[Book] 11) API 만들어보기! -4
🕶 업데이트 기능을 만들어 봅시다!. Controller 클래스에 기능 추가해보기! @PutMapping("/api/v1/posts/{id}") -> http put() 사용합니다. public Long update(@PathVariable Long id, @RequestBody PostsUpdateRequestDto requestDto) { return postsService.update(id, requestDto); } updateRequestDto 클래스를 활용하여 업데이트 할 데이터를 담아서 엔티티에 전달하게 합니다. updateRequestDto 클래스 생성해보기! @Getter @NoArgsConstructor public class PostsUpdateRequestDto{ private St..
[Book] 10) API 만들어보기! -3
👻 Repository 에 저장된 값을 조회하는 기능을 만들어보자! controller 클래스에 findById() 기능을 추가해봅시다. @GetMapping("/api/v1/posts/{id}") -> http get() 사용 public PostsResponseDto findById(@PathVariable Long id) { -> uri 에 있는 변수값을 설정 return postsService.findById(id); } 다음으로는 응답을 받아주는 ResponseDto 클래스를 생성해 봅시다. @Getter public class PostsResponseDto { private final Long id; // id private final String title; // 제목 private fina..
[Book] 9) API 만들어보기! - 2
👻 저장 API를 만들어 봅시다!. RestController 를 생성하여 save() 라는 기능을 만들어 봅시다. 현재 조립해야 할 클래스들은 PostsService 클래스와 PostsSaveRequestDto 클래스 2가지가 있습니다. 이 2가지도 같이 생성하겠습니다. @RequiredArgsConstructor -> final 필드의 생성자를 만들어줍니다. @RestController -> @ResponseBody + @Controller 인 기능입니다. public class PostsApiController { private final PostsService postsService; @PostMapping("/api/v1/posts") -> http 메서드의 Post 메서드를 사용합니다. pub..
[Book] 8) API 만들어보기! - 1
👻 들어가기 앞서.. API 를 만들기 전에 총 3개의 클래스들이 필요 합니다. Request 데이터를 받을 Dto API 요청을 받을 Controller 트랜잭션, 도메인 기능 간의 순서를 보장하는 Service Service에서 비지니스 로직을 처리 해야하는 오해가 있는데 Service 클래스는 트랜잭션, 도메인 간 순서 보장의 역할만 합니다. 그럼 비지니스 로직은 누가 처리하나요?? 도메인 클래스에서 비지니스 로직을 처리합니다. 다음 layer 그림을 봅시다. Web Layer 컨트롤러(@Controller) 와 뷰 템플릿 영역 입니다. 이외에도 필터(@Filter), 인터셉터, 컨트롤러 어드바이스(@ControllerAdvice) 등 외부 요청과 응답에 대한 전반적인 영역 입니다. Service ..