본문 바로가기
회고

210521_TIL

코동이 2021. 5. 22.

1. Facts(사실, 객관)

- 클린코드 8장, 9장, 10장

- Adapter 패턴 공부

- Service, ServiceImpl 구분에 대한 이유 공부

- 인터페이스에 대한 강의

- JPA 상속매핑에 대한 강의

2. Feelings(느낌, 주관)

- 클린코드 8장, 9장, 10장을 읽었습니다. 이상하게 두껍지만 읽을수록 너무 재미있습니다. 어쩌면 이 책은 방대한 주제를 조금씩만 다뤄서 그렇다고 생각합니다. 원래 의도는 8장 혹은 8,9장만 읽을려고 했는데 쉽고 재미있게 풀어쓴 책이라 그런지 거부감 없이 쭉쭉 읽었습니다. 8장의 경계에서 Adapter 패턴을 유심히 보며 인터페이스에 대한 궁금증이 생겨 하루종일 인터페이스를 다방면으로 공부했습니다. 10장 클래스에 나오는 OCP원칙에서도 인터페이스가 중요한 역할을 해야 하는 것도 알았습니다.

 

- 인터넷 강의 중에 가보면 아주 간단하게 디자인패턴을 설명하고 예시를 보여주는 영상들이 있습니다. 유무료로 간단히 맛을 본 적이 있는데, 필요한 때에 다시 한번씩 들춰보면서 공부하는 맛이 있습니다. 클린코드 8장에 나온 Adapter 패턴도 다시 영상을 보면서 인터페이스의 중요성을 깨달았습니다. 

 

- 웹 프로젝트에서 Service와 ServiceImpl을 나누어 사용하는 프로젝트들을 많이 보고 어떻게 사용하는지 궁금증을 가졌습니다. 그러던 중, 흥미있는 글을 발견하고 인터페이스의 존재 목적을 다시 생각해보게되었습니다.

3. Findings (배운 점)

 

- 웹 프로젝트에서 Service와 ServiceImpl을 무작정 나누는 것은 좋지 못하다는 것을 알았습니다. 인터페이스로 만드는 것은 다양한 구현 방식을 염두하여 세운 전략이어야 합니다. 정말 단순한 CRUD Service를 인터페이스까지 만들어서 구현해야하는가는 고민이 필요합니다.

* 클린 코드

*8장 경계

- 대표적으로 Map은 사용자에게 필요하지 않은 기능까지 제공하는 경계 인터페이스이다. 이 경계 인터페이스를 여기저기로 넘길 경우, 인터페이스가 변경되었을 때 엄청난 수정이 필요하다. 따라서, 클래스로 한번 감싸서 감추는 것이 훨씬 현명한 선택이다.

- 외부의 API가 내 프로젝트에 필요할 때 미리 간단한 테스트코드를 작성하여 익히는 "학습 테스트"를 한다. 이 테스트 이후 필요한 기능들을 마찬가지로 한번 감싸는 캡슐화를 한다

- 테스트코드를 작성해두면 나중에 새로운 버젼으로 이전이 쉽다

 

*9장 테스트

TDD 3법칙

- 실패코드 작성하기 전까지 실제코드 작성하지 않기

- 컴파일이 아닌 실행이 실패할 정도의 짧은 단위테스트 작성

- 현재 실행 실패 테스트가 통과할 정도로만 실제코드 작성하기

이것을 따르면, 테스트와 개발이 30초 주기로 묶인다~!!

 

- 테스트하는 단위는 작게, assert 갯수는 적게

 

F.I.R.S.T 법칙

fast : 빠르게 작성한다

independent : 테스트별로 독립적인 실행이 가능하다

repeatedly : 테스트는 어떤 환경에서도 반복될 수 있다

self-validating : 테스트 스스로 성공, 실패결과가 명확해야한다

timely : 테스트는 실제 코드 구현 이전에 작성한다

 

*10장 클래스

- 이전에 함수와 마찬가지로 클래스 역시 단위가 작아야, 작아야, 작아야한다

- 클래스가 변경될 경우, 그 이유가 1가지여야 하는 SRP 원칙

- 확장에는 열려있고, 수정에는 닫혀있는 OCP 원칙

- 응집도가 높게 클래스를 만들어야 한다.(클래스 변수를 각 메서드에서 최대한 사용한다 ex)Stack)

반대로 한 클래스에서 특정 응집도가 확인되면 새로운 클래스로 분리한다

 

* JPA 상속관계

- 객체는 부모-자식의 상속관계가 있지만, DB에서는 없다 따라서 전략이 필요하다

- 자식클래스가 부모 클래스를 extends로 상속한다는 것은 같다

 

1. 조인전략

- 부모 id와 자식 id를 일치시키고, 마치 객체의 부모-자식 관계를 만들어주는 것이다.

@Entity
@Inheritance(Stragy = InheritanceType.JOINED)
@DiscriminatorColumn("DTYPE")
public class Item {
...
}

- 부모 테이블과, 자식 테이블은 같은 id를 공유한다

- 부모 테이블에서는 자식들을 구분할 수 있는 칼럼을 만든다(@DiscriminatorColumn)

장점 : 설계 깔끔, 저장공간이 효율적

단점 : Join 많다, Insert 2번 필요하다

 

2. 싱글 테이블 전략

- 조인 전략의 JOINED에서 SINGLE_TABLE로만 바꿔주면 쉽게 구현이 가능하다

- 여러개의 클래스를 만들어 둘 지라도, db는 1개의 클래스 안에 모든 정보가 담긴다

@Entity
@Inheritance(Stragy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn("DTYPE")
public class Item {
...
}

장점 : 테이블이 하나이기 때문에 조회쿼리 단순, 성능 빠름

단점 : 사용하지 않는 칼럼들은 모두 null, 테이블이 너무 커지면 오히려 성능 저하

 

3. 구현클래스마다 테이블 전략

- 절대절대 쓰지 않는다. 각 테이블이 서로 묶이는 공통이 없기 때문에 좋은 설계가 아니다

- 따라서 @DiscriminatorColumn 도 필요가 없다

- 심지어 부모 클래스는 추상 클래스어야 한다. 왜냐하면 Item 클래스는 존재하지 않는 것이 전제이기 때문

@Entity
@Inheritance(Stragy = InheritanceType.TABLE_PER_CLASS)
public abstract class Item {
...
}

 

*Adapter 패턴

예시로 110V, 220V를 많이 든다. 한국에서 220V 제품을 사용하기 때문에 대부분 220V단자이지만 외국에서 110V 제품을 가져왔다고 생각해본다. 단자가 호환이 되지 않아 사용할 수 없고, 110V를 220V로 변경해주는 Adapter가 필요하다.

 

여기서 핵심은 외국제품의 110V를 220V로 튜닝한다거나, 220V단자 내부를 바꿔서 110V로 수정하지 않는다. 외국제품의 110V전선이 봉합되어있어 연 순간 제품은 고철이되고(가정), 220V단자 내부를 바꾸면 기존에 쓰고 있던 모든 220V 제품들을 사용할 수 없게 되는 것이다.

 

따라서 Adapter를 이용해 2개가 호환이 되도록 잘 연결해주어야 한다. 우리는 너무나도 당연하게 실제 생활에서 아이폰충전기와 갤럭시 충전기를 호환할 때 쓰는 방식이다. 또한 노트북에 젠더를 이용해서 내 노트북 규격에 맞게 모양을 바꾸는 경우도 있다.

 

다시 돌아와서, 이것은 우리 팀의 프로젝트에서 외부 API가 필요할 때 사용할 수 있는 좋은 전략이다. 우리 프로젝트에서 client가 평소처럼 인터페이스를 호출해서 작업을 한다고 보여지지만, 실제로는 그 인터페이스를 구현하는 새로운 Adapter가 외부의 adaptee정보를 가지고 있어서 adaptee가 일을 처리하게 하는 것이다. 외부API를 연동해야 한다면 필히 클래스로 감싸는 것, Adapter 전략을 고민해야 한다.

 

4. Affirmation (자기 선언)

- 나는, 내가 필요한 지식을 강의, 책 등에서 열심히 참고하고 익히는 사람이다

5. Future Action ("구체적" 행동 계획)

반응형

'회고' 카테고리의 다른 글

TIL_210525  (0) 2021.05.27
TIL_210524  (0) 2021.05.25
210520_TIL  (0) 2021.05.21
210519_TIL  (0) 2021.05.20
210518_TIL  (0) 2021.05.19