ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Getter 와 Setter 말고 다른방식으로?
    생각해보기 2023. 7. 18. 10:15

    개인 프로젝트를 진행하면서 도메인 모델들에 대해 값을 찾을때 필드는 private 처리를 하니 Getter와 Setter를 당연시하며 무분별하게 사용했다.

    그런데 최근에 객체지향을 공부하고 짰던 코드를 다시 보니 이렇게하면 캡슐화(은닉)이 다 깨지는거 아닌가? 라는 생각이 들었다.

    그래서 좀 찾아보니 Getter와 Setter를 지양해야한다는 의견들이 있었다.

     

    내가 생각했던 캡슐화(보안상)의 문제도 있었지만 다른 점도 생각해볼것이 있었다. 그리고 코드까지 바꿔보자.

     

    MVC를 배운이후 정말 아무생각없이 Service 부분에서 웬만한 로직을 다 처리하려했다. 

    Service단에서 해당 객체의 로직을 처리하려면 Setter와 Getter가 필요했다. 

     

    네이버 뉴스를 크롤링하는 로직이다.  

    import lombok.Getter;
    import lombok.Setter;
    
    @Setter
    @Getter
    public class News {
        private String link;
        private String imgLink;
        private String title;
        private String content;
    }
    @Service
    public class NewsService {
        //문화,생활 뉴스만 뽑아오기
        public List<News> CrawlingNews() throws IOException {
            String url = "https://news.naver.com/main/list.naver?mode=LS2D&mid=shm&sid1=103&sid2=237";
            Document doc = Jsoup.connect(url).get();
    
            Elements elementsByClass = doc.getElementsByClass("photo");
            Elements content = doc.getElementsByClass("lede");
            List<News> newsList = new ArrayList<>();
            for (int i=0;i<7;i++) {
                News news = new News();
                news.setLink(elementsByClass.get(i).select("a").attr("abs:href"));
                news.setImgLink(elementsByClass.get(i).select("img").attr("abs:src"));
                news.setTitle(elementsByClass.get(i).select("img").attr("abs:alt").substring(28));
                news.setContent(content.get(i).text());
                newsList.add(news);
            }
            return newsList;
        }
    }

    Service에서 뉴스 객체를 생성하고 setter로 값을 설정하고있다. 

     

    하지만, 도메인 영역에서 모델이 직접 처리할 수 있는건 직접 하면 굳이 Service에서 Setter와 Getter를 써서 캡슐화를 깨뜨리고 Setter  로 인한 데이터 변경 위험을 없앨 수 있는거 아닌가? 

     

    위의 내 코드를 리팩토링 해보았다.

     

    @Getter //thymeleaf로 값을 보여줘야해서 필요한 부분이다.
    public class News {
        private String link;
        private String imgLink;
        private String title;
        private String content;
    
        public List<News> Crawling() throws IOException {
            String url = "https://news.naver.com/main/list.naver?mode=LS2D&mid=shm&sid1=103&sid2=237";
            Document doc = Jsoup.connect(url).get();
    
            Elements elementsByClass = doc.getElementsByClass("photo");
            Elements content = doc.getElementsByClass("lede");
            List<News> newsList = new LinkedList<>();
            for (int i=0;i<10;i++) {
                News news = new News();
                newsList.add(news.changeNews(elementsByClass.get(i), content.get(i)));
            }
            return newsList;
        }
        public News changeNews(Element element,Element text) {
            this.link = (element.select("a").attr("abs:href"));
            this.imgLink=(element.select("img").attr("abs:src"));
            this.title = (element.select("img").attr("abs:alt").substring(28));
            this.content =text.text();
            return this;
        }
    }
    @Service
    public class NewsService {
    
    	public List<News> CrawlingNews() throws IOException {
            News news = new News();
    
            return news.Crawling();
        }
    }

    NewsService에서 News에 접근해서 크롤링하던 로직을 모두 News 자신의 영역에서 처리할수 있게 바꿔보았다.

    Getter, Setter모두 사용하지 않아도 됨으로 캡슐화를 잘 지키는 코드로 변경되었다.

     

    사실 내 코드는 간단해서 Getter랑 Setter가 필요하지 않은 경우지만, 코드가 좀 복잡해져서 필요한 경우가 많을 것이다.그런 경우에는 우 선 객체 중심의 로직을 생각해본 후, 안된다면 Getter와 Setter를 적절히 사용해야겠다.

     

    참고자료:

    https://tecoble.techcourse.co.kr/post/2020-04-28-ask-instead-of-getter/

     

    https://velog.io/@backfox/setter-%EC%93%B0%EC%A7%80-%EB%A7%90%EB%9D%BC%EA%B3%A0%EB%A7%8C-%ED%95%98%EA%B3%A0-%EA%B0%80%EB%B2%84%EB%A6%AC%EB%A9%B4-%EC%96%B4%EB%96%A1%ED%95%B4%EC%9A%94

Designed by Tistory.