인프런 워밍업 클럽 백엔드 스터디 2기 | 1주차 발자국🐾

인프런 워밍업 클럽 백엔드 스터디 2기 | 1주차 발자국🐾

image

 

박우빈 님의 Readable Code: 읽기 좋은 코드를 작성하는 사고법 을 듣고 작성한 게시글입니다.

 

image

 

강의 수강 내용 요약

강의에서 사용되는 용어들

🔑도메인(domain)

- 해결하고자 하는 문제 영역

- ex) 결제 도메인, 주문 도메인, 상품 도메인...

🔑 도메인 지식

- 도메인을 이해하고 해결하는 데 필요한 지식

부끄러운 이야기지만 도메인(domain) 이라는 이야기를 많이 들어보긴 했어도 도메인의 정의에 대해서는 따로 생각해보지 않았던 것 같다. 강의에 시작하기 앞서 사용되는 용어들에 대해 정리해 보면서 프로그래밍은 문제(=도메인)를 해결하기 위한 도구라는 생각을 다시 한 번 상기한 상태로 본 강의를 수강할 수 있었다.

 

추상 (抽象)

사물을 정확하게 이해하기 위해서 사물이 지니고 있는 여러 가지 측면 가운데서 특정한 측면만을 가려내어 포착하는 것, 어떤 일면만을 추상하는 것은 다른 측면을 버린다는 것과 같다.

'깨끗한 코드를 쓰는 것'은 많은 개발자들의 로망이자 지켜야 할 규칙으로 자리잡고 있다. 그렇지만 우리에게 중요한 건 단순히 규칙을 지키는 것이 아니다. 개발자는 프로그램을 만드는 순간 순간 최적의 선택을 해야 하기 때문에 '왜 그런 규칙이 생겨났는가' 가 중요하다. 어떤 경우에는 규칙을 깨야 하는 경우도 존재한다. 그 편이 소프트웨어와 소프트웨어를 사용하는 사람들에게 더 좋다고 판단된다면!

지식 공유자님이 말씀하시는 클린 코드가 중요한 이유가독성이다. 글이 잘 읽힌다는 것은 이해가 잘 된다는 뜻이고, 유지보수 하기가 수월해지므로 우리의 시간과 자원을 절약하게 해준다. 클린 코드라 지칭하는 수많은 원칙이나 조언은 이를 위해서라고 한다. 레거시 코드를 읽을 미래의 나나 다른 개발자가 코드를 빠르게 이해할 수 있는 코드를 짜두면 장기적으로 더 나은 생산성을 보이게 된다.

이런 가독성을 위해서 중요하게 여겨지는 개념이 추상(抽象)이다. 무언가를 추상화한다는 것이 어렵게 다가오겠지만, 우리 뇌는 일상적으로 이 일을 수행하고 있다. 예를 들면 '차를 마신다'는 것도 다음과 같은 행위의 추상이다.

1. 물을 끓인다.
2. 끓인 물을 컵에 붓는다.
3. 끓인 물이 들어있는 컵에 티백을 넣는다.
4. 찻물을 2~3분 정도 우린 후 마신다.

컴퓨터 과학에서의 대표적인 예는 자료형(Type)이다. 1byte8bit를 묶은 것이고, char1byte로 문자 1개를 의미한다. 즉, 데이터(=bit) 덩어리를 어떻게 읽을 것인지에 대한 추상이다. 이렇게 적절한 추상화는 복잡한 데이터와 복잡한 로직을 단순화하여 이해하기 쉽도록 돕는다.

적절한 추상화는 구체를 유추할 수 있게 한다. 누군가 '차를 마셨다' 라고 하면 물을 끓여 찻잎을 우리는 모습을 쉽게 상상할 수 있다. 그러나 잘못된 추상화가 야기하는 사이드 이펙트 또한 크다. 추상으로부터 구체를 유추하지 못한다면 잘못된 추상화이다. 이런 경우가 발생하는 이유는 다음과 같다.

  1. 추상화 과정에서 중요한 정보를 부각시키지 못했다.

  2. 해석자가 동일하게 공유하는 문맥이 없다.

예를 들어 우리 집에서는 '밥 먹기' 를 '냠냠이 먹기' 라고 한다고 가정하자.

회사 동료에게 '저는 어제 8시에 냠냠이 먹었어요.' 라고 한다면..

image

아마도 갑자기 왜 귀여운 척을 하지? 라고 생각하지 않을까?

이런 상황을 방지하기 위해서는 중요한 정보만 남도록 잘 덜어내어 추상화 하고, 적절한 이름을 짓는 것이 필요하다.

어떻게 보면 '냠냠' 이라는 건 '먹는다' 는 구체를 떠올릴 수 있게 해주니, 아주 틀린 추상은 아닐지도 모르겠다. 이상한 사람 취급을 받을 수는 있겠지만

 

메서드와 추상화 레벨

이름을 짓는 것과 더불어 인상깊었던 부분은 메서드와 추상화 레벨에 관한 부분이었다.

'메서드명 뿐만 아니라 메서드 선언부 전체가 유기적으로 관여해서 의미를 전달한다' 는 것! 프로그램을 짤 때 메서드명은 최대한 메서드의 행동이 잘 드러나도록 작성하려고 하는 편인데, 파라미터나 반환타입까지 고려해야 한다는 생각은 해본 적이 없었다.

회고를 하면서, 최근 넷플릭스에서 본 흑백요리사가 떠올랐다.

image출처: 넷플릭스

안성재 셰프는 '요리를 만든 사람의 의도가 전해지는 것' 을 가장 중시한다. 요리에 쓸모없는 데코레이션을 올리는 것 보다 각 음식의 재료들이 자신의 역할을 다하길 바란다. 프로그램을 짜는 것도 다르지 않다는 생각이 들었다. 파라미터, 반환타입, 메서드명이라는 재료를 가지고, 누구나 이 메서드가 의도한 바를 명확히 알 수 있도록 하는 것. 모든 메서드를 이런 마음가짐으로 설계한다면 프로그래머계의 미슐랭 3스타를 받을 수 있지 않을까?

 

논리, 사고의 흐름

image뇌 메모리를 적게 쓰는 방법에 대해 알게 되어 좋았다.

전에 클린 코드나 객체지향 생활체조 원칙에 대해 읽으면서 크게 와닿지 않았는데 직접 코드를 읽어보고, 고쳐보고, 고친 코드를 읽어보는 과정을 반복하니 이해할 수 있었다. if ~ else if ~ else문으로 코드를 짜는 게 본인 입장에서는 확실히 직관적이고 편하지만.. 겪어야 할 고통을 미래로 미뤄두는 것 뿐이다. 심지어 그 고통은 복리로 돌아온다. return 할수 있는 부분은 빨리 return 하고, 메서드로 쪼갤 수 있는 부분은 쪼개자! 물론 어떤 것이 효율적일지에 대한 적절한 판단이 필요하다.

예외에 관한 부분도 좋았다. 프로그램을 짜다 보면 대부분 '대충 이렇게 잘 흘러가겠지?' 라고(해피케이스) 생각하게 되기 쉽다. 그러나 우리는 항상 방심하지 말고 예외가 발생하는 상황을 염두에 두어야 한다. 그냥 처음부터 '아마 생각한대로 흘러가진 않겠지만 이렇게 되긴 해야 돼..' 라고 생각하는 게 나을지도 모르겠다. 의도한 예외의도하지 않은 예외를 잘 구분해서 예상치 못한 상황이 발생하더라도 대참사만은 막을 수 있도록 안전한 프로그램을 설계하는 연습을 해야겠다.

 

객체 지향 패러다임과 SOLID

SOLID.. 정보처리기사 공부 했던 때가 주마등처럼 스쳐지나갔다. 뭔지도 모르고 달달 외웠었는데..

코드를 직접 수정하며 각각 원칙을 적용해보는게 재미있었다. 다만 따라하면서 만약 내가 프로그램을 설계한다면 이 원칙들을 다 지키도록 설계할 수 있을까? 하는 생각이 들었다. 조금만 프로그램 규모가 커져도 지금보다 훨씬 복잡해질 것 같다😥 확실히 읽기에 편한 만큼 쓰는 사람이 고생해야 한다.. 그만큼 더 많이 복습하고, 더 많은 코드들을 봐야겠다고 다짐했다.

 

미션 수행 요약

DAY2 - 추상과 구체의 예시 들기

추상과 구체의 예시를 생각하는 것은 그리 어렵지 않았다. 그렇지만 '일상 생활에서 이렇게 많은 추상화가 이루어지고 있었구나' 하는 생각이 들어 신기했다. 추상이라는게 되게.. 어려운 말이라고 생각했는데 그냥 필요한 부분만 뽑아내는 것이라는게 체감됐다.

책을 읽는 행위를 구체화 한다면?

1. 책을 손에 쥐거나 디지털 장치에서 페이지를 연다.
2. 눈으로 글자를 추적한다.
3. 글자를 인식하는 즉시 문장과 단어들이 뇌에서 의미로 변환된다.
4. 글 속의 아이디어와 자신의 가치관을 비교하고 의미를 추측해 자신의 해석을 만들어 낸다.

다른 분이 하신 과제도 간간히 구경했는데, 특히 기억에 남는 과제가 있었다. 추상: 아침엔 네 다리로 걷고, 점심엔 두 다리로 걷고, 저녁엔 세 다리로 걷는다. 구체: 인간 ... 진짜 생각지도 못했다. 이런 수수께끼들도 사실 추상이었다👏🏻👏🏻

 

DAY4 - 코드 리팩토링, SOLID 요약

🛠 리팩토링 전

public boolean validateOrder(Order order) {
    if (order.getItems().size() == 0) {
        log.info("주문 항목이 없습니다.");
        return false;
    } else {
        if (order.getTotalPrice() > 0) {
            if (!order.hasCustomerInfo()) {
                log.info("사용자 정보가 없습니다.");
                return false;
            } else {
                return true;
            }
        } else if (!(order.getTotalPrice() > 0)) {
            log.info("올바르지 않은 총 가격입니다.");
            return false;
        }
    }
    return true;
}

🛠 리팩토링 후

public class ValidateException extends IllegalArgumentException {
    public ValidateException(String message) {
        super(message);
    }
}
public boolean validateOrder(Order order) {
        if (order.getItems().size() == 0) {
            throw new ValidateException("주문 항목이 없습니다.");
        }

        if (order.getTotalPrice() < 0) {
            throw new ValidateException("올바르지 않은 총 가격입니다.");
        }

        if (order.hasNotCustomerInfo()) {
            throw new ValidateException("사용자 정보가 없습니다.");
        }
        return true;
    }

지금까지 배운 내용을 토대로 리팩토링을 진행했는데 너무너무 재밌었다. 이게 천직인가 싶을 정도로.. 예전에 현업에 있을 때도 그랬는데 구현보다 레거시 코드 뜯어 고치는게 더 재밌는거 정상이죠?

확실히 강의를 들으며 공부하는 것과 실제로 배운 걸 적용해보는건 다르다. 앞으로 더 많이 뜯고, 읽고, 쓰면서 욕도 먹어보고 해야겠다. 갈길이 멀다.

KPT

Keep: 앞으로 지속하고 싶은 부분

회고

회고를 작성하면서 기록했던 부분을 다시 돌아보니 당시에 들었던 강의 내용이 생생하게 기억나서 좋았다. 사실 개발 외적으로도 주간 회고, 월간 회고, 이런 저런 회고 방법을 시도했었지만 딱히 와닿지 않았다. 그런데 이번에 1주차 발자국을 작성하면서 공부했던 내용을 돌아보게 되고 내가 알게된 것들과 몰랐던 것들에 대한 경계선이 뚜렷해지는 느낌을 받았다. 우빈 님 추천으로 KPT 방식도 알게 되고.. 4주차 회고를 진행할 땐 회고의 달인이 된 내 모습까지 기대해보며👶🏻

커뮤니티 활동

imageimage낯을 많이 가리는 나지만.. 나름 열심히 커뮤니티 활동에 참여하려고 노력하고 있다. 뭔가 아는 척 하는 것 같아 보일까 보내고 난 직후에도 삭제할까 말까, 괜히 보냈나 백 번 고민했다😥 그래도 인프런 워밍업 클럽이 제공하는 가장 큰 혜택이 이 커뮤니티 아닐까 싶다. 실제로 다른 분들이 이야기 하는 걸 구경하기만 해도 지식이 느는 기분이다. 직접 참여할 때는 두말 할 것 없이 성장한다. 위 대화만 해도 JVM과 스레드에 대해 다시 한 번 정리해볼 수 있는 시간이었다. 늘 커뮤니티에 상주하고 계신 몇몇 분들 덕분에 자극도 많이 받는다👍🏻

Problem: 아쉬웠던 점

기록

나는 강의를 들으면서 거의 모든 내용을 기록해둔다. 당시에 생각나는 것, 듣고 있는 내용... 쓰다보면 사실 회의감이 들 때도 있다. 시간이 거의 두 세배는 넘게 걸리니 비효율적이지 않은가? 하는 생각이 들고 있었다. 시간이 오래 걸리니 강의를 틀기까지 꽤 큰 결심이 필요한데 필기 방식을 바꿔야하나 고민 중이다.

일정

이번에 진도표에 적힌 진도를 모두 따라가지 못했다. 다음 주에는 이번 주에 밀린 진도까지 꼭 학습해야겠다.

Try: Problem을 해결하기 위해 시도해볼 점

  • 인프런의 강의 노트 기능을 이용해보는건 어떨까?

  • 일정은.. 그냥 열심히 하는 수밖에 없다. 이번엔 꼭 주말 전까지 2주차 진도를 끝내 놓을 것🔥🔥🔥

댓글을 작성해보세요.

채널톡 아이콘