객체지향 설계와 도메인-주도 설계에 관심이 많으며 행복한 팀과 깔끔한 코드, 존중과 협력이 훌륭한 소프트웨어를 낳는다는 믿음을 가지고 있는 평범한 개발자입니다. 개발자, 교육자, 관리자를 오가며 익힌 다양한 경험을 바탕으로 좋은 코드와 함께 좋은 프로덕트를 만들기 위해 노력하고 있습니다.
저서로는 『객체지향의 사실과 오해』와 『오브젝트』가 있고 번역서로는 『엘레강트 오브젝트』가 있으며 『만들면서 배우는 클린 아키텍처』에 감수자로 참여했습니다.
💡개인블로그 : https://eternity-object.tistory.com/
Khóa học
Đánh giá khóa học
- Đối tượng - Phần nguyên tắc thiết kế
- Đối tượng - Phần nguyên tắc thiết kế
- Đối tượng - Cơ bản
- Đối tượng - Phần nguyên tắc thiết kế
- Đối tượng - Cơ bản
Bài viết
Hỏi & Đáp
함수형 스타일에 대해선 어떻게 생각하시나요?
빡소리님 안녕하세요. 저같은 경우에는 객체지향쪽에 치우쳐 있기 때문에 객체지향 패러다임을 중심으로 함수형 패러다임을 접목시키는 방식으로 사용하고 있습니다. 전체 구조를 메시지를 주고 받는 객체사이의 협력을 기반으로 구현한다는 점은 동일합니다.차이점은 객체의 상태 변경 대신 새로운 객체를 반환하거나 도메인 이벤트를 발행시키는 등 함수형을 제한적으로 사용하고 있습니다.객체 인터페이스에 나타나는 람다는 strategy 패턴을 대체하는 정도의 용도로만 제한적으로 사용하고 있습니다. 코틀린 진영을 보면 불변 data 클래스를 사용하고 로직을 함수로 분리하는 방식으로 좀 더 적극적으로 함수형 프로그래밍을 적용하시는 케이스에 대한 이야기를 많이 듣고 있는데 이 부분에 대해서는 저도 경험이 많지 않아서 깊이 있는 내용을 말씀드리기 어렵네요. 🙂 설명이 부족해서 죄송합니다.
- 1
- 2
- 25
Hỏi & Đáp
값 객체 활용에 대해
빡소리님 안녕하세요. 좋은 질문해 주셔서 감사합니다. 당연한 이야기겠지만 값 객체 컬렉션이 필요한 경우에는 @ElementCollection을 지정해서 값 객체를 별도의 테이블에 저장합니다.하지만 하나의 값 객체만 필요한 경우에는 동일한 테이블에 저장해서 영속성 전이나 생명 주기 관리 등의 복잡성을 JPA가 처리하도록 만드는게 좋습니다. 값 객체를 별도의 테이블에 저장하려면 클래스에 @Embeddable이 아닌 @Entity를 붙이고 영속성 전이와 생명 주기 관리와 관련된 애너테이션을 직접 지정해주면 됩니다.대표적인 케이스로는 값 객체에 상속을 적용해서 다형적인 행위를 구현할 필요가 있거나, 값 객체 컬렉션에 요소를 추가할 때 실행되는 쿼리를 줄이고 싶을 경우 등에 한해서 클래스에 @Entity를 붙이고 값 객체로 구현하기도 합니다.다만 이 경우에는 영속성 전이와 생명 주기 관리와 관련된 부분을 개발자가 직접 지정해줘야하고, @Entity와 값 객체 사이의 불일치를 기억해야 하는 부담이 따를뿐만 아니라, 추가적인 테이블 조인이 발생할 수 있기 때문에 꼭 필요한 경우로 한정해서 사용하는게 좋습니다. 답변이 되었는지 모르겠네요.
- 1
- 2
- 40
Hỏi & Đáp
실례지만 여기에 후기 올립니다.
ycseol님께 드렸던 답변 이후에도 이 주제가 계속 머릿속을 맴돌아 며칠 뒤 따로 생각을 정리해서 링크드인에 올렸습니다.혹시 관심 있으실까 싶어 여기에도 함께 공유드립니다.질문을 통해 강의 방향에 대해 다시 고민해보는 계기가 되었습니다.좋은 인사이트를 주신 점 다시 한번 감사드립니다.인프런의 오브젝트 - 설계 원칙편을 수강하신 분이 감사하게도 Q&A에 정성스러운 후기를 남겨주셨습니다. 수강생분의 의견을 한 줄로 요약하면 자바 진영의 표준으로 사용되는 스프링을 기반으로 설계 원칙을 적용한 예제도 있었으면 좋지 않겠냐로 요약할 수 있습니다. 이 후기를 읽고나서 한 동안 머릿속으로 많은 생각이 흘러 지나갔습니다. 그리고 여러 번 답변을 수정하는 동안 제가 가지고 있던 생각에 대해서도 다시 한번 돌아보는 계기가 되기도 했습니다.사실 이 부분은 첫 번째 강의인 오브젝트 - 기초편을 만들기 시작할 때부터 많이 고민했던 주제이기도 합니다. 그리고 그 때의 고민이 이번 후기를 통해 강의의 정체성과 방향성에 대한 새로운 고민으로 이어지게 되었구요. 아무래도 국내의 개발자 대부분이 스프링을 주요 프레임워크로 사용하고 있고 많은 인기 강의들이 스프링(그리고 JPA) 중심으로 구성되어 있다보니 강의를 만드는 입장에서는 스프링 기반의 강의를 만드는게 ROI 관점에서 훨씬 더 효율적으로 다가올 수 밖에 없습니다. 그럼에도 스프링을 포함한 특정 프레임워크나 기술을 최대한 배제하고 강의를 만든 이유는 오롯이 객체지향적인 사고방식과 설계에 집중하는 강의로 시작해서 스프링이나 JPA를 사용한 강의로 나아가는 로드맵을 계획하고 있기 때문입니다. 스프링 안에 객체지향 설계를 가둬두기 보다는 제가 성장했던 경험을 기반으로 객체지향에 대한 이해도를 높여서 자연스럽게 스프링을 포함한 다양한 코드를 이해할 수 있도록 만드는게 좋지 않을까라는 생각도 있었구요.하지만 전체는 아니더라도 일부 예제라도 스프링을 기반으로 설명해주면 좋지 않겠냐는 의견은 제 입장에서 깊이 고민해봐야하는 주제라고 생각합니다. 다음 강의는 원래의 계획대로 기본 개념을 쌓는 쪽으로 갈 지, 아니면 기존 강의에 라이브 코딩을 보강하거나 실무 관점에서 지금까지 설명했던 개념들을 적용하는 중간 단계의 실무 강의를 만드는게 좋을 지 좀 더 고민해 봐야겠어요. 저자가 전달하고 싶은 내용을 담게 되는 책과 다르게 빠르게 피드백을 주고 받으면서 경로를 수정할 수 있는게 온라인 강의의 매력이라는 생각이 드네요. 후기를 남겨주신 분처럼 강의에 대한 다양한 의견을 주시면 기존 강의를 개선하거나 이후의 방향을 조정하는데 큰 도움이 될 것 같습니다. 🙂
- 4
- 3
- 329
Hỏi & Đáp
실례지만 여기에 후기 올립니다.
ycseol님 안녕하세요.먼저 강의에 대한 의견 주셔서 감사합니다. :)개인적으로도 언젠가는 스프링이나 JPA 관련된 강의를 하는게 좋지 않을까라는 생각을 하고 있는데 일단 객체지향 - 설계 원칙편 강의를 만드는 동안에는 순수하게 객체지향 자체에 집중하는 쪽을 선택했어요.이유를 간단히 말씀드리겠습니다. “시중에 나와 있는 서적과 강좌가 정말 잘 되어 있는 만큼 사람들이 많이 사용하는 스프링 프레임워크에 적용한 예제도 가끔 있으면 어떨까 합니다”라고 말씀해 주셨는데 오브젝트 - 설계 원칙편은 의도적으로 스프링이나 JPA와 같은 특정 기술과 관련된 내용을 배제하고 객체지향적인 코드를 작성할 때 필요한 원칙과 사고방식에 집중할 수 있도록 구성했습니다.몇 가지 예제를 제외하면 가급적 Java 표준에 포함된 라이브러리를 사용한 이유도 그 때문이구요.이 부분은 개인적으로 고민을 많이 한 부분인데요 스프링이나 JPA처럼 많이 사용되는 기술을 기준으로 강의를 구성하는 편이 강의 판매 측면에서는 더 좋은건 당연한 이야기이기 때문입니다. 하지만 이 경우에는 객체지향 설계를 할 때 어떻게 사고하면 좋은지에 초점을 맞추는게 아니라 예제로 사용된 스프링이나 JPA에 대한 프레임워크를 설명하는데 더 큰 노력이 들어갈 수 밖에 없습니다. 이 강의는 객체지향 초급자들을 대상으로 설계된만큼 스프링이나 JPA를 기준으로 강의를 구성하면 결국은 예제에서 다루는 스프링이나 JPA를 경험하지 않은 분들은 강의를 따라오실 수 없고 맥락을 전혀 이해하실 수 없으실 거구요.강의에 사용한 라이브러리들은 모르시더라도 강의의 흐름을 쫓아오시는데 큰 무리가 없거나 예제를 구성하는 핵심이 아닌 것으로 선정한 이유이기도 합니다. 그리고 "이 부분을 만약에 업무에 적용시킨다면 어떻게 해야 할까나?”라는 생각을 할거라고 말씀하셨는데, 강의에 있는 원칙들은 실제로 업무에서 코드를 적용할 때 사용할 수 있는 내용들입니다.스프링이나 JPA처럼 특정한 프레임워크를 사용하지 않는건 업무에서 사용하는 예제가 아니라고 생각하시거나 객체지향적인 설계를 실제 업무에 적용하지 않을 경우에 발생할 수 있는 시각적인 차이라고 생각합니다. 스프링 관점에서 특정한 기술에 기반한 설계 방식이 더 궁금하시다면 오히려 이쪽 주제로 더 좋은 강의들이 많이 나와있기 때문에 제 강의보다는 해당 기술을 다룬 강의를 들으시는 것을 추천드립니다.마침 토비님 강의가 새로 나왔으니 이 강의를 한번 보시면 어떨까 싶고(https://inf.run/cKwn3) 저보다 더 잘 아시겠지만 영한님 강의가 이런 측면에서는 정말 탁월합니다.제 강의를 보신 상태에서 두 분의 강의를 보시면 필요한 부분을 충족시킬 수 있으리라 생각합니다. 🙂 설계 원칙편을 스프링과 JPA에 응용한 강의를 만들어 보는 것도 현재 고려하고 있기는 합니다만 바로 진행할지 추가 강의를 만든 후에 진행할지 조금 고민하고 있어요.다만 현재 강의는 설계 원칙 자체를 깊이있게 다루는 것을 목표로 한다는 점을 강조하고 싶습니다.(이게 수강생이 적은 이유일 수도 있겠지만... ㅠㅠ) 애정어린 조언 감사드립니다.
- 4
- 3
- 329
Hỏi & Đáp
동일성과 동등성 설명이 바뀐 것 같습니다.
안녕하세요. 말씀하신 것처럼 identical은 동일성으로, equality는 동등성으로 해석하는게 맞습니다. 제가 강의 자료를 만들면서 혼동한 것 같은데 해당 부분은 수정하도록 할게요. 🙂 자료 양이 많다보니 제가 실수한 부분이 많을 수 있는데 보시다가 이상한 부분이 있으면 편하게 수정 요청해 주시면 감사하겠습니다. 강의 꼼꼼하게 봐주시는 부분도 감사드려요.
- 1
- 2
- 43
Hỏi & Đáp
인터페이스명이 변경된 걸까요??
김철준님 안녕하세요.먼저 불편을 드려 죄송하다는 말씀 드립니다.해당 인터페이스명은 TemporalExpression가 아니라 RecurringPlan이 맞습니다.강의 마무리 작업 시에 해당 부분은 싱크를 맞추지 못했네요.확인해보니 장표 3개에서 TemporalExpression으로 되어 있는 부분이 남아있는데 이 부분은 주말 내에 동영상을 재촬영해서 업로드 하도록 하겠습니다.TemporalExpression 인터페이스는 RecurringPlan 인터페이스라고 이해해주시면 될것 같습니다.감사합니다!
- 0
- 2
- 42
Hỏi & Đáp
3-1 강의 질문입니다.
자스비님 안녕하세요.좋은 질문 남겨 주셔서 감사합니다. 지적하신 부분을 살펴보니 "프로세스와 데이터가 하나의 모듈 안에 모여 있으면 코드를 수정하기 어렵기 때문이죠 "이네요.강의를 만들 때는 인지하지 못했는데 자스비님의 질문을 받고 보니 제가 잘못 설명한게 맞습니다.이 부분은 먼저 사과드립니다. 말씀하신 것처럼 데이터와 로직이 서로 다른 모듈 안에 분리되어 있기 때문에 관련된 로직을 데이터로 옮겨 하나의 모듈 안에 두는 리팩터링을 수행했습니다.문맥 상으로 "프로세스와 데이터가 하나의 모듈 안에 모여 있으면 코드를 수정하기 어렵기 때문이죠 "라는 문장은 두 가지중 하나로 수정하는게 맞습니다.모든 프로세스와 모든 데이터가 하나의 모듈 안에 모여 있으면 코드를 수정하기 어렵기 때문이죠.프로세스와 데이터가 하나의 모듈 안에 모여 있으면 코드를 수정하기 쉽기 때문이죠.원래의 의도는 첫 번째 문장에 쓴 것처럼 관련없는 코드들이 하나의 모듈 안에 섞여 있으면 변경이 어렵기 때문에 서로 다른 모듈로 분리하는게 좋다라는 의미를 전달하고 싶었던 것인데 아예 다른 의미가 되어 버렸네요.문맥의 흐름상으로 봤을 때는 두 번째 문장으로 설명하는게 더 자연스러워 보입니다. 이 부분은 다시 재녹음을 할 때 두 번째 문장으로 수정해서 다른 분들이 혼란스럽지 않도록 조치하겠습니다. 꼼꼼하게 학습하시고 해당 부분 지적해 주셔서 감사드립니다. 🙂 보시다가 이상한 부분이 있으면 언제라도 문의 부탁드릴게요. 불금 행복하게 보내세요!
- 1
- 2
- 38
Hỏi & Đáp
player 내부에 worldmap
김철준님 안녕하세요.Player 내부에 WorldMap이 위치하는게 어색한 이유와 Game 안에 포함되는게 더 낫다고 생각하시는 이유를 적어 주시면 좀 더 정확한 답변을 드릴 수 있을 것 같습니다.더 자세한 답변은 위 내용을 적어주시면 드리기로 하고 우선 대략적으로 답변드릴게요. 어떤 구조를 선택할 것인지는 응집도나 결합도와 같은 측면을 트레이드오프해서 그 중에서 합리적인 안을 선택해야 합니다.말씀하신 안이 아래 그림의 (A)인지 (B)인지 정확하게 몰라서 둘 모두를 기준으로 답변드릴게요.(사진)현재의 텍스트 어드벤처 게임은 Player를 기준으로 특정한 액션을 수행하고 있습니다.(A)안이 구조로 설계하면 Game이 Player와 WorldMap을 조율해서 Player의 동작을 처리해야 합니다. 따라서 Game에 Player를 처리하는 로직이 위치하게 되어 응집도가 낮아지게 됩니다. 추가로 Game이 WorldMap과 Player 모두를 알아야 하기 때문에 Game의 결합도가 높아지게 됩니다.(B)안이 구조로 설계하면 Player를 처리하기 위해 WorldMap을 거쳐야 합니다. 따라서 Player만 필요한 로직의 경우에도 WorldMap에 Player로의 위임 로직을 추가해야 합니다.따라서 WorldMap의 응집도가 낮아지게 됩니다.또한 Player는 처리를 위해 WorldMap의 정보가 필요하기 때문에 양방향 연관 관계가 추가하거나 WorldMap의 데이터를 전달해야 하기 때문에 결합도가 높아지거나 코드가 복잡해지게 됩니다. 위 이유로 Player가 WorldMap을 참조하도록 구성했습니다.제가 드린 답변이 생각하신 이슈와 상관이 없다면 어색하다고 느끼신 이유와 Game에 포함시켰을 때 더 개선된다고 생각하시는 부분을 남겨 주시면 더 자세히 답변 드릴게요.
- 3
- 2
- 65
Hỏi & Đáp
7-3 AbstractReader에 대해
반대로 XML리더나 HTML 리더를 만들때도 공통 코드가 달라진다고 보장할 수도 없습니다.이 시점까지 구현해야 한다고 알고 있는 JsonReader와 CsvReader는 모두 로컬 파일시스템에서 파일을 읽는 로직을 공유합니다.따라서 실제로 필요한 변경이 일어날 때까지는 현재 알고 있는 내용 안에서 구현하면 되는거죠.상위 모듈은 하위 모듈에 비해 상대적으로 안정적인 부분입니다.다시 말해서 변경할 수 없는 코드가 아니라 하위 모듈보다 상대적으로 더 적게 변경하는 부분입니다.원격에서 읽는 부분에 대해서 문의 주셨는데 강의를 보시면 아시겠지만 원격이라는 요구사항이 추가되는 순간 현재이 구조는 리팩터링하게 됩니다.현재 상황에서 추상 클래스가 상위 모듈 안에 위치하는게 중복 코드나 의존성 관리 측면에서 유리한 것이기 때문에 현재 구조는 유효합니다.
- 0
- 2
- 24
Hỏi & Đáp
9-6 순환참조인거 같은데..
Game을 수정했을 때 Gui, Cui로 변경되는 문제는 양방향 참조와는 무관합니다.단순히 Gui와 Cui가 각각 Game에 의존하고 있기 때문에 Game 수정 시에 영향을 받는 것뿐입니다.Game과 Gui, Cui가 양방향 참조라면 Game 클래스 안에 Gui와 Cui 인스턴스를 참조로 포함해야 합니다.마찬가지로 순환참조도 아닙니다.순환참조는 자기 자신에서 시작해서 의존성 그래프를 따라갔을 때 자기 자신으로 돌아와야 합니다.그림에서 보시면 모든 의존성은 GameLoop에서 끊깁니다.
- 0
- 2
- 63