백엔드 데브코스 TIL #1

잼구·2023년 9월 20일
6
post-thumbnail

해당 게시글은 실무 자바 개발을 위한 OOP와 핵심 디자인 패턴 강의를 참고해서 작성한 게시글임을 밝힙니다.

객체지향적으로 개발해야 하는 이유

면접에서 만약 "객체지향적으로 개발해야 하는 이유가 뭘까요?" 라고 묻는다면, 나는 뭐라고 대답할까?
아마.. "코드의 유지보수성이 좋고.. 어.."(오열하며 면접장을 뛰쳐나간다)

보통은 객체지향의 4가지 특징이나 SOLID 원칙을 많이 말할 것이다.
하지만 우리는 객체지향 프로그래밍도 결국엔 절차지향 프로그래밍의 문제를 해결하기 위해 나온 것임을 알아야한다!

절차지향 프로그래밍의 주요 특징

  1. 절차지향적 프로그래밍에서 데이터와 함수는 분리되어있음.
    • 데이터와 해당 데이터를 다루는 함수 사이 연관관계가 상대적으로 낮음.
  2. 절차지향적 프로그래밍은 확장성과 유연성이 낮음.

위 1,2번의 문제를 객체지향 프로그래밍에서는 캡슐화다형성으로 해결 할 수 있다.

이러한 관점에서 만약 저런 질문을 받게 된다면, 우리가 어떤 문제들을 해결하기 위해 (피똥싸며) 객체지향 프로그래밍을 하는지 생각해서 말하는 것이 좋은 답변이 될 것이다.


오버라이딩

나는.. 오버라이딩에 좋지 못한 추억이 있다..
그거슨 바로바로~ 모 면접때 오버라이딩의 이점 대해 설명해보라는 질문을 받았는데 제대로 대답하지 못했던것...!!

사실 너무 숨쉬듯이 쓰고 무아지경으로 에디터가 만들어주는 @Override 에 절여져서 이게 왜 좋은지는 설명하지 못했당...

그 당시 내 대답 😉 :
자식 클래스에서 부모 클래스를 상속받았을때 해당 함수를 부모 클래스의 함수와 다른 목적(?)으로 사용하고 싶을때 재정의를 하는거니까.. 음.. 코드 재사용성이 좋다는 이점이..있습니다..

네. 맞습니다. 저 코드 재사용성을 빼고는 한마디도 할 수 없는 인간 입니다~
그 이후에 구글링 좀 해봐도 그렇다할 대답을 못찾았는데 이번에 팀원들과 함께 이야기하다가 실마리를 찾았다!

면접관님은 버벅거리는 나에게 "오버라이딩을 어떤 경우에 사용하는지 생각해봐라" 라고 하셨다.

메소드 오버라이딩을 하는 경우
1. 자식 클래스가 부모 클래스를 상속 받았을때, 사용하기 부적합한 메소드를 자식 클래스에서 재정의 해서 사용.
2. 인터페이스/추상 클래스를 구현/상속 할때, 추상 메소드는 모두 오버라이드 해야함.

해당 경우들의 이점
1. 부모 클래스의 기존 코드를 수정하지 않고도 새로운 기능이나 동작 방식을 추가하거나 변경할 수 있어 코드의 확장성이 높아짐.
2. 여러 클래스의 객체가 같은 인터페이스나 추상 클래스를 상속/구현하는 경우, 동일한 메소드 호출에 대해 각 객체의 오버라이딩된 메서드를 실행할 수 있음. 이런 다형성을 통해 코드 유연성이 높아진다.

그렇다..!! 고슬링 행님은 오버라이딩을 그냥 만들어 놓은 것이 아니었던 것이다...~~ 차근차근 생각하면 알 수 있는 것인데.. 평소에도 생각을 좀 하면서 코딩 해야한다는 교훈을 배웠다..

소녀시대 노래를 들으며 자바를 실행시키면 컴파일 에러가 0% 라는 소문이..!!

오버라이딩에 대해 헷갈릴 수 있는 사실들

  1. 자바에서 return type 은 메소드 시그니처에 포함되지 않기 때문에 오버라이딩 할때 2가지 조건을 만족시키면 바꿔도 된다.
    • 반환타입이 primitive type 나 void 가 아님.
    • 내가 변경 할 리턴 타입이 부모 클래스 메소드의 리턴 타입으로 자동 형변환 가능할때.
  2. 자식 클래스를 부모 클래스 Type 으로 선언해도, 오버라이딩한 메소드는 부모 클래스 메소드가 아닌 오버라이딩 한 메소드로 호출된다.
  3. super.오버라이딩할 메소드(); 호출 시 오버라이딩 하는 함수 안에서 부모 클래스 메소드를 불러올 수 있다. -> 코드 중복 제거 가능.

상속 관련 주의 사항

올바른 상속 = 메소드 재사용 위해X 필드 재사용 위해O
메소드 재사용은 -> 구성 사용


Interface With Default Methods vs Abstract Class

평소에 구현 메소드가 많으면 추상 클래스! 하나도 없다면 인터페이스! 라고 생각하고 코드를 짬
내가 알고 있던 개념 ⬇️

목적
추상 클래스 - 실체 클래스의 멤버 통일화
인터페이스 - 객체 사용법을 정의, 코드와 객체가 서로 통신하는 접점
실제 구현
추상 클래스 - 추상메소드 & 일반 메소드 & 일반 필드 ⇒ 부분 완성 설계도
인터페이스 - 추상메소드 & 디폴트 메소드 & 상수 ⇒ 아무것도 구현 안된 기본 설계도

디폴트 메소드는 java8 에서 도입 되었고, 기존 인터페이스의 문제점을 해결하기 위해 도입 됨.

기존 인터페이스의 문제

인터페이스에 새로운 메소드를 추가하면 해당 인터페이스를 구현하는 모든 클래스가 그 메소드를 구현해야 함. 이로 인해 기존 코드에 큰 변화를 주지 않고는 인터페이스를 변경하기 어려웠음.

추상클래스를 사용해야만 하는 경우

  1. 인스턴스 필드가 필요할때
  2. 생성자가 필요할때
  3. Object 클래스를 오버라이딩 하고 싶을때 (equals(), hashCode(), toString()와 같은 메서드를 오버라이드할 때, 객체의 상태를 기반으로 한 동작을 정의하려면 상태 유지가 필요함)

=> 결론 : 상태유지가 필요한 상황에만 추상클래스를 쓰자.


Enum 사용법 (+실제 코드 개선)

Enum 강의를 들으며 가장 무릎을 타아악!!! 쳤다..
사실 전에 우아한 형제들 Java Enum 활용기 글을 읽으며, 정말 좋아보이는데 이게 무슨말이지? 라고 생각하며 이해를 포기했었당 ㅎ 그때는 너무 추상적이라고 느껴졌던 글이 강의를 듣고 다시 읽으니 이해가 쏙쏙~ 공중제비 10바퀴~

우리가 Enum 을 쓰는 이유는 여러가지가 있지만,

  • 정해진 상태를 String 으로 관리하는 것은 휴먼에러(오타)를 일으킬 수도 있음. 타입안정성을 위해.
  • Enum 제공 메소드를 사용하기 위해.

나는 이 2가지 정도였다. 근데 강의를 들으며 Enum 내부 메소드를 통해 상태와 행위를 한곳에서 관리해 유지보수성을 높일 수 있다는 사실을 알았다. 실제 내 코드를 보며 설명해 보겠다.


개선 전 코드

Category Enum

해당 Enum 을 사용하는 메소드

메소드의 목적

  • 크롤링 한 데이터의 카테고리(소분류)를 내 서비스의 카테고리(대분류)와 매칭해서 변환해줘야 함.

메소드의 구린 점

  • 하나의 카테고리로 묶여 같은 의미임을 명확하게 나타내야하는 "전자기기", "컴퓨터" 같은 소분류가 그냥 List 로 선언 되어 있음.
  • 모든 분기를 if/else 로 처리해 카테고리나 크롤링 데이터 변화 시 메소드 변화 필요.
  • 똑같은 기능을 까먹고 여러군데에서 만들 가능성 높음.
  • 어디서 얼마나 쓰일 메소드인지 모르기에 위치도 애매하고 접근 제한자도 애매함.

-> 우아한 형제들 Java Enum 활용기 여기서 나온 1,2 번의 문제점이 집대성 된 코드임;;

개선 후 코드

Category Enum

개선 후 좋아진 부분

  • 소분류들을 생성자에 넣어 한묶음 처리해 대분류와 관계를 명확하게 표현
  • 소분류를 받아 대분류 Enum 으로 반환하는 메소드를 Enum 안에 넣어,
    • 상태와 행위를 한곳에서 관리해 유지보수성 높아짐
    • 상태와 행위의 한곳에서 관리해 중복생성 할 확률이 낮음

해당 Enum 을 사용하는 메소드

이 부분도 3줄로 아주 깔끔하게 줄었다! 만족만족 ㅠㅠ

해당 강의와 우아한 형제들 글을 읽으며, 유지보수성이 높은 코드도 중요하지만 코드 사이의 연관관계를 명확하게 설정해 읽는이로 하여금 혼란을 야기할 상황을 만들지 않는 것도 중요하다는 것을 배웠다.
강의와 우아한 형제들 둘다 계산 관련 Enum 이라서 함수를 파라미터로 받아 가공하는 팁도 있었다!


예외

Checked Exception 과 Unchecked Exception 의 차이는?
나는 컴파일 시점에 해당 예외를 알 수 있느냐 없느냐의 차이라고 알고 있었다!
-> 근데 그건 컴파일 에러 였구요..~~

하지만 정답은.. 두둥..!
컴파일 시점에 에러 처리를 강제하느냐 아니냐의 차이다.
Checked Exception 은 컴파일 할 때 예외 처리 코드가 있어야하고, Unchecked Exception 은 예외에 처리코드 검사를 안한다.

강의에서 새로 안 사실은 Checked Exception 의 경우 예외를 던지든, 외부에서 try/catch 문을 적든 처리를 해야하는데 이 행위가 예외가 발생하는 메소드의 캡슐화를 깨는 행위라는 것이다. 외부에서는 예외를 통해 내부에서 해당 예외를 던지는 메소드를 사용함을 알 수 있다.

생각해 봐야 할 것 :
나는 평소에 try/catch 를 통해 예외 발생 시 로그를 찍거나 예외를 변환해 다시 던지는 작업을 많이 하는데 지양해야 하는 행위인가?🤔

profile
잼구입니다

5개의 댓글

comment-user-thumbnail
2023년 9월 21일

Enum관련한 부분은 상당히 유용하네요 잘봤습니다

1개의 답글
comment-user-thumbnail
2023년 9월 22일

유용한 정리 내용에 감탄하며 공중제비 10바퀴 돌고갑니다 ~~

1개의 답글