본문 바로가기
Language/Java

[Java] Lombok 실제 사용법(2)

by lucas_owner 2023. 1. 17.

Lombok 라이브러리 실제 사용법 및 적용법을 코드를 통해 알아보자!

 

롬복의 기본 개념과 어노테이션들에 대한 자세한 설명은 아래 링크에서 확인하세요! 

https://lucas-owner.tistory.com/26

 

[Java] LomBok이란? & 어노테이션 정리 (1)

Java 라이브러리 Lombok이란? + 자주 사용 어노테이션 정리! ○ LomBok 이란? LomBok이란 어노테이션 기반으로 코드 자동완성 기능을 제공하는 라이브러리이다. Spring, Spring Boot 로 Web 개발을 하다보면 반

lucas-owner.tistory.com

 

- 해당 코드 사용법은 필자의 개인적인 코딩 스타일이 적용되어 있고, 정답이 아닐수 있습니다! (상황에 따라 사용하세요!)


○ Code

- 우선 아래와 같은 일반적인 DTO 를 Lombok 을 적용시켜서 알아보도록 하자.

- Baisc DTO

public class StoreDTO {

    private String storeName;       /* 가게명 */
    private String storeTypeCode;   /* 가게 업종 코드 */
    private String tele;            /* 가게 전화번호 */
    private String storeType;       /* 업종명() */
    private String addr;            /* 가게 주소 */
    
    /...Getter, Setter, ToString.../
}

 

● @Data

- @Data 어노테이션은 주석내용과 같이

   @Getter, @Setter, @ToString, @RequiredArgsConstructor, @EqualsAndHashCode 어노테이션의 집합체이다.

- 해당 기능은 누가봐도 좋게 보인다고 생각한다. 다만 강력한 기능을 제공함에 따라, 그만큼의 부작용도 많다고 생각한다.

 

- JPA Entity 예시 : @Data 에는 @ToString이 포함되어있으므로, 양방향 연관관계에서 순환참조 문제가 발생한다.(무한)

- 예시 2 : setter 가 포함되어 있으므로, 객체의 안전성이 보장받기 힘들다. -> 이말은 객체를 어디서든지 변경할 수 있는 여지가 있는것이며 변경이 필요할 경우 메서드나 다른 기능을 사용하는것을 추천한다.

@Data // Getter, Setter, toString, RequiredArgsConstrutcor, EqualsAndHashCode
public class StoreDTO {

    private String storeName;       /* 가게명 */
    private String storeTypeCode;   /* 가게 업종 코드 */
    private String tele;            /* 가게 전화번호 */
    private String storeType;       /* 업종명() */
    private String addr;            /* 가게 주소 */
    
}

 

 

 

● @Getter,  @Setter

- @Getter, @Setter 의 경우 클래스 위에 적용시킨다면 모든 변수들에 적용이 된다.

- 아래와 같이 필드(변수) 위에 할당한다면 해당 변수에만 적용이 가능 하다.

 

예시.) 아래의 경우 storeName 에만 @Setter가 할당 되어 있으므로 dto(객체).set~ 메서드는 storeName 하나만 사용이 가능하다.

@Getter
public class StoreDTO {

	@Setter
    private String storeName;       /* 가게명 */
    private String storeTypeCode;   /* 가게 업종 코드 */
    private String tele;            /* 가게 전화번호 */
    private String storeType;       /* 업종명() */
    private String addr;            /* 가게 주소 */
}

 

 

● @ToString

- 클래스 전체에 적용 시킨다면 해당 클래스 변수들을 toString 메서드를 자동 완성시켜준다.

- toString을 적용하고 싶지 않다면? -> 원치 않는 필드 위에 @ToString.Exclude 를 붙여주거나

  클래스위에서 -> @ToString(exclude = "storeType")을 붙여주면 된다.

@ToString(exclude = "storeType")
public class StoreDTO {

    private String storeName;       /* 가게명 */
    private String storeTypeCode;   /* 가게 업종 코드 */
    private String tele;            /* 가게 전화번호 */
    private String storeType;       /* 업종명() */
    
    @ToString.Exclude
    private String addr;            /* 가게 주소 */


}

 

 

 

 

● @AllArgsConstructor

- 해당 어노테이션은 모든 필드를 사용하는 생성자를 만들어 주는 어노테이션이다.

@AllArgsConstructor
public class StoreDTO {

    private String storeName;       /* 가게명 */
    private String storeTypeCode;   /* 가게 업종 코드 */
    private String tele;            /* 가게 전화번호 */
    private String storeType;       /* 업종명() */
    private String addr;            /* 가게 주소 */



//  아래의 생성자를 @AllArgsConstructor를 통해 생성한다.
    /*public StoreDTO(String storeName, String storeTypeCode, String tele, String storeType, String addr) {
        this.storeName = storeName;
        this.storeTypeCode = storeTypeCode;
        this.tele = tele;
        this.storeType = storeType;
        this.addr = addr;
    }*/
}

 

 

● @NoArgsConstructor

- @NoArgsConstructor는 파라미터가 없는 생성자를 만들어준다.

@NoArgsConstructor
public class StoreDTO {

    private String storeName;       /* 가게명 */
    private String storeTypeCode;   /* 가게 업종 코드 */
    private String tele;            /* 가게 전화번호 */
    private String storeType;       /* 업종명() */
    private String addr;            /* 가게 주소 */
      
//  @NoArgsConstructor 사용시 만들어지는 생성자  
//	public Store() {}

}

 

 

● @RequiredArgsConstructor 

- 해당 annotation은 final 키워드가 붙은 필드를 포함하여 생성자를 생성해준다.

- DI 주입시 주로 사용한다.

  Controller가 Spring Container에 Bean 이 등록될 때 Service 를 주입시켜준다. 

- 가장 많이 쓰이는 예시로 Controller class 로 예제를 보겠다.

@RestController
@RequiredArgsConstructor
@Slf4j
@CrossOrigin(origins = "http://localhost:3000")
@RequestMapping("/item/v1/")
public class ItemBoardController {

    private final ItemBoardService service;

	// @RequiredArgsConstructor가 생성해주는 부분
	*/public ItemBoardController(ItemBoardService itemBoardService) {
    this.service = itemBoardService;
    }*/


	/.../
    
    }

 

● @EqualsAndHashCode

- 클래스에 대한 equals(), hashCode() 함수를 자동 생성해준다.

- 2개의 객체가 존재할 때 서로 같은 객체인지 판단하고 싶을 때 사용한다.

@Getter
@Setter
@ToString
@RequiredArgsConstructor
@EqualsAndHashCode(of = {"storeName"})
public class StoreDTO {
	
    @NonNull
    private String storeName;       /* 가게명 */
    private String storeTypeCode;   /* 가게 업종 코드 */
    private String tele;            /* 가게 전화번호 */
    private String storeType;       /* 업종명() */
    private String addr;            /* 가게 주소 */


}

- 적용 예시

@Slf4J
public class testClass() {

	Store store1 = new Store("store1");
    Store store2 = new Store("store2");
    Store store3 = new Store("store2");
	
    // 비교 
    log.debug(store1.equals(store2)); // false
    
    log.debug(store2.equals(store3)); // true
}

 

● @Builder

- 클래스위에 적용 한다면 해당 클래스 모든 변수에 대해서 빌더 패턴을 사용할 수 있게 해준다. 

- 특정 변수만에 적용 할 수 있다.

/.../
@Builder
public class StoreDTO {

    private String storeName;       /* 가게명 */
    private String storeTypeCode;   /* 가게 업종 코드 */
    private String tele;            /* 가게 전화번호 */
    private String storeType;       /* 업종명() */
    private String addr;            /* 가게 주소 */


}

- 사용 예제

@Slf4J
public class testClass() {

	Store store = Store.builder()
    				   .storeName("스토어1")
                       .tele("01012341234")
                       .build();
    
	/*
    store = [storeName="스토어1", tele="01012341234"]
	*/
}

 

 

● JPA Entity Lombok 적용 예제

@Entity
@Table(name = "store")
@ToString
@Getter
@NoArgsConstructor
public class Store extends Common {

    private String storeName;       /* 가게명 */
    private String storeTypeCode;   /* 가게 업종 코드 */
    private String tele;            /* 가게 전화번호 */
    private String storeType;       /* 업종명() */
    private String addr;            /* 가게 주소 */
	
    
    @Builder
    public Store(String storeName, String storeTypeCode){
        this.storeName = storeName;
        this.storeTypeCode = storeTypeCode;
    }
    
}

 

 

 

● 실무 예제 - (정답이 아님)

- 물론 사람마다, 프로젝트 따라 사용하는 방법은 천차 만별이 될것이다...

  Lombok 을 공부할때 "어? 이건 이렇게 사용하면 위험하다고 했는데,,,," 라는 경우가 굉장히 많았다.

  하지만 프로젝트를 설계한 아키텍처의 DTO 개발가이드는 아래와 같이 정의 되어있었다.

@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Slf4J
@Builder
public class StoreDTO {
	
    @NonNull // Null이면 안되는 필드
    private String storeName;       /* 가게명 */
    private String storeTypeCode;   /* 가게 업종 코드 */
    private String tele;            /* 가게 전화번호 */
    private String storeType;       /* 업종명() */
    private String addr;            /* 가게 주소 */
    
    /... 추가 Inner DTO.../
    
}

- LomBok에 대해 수많은 글을 보면 권장하는 방법은 ~ 이런방식이 좋다. 라는 글을 봤을것이다.

  그 글과 위의 가이드 코드는 괴리감이 크다. 

 

- 공부를 했음에도 나는 아직도 DTO는 어떻게 사용하는게 좋은 코드인지는 잘 모르겠다.

위의 가이드를 굳이! 작성한 이유는 나와 같이 신입개발자, 주니어개발자분들에게 조금이라도 도움이 됬으면 하는 의도로 작성 하였다.

만약 DTO 구조에 대해서 좋은 방법이 있다면 언제든지 공유해주시면 좋을것 같다. 

 

 


부족한 점이 많은 글이지만 누군가에게는 도움이 되었으면 좋겠다.

 

틀린점, 더 좋은 설명이나 방법이 있다면 언제든 공유해주세요!! 피드백은 감사합니다~

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형

댓글