{"componentChunkName":"component---src-containers-post-index-tsx","path":"/backend/object/chapter15/디자인_패턴과_프레임워크/","result":{"pageContext":{"next":{"id":"d8be73e1-803f-536a-af27-6b27955acd94","html":"<p>객체는 협력을 위해 존재한다.</p>\n<h2 id=\"-141-핸드폰-과금-시스템-변경하기\" style=\"position:relative;\"><a href=\"#-141-%ED%95%B8%EB%93%9C%ED%8F%B0-%EA%B3%BC%EA%B8%88-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0\" aria-label=\" 141 핸드폰 과금 시스템 변경하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 14.1 핸드폰 과금 시스템 변경하기</h2>\n<h3 id=\"-1411-기본-정책-확장\" style=\"position:relative;\"><a href=\"#-1411-%EA%B8%B0%EB%B3%B8-%EC%A0%95%EC%B1%85-%ED%99%95%EC%9E%A5\" aria-label=\" 1411 기본 정책 확장 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 14.1.1 기본 정책 확장</h3>\n<p>기본 정책을 구성하는 4가지 방식</p>\n<ol>\n<li>고정요금 방식</li>\n<li>시간대별 방식</li>\n<li>요일별 방식</li>\n<li>구간별 방식</li>\n</ol>\n<h3 id=\"-1412-고정요금-방식-구현하기\" style=\"position:relative;\"><a href=\"#-1412-%EA%B3%A0%EC%A0%95%EC%9A%94%EA%B8%88-%EB%B0%A9%EC%8B%9D-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0\" aria-label=\" 1412 고정요금 방식 구현하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 14.1.2 고정요금 방식 구현하기</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class FixedFeePolicy extends BasicRatePolicy {\n\n    private final Money amount;\n    private final Duration seconds;\n\n    @Override\n    protected Money calculateCallFee(Call call) {\n        return amount.times((double) call.getDuration().getSeconds() / seconds.getSeconds());\n    }\n}</code>\n        </deckgo-highlight-code>\n<h3 id=\"-1413-시간대별-방식-구현하기\" style=\"position:relative;\"><a href=\"#-1413-%EC%8B%9C%EA%B0%84%EB%8C%80%EB%B3%84-%EB%B0%A9%EC%8B%9D-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0\" aria-label=\" 1413 시간대별 방식 구현하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 14.1.3 시간대별 방식 구현하기</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@Getter\n@RequiredArgsConstructor\npublic class DateTimeInterval {\n\n    private final LocalDateTime from;\n    private final LocalDateTime to;\n\n    public static DateTimeInterval of(LocalDateTime from, LocalDateTime to) {\n        return new DateTimeInterval(from, to);\n    }\n\n    public static DateTimeInterval toMidnight(LocalDateTime from) {\n        return new DateTimeInterval(\n                from,\n                LocalDateTime.of(from.toLocalDate(), LocalTime.of(23, 59, 59, 999_999_999)));\n    }\n\n    public static DateTimeInterval fromMidnight(LocalDateTime to) {\n        return new DateTimeInterval(\n                LocalDateTime.of(to.toLocalDate(), LocalTime.of(0, 0)),\n                to);\n    }\n\n    public static DateTimeInterval during(LocalDate date) {\n        return new DateTimeInterval(\n                LocalDateTime.of(date, LocalTime.of(0, 0)),\n                LocalDateTime.of(date, LocalTime.of(23, 59, 59, 999_999_999)));\n    }\n\n    public Duration duration() {\n        return Duration.between(from, to);\n    }\n    \n    public List&lt;DateTimeInterval&gt; splitByDay() {\n        if (days() &gt; 0) {\n            return splitByDay(days());\n        }\n        \n        return List.of(this);\n    }\n    \n    private long days() {\n        return Duration.between(from.toLocalDate().atStartOfDay(), to.toLocalDate().atStartOfDay()).toDays();\n    }\n    \n    private List&lt;DateTimeInterval&gt; splitByDay(long days) {\n        List&lt;DateTimeInterval&gt; result = new ArrayList&lt;&gt;();\n        \n        addFirstDay(result);\n        addMiddleDays(result, days);\n        addLastDay(result);\n        \n        return result;\n    }\n    \n    private void addFirstDay(List&lt;DateTimeInterval&gt; result) {\n        result.add(DateTimeInterval.toMidnight(from));\n    }\n    \n    private void addMiddleDays(List&lt;DateTimeInterval&gt; result, long days) {\n        for (int loop = 1; loop &lt; days; loop++) {\n             result.add(DateTimeInterval.during(from.toLocalDate().plusDays(loop)));\n        }\n    }\n    \n    private void addLastDay(List&lt;DateTimeInterval&gt; result) {\n        result.add(DateTimeInterval.fromMidnight(to));\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class Call {\n\n    @Getter\n    private final DateTimeInterval interval;\n\n    public Call(LocalDateTime from, LocalDateTime to) {\n        this.interval = DateTimeInterval.of(from, to);\n    }\n\n    public Duration getDuration() {\n        return interval.duration();\n    }\n\n    public LocalDateTime getFrom() {\n        return interval.getFrom();\n    }\n\n    public LocalDateTime getTo() {\n        return interval.getTo();\n    }\n\n    public List&lt;DateTimeInterval&gt; splitByDay() {\n        return interval.splitByDay();\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class TimeOfDayDiscountPolicy extends BasicRatePolicy {\n\n    private List&lt;LocalTime&gt; starts = new ArrayList&lt;&gt;();\n    private List&lt;LocalTime&gt; ends = new ArrayList&lt;&gt;();\n    private List&lt;Duration&gt; durations = new ArrayList&lt;&gt;();\n    private List&lt;Money&gt; amounts = new ArrayList&lt;&gt;();\n\n    @Override\n    protected Money calculateCallFee(Call call) {\n        Money result = Money.ZERO;\n        for (DateTimeInterval interval : call.splitByDay()) {\n            for (int loop = 0; loop &lt; starts.size(); loop++) {\n                result.plus(amounts.get(loop).times(\n                        (double) Duration.between(from(interval, starts.get(loop)), to(interval, ends.get(loop)))\n                                .getSeconds() / durations.get(loop).getSeconds()));\n            }\n        }\n        return result;\n    }\n\n    private LocalTime from(DateTimeInterval interval, LocalTime from) {\n        return interval.getFrom().toLocalTime().isBefore(from) ? from : interval.getFrom().toLocalTime();\n    }\n\n    private LocalTime to(DateTimeInterval interval, LocalTime to) {\n        return interval.getTo().toLocalTime().isAfter(to) ? to : interval.getTo().toLocalTime();\n    }\n}</code>\n        </deckgo-highlight-code>\n<h3 id=\"-1414-요일별-방식-구현하기\" style=\"position:relative;\"><a href=\"#-1414-%EC%9A%94%EC%9D%BC%EB%B3%84-%EB%B0%A9%EC%8B%9D-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0\" aria-label=\" 1414 요일별 방식 구현하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 14.1.4 요일별 방식 구현하기</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class DayOfWeekDiscountRule {\n    \n    private final List&lt;DayOfWeek&gt; dayOfWeeks = new ArrayList&lt;&gt;();\n    private final Duration duration = Duration.ZERO;\n    private final Money amount = Money.ZERO;\n    \n    public Money calculate(DateTimeInterval interval) {\n        if (dayOfWeeks.contains(interval.getFrom().getDayOfWeek())) {\n            return amount.times((double) interval.duration().getSeconds() / duration.getSeconds());\n        }\n        \n        return Money.ZERO;\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class DayOfWeekDiscountPolicy extends BasicRatePolicy {\n\n    private final List&lt;DayOfWeekDiscountRule&gt; rules = new ArrayList&lt;&gt;();\n\n    @Override\n    protected Money calculateCallFee(Call call) {\n        Money result = Money.ZERO;\n\n        for (DateTimeInterval interval : call.getInterval().splitByDay()) {\n            for (DayOfWeekDiscountRule rule : rules) {\n                result.plus(rule.calculate(interval));\n            }\n        }\n        \n        return result;\n    }\n}</code>\n        </deckgo-highlight-code>\n<h3 id=\"-1415-구간별-방식-구현하기\" style=\"position:relative;\"><a href=\"#-1415-%EA%B5%AC%EA%B0%84%EB%B3%84-%EB%B0%A9%EC%8B%9D-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0\" aria-label=\" 1415 구간별 방식 구현하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 14.1.5 구간별 방식 구현하기</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class DurationDiscountRule extends FixedFeePolicy {\n\n    private final Duration from;\n    private final Duration to;\n\n    public DurationDiscountRule(Money amount, Duration seconds, Duration from, Duration to) {\n        super(amount, seconds);\n        this.from = from;\n        this.to = to;\n    }\n\n    public Money calculate(Call call) {\n        if (call.getDuration().compareTo(to) &gt; 0) {\n            return Money.ZERO;\n        }\n\n        if (call.getDuration().compareTo(from) &lt; 0) {\n            return Money.ZERO;\n        }\n        \n        return super.calculateCallFee(new Call(call.getFrom().plus(from),\n                call.getDuration().compareTo(to) &gt; 0 ? call.getFrom().plus(to) : call.getTo()));\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>상속을 잘못 사용했다! 예시코드를 바꿔서 넣어봄.</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class DurationDiscountPolicy extends BasicRatePolicy {\n\n    private final List&lt;DurationDiscountRule&gt; rules = new ArrayList&lt;&gt;();\n\n    @Override\n    protected Money calculateCallFee(Call call) {\n        Money result = Money.ZERO;\n        for (DurationDiscountRule rule : rules) {\n            result.plus(rule.calculate(call));\n        }\n        return result;\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>이해하기도 힘들고 설계 개선과 새로운 기능의 추가를 방해한다.</li>\n<li>코드 재사용을 위한 상속은 해롭다.</li>\n</ul>\n<h2 id=\"-142-설계에-일관성-부여하기\" style=\"position:relative;\"><a href=\"#-142-%EC%84%A4%EA%B3%84%EC%97%90-%EC%9D%BC%EA%B4%80%EC%84%B1-%EB%B6%80%EC%97%AC%ED%95%98%EA%B8%B0\" aria-label=\" 142 설계에 일관성 부여하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 14.2 설계에 일관성 부여하기</h2>\n<p>협력을 일관성 있게 만들기 위해 다음과 같은 기본 지침을 따르자.</p>\n<ol>\n<li>변하는 개념을 변하지 않는 개념으로부터 분리하라.</li>\n<li>변하는 개념을 캡슐화하라.</li>\n</ol>\n<h3 id=\"-1421-조건-로직-대-객체-탐색\" style=\"position:relative;\"><a href=\"#-1421-%EC%A1%B0%EA%B1%B4-%EB%A1%9C%EC%A7%81-%EB%8C%80-%EA%B0%9D%EC%B2%B4-%ED%83%90%EC%83%89\" aria-label=\" 1421 조건 로직 대 객체 탐색 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 14.2.1 조건 로직 대 객체 탐색</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public abstract class DiscountPolicy {\n    private final List&lt;DiscountCondition&gt; conditions;\n\n    protected DiscountPolicy(DiscountCondition... conditions) {\n        this.conditions = Arrays.asList(conditions);\n    }\n\n    public Money calculateDiscountAmount(Screening screening) {\n        for (DiscountCondition condition : conditions) {\n            if (condition.isSatisfiedBy(screening)) {\n                return getDiscountAmount(screening);\n            }\n        }\n        return Money.ZERO;\n    }\n    protected abstract Money getDiscountAmount(Screening screening);\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@AllArgsConstructor\npublic class Movie {\n\n    /**\n     * 제목\n     */\n    private String title;\n\n    /**\n     * 상영시간\n     */\n    private Duration runningTime;\n\n    /**\n     * 기본요금\n     */\n    @Getter\n    private Money fee;\n\n    /**\n     * 할인 정책\n     */\n    private DiscountPolicy discountPolicy;\n\n    public Money calculateMovieFee(Screening screening) {\n        return fee.minus(discountPolicy.calculateDiscountAmount(screening));\n    }\n\n    public void changeDiscountPolicy(DiscountPolicy discountPolicy) {\n        this.discountPolicy = discountPolicy;\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>실제로 협력에 참여하는 주체는 구체적인 객체다.</li>\n<li>변경에 초점을 맞추고 캡슐화의 관점에서 설계를 바라보면 일관성 있는 협력 패턴을 얻을 수 있다.</li>\n</ul>\n<h3 id=\"-1422-캡슐화-다시-살펴보기\" style=\"position:relative;\"><a href=\"#-1422-%EC%BA%A1%EC%8A%90%ED%99%94-%EB%8B%A4%EC%8B%9C-%EC%82%B4%ED%8E%B4%EB%B3%B4%EA%B8%B0\" aria-label=\" 1422 캡슐화 다시 살펴보기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 14.2.2 캡슐화 다시 살펴보기</h3>\n<p>데이터 은닉</p>\n<ul>\n<li>오직 외부에 공개된 메서드를 통해서만 객체의 내부에 접근할 수 있게 제한함으로써 객체 내부의 상태 구현을 숨기는 기법</li>\n<li>해당 클래스의 메서드만이 인스턴스 변수에 접근할 수 있어야 한다.</li>\n<li>캡슐화는 데이터 은닉 이상이다.</li>\n</ul>\n<blockquote>\n<p>캡슐화란 변하는 어떤 것이든 감추는 것이다.</p>\n</blockquote>\n<ul>\n<li>데이터 캡슐화</li>\n<li>메서드 캡슐화</li>\n<li>객체 캡슐화</li>\n<li>서브타입 캡슐화</li>\n</ul>\n<p>변경을 캡슐화할 수 있는 다양한 방법이 존재하지만 협력을 일관성 있게 만들기 위해 가장 일반적으로 사용하는 방법은 서브타입 캡슐화와 객체 캡슐화를 조합하는 것이다.</p>\n<ul>\n<li>변하는 부분을 분리해서 타입 계층을 만든다.</li>\n<li>변하지 않는 부분의 일부로 타입 계층을 합성한다.</li>\n</ul>\n<h2 id=\"-143-일관성-있는-기본-정책-구현하기\" style=\"position:relative;\"><a href=\"#-143-%EC%9D%BC%EA%B4%80%EC%84%B1-%EC%9E%88%EB%8A%94-%EA%B8%B0%EB%B3%B8-%EC%A0%95%EC%B1%85-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0\" aria-label=\" 143 일관성 있는 기본 정책 구현하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 14.3 일관성 있는 기본 정책 구현하기</h2>\n<h3 id=\"-1431-변경-분리하기\" style=\"position:relative;\"><a href=\"#-1431-%EB%B3%80%EA%B2%BD-%EB%B6%84%EB%A6%AC%ED%95%98%EA%B8%B0\" aria-label=\" 1431 변경 분리하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 14.3.1 변경 분리하기</h3>\n<ul>\n<li>고정요금 방식\n<ul>\n<li>단위시간당 요금</li>\n</ul>\n</li>\n<li>시간대별 방식\n<ul>\n<li>시작시간 ~ 종료시간까지 단위시간당 요금</li>\n</ul>\n</li>\n<li>요일별 방식\n<ul>\n<li>요일별 단위시간당 요금</li>\n</ul>\n</li>\n<li>구간별 방식\n<ul>\n<li>통화구간동안 단위시간당 요금</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-1432-변경-캡슐화하기\" style=\"position:relative;\"><a href=\"#-1432-%EB%B3%80%EA%B2%BD-%EC%BA%A1%EC%8A%90%ED%99%94%ED%95%98%EA%B8%B0\" aria-label=\" 1432 변경 캡슐화하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 14.3.2 변경 캡슐화하기</h3>\n<ul>\n<li>변하는 것: 적용조건</li>\n<li>변하지 않는 것: 규칙</li>\n</ul>\n<p>규칙으로부터 적용조건을 분리해서 추상화한 후 시간대별, 요일별, 구간별 방식을 이 추상화의 서브타입으로 만든다.</p>\n<h3 id=\"-1433-협력-패턴-설계하기\" style=\"position:relative;\"><a href=\"#-1433-%ED%98%91%EB%A0%A5-%ED%8C%A8%ED%84%B4-%EC%84%A4%EA%B3%84%ED%95%98%EA%B8%B0\" aria-label=\" 1433 협력 패턴 설계하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 14.3.3 협력 패턴 설계하기</h3>\n<ol>\n<li>적용조건을 가장 잘 알고 있는 정보 전문가인 <code>FeeCondition</code>에게 할당</li>\n<li>단위요금을 적용해서 요금을 계산하는 두 번째 작업은 요금기준의 정보 전문가인 <code>FeeRule</code>이 담당</li>\n</ol>\n<h3 id=\"-1434-추상화-수준에서-협력-패턴-구현하기\" style=\"position:relative;\"><a href=\"#-1434-%EC%B6%94%EC%83%81%ED%99%94-%EC%88%98%EC%A4%80%EC%97%90%EC%84%9C-%ED%98%91%EB%A0%A5-%ED%8C%A8%ED%84%B4-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0\" aria-label=\" 1434 추상화 수준에서 협력 패턴 구현하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 14.3.4 추상화 수준에서 협력 패턴 구현하기</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public interface FeeCondition {\n    \n    List&lt;DateTimeInterval&gt; findTimeIntervals(Call call);\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class FeePerDuration {\n\n    private final Money fee;\n\n    private final Duration duration;\n\n    public Money calculate(DateTimeInterval interval) {\n        return fee.times(Math.ceil((double) interval.duration().toNanos() / duration.toNanos()));\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class FeeRule {\n\n    private final FeeCondition feeCondition;\n\n    private final FeePerDuration feePerDuration;\n\n    public Money calculateFee(Call call) {\n        return feeCondition.findTimeIntervals(call)\n                .stream()\n                .map(feePerDuration::calculate)\n                .reduce(Money.ZERO, Money::plus);\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor(access = AccessLevel.PROTECTED)\npublic abstract class BasicRatePolicy implements RatePolicy {\n\n    private final List&lt;FeeRule&gt; feeRules;\n\n    @Override\n    public Money calculateFee(Phone phone) {\n        return phone.getCalls()\n                .stream()\n                .map(this::calculate)\n                .reduce(Money.ZERO, Money::plus);\n    }\n\n    private Money calculate(Call call) {\n        return feeRules.stream()\n                .map(rule -&gt; rule.calculateFee(call))\n                .reduce(Money.ZERO, Money::plus);\n    }\n\n    protected abstract Money calculateCallFee(Call call);\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>변하지 않는 요소와 추상적인 요소만으로도 요금 계산에 필요한 전체적인 협력 구조를 설명할 수 있다.</li>\n</ul>\n<h3 id=\"-1435-구체적인-협력-구현하기\" style=\"position:relative;\"><a href=\"#-1435-%EA%B5%AC%EC%B2%B4%EC%A0%81%EC%9D%B8-%ED%98%91%EB%A0%A5-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0\" aria-label=\" 1435 구체적인 협력 구현하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 14.3.5 구체적인 협력 구현하기</h3>\n<h4 id=\"️-시간대별-정책\" style=\"position:relative;\"><a href=\"#%EF%B8%8F-%EC%8B%9C%EA%B0%84%EB%8C%80%EB%B3%84-%EC%A0%95%EC%B1%85\" aria-label=\"️ 시간대별 정책 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🛠️ 시간대별 정책</h4>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class TimeOfDayFeeCondition implements FeeCondition {\n\n    private final LocalTime from;\n    private final LocalTime to;\n\n    @Override\n    public List&lt;DateTimeInterval&gt; findTimeIntervals(Call call) {\n        return call.getInterval().splitByDay()\n                .stream()\n                .filter(each -&gt; from(each).isBefore(to(each)))\n                .map(each -&gt; DateTimeInterval.of(\n                        LocalDateTime.of(each.getFrom().toLocalDate(), from(each)),\n                        LocalDateTime.of(each.getTo().toLocalDate(), to(each))))\n                .collect(toList());\n    }\n\n    public LocalTime from(DateTimeInterval interval) {\n        return interval.getFrom().toLocalTime().isBefore(from) ? from : interval.getFrom().toLocalTime();\n    }\n\n    public LocalTime to(DateTimeInterval interval) {\n        return interval.getTo().toLocalTime().isAfter(to) ? to : interval.getTo().toLocalTime();\n    }\n}</code>\n        </deckgo-highlight-code>\n<h4 id=\"️-요일별-정책\" style=\"position:relative;\"><a href=\"#%EF%B8%8F-%EC%9A%94%EC%9D%BC%EB%B3%84-%EC%A0%95%EC%B1%85\" aria-label=\"️ 요일별 정책 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🛠️ 요일별 정책</h4>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class DayOfWeekFeeCondition implements FeeCondition {\n\n    private final List&lt;DayOfWeek&gt; dayOfWeeks;\n\n    @Override\n    public List&lt;DateTimeInterval&gt; findTimeIntervals(Call call) {\n        return call.getInterval()\n                .splitByDay()\n                .stream()\n                .filter(each -&gt; dayOfWeeks.contains(each.getFrom().getDayOfWeek()))\n                .collect(toList());\n    }\n}</code>\n        </deckgo-highlight-code>\n<h4 id=\"️-구간별-정책\" style=\"position:relative;\"><a href=\"#%EF%B8%8F-%EA%B5%AC%EA%B0%84%EB%B3%84-%EC%A0%95%EC%B1%85\" aria-label=\"️ 구간별 정책 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🛠️ 구간별 정책</h4>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class DurationFeeCondition implements FeeCondition {\n\n    private final Duration from;\n    private final Duration to;\n\n    @Override\n    public List&lt;DateTimeInterval&gt; findTimeIntervals(Call call) {\n        if (call.getInterval().duration().compareTo(from) &lt; 0) {\n            return Collections.emptyList();\n        }\n\n        return List.of(DateTimeInterval.of(\n                call.getInterval().getFrom().plus(from),\n                call.getInterval().duration().compareTo(to) &gt; 0 ?\n                        call.getInterval().getFrom().plus(to) :\n                        call.getInterval().getTo()));\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>유사한 기능에 대해 유사한 협력 패턴을 적용하는 것은 객체지향 시스템에서 <strong>개념적 무결성</strong>을 유지할 수 있는 가장 효과적인 방법이다.</li>\n</ul>\n<h3 id=\"-1436-협력-패턴에-맞추기\" style=\"position:relative;\"><a href=\"#-1436-%ED%98%91%EB%A0%A5-%ED%8C%A8%ED%84%B4%EC%97%90-%EB%A7%9E%EC%B6%94%EA%B8%B0\" aria-label=\" 1436 협력 패턴에 맞추기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 14.3.6 협력 패턴에 맞추기</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class FixedFeeCondition implements FeeCondition {\n\n    @Override\n    public List&lt;DateTimeInterval&gt; findTimeIntervals(Call call) {\n        return Collections.singletonList(call.getInterval());\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>개념적 무결성을 무너뜨리는 것보다는 약간의 부조화를 수용하는 편이 더 낫다.</li>\n</ul>\n<h3 id=\"-1437-패턴을-찾아라\" style=\"position:relative;\"><a href=\"#-1437-%ED%8C%A8%ED%84%B4%EC%9D%84-%EC%B0%BE%EC%95%84%EB%9D%BC\" aria-label=\" 1437 패턴을 찾아라 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 14.3.7 패턴을 찾아라</h3>\n<p>애플리케이션에서 유사한 기능에 대한 변경이 지속적으로 발생하고 있다면 변경을 캡슐화할 수 있는 적절한 추상화를 찾은 후, 이 추상화에 변하지 않는 공통적인 책임을 할당하라.</p>\n<p>협력을 일관성 있게 만든다는 것은 유사한 변경을 수용할 수 있는 협력 패턴을 발견하는 것과 동일하다.</p>","excerpt":"객체는 협력을 위해 존재한다. 📖 14.1 핸드폰 과금 시스템 변경하기 🔖 14.1.1 기본 정책 확장 기본 정책을 구성하는 4가지 방식 고정요금 방식 시간대별 방식 요일별 방식 구간별 방식 🔖 14.1.2 고정요금 방식 구현하기 🔖 14.1.3 시간대별 방식 구현하기 🔖 14.1.4 요일별 방식 구현하기 🔖 14.1.…","fields":{"slug":"/backend/object/chapter14/일관성_있는_협력/"},"frontmatter":{"title":"Object - 14장 일관성 있는 협력","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/dd0e1990925e942697544e2bdcd9332e/9b73b/object.png"}}},"draft":false,"category":"Back-End","tags":["java"],"date":"November 26, 2023"}},"previous":{"id":"06700cd2-2245-5186-9a8f-f542df019318","html":"<h2 id=\"-21-기본-요소-함수와-변수\" style=\"position:relative;\"><a href=\"#-21-%EA%B8%B0%EB%B3%B8-%EC%9A%94%EC%86%8C-%ED%95%A8%EC%88%98%EC%99%80-%EB%B3%80%EC%88%98\" aria-label=\" 21 기본 요소 함수와 변수 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 2.1 기본 요소: 함수와 변수</h2>\n<h3 id=\"-211-첫-번째-코틀린-프로그램-작성-hello-world\" style=\"position:relative;\"><a href=\"#-211-%EC%B2%AB-%EB%B2%88%EC%A7%B8-%EC%BD%94%ED%8B%80%EB%A6%B0-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EC%9E%91%EC%84%B1-hello-world\" aria-label=\" 211 첫 번째 코틀린 프로그램 작성 hello world permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.1.1 첫 번째 코틀린 프로그램 작성: Hello, World!</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun main() {\n        println(&quot;Hello World!&quot;)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>함수를 모든 코틀린 파일의 최상위 수준에 정의 가능</li>\n<li>main에 인자가 없어도 된다.</li>\n<li>간결성 강조</li>\n<li>세미콜론(;)을 붙이지 않는 것을 더 권장한다.</li>\n</ul>\n<h3 id=\"-212-파라미터와-반환값이-있는-함수-선언\" style=\"position:relative;\"><a href=\"#-212-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0%EC%99%80-%EB%B0%98%ED%99%98%EA%B0%92%EC%9D%B4-%EC%9E%88%EB%8A%94-%ED%95%A8%EC%88%98-%EC%84%A0%EC%96%B8\" aria-label=\" 212 파라미터와 반환값이 있는 함수 선언 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.1.2 파라미터와 반환값이 있는 함수 선언</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun max(a: Int, b: Int): Int {\n        return if (a &gt; b) a else b\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>파라미터 이름이 먼저 오고 그 뒤에 타입 지정\n<ul>\n<li>콜론(:)으로 구분</li>\n</ul>\n</li>\n<li>함수의 반환 타입은 파라미터 목록을 닫는 괄호 다음에 옴.</li>\n<li>위와 같은 코드를 블록 본문 함수(block body function)이라고 부름.</li>\n</ul>\n<h3 id=\"-213-식-본문을-사용해-함수를-더-간결하게-정의\" style=\"position:relative;\"><a href=\"#-213-%EC%8B%9D-%EB%B3%B8%EB%AC%B8%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%B4-%ED%95%A8%EC%88%98%EB%A5%BC-%EB%8D%94-%EA%B0%84%EA%B2%B0%ED%95%98%EA%B2%8C-%EC%A0%95%EC%9D%98\" aria-label=\" 213 식 본문을 사용해 함수를 더 간결하게 정의 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.1.3 식 본문을 사용해 함수를 더 간결하게 정의</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun max(a: Int, b: Int): Int = if (a &gt; b) a else b</code>\n        </deckgo-highlight-code>\n<ul>\n<li>위와 같은 함수를 본문 함수(expression body function)이라고 부름.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun max(a: Int, b: Int) = if (a &gt; b) a else b</code>\n        </deckgo-highlight-code>\n<ul>\n<li>반환 타입이 없지만 컴파일러가 타입 추론(inference)하여 반환 타입을 지정\n<ul>\n<li>이 경우, 식 본문 함수만 반환 타입이 생략 가능</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-214-데이터를-저장하기-위해-변수-선언\" style=\"position:relative;\"><a href=\"#-214-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%EC%A0%80%EC%9E%A5%ED%95%98%EA%B8%B0-%EC%9C%84%ED%95%B4-%EB%B3%80%EC%88%98-%EC%84%A0%EC%96%B8\" aria-label=\" 214 데이터를 저장하기 위해 변수 선언 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.1.4 데이터를 저장하기 위해 변수 선언</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val question: String = &quot;삶, 우주, 그리고 모든 것에 대한 궁극적인 질문&quot;\nval answer: Int = 42</code>\n        </deckgo-highlight-code>\n<ul>\n<li>변수 선언은 val or var로 가능하다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val question = &quot;삶, 우주, 그리고 모든 것에 대한 궁극적인 질문&quot;\nval answer = 42</code>\n        </deckgo-highlight-code>\n<ul>\n<li>타입 선언 생략 가능</li>\n</ul>\n<h3 id=\"-215-변수를-읽기-전용-변수나-재대입-가능-변수로-표시\" style=\"position:relative;\"><a href=\"#-215-%EB%B3%80%EC%88%98%EB%A5%BC-%EC%9D%BD%EA%B8%B0-%EC%A0%84%EC%9A%A9-%EB%B3%80%EC%88%98%EB%82%98-%EC%9E%AC%EB%8C%80%EC%9E%85-%EA%B0%80%EB%8A%A5-%EB%B3%80%EC%88%98%EB%A1%9C-%ED%91%9C%EC%8B%9C\" aria-label=\" 215 변수를 읽기 전용 변수나 재대입 가능 변수로 표시 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.1.5 변수를 읽기 전용 변수나 재대입 가능 변수로 표시</h3>\n<h4 id=\"valvalue\" style=\"position:relative;\"><a href=\"#valvalue\" aria-label=\"valvalue permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>val(value)</h4>\n<ul>\n<li>읽기 전용 참조(read-only reference)를 선언</li>\n<li>단 한 번만 대입 가능</li>\n<li>코틀린에서는 모든 변수를 val 키워드를 사용해 선언하는 방식을 지켜야 함.</li>\n</ul>\n<h4 id=\"varvariable\" style=\"position:relative;\"><a href=\"#varvariable\" aria-label=\"varvariable permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>var(variable)</h4>\n<ul>\n<li>재대입 가능한 참조(reassignable reference)를 선언</li>\n<li>초기화 이후, 다른 값 대입 가능</li>\n<li>반드시 필요할 때에만 var로 변경</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun main() {\n        val result: String\n        if (canPerformOperation()) {\n            result = &quot;Success&quot;\n        }\n        else {\n            result = &quot;Can&#39;t perform operation&quot;\n        }\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>val 참조가 가리키는 객체의 내부 값은 변경될 수 있음.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun main() {\n        var answer = 42\n        answer = &quot;no answer&quot;\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>var는 변수의 값은 변경할 수 있지만 변수의 타입은 고정된다.</li>\n</ul>\n<h3 id=\"-216-더-쉽게-문자열-형식-지정-문자열-템플릿\" style=\"position:relative;\"><a href=\"#-216-%EB%8D%94-%EC%89%BD%EA%B2%8C-%EB%AC%B8%EC%9E%90%EC%97%B4-%ED%98%95%EC%8B%9D-%EC%A7%80%EC%A0%95-%EB%AC%B8%EC%9E%90%EC%97%B4-%ED%85%9C%ED%94%8C%EB%A6%BF\" aria-label=\" 216 더 쉽게 문자열 형식 지정 문자열 템플릿 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.1.6 더 쉽게 문자열 형식 지정: 문자열 템플릿</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun main() {\n        val input = readln()\n        val name = if (input.isNotBlank()) input else &quot;Kotlin&quot;\n        println(&quot;Hello, $name!&quot;)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린 또한 변수 이름 앞에 $를 덧붙이면 변수를 문자열 안에 참조할 수 있다.</li>\n<li>$ 문자를 문자열에 넣고 싶으면 \\를 사용해 escape 시키면 됨.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun main() {\n        val name = readln()\n        println(&quot;Hello, ${if (name.isBlank()) &quot;someone&quot; else name}!&quot;)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>중괄호로 둘러쌓인 식 안에서 여전히 큰따옴표를 사용할 수 있다.</li>\n</ul>\n<h2 id=\"-22-행동과-데이터-캡슐화-클래스와-프로퍼티\" style=\"position:relative;\"><a href=\"#-22-%ED%96%89%EB%8F%99%EA%B3%BC-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%BA%A1%EC%8A%90%ED%99%94-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0\" aria-label=\" 22 행동과 데이터 캡슐화 클래스와 프로퍼티 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 2.2 행동과 데이터 캡슐화: 클래스와 프로퍼티</h2>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Person(val name: String)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>java의 getter와 생성자가 한줄로 요약된다.</li>\n<li>public visibility modifier가 사라진다.</li>\n<li>코틀린의 기본 가시성은 public이다.</li>\n</ul>\n<h3 id=\"-221-클래스와-데이터를-연관시키고-접근-가능하게-만들기-프로퍼티\" style=\"position:relative;\"><a href=\"#-221-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%EC%97%B0%EA%B4%80%EC%8B%9C%ED%82%A4%EA%B3%A0-%EC%A0%91%EA%B7%BC-%EA%B0%80%EB%8A%A5%ED%95%98%EA%B2%8C-%EB%A7%8C%EB%93%A4%EA%B8%B0-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0\" aria-label=\" 221 클래스와 데이터를 연관시키고 접근 가능하게 만들기 프로퍼티 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.2.1 클래스와 데이터를 연관시키고, 접근 가능하게 만들기: 프로퍼티</h3>\n<ul>\n<li>클래스라는 개념은 데이터를 캡슐화하고 캡슐화한 데이터를 다루는 코드를 한 주체 안에 가두는 것이다.</li>\n<li>자바에서는 필드와 접근자를 한데 묶어 property라고 부른다.</li>\n<li>코틀린 property는 자바의 필드와 접근자 메서드를 완전히 대신한다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Person(\n    val name: String,\n    var isStudent: Boolean\n)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>val, var를 같이 선언할 수 있다.</li>\n<li>val는 getter를 만들어내고, var는 getter와 setter를 만들어낸다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun main() {\n        val person = Person(&quot;Bob&quot;, true)\n        println(person.name)\n        println(person.isStudent)\n        person.isStudent = false\n        println(person.isStudent)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>new 키워드 사용하지 않고 생성자 호출 가능</li>\n<li>프로퍼티 이름을 직접 사용해도 getter, setter 호출 가능</li>\n</ul>\n<h3 id=\"-222-프로퍼티-값을-저장하지-않고-계산-커스텀-접근자\" style=\"position:relative;\"><a href=\"#-222-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0-%EA%B0%92%EC%9D%84-%EC%A0%80%EC%9E%A5%ED%95%98%EC%A7%80-%EC%95%8A%EA%B3%A0-%EA%B3%84%EC%82%B0-%EC%BB%A4%EC%8A%A4%ED%85%80-%EC%A0%91%EA%B7%BC%EC%9E%90\" aria-label=\" 222 프로퍼티 값을 저장하지 않고 계산 커스텀 접근자 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.2.2 프로퍼티 값을 저장하지 않고 계산: 커스텀 접근자</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Rectangle(var height: Int, var width: Int) {\n    val isSquare: Boolean\n        get() {\n            return height == width\n        }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>isSquare 프로퍼티는 on the go 프로퍼티이다.</li>\n<li>커스텀 게터를 정의하는 방식과 클래스 안에 파라미터가 없는 함수를 정의하는 방식은 비슷하다.\n<ul>\n<li>구현이나 성능 차이 없음.</li>\n<li>가독성 차이</li>\n<li>클래스의 특성을 기술하고 싶다면 프로퍼티로 정의</li>\n<li>클래스의 행동을 기술하고 싶다면 멤버 함수 선택</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-223-코틀린-소스코드-구조-디렉터리와-패키지\" style=\"position:relative;\"><a href=\"#-223-%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%86%8C%EC%8A%A4%EC%BD%94%EB%93%9C-%EA%B5%AC%EC%A1%B0-%EB%94%94%EB%A0%89%ED%84%B0%EB%A6%AC%EC%99%80-%ED%8C%A8%ED%82%A4%EC%A7%80\" aria-label=\" 223 코틀린 소스코드 구조 디렉터리와 패키지 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.2.3 코틀린 소스코드 구조: 디렉터리와 패키지</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">package com.bottleh.studycodecollection.kotlin.chap2\n\nclass Rectangle(var height: Int, var width: Int) {\n    val isSquare: Boolean\n        get() {\n            return height == width\n        }\n}\n\nfun createUnitSquare(): Rectangle {\n    return Rectangle(1, 1)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>같은 패키지에 속해 있다면 다른 파일에서 정의한 선언일지라도 직접 사용할 수 있다.</li>\n<li>다른 패키지에 정의한 선언을 사용하려면 import 키워드를 사용해서 다른 패키지를 불러올 수 있다.</li>\n<li>자바에서는 패키지의 구조와 디렉터리 계층구조가 같아야 한다.</li>\n<li>코틀린에서는 패키지와 디렉터리 구조가 맞아 떨어질 필요가 없다.\n<ul>\n<li>다만, 자바와 같이 패키지별로 디렉터리를 구성하는 편이 낫다.</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"-23-선택-표현과-처리-이넘과-when\" style=\"position:relative;\"><a href=\"#-23-%EC%84%A0%ED%83%9D-%ED%91%9C%ED%98%84%EA%B3%BC-%EC%B2%98%EB%A6%AC-%EC%9D%B4%EB%84%98%EA%B3%BC-when\" aria-label=\" 23 선택 표현과 처리 이넘과 when permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 2.3 선택 표현과 처리: 이넘과 when</h2>\n<h3 id=\"-231-이넘-클래스와-이넘-상수-정의\" style=\"position:relative;\"><a href=\"#-231-%EC%9D%B4%EB%84%98-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EC%9D%B4%EB%84%98-%EC%83%81%EC%88%98-%EC%A0%95%EC%9D%98\" aria-label=\" 231 이넘 클래스와 이넘 상수 정의 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.3.1 이넘 클래스와 이넘 상수 정의</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">enum class Color {\n    RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>java는 enum이지만 kotlin은 enum class다.</li>\n<li>enum은 소프트 키워드라서 class 앞이 아니라면 다른곳에서 사용할 수 없다.</li>\n<li>class는 하드 키워드라서 클래스를 표현하는 변수 등을 정의할 때 clazz 등을 사용해야 한다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">package com.bottleh.studycodecollection.kotlin.chap2\n\nenum class Color(\n    val r: Int, val g: Int, val b: Int\n) {\n    RED(255, 0, 0), \n    ORANGE(255, 165, 0),\n    YELLOW(255, 255, 0),\n    GREEN(0, 255, 0),\n    BLUE(0, 0, 255),\n    INDIGO(75, 0, 130),\n    VIOLET(238, 130, 238);\n    \n    fun rgb() = (r * 256 + g) * 256 + b\n    fun printColor() = println(&quot;$this is ${rgb()}&quot;)\n}\n\nfun main() {\n    println(Color.BLUE.rgb())\n    Color.GREEN.printColor()\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>enum class 안에 메서드를 정의하는 경우 반드시 이넘 상수 목록과 메서드 정의 사이에 세미콜론을 넣어야 한다.\n<ul>\n<li>코틀린에서 세미콜론이 필수인 유일한 경우다.</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-232-when으로-이넘-클래스-다루기\" style=\"position:relative;\"><a href=\"#-232-when%EC%9C%BC%EB%A1%9C-%EC%9D%B4%EB%84%98-%ED%81%B4%EB%9E%98%EC%8A%A4-%EB%8B%A4%EB%A3%A8%EA%B8%B0\" aria-label=\" 232 when으로 이넘 클래스 다루기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.3.2 when으로 이넘 클래스 다루기</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun getMnemonic(color: Color) = \n    when (color) {\n        Color.RED -&gt; &quot;Richard&quot;\n        Color.ORANGE -&gt; &quot;Of&quot;\n        Color.YELLOW -&gt; &quot;York&quot;\n        Color.GREEN -&gt; &quot;Gave&quot;\n        Color.BLUE -&gt; &quot;Battle&quot;\n        Color.INDIGO -&gt; &quot;In&quot;\n        Color.VIOLET -&gt; &quot;Vain&quot;\n    }\n\nfun main() {\n    println(getMnemonic(Color.BLUE))\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>java와 달리 break를 넣지 않아도 된다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun measureColor() = Color.ORANGE\n\nfun getWarmthFromSensor(): String {\n    val color = measureColor()\n    return when(color) {\n        Color.RED, Color.ORANGE, Color.YELLOW -&gt; &quot;warm (red = ${color.r})&quot;\n        Color.GREEN -&gt; &quot;neutral (green = ${color.g})&quot;\n        Color.BLUE, Color.INDIGO, Color.VIOLET -&gt; &quot;cold (blue = ${color.b})&quot;\n    }\n}\n\nfun main() {\n    println(getWarmthFromSensor())\n}</code>\n        </deckgo-highlight-code>\n<h3 id=\"-233-when식의-대상을-변수에-캡처\" style=\"position:relative;\"><a href=\"#-233-when%EC%8B%9D%EC%9D%98-%EB%8C%80%EC%83%81%EC%9D%84-%EB%B3%80%EC%88%98%EC%97%90-%EC%BA%A1%EC%B2%98\" aria-label=\" 233 when식의 대상을 변수에 캡처 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.3.3 when식의 대상을 변수에 캡처</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun getWarmthFromSensor() =\n    when(val color = measureColor()) {\n        Color.RED, Color.ORANGE, Color.YELLOW -&gt; &quot;warm (red = ${color.r})&quot;\n        Color.GREEN -&gt; &quot;neutral (green = ${color.g})&quot;\n        Color.BLUE, Color.INDIGO, Color.VIOLET -&gt; &quot;cold (blue = ${color.b})&quot;\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>when 식 대상 값을 변수에 넣을 수 있다.</li>\n<li>캡처한 변수의 프로퍼티에 접근 가능하다.</li>\n</ul>\n<h3 id=\"-234-when의-분기-조건에-임의의-객체-사용\" style=\"position:relative;\"><a href=\"#-234-when%EC%9D%98-%EB%B6%84%EA%B8%B0-%EC%A1%B0%EA%B1%B4%EC%97%90-%EC%9E%84%EC%9D%98%EC%9D%98-%EA%B0%9D%EC%B2%B4-%EC%82%AC%EC%9A%A9\" aria-label=\" 234 when의 분기 조건에 임의의 객체 사용 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.3.4 when의 분기 조건에 임의의 객체 사용</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun mix(c1: Color, c2: Color) =\n    when(setOf(c1, c2)) {\n        setOf(RED, YELLOW) -&gt; ORANGE\n        setOf(YELLOW, BLUE) -&gt; GREEN\n        setOf(BLUE, VIOLET) -&gt; INDIGO\n        else -&gt; throw Exception(&quot;Dirty color&quot;)\n    }\n\nfun main() {\n    println(mix(BLUE, YELLOW))\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>when의 분기 조건 부분에 식을 넣을 수 있기 때문에 많은 경우 코드를 더 간결하고 아름답게 작성할 수 있다.</li>\n</ul>\n<h3 id=\"-235-인자-없는-when-사용\" style=\"position:relative;\"><a href=\"#-235-%EC%9D%B8%EC%9E%90-%EC%97%86%EB%8A%94-when-%EC%82%AC%EC%9A%A9\" aria-label=\" 235 인자 없는 when 사용 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.3.5 인자 없는 when 사용</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun mixOptimized(c1: Color, c2: Color) =\n    when {\n        (c1 == RED &amp;&amp; c2 == YELLOW) || (c1 == YELLOW &amp;&amp; c2 == RED) -&gt; ORANGE\n        (c1 == YELLOW &amp;&amp; c2 == BLUE) || (c1 == BLUE &amp;&amp; c2 == YELLOW) -&gt; GREEN\n        (c1 == BLUE &amp;&amp; c2 == VIOLET) || (c1 == VIOLET &amp;&amp; c2 == BLUE) -&gt; INDIGO\n        \n        else -&gt; throw Exception(&quot;Dirty color&quot;)\n    }\n\nfun main() {\n    println(mixOptimized(BLUE, YELLOW))\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>인자가 없는 when 식을 사용하면 불필요한 객체 생성을 막을 수 있다.</li>\n<li>다만, 코드의 가독성은 떨어진다.</li>\n</ul>\n<h3 id=\"-236-스마트-캐스트-타입-검사와-타입-캐스트-조합\" style=\"position:relative;\"><a href=\"#-236-%EC%8A%A4%EB%A7%88%ED%8A%B8-%EC%BA%90%EC%8A%A4%ED%8A%B8-%ED%83%80%EC%9E%85-%EA%B2%80%EC%82%AC%EC%99%80-%ED%83%80%EC%9E%85-%EC%BA%90%EC%8A%A4%ED%8A%B8-%EC%A1%B0%ED%95%A9\" aria-label=\" 236 스마트 캐스트 타입 검사와 타입 캐스트 조합 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.3.6 스마트 캐스트: 타입 검사와 타입 캐스트 조합</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface Expr\n\nclass Num(val value: Int) : Expr\nclass Sum(val left: Expr, val right: Expr) : Expr</code>\n        </deckgo-highlight-code>\n<ul>\n<li>여러 타입의 식 객체를 아우르는 공통 타입 역할만 수행하는 인터페이스를 <strong>마커 인터페이스</strong>라고 부른다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun eval(e: Expr): Int {\n    if (e is Num) {\n        val n = e as Num // 불필요한 중복\n        return n.value\n    }\n    if (e is Sum) {\n        return eval(e.left) + eval(e.right)\n    }\n    throw IllegalArgumentException(&quot;Unknown expression&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린의 is 검사는 어떤 변수의 타입을 확인한 다음에 그 타입에 속한 멤버에 접근하기 위해 명시적으로 변수 타입을 변환하지 않아도 된다.</li>\n<li>실제로는 컴파일러가 타입을 대신 변환(스마트 캐스트)</li>\n</ul>\n<h3 id=\"-237-리팩터링-if를-when으로-변경\" style=\"position:relative;\"><a href=\"#-237-%EB%A6%AC%ED%8C%A9%ED%84%B0%EB%A7%81-if%EB%A5%BC-when%EC%9C%BC%EB%A1%9C-%EB%B3%80%EA%B2%BD\" aria-label=\" 237 리팩터링 if를 when으로 변경 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.3.7 리팩터링: if를 when으로 변경</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun eval(e: Expr): Int =\n    if (e is Num) {\n        e.value\n    } else if (e is Sum) {\n        eval(e.right) + eval(e.left)\n    } else {\n        throw IllegalArgumentException(&quot;Unknown expression&quot;)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>if는 식이라서 삼항 연산자가 따로 없다.</li>\n<li>중괄호를 없애고 본문 구문을 사용해 작성 가능하다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun eval(e: Expr): Int =\n    if (e is Num) e.value\n    else if (e is Sum) eval(e.right) + eval(e.left)\n    else throw IllegalArgumentException(&quot;Unknown expression&quot;)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>if의 분기에 식이 하나밖에 없다면 중괄호를 생략해도 된다.</li>\n<li>블록을 사용한다면 블록의 마지막 식이 그 분기의 결괏값이다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun eval(e: Expr): Int =\n    when (e) {\n        is Num -&gt; e.value\n        is Sum -&gt; eval(e.right) + eval(e.left)\n        else -&gt; throw IllegalArgumentException(&quot;Unknown expression&quot;)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>when으로 변경된 코드</li>\n</ul>\n<h3 id=\"-238-if와-when의-분기에서-블록-사용\" style=\"position:relative;\"><a href=\"#-238-if%EC%99%80-when%EC%9D%98-%EB%B6%84%EA%B8%B0%EC%97%90%EC%84%9C-%EB%B8%94%EB%A1%9D-%EC%82%AC%EC%9A%A9\" aria-label=\" 238 if와 when의 분기에서 블록 사용 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.3.8 if와 when의 분기에서 블록 사용</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun evalWithLogging(e: Expr): Int =\n    when (e) {\n        is Num -&gt; {\n            println(&quot;num: ${e.value}&quot;)\n            e.value\n        }\n        is Sum -&gt; {\n            val left = evalWithLogging(e.left)\n            val right = evalWithLogging(e.right)\n            println(&quot;sum: $left + $right&quot;)\n            left + right\n        }\n        else -&gt; throw IllegalArgumentException(&quot;Unknown expression&quot;)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>if나 when 모두 분기에 블록을 사용할 수 있다.</li>\n<li><em>블록의 마지막 식이 블록의 결과</em> 라는 규칙은 블록이 값을 만들어내야 하는 경우 항상 성립한다.</li>\n</ul>\n<h2 id=\"-24-대상-이터레이션-while과-for-루프\" style=\"position:relative;\"><a href=\"#-24-%EB%8C%80%EC%83%81-%EC%9D%B4%ED%84%B0%EB%A0%88%EC%9D%B4%EC%85%98-while%EA%B3%BC-for-%EB%A3%A8%ED%94%84\" aria-label=\" 24 대상 이터레이션 while과 for 루프 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 2.4 대상 이터레이션: while과 for 루프</h2>\n<h3 id=\"-241-조건이-참인-동안-코드-반복-while-루프\" style=\"position:relative;\"><a href=\"#-241-%EC%A1%B0%EA%B1%B4%EC%9D%B4-%EC%B0%B8%EC%9D%B8-%EB%8F%99%EC%95%88-%EC%BD%94%EB%93%9C-%EB%B0%98%EB%B3%B5-while-%EB%A3%A8%ED%94%84\" aria-label=\" 241 조건이 참인 동안 코드 반복 while 루프 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.4.1 조건이 참인 동안 코드 반복: while 루프</h3>\n<ul>\n<li>코틀린에는 while과 do-while 루프가 있다.</li>\n<li>내포된 루프의 경우 레이블을 지정할 수 있다.\n<ul>\n<li>break나 continue를 사용할 때 레이블을 참조할 수 있다.</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-242-수에-대해-이터레이션-범위와-순열\" style=\"position:relative;\"><a href=\"#-242-%EC%88%98%EC%97%90-%EB%8C%80%ED%95%B4-%EC%9D%B4%ED%84%B0%EB%A0%88%EC%9D%B4%EC%85%98-%EB%B2%94%EC%9C%84%EC%99%80-%EC%88%9C%EC%97%B4\" aria-label=\" 242 수에 대해 이터레이션 범위와 순열 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.4.2 수에 대해 이터레이션: 범위와 순열</h3>\n<p><code>val oneToTen = 1..10</code></p>\n<ul>\n<li>코틀린에서는 범위를 사용하여 루프를 한다.\n<ul>\n<li>폐구간(양끝 포함)</li>\n<li>두번째 값이 항상 범위에 포함</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun fizzBuzz(i: Int) = when {\n    i % 15 == 0 -&gt; &quot;FizzBuzz&quot;\n    i % 3 == 0 -&gt; &quot;Fizz&quot;\n    i % 5 == 0 -&gt; &quot;Buzz&quot;\n    else -&gt; &quot;$i&quot;\n}\n\nfun main() {\n    for (i in 1..100) {\n        println(fizzBuzz(i))\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>피즈버즈 게임 구현 예시</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    for (i in 100 downTo 1 step 2) {\n        println(fizzBuzz(i))\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>역방향 순열 예시</li>\n<li>반폐구간에 대해 이터레이션 하고 싶다면 ..&#x3C; 연산 사용</li>\n</ul>\n<h3 id=\"-243-맵에-대한-이터레이션\" style=\"position:relative;\"><a href=\"#-243-%EB%A7%B5%EC%97%90-%EB%8C%80%ED%95%9C-%EC%9D%B4%ED%84%B0%EB%A0%88%EC%9D%B4%EC%85%98\" aria-label=\" 243 맵에 대한 이터레이션 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.4.3 맵에 대한 이터레이션</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val collection = listOf(&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;)\n    for (color in collection) {\n        println(&quot;$color &quot;)\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>단순 컬렉션 이터레이션 예시</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val binaryReps = mutableMapOf&lt;Char, String&gt;()\n    for (char in &#39;A&#39;..&#39;F&#39;) {\n        val binary = char.code.toString(radix = 2) // 아스키 코드를 이진 표현으로 변환\n        binaryReps[char] = binary\n    }\n    for ((letter, binary) in binaryReps) {\n        println(&quot;$letter = $binary&quot;)\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>java의 경우 map에 put method를 써야하지만 코틀린은 그렇지 않다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val list = listOf(&quot;10&quot;, &quot;11&quot;, &quot;1001&quot;)\n    for ((index, element) in list.withIndex()) {\n        println(&quot;$index: $element&quot;)\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>index와 함께 컬렉션을 이터레이션 함</li>\n</ul>\n<h3 id=\"-244-in으로-컬렉션이나-범위의-원소-검사\" style=\"position:relative;\"><a href=\"#-244-in%EC%9C%BC%EB%A1%9C-%EC%BB%AC%EB%A0%89%EC%85%98%EC%9D%B4%EB%82%98-%EB%B2%94%EC%9C%84%EC%9D%98-%EC%9B%90%EC%86%8C-%EA%B2%80%EC%82%AC\" aria-label=\" 244 in으로 컬렉션이나 범위의 원소 검사 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.4.4 in으로 컬렉션이나 범위의 원소 검사</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun isLetter(c: Char) = c in &#39;a&#39;..&#39;z&#39; || c in &#39;A&#39;..&#39;Z&#39;\nfun isNotDigit(c: Char) = c !in &#39;0&#39;..&#39;9&#39;</code>\n        </deckgo-highlight-code>\n<ul>\n<li>!in을 사용하면 어떤 값이 범위에 속하지 않는지 검사할 수 있다.</li>\n<li>when에서 in 검사를 사용할 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    println(&quot;Kotlin&quot; in &quot;Java&quot;..&quot;Scala&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>알파벳 순서로 비교하기 때문에 true 반환</li>\n<li>컬렉션도 마찬가지로 in 연산을 사용할 수 있다.</li>\n</ul>\n<h2 id=\"-25-코틀린에서-예외-던지고-잡아내기\" style=\"position:relative;\"><a href=\"#-25-%EC%BD%94%ED%8B%80%EB%A6%B0%EC%97%90%EC%84%9C-%EC%98%88%EC%99%B8-%EB%8D%98%EC%A7%80%EA%B3%A0-%EC%9E%A1%EC%95%84%EB%82%B4%EA%B8%B0\" aria-label=\" 25 코틀린에서 예외 던지고 잡아내기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 2.5 코틀린에서 예외 던지고 잡아내기</h2>\n<ul>\n<li>자바와 달리 코틀린의 throw는 식이므로 다른 식에 포함될 수 있다.</li>\n</ul>\n<h3 id=\"-251-try-catch-finally를-사용한-예외-처리와-오류-복구\" style=\"position:relative;\"><a href=\"#-251-try-catch-finally%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-%EC%98%88%EC%99%B8-%EC%B2%98%EB%A6%AC%EC%99%80-%EC%98%A4%EB%A5%98-%EB%B3%B5%EA%B5%AC\" aria-label=\" 251 try catch finally를 사용한 예외 처리와 오류 복구 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.5.1 try, catch, finally를 사용한 예외 처리와 오류 복구</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun readNumber(reader: BufferedReader): Int? {\n    try {\n        val line = reader.readLine()\n        return Integer.parseInt(line)\n    } catch (e: NumberFormatException) {\n        return null\n    } finally {\n        reader.close()\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>java와 달리 함수가 던질 수 있는 예외를 명시할 필요가 없다. (throws)</li>\n<li>코틀린은 checked exception과 unchecked exception을 구별하지 앟는다.</li>\n<li>코틀린에서는 컴파일러가 예외 처리를 강제하지 않는다.</li>\n</ul>\n<h3 id=\"-252-try를-식으로-사용\" style=\"position:relative;\"><a href=\"#-252-try%EB%A5%BC-%EC%8B%9D%EC%9C%BC%EB%A1%9C-%EC%82%AC%EC%9A%A9\" aria-label=\" 252 try를 식으로 사용 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 2.5.2 try를 식으로 사용</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun readNumber(reader: BufferedReader) {\n    val number = try {\n        Integer.parseInt(reader.readLine())\n    } catch (e: NumberFormatException) {\n        return\n    }\n    \n    println(number)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>try의 본문은 반드시 중괄호로 둘러싸야 한다.</li>\n<li>마지막 식의 값이 전체 결과값이다.</li>\n</ul>","excerpt":"📖 2.1 기본 요소: 함수와 변수 🔖 2.1.1 첫 번째 코틀린 프로그램 작성: Hello, World! 함수를 모든 코틀린 파일의 최상위 수준에 정의 가능 main에 인자가 없어도 된다. 간결성 강조 세미콜론(;)을 붙이지 않는 것을 더 권장한다. 🔖 2.1.2 파라미터와 반환값이 있는 함수 선언 파라미터 이름이 먼저 오고 그 뒤에 타입 지정 콜론(:)으로 구분 함수의 반환 타입은 파라미터 목록을 닫는 괄호 다음에 옴. 위와 같은 코드를 블록 본문 함수(block body function…","fields":{"slug":"/backend/kotlin-in-action/2장-코틀린_기초/"},"frontmatter":{"title":"Kotlin in Action - 2장 코틀린 기초","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/f7f7ddfa31d1614405dc5af1487b9ec4/9c94d/kotlin-in-action.png"}}},"draft":false,"category":"Back-End","tags":["Kotlin"],"date":"March 09, 2025"}},"node":{"id":"3210e7da-a86b-584f-9d51-04ced27c803f","html":"<p>디자인 패턴</p>\n<ul>\n<li>소프트웨어 설계에서 반복적으로 발생하는 문제에 대해 반복적으로 적용할 수 있는 해결 방법</li>\n<li>설계를 재사용하는 것이 목적</li>\n</ul>\n<p>프레임워크</p>\n<ul>\n<li>설계와 코드를 함께 재사용하는 것이 목적</li>\n<li>특정한 변경을 일관성 있게 다룰 수 있는 확장 가능한 코드 템플릿을 제공</li>\n</ul>\n<h2 id=\"-151-디자인-패텅과-설계-재사용\" style=\"position:relative;\"><a href=\"#-151-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%85%85%EA%B3%BC-%EC%84%A4%EA%B3%84-%EC%9E%AC%EC%82%AC%EC%9A%A9\" aria-label=\" 151 디자인 패텅과 설계 재사용 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 15.1 디자인 패텅과 설계 재사용</h2>\n<h3 id=\"-1511-소프트웨어-패턴\" style=\"position:relative;\"><a href=\"#-1511-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%ED%8C%A8%ED%84%B4\" aria-label=\" 1511 소프트웨어 패턴 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 15.1.1 소프트웨어 패턴</h3>\n<p>패턴이란❓</p>\n<ul>\n<li>패턴은 반복적으로 발생하는 문제와 해법의 쌍으로 정의</li>\n<li>패턴을 사용함으로써 이미 알려진 문제와 이에 대한 해법을 문서로 정리할 수 있으며, 이 지식을 다른 사람과 의사소통할 수 있다.</li>\n<li>패턴은 추상적인 원칙과 실제 코드 작성 사이의 간극을 메워주며 실질적인 코드 작성을 돕는다.</li>\n<li>패턴의 요점은 패턴이 실무에서 탄생했다는 점이다.</li>\n</ul>\n<blockquote>\n<p>하나의 실무 컨텍스트에서 유용하게 사용해 왔고 다른 실무 컨텍스트에서도 유용할 것이라고 예상되는 아이디어다. - 마틴 파울러</p>\n</blockquote>\n<p>🛠️ 3의 규칙</p>\n<ul>\n<li>최소 세 가지의 서로 다른 시스템에 특별한 문제 없이 적용할 수 있고 유용한 경우에만 패턴으로 간주할 수 있다.</li>\n</ul>\n<p>패턴의 이름은 높은 수준의 대화를 가능하게하는 원천이다.</p>\n<p>패턴은 홀로 존재하지 않는다.</p>\n<ul>\n<li>연관된 패턴들의 집합들이 모여 하나의 패턴 언어(패턴 시스템)를 구성한다.</li>\n</ul>\n<h3 id=\"-1512-패턴-분류\" style=\"position:relative;\"><a href=\"#-1512-%ED%8C%A8%ED%84%B4-%EB%B6%84%EB%A5%98\" aria-label=\" 1512 패턴 분류 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 15.1.2 패턴 분류</h3>\n<ul>\n<li>디자인 패턴\n<ul>\n<li>특정 정황 내에서 일반적인 설계 문제를 해결하며, 협력하는 컴포넌트들 사이에서 반복적으로 발생하는 구조를 서술</li>\n</ul>\n</li>\n<li>아키텍처 패턴\n<ul>\n<li>소프트웨어의 전체적인 구조를 결정하기 위해 사용할 수 있다.</li>\n<li>미리 정의된 서브시스템들을 제공하고, 각 서브시스템들의 책임을 정의하며, 서브시스템들 사이의 관계를 조직화하는 규칙과 가이드라인을 포함</li>\n<li>구체적인 소프트웨어 아키텍처를 위한 템플릿을 제공</li>\n</ul>\n</li>\n<li>이디엄(Idiom)\n<ul>\n<li>특정 프로그래밍 언어에만 국한된 하위 레벨 패턴</li>\n<li>주어진 언어의 기능을 사용해 컴포넌트, 컴포넌트 간의 특정 측면을 구현하는 방법을 서술</li>\n<li>언어에 종속적</li>\n</ul>\n</li>\n<li>분석 패턴\n<ul>\n<li>도메인 내의 개념적인 문제를 해결하는 데 초점을 맞춤.</li>\n<li>업무 모델링 시에 발견되는 공통적인 구조를 표현하는 개념들의 집합</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-1513-패턴과-책임-주도-설계\" style=\"position:relative;\"><a href=\"#-1513-%ED%8C%A8%ED%84%B4%EA%B3%BC-%EC%B1%85%EC%9E%84-%EC%A3%BC%EB%8F%84-%EC%84%A4%EA%B3%84\" aria-label=\" 1513 패턴과 책임 주도 설계 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 15.1.3 패턴과 책임-주도 설계</h3>\n<p>객체지향 설계에서 가장 중요한 일은 올바른 책임을 올바른 객체에게 할당하고 객체 간의 유연한 협력관계를 구축하는 일이다.</p>\n<ul>\n<li>패턴을 따르면 특정한 상황에 적용할 수 있는 설계를 쉽고 빠르게 떠올릴 수 있다.</li>\n<li>패턴의 구성 요소는 클래스와 메서드가 아니라 '역할과 책임'이다.</li>\n<li>어떤 구현 코드가 어떤 디자인 패턴을 따른다고 이야기할 때는 역할, 책임, 협력의 관점에서 유사성을 공유한다는 것이지 특정한 구현 방식을 강제하는 것은 아니다.</li>\n</ul>\n<h3 id=\"-1514-캡슐화와-디자인-패턴\" style=\"position:relative;\"><a href=\"#-1514-%EC%BA%A1%EC%8A%90%ED%99%94%EC%99%80-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4\" aria-label=\" 1514 캡슐화와 디자인 패턴 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 15.1.4 캡슐화와 디자인 패턴</h3>\n<p>대부분의 디자인 패턴의 목적은 특정한 변경을 캡슐화함으로써 유연하고 일관성 있는 협력을 설계할 수 있는 경험을 공유하는 것</p>\n<ul>\n<li>디자인 패턴에서 중요한 것은 디자인 패턴의 구현 방법이나 구조가 아니다.</li>\n<li>어떤 디자인 패턴이 어떤 변경을 캡슐화하는지를 이해하는 것이 중요하다.</li>\n<li>디자인 패턴이 변경을 캡슐화하기 위해 어떤 방법을 사용하는지를 이해하는 것이 더 중요하다.</li>\n</ul>\n<h3 id=\"-1515-패턴은-출발점이다\" style=\"position:relative;\"><a href=\"#-1515-%ED%8C%A8%ED%84%B4%EC%9D%80-%EC%B6%9C%EB%B0%9C%EC%A0%90%EC%9D%B4%EB%8B%A4\" aria-label=\" 1515 패턴은 출발점이다 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 15.1.5 패턴은 출발점이다</h3>\n<p>패턴은 출발점이지 목적지가 아니다. 디자인 패턴이 현재의 요구사항이나 적용 기술, 프레임워크에 적합하지 않다면 패턴을 그대로 따르지 말고 목적에 맞게 패턴을 수정하라.</p>\n<ul>\n<li>해결하려는 문제가 아니라 패턴이 제시하는 구조를 맹목적으로 따르는 것은 불필요하게 복잡하고, 난해하며, 유지보수하기 어려운 시스템을 낳는다.</li>\n</ul>\n<h2 id=\"-152-프레임워크와-코드-재사용\" style=\"position:relative;\"><a href=\"#-152-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC%EC%99%80-%EC%BD%94%EB%93%9C-%EC%9E%AC%EC%82%AC%EC%9A%A9\" aria-label=\" 152 프레임워크와 코드 재사용 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 15.2 프레임워크와 코드 재사용</h2>\n<h3 id=\"-1521-코드-재사용-대-설계-재사용\" style=\"position:relative;\"><a href=\"#-1521-%EC%BD%94%EB%93%9C-%EC%9E%AC%EC%82%AC%EC%9A%A9-%EB%8C%80-%EC%84%A4%EA%B3%84-%EC%9E%AC%EC%82%AC%EC%9A%A9\" aria-label=\" 1521 코드 재사용 대 설계 재사용 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 15.2.1 코드 재사용 대 설계 재사용</h3>\n<p>재사용 관점에서 설계 재사용보다 더 좋은 방법은 코드 재사용이다.</p>\n<p>프레임워크란❓</p>\n<ul>\n<li>추상 클래스나 인터페이스를 정의하고 인스턴스 사이의 상호작용을 통해 시스템 전체 혹은 일부를 구현해 놓은 재사용 가능한 설계</li>\n<li>애플리케이션 개발자가 현재의 요구사항에 맞게 머스터마이징할 수 있는 애플리케이션의 골격(skeleton)</li>\n<li>코드를 재사용함으로써 설계 아이디어를 재사용</li>\n</ul>\n<h3 id=\"-1522-상위-정책과-하위-정책으로-패키지-분리하기\" style=\"position:relative;\"><a href=\"#-1522-%EC%83%81%EC%9C%84-%EC%A0%95%EC%B1%85%EA%B3%BC-%ED%95%98%EC%9C%84-%EC%A0%95%EC%B1%85%EC%9C%BC%EB%A1%9C-%ED%8C%A8%ED%82%A4%EC%A7%80-%EB%B6%84%EB%A6%AC%ED%95%98%EA%B8%B0\" aria-label=\" 1522 상위 정책과 하위 정책으로 패키지 분리하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 15.2.2 상위 정책과 하위 정책으로 패키지 분리하기</h3>\n<p>상위 정책은 상대적으로 변경에 안정적이지만 세부 사항은 자주 변경된다. 그리고 상위 정책이 세부 사항에 비해 재사용될 가능성이 높다.</p>\n<ul>\n<li>상위 정책이 세부 사항보다 더 다양한 상황에서 재사용될 수 있어야 한다.\n<ul>\n<li>상위 정책이 세부 사항에 의존하게 되면 상위 정책이 필요한 모든 경우에 세부 사항도 항상 함께 존재해야 하기 때문에 상위 정책의 재사용성이 낮아진다.</li>\n<li>의존성 역전 원칙에 맞게 상위 정책과 세부 사항 모두 추상화에 의존하게 만든다.</li>\n</ul>\n</li>\n<li>변하는 것(구체적인 세부 사항)과 변하지 않는 것(상위 정책에 속하는 역할들의 협력구조)을 서로 다른 주기로 배포할 수 있도록 별도의 '배포 단위'로 분리해야 한다.\n<ul>\n<li>상위 정책을 구현하고 있는 패키지를 다른 애플리케이션에 재사용할 수 있다.</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-1523-제어-역전-원리\" style=\"position:relative;\"><a href=\"#-1523-%EC%A0%9C%EC%96%B4-%EC%97%AD%EC%A0%84-%EC%9B%90%EB%A6%AC\" aria-label=\" 1523 제어 역전 원리 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 15.2.3 제어 역전 원리</h3>\n<p>프레임워크를 사용할 경우 개별 애플리케이션에서 프레임워크로 제어 흐름의 주체가 이동한다.</p>\n<ul>\n<li>의존성을 역전시키면 제어 흐름의 주체 역시 역전된다.</li>\n<li>IoC 원리, Hollywood 원리</li>\n</ul>\n<p>프레임워크에서는 일반적인 해결책만 제공하고 애플리케이션에 따라 달라질 수 있는 특정한 동작은 비워둔다.</p>\n<ul>\n<li>완성되지 않은 채로 남겨진 동작을 훅(hook)이라고 부른다.</li>\n<li>재정의된 훅은 제어 역전 원리에 따라 프레임워크가 원하는 시점에 호출</li>\n<li>우리는 프레임워크가 적절한 시점에 실행할 것으로 예상되는 코드를 작성할 뿐이다.</li>\n</ul>\n<p>제어의 역전이 프레임워크의 핵심 개념인 동시에 코드의 재사용을 가능하게 하는 힘이라는 사실을 이해해야 한다.</p>","excerpt":"디자인 패턴 소프트웨어 설계에서 반복적으로 발생하는 문제에 대해 반복적으로 적용할 수 있는 해결 방법 설계를 재사용하는 것이 목적 프레임워크 설계와 코드를 함께 재사용하는 것이 목적 특정한 변경을 일관성 있게 다룰 수 있는 확장 가능한 코드 템플릿을 제공 📖 15.1 디자인 패텅과 설계 재사용 🔖 15.1.…","fields":{"slug":"/backend/object/chapter15/디자인_패턴과_프레임워크/"},"frontmatter":{"title":"Object - 15장 디자인 패턴과 프레임워크","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/dd0e1990925e942697544e2bdcd9332e/9b73b/object.png"}}},"draft":false,"category":"Back-End","tags":["java"],"date":"December 03, 2023"}}}},"staticQueryHashes":["2374173507","2996537568","3691437124"]}