<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>탄탄한 개발자 성장일지</title>
    <link>https://comhwang.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sat, 20 Jun 2026 13:18:58 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>_차누_</managingEditor>
    <image>
      <title>탄탄한 개발자 성장일지</title>
      <url>https://tistory1.daumcdn.net/tistory/4083600/attach/ae888e4d95864b02907cc6a32438c2d3</url>
      <link>https://comhwang.tistory.com</link>
    </image>
    <item>
      <title>[프로그래머스] 연속된 부분 수열의 합</title>
      <link>https://comhwang.tistory.com/81</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/178870&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/178870&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1692101277600&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래머스&quot; data-og-description=&quot;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/178870&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fYsHq/hyTFa7I2a2/JQiMyKO1jpg1bj7SxMYK31/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/eQw1g/hyTCLIwhhH/MnzKpSgRkEpTm33Zz9MlCk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/178870&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/178870&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fYsHq/hyTFa7I2a2/JQiMyKO1jpg1bj7SxMYK31/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/eQw1g/hyTCLIwhhH/MnzKpSgRkEpTm33Zz9MlCk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;접근법1&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이중 반복문을 통해 조건을 만족하는 부분 수열을 구하는 방식으로 진행했지만, 이중 반복문 사용으로 시간초과가 발생했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;&lt;b&gt;문제풀이&lt;/b&gt;&lt;/summary&gt;
&lt;pre id=&quot;code_1692101323624&quot; class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(sequence, k):
    answer = [0,1000000]
    
    len_seq= len(sequence)

    for i in range(len_seq) :
        sum_i = 0
        for j in range(i,len_seq) :
            if sum_i+sequence[j] == k :
                if answer[1]-answer[0] &amp;gt; j-i :
                    answer = [i,j]
                break
            elif sum_i+sequence[j] &amp;gt; k :
                break
            sum_i+=sequence[j]

    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;접근법2&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이중 반복문을 사용하면 사용시 시간초과 발생하기 때문에 투포인터 알고리즘을 사용하여 해결했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;start, end 두 개의 포인터를 이동시키면서 진행했습니다. 만약 현재 합이 k보다 작으면 end를 우측으로 이동시키고, 현재 합이 k 보다 같거나 크면 start를 우측으로 이동시키면서 답을 구했습니다.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;&lt;b&gt;문제풀이&lt;/b&gt;&lt;/summary&gt;
&lt;pre id=&quot;code_1692101424868&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(sequence, k):
    answer = [0,1000000]
    len_seq= len(sequence)

    # 첫 인덱스의 값이 k일 경우를 위해 end는 -1부터 시작
    start=0
    end=-1
    sum_cur=0

    # 투포인터 알고리즘
    while True :
        # 합이 원하는 값보다 작을 경우 end를 우측으로 한칸 이동
        if sum_cur &amp;lt; k :
            end+=1
            if end == len_seq : break
            sum_cur+=sequence[end]
        # 합이 원하는 값보다 크거나 같을 경우 start를 우측으로 한칸 이동
        else :
            if start == len_seq : break
            sum_cur-=sequence[start]
            start+=1
        # 합이 원하는 값과 일치하고, 기존 answer 의 인덱스 차이보다 작으면 교체
        if sum_cur == k :
            if answer[1]-answer[0] &amp;gt; end-start :
                answer = [start,end]

    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://comhwang.tistory.com/4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://comhwang.tistory.com/4&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1692102255144&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[알고리즘] 투 포인터 알고리즘&quot; data-og-description=&quot;투 포인터 알고리즘 리스트에 순차적으로 접근해야 할 때 두 개의 점의 위치를 기록하면서 진행하는 알고리즘입니다. 완전탐색 알고리즘 등을 사용하여 문제에 접근할 경우 테스트 케이스에 큰&quot; data-og-host=&quot;comhwang.tistory.com&quot; data-og-source-url=&quot;https://comhwang.tistory.com/4&quot; data-og-url=&quot;https://comhwang.tistory.com/4&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/beQ3W1/hyTCAUDxkG/9DW7bE7iQvqhbxyAVqhnL1/img.jpg?width=757&amp;amp;height=222&amp;amp;face=0_0_757_222,https://scrap.kakaocdn.net/dn/K0svN/hyTFoE1O86/XwlkaCexlCKGaGr26gew21/img.jpg?width=757&amp;amp;height=222&amp;amp;face=0_0_757_222,https://scrap.kakaocdn.net/dn/G9QwB/hyTCxQ7YuU/KQuUa60ClGKmUUnI7V93aK/img.jpg?width=757&amp;amp;height=222&amp;amp;face=0_0_757_222&quot;&gt;&lt;a href=&quot;https://comhwang.tistory.com/4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://comhwang.tistory.com/4&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/beQ3W1/hyTCAUDxkG/9DW7bE7iQvqhbxyAVqhnL1/img.jpg?width=757&amp;amp;height=222&amp;amp;face=0_0_757_222,https://scrap.kakaocdn.net/dn/K0svN/hyTFoE1O86/XwlkaCexlCKGaGr26gew21/img.jpg?width=757&amp;amp;height=222&amp;amp;face=0_0_757_222,https://scrap.kakaocdn.net/dn/G9QwB/hyTCxQ7YuU/KQuUa60ClGKmUUnI7V93aK/img.jpg?width=757&amp;amp;height=222&amp;amp;face=0_0_757_222');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[알고리즘] 투 포인터 알고리즘&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;투 포인터 알고리즘 리스트에 순차적으로 접근해야 할 때 두 개의 점의 위치를 기록하면서 진행하는 알고리즘입니다. 완전탐색 알고리즘 등을 사용하여 문제에 접근할 경우 테스트 케이스에 큰&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;comhwang.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/프로그래머스</category>
      <author>_차누_</author>
      <guid isPermaLink="true">https://comhwang.tistory.com/81</guid>
      <comments>https://comhwang.tistory.com/81#entry81comment</comments>
      <pubDate>Tue, 15 Aug 2023 21:10:56 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 혼자서 하는 틱택토</title>
      <link>https://comhwang.tistory.com/80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/160585&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/160585&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1691063209860&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래머스&quot; data-og-description=&quot;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/160585&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Nilr0/hyTwpFDmLT/t1w8pU9HvLR34An3S4pn61/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/VRHbg/hyTwdyoKpO/GylgFxiJF5zRgJa0Pn8LX1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/160585&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/160585&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Nilr0/hyTwpFDmLT/t1w8pU9HvLR34An3S4pn61/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/VRHbg/hyTwdyoKpO/GylgFxiJF5zRgJa0Pn8LX1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;%EC%A0%91%EA%B7%BC%EB%B2%95-1&quot; style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;접근법&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;오류 조건인 경우에 if문을 통해 0을 반환해주고, if문에 걸리지 않을 경우 최종적으로 1을 반환해주는 방식으로 진행했습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오류 조건&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;O과 X 둘 다 성공하는 경우&lt;/li&gt;
&lt;li&gt;성공했는데 게임을 진행하는 경우
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;O이 성공했는데 X와 수가 같은 경우&lt;/li&gt;
&lt;li&gt;X가 성공했는데 O의 수가 더 많은 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;두 갯수 차이가 2이상 차이나는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;&lt;b&gt;문제풀이&lt;/b&gt;&lt;/summary&gt;
&lt;pre id=&quot;code_1691063506279&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 틱택토 성공여부 판단(O,X)
def isSuccess(board,X_O) :
    # 가로,세로,대각선이 모두 O or X 면 틱택토 성공
    success = [[0,1,2],[3,4,5],[6,7,8],[0,4,8],[2,4,6],[0,3,6],[1,4,7],[2,5,8]]
    for ele in success :
        if board[ele[0]] == X_O and board[ele[1]] == X_O and board[ele[2]] == X_O :
            return 1
    return 0

def solution(board):
    split_board = list(map(lambda x:list(x),board)) # 각 요소를 배열로 변환
    sum_board = sum(split_board,[]) # 배열로 변환한 2차원 배열을 1차원 배열로 합침
    sum_O = sum_board.count('O')
    sum_X = sum_board.count('X')

    # 만약 O,X의 수 차이가 2 이상 나면 실수로 판단
    if sum_O - sum_X &amp;gt; 1 or sum_O &amp;lt; sum_X :
        return 0

    # O과 X의 성공여부 판단
    success_O = isSuccess(sum_board,'O')
    success_X = isSuccess(sum_board,'X')

    # X,O가 모두 성공하면 실수로 판단
    if success_O == 1 and success_X  == 1:
        return 0

    # 성공 후에도 게임을 진행했으면 실수로 판단
    if success_O == 1 and sum_O &amp;lt;= sum_X :
        return 0
    elif success_X == 1 and sum_O &amp;gt; sum_X :
        return 0

    return 1&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/프로그래머스</category>
      <author>_차누_</author>
      <guid isPermaLink="true">https://comhwang.tistory.com/80</guid>
      <comments>https://comhwang.tistory.com/80#entry80comment</comments>
      <pubDate>Thu, 3 Aug 2023 20:53:05 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 과제 진행하기</title>
      <link>https://comhwang.tistory.com/78</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/176962&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/176962&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1690814499850&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래머스&quot; data-og-description=&quot;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/176962&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bBtKwV/hyTvlPQGDf/69uZ1QTOh2O165wGKrdaH1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bLda93/hyTu9BToVm/FAtAL1So2HMLjqQvStCZ9k/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/176962&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/176962&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bBtKwV/hyTvlPQGDf/69uZ1QTOh2O165wGKrdaH1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bLda93/hyTu9BToVm/FAtAL1So2HMLjqQvStCZ9k/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;접근법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;00:00부터&amp;nbsp;시작하여&amp;nbsp;현재&amp;nbsp;시간에&amp;nbsp;해당하는&amp;nbsp;요소가&amp;nbsp;있을&amp;nbsp;경우&amp;nbsp;작업&amp;nbsp;리스트에&amp;nbsp;append로&amp;nbsp;맨&amp;nbsp;뒤에&amp;nbsp;추가하고,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장&amp;nbsp;뒤에&amp;nbsp;있는&amp;nbsp;작업의&amp;nbsp;소요시간을&amp;nbsp;분마다&amp;nbsp;-1씩&amp;nbsp;감소시킨다.&amp;nbsp;그리고&amp;nbsp;소요시간이&amp;nbsp;0이&amp;nbsp;된&amp;nbsp;작업이&amp;nbsp;있으면&amp;nbsp;pop&amp;nbsp;하여&amp;nbsp;answer에&amp;nbsp;추가해&amp;nbsp;준다. &lt;br /&gt;추가적으로&amp;nbsp;작업해야&amp;nbsp;하는&amp;nbsp;작업이&amp;nbsp;없을&amp;nbsp;경우&amp;nbsp;시간을&amp;nbsp;1분&amp;nbsp;증가시키고,&amp;nbsp;continue를&amp;nbsp;통해&amp;nbsp;빠져나간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;시도1&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;plans 배열이 정렬이 되어있지 않기 때문에 any를 통해 현재 시간에 해당하는 요소가 있는 확인하고, 있으면 해당 인덱스를 찾아 작업 리스트에 넣어주는 방식으로 했지만 5개의 테스트에서 시간 초과가 발생하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;&lt;b&gt;문제풀이&lt;/b&gt;&lt;/summary&gt;
&lt;pre id=&quot;code_1690814539982&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(plans):

    plans = list(map(lambda x: [x[0],x[1],int(x[2])] ,plans))
    len_answer = len(plans)
    timer = [0,0]
    queue_job = []
    answer = []

    while len(answer) != len_answer :

        # 만약 새로운 작업이 들어온다면
        if any(sublist[1] == f&quot;{timer[0]:02d}:{timer[1]:02d}&quot; for sublist in plans) :
            target_idx = [index for index, target in enumerate(plans) if target[1] == f&quot;{timer[0]:02d}:{timer[1]:02d}&quot;][0]
            queue_job.append(plans[target_idx])
        
        # 작업해야하는 일이 없을 경우
        if len(queue_job) == 0:
            if timer[1] == 59 :
                timer[0]+=1
                timer[1]=0
            else :
                timer[1]+=1
            continue

        # 1분만큼 소요시간을 줄인다
        queue_job[-1][2] -= 1
        
        # 해당 작업의 소요시간이 0이면 answer에 추가한다
        if queue_job[-1][2] == 0 :
            answer.append(queue_job[-1][0])
            queue_job.pop()

        if timer[1] == 59 :
            timer[0]+=1
            timer[1]=0
        else :
            timer[1]+=1


    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;시도2와 정답&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #424242; text-align: start;&quot;&gt;while 문으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;반복될 때마다&lt;span style=&quot;background-color: #ffffff; color: #424242; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;any와 index를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;반복하는 걸&lt;span style=&quot;background-color: #ffffff; color: #424242; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;해결하면 문제가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;해결될 것이라는&lt;span style=&quot;background-color: #ffffff; color: #424242; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;생각이 들었습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #424242; text-align: start;&quot;&gt;정렬이 되지&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;않았어&lt;span style=&quot;background-color: #ffffff; color: #424242; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;사용했기 때문에 처음부터 정렬을 하고 0인덱스와 비교하는 방식으로 해결했습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #424242; text-align: start;&quot;&gt;추가적으로 시간&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;업데이트하는&lt;span style=&quot;background-color: #ffffff; color: #424242; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;함수를 만들어서 사용했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;&lt;b&gt;문제풀이&lt;/b&gt;&lt;/summary&gt;
&lt;pre id=&quot;code_1690815837100&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def increaseTime(timer) :
    if timer[1] == 59 :
        timer[0]+=1
        timer[1]=0
    else :
        timer[1]+=1
    return timer

def solution(plans):

    len_answer = len(plans)
    plans = list(map(lambda x: [x[0],x[1],int(x[2])] ,plans))
    plans = sorted(plans, key=lambda x: x[1])
    timer = [0,0]
    queue_job = []
    answer = []

    while len(answer) != len_answer :

        # 만약 새로운 작업이 들어온다면
        if plans and plans[0][1] == f&quot;{timer[0]:02d}:{timer[1]:02d}&quot; :
            queue_job.append(plans.pop(0))

        # 작업해야하는 일이 없을 경우
        if len(queue_job) == 0:
            timer = increaseTime(timer) 
            continue

        # 1분만큼 소요시간을 줄인다
        queue_job[-1][2] -= 1
        
        # 해당 작업의 소요시간이 0이면 answer에 추가한다
        if queue_job[-1][2] == 0 :
            answer.append(queue_job[-1][0])
            queue_job.pop()

        timer = increaseTime(timer) 

    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/프로그래머스</category>
      <category>과제 진행하기</category>
      <category>알고리즘</category>
      <category>프로그래머스</category>
      <author>_차누_</author>
      <guid isPermaLink="true">https://comhwang.tistory.com/78</guid>
      <comments>https://comhwang.tistory.com/78#entry78comment</comments>
      <pubDate>Mon, 31 Jul 2023 23:44:58 +0900</pubDate>
    </item>
    <item>
      <title>Proxy</title>
      <link>https://comhwang.tistory.com/68</link>
      <description>&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Proxy&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;CORS 정책이 필요한 이유&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot;&gt;다른 도메인에서 API를 요청해서 사용할 수 있게 해 주려면&amp;nbsp;&lt;/span&gt;CORS 설정&lt;span style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot;&gt;이 필요합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot;&gt;만일 실제 서비스가 되는 상용 앱을 운영 중이라면, 구축한 클라이언트 뒤의 서버와 연결되어 있는 DB에는 라이브 데이터가 쌓일 것입니다. &lt;span style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot;&gt;이런 라이브 데이터는 민감성이 높은 데이터들이 위주이기 때문에 보안이 무엇보다 중요합니다. 그러나 여러분들의 서비스 및 프로젝트가 모든 출처의 접근을 허락한다면 이러한 보안성이 현저히 낮아지고, 해킹의 위험에 그대로 노출되게 됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot;&gt;따라서 모든 도메인을 허용해서는 안 되고, 특정 도메인을 허용하도록 구현해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Proxy&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot;&gt;React 라이브러리, 혹은 Webpack Dev Server에서 제공하는 proxy 기능을 사용하면 CORS 정책을 우회할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot;&gt;이는 별도의 응답 헤더를 받을 필요 없이 브라우저는 React 앱으로 데이터를 요청하고, 해당 요청을 백엔드로 전달하게 됩니다. 여기서 React 앱이 서버로부터 받은 응답 데이터를 다시 브라우저로 전달하는 방법을 쓰기 때문에 브라우저는 CORS 정책을 위반했는지 모르게 됩니다. 브라우저를 proxy 기능을 통해 속이는 것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1279&quot; data-origin-height=&quot;828&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOjwHX/btsiPPmsDAr/4amPBdnk2Rb6BXJhOUbOp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOjwHX/btsiPPmsDAr/4amPBdnk2Rb6BXJhOUbOp0/img.png&quot; data-alt=&quot;코드스테이츠 강의자료 중&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOjwHX/btsiPPmsDAr/4amPBdnk2Rb6BXJhOUbOp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOjwHX%2FbtsiPPmsDAr%2F4amPBdnk2Rb6BXJhOUbOp0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1279&quot; height=&quot;828&quot; data-origin-width=&quot;1279&quot; data-origin-height=&quot;828&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;코드스테이츠 강의자료 중&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;프록시 서버의 기능&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;캐시 수행
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;서버에서 받은 응답을 캐시에 저장합니다. 만약 클라이언트에서 같은 요청을 보낼 시 저장해뒀던 응답을 바로 전달합니다.&lt;/li&gt;
&lt;li&gt;불필요한 네트워크 요청을 줄일 수 있습니다. 속도가 조금 향상되는 효과가 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;보안 기능 수행
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;클라이언트의 IP 주소를 숨깁니다.&lt;/li&gt;
&lt;li&gt;서버로부터 오는 응답 등을 필터링합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>프론트엔드/Section4</category>
      <author>_차누_</author>
      <guid isPermaLink="true">https://comhwang.tistory.com/68</guid>
      <comments>https://comhwang.tistory.com/68#entry68comment</comments>
      <pubDate>Wed, 7 Jun 2023 10:02:59 +0900</pubDate>
    </item>
    <item>
      <title>[딥다이브] 39장 DOM(8.스타일, 9.DOM 표준)</title>
      <link>https://comhwang.tistory.com/66</link>
      <description>&lt;h2 id=&quot;39%EC%9E%A5%C2%A0DOM(6.DOM%C2%A0%EC%A1%B0%EC%9E%91%C2%A0~%C2%A07.%EC%96%B4%ED%8A%B8%EB%A6%AC%EB%B7%B0%ED%8A%B8)-1&quot; style=&quot;background-color: #ffffff; color: #353638; text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;39장 DOM(8.스타일,&amp;nbsp;9.DOM&amp;nbsp;표준)&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h2 id=&quot;6.%20DOM%20%EC%A1%B0%EC%9E%91-1&quot; style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;8. 스타일&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 인라인 스타일 조작&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTMLElement.prototype.style 프로퍼티는 setter와 getter 모두 존재하는 접근자 프로퍼티로서 요소 노드의 인라인 스타일을 취득하거나 추가 또는 변경한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685459572786&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;ko&quot;&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;div style=&quot;color: red&quot;&amp;gt;Hello World&amp;lt;/div&amp;gt;
    &amp;lt;script&amp;gt;
      $div = document.querySelector(&quot;div&quot;);
      
      console.log($div.style); // CSSStyleDeclaration { 0: 'color', ... }
      
      // 인라인 스타일 변경 및 추가
      $div.style.color = &quot;blue&quot;;
      $div.style.width = '100px';
    &amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CSS 프로퍼티는 케밥 케이스를 따른다. 이에 대응하는 CSSStyleDeclaration 객체의 프로퍼티는 카멜 케이스를 따른다. 예를 들어, CSS 프로퍼티 background-color에 대응하는 CSSStyleDeclaration 객체의 프로퍼티 backgroundColor이다.&lt;/p&gt;
&lt;pre id=&quot;code_1685459840108&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$div.style.backgroundColor = 'yellow';
$div.style['background-color'] = 'yellow';&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. 클래스 조작&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;className&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Element.prototype.className 프로퍼티는 setter와 getter 모두 존재하는 접근자 프로퍼티로서 HTML 요소의 class 어트리뷰트 값을 취득하거나 변경한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요소 노드의 className 프로퍼티를 참조하면 class 어트리뷰트 값을 문자열로 반환하고, 요소 노드의 className 프로퍼티에 문자열을 할당하면 class 어트리뷰트 값을 할당한 문자열로 변경한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685517260332&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div class='box red'&amp;gt;&amp;lt;/div&amp;gt;
...
const $box = document.querySelector('.box');
console.log($box.className); // 'box red'

$box.className = $box.className.replace('red','blue');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;classList&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Element.prototype.classList 프로퍼티는 class 어트리뷰트의 정보를 담은 DOMTokenList 객체를 반환한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685517410757&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div class='box red'&amp;gt;&amp;lt;/div&amp;gt;
...
const $box = document.querySelector('.box');
console.log($box.classList);
// DOMTokenList(2) [length:2, value: 'box red', 0: 'box', 1: 'red']


// DOMTokenList 객체 메서드
// add : class 추가
$box.classList.add('foo');
$box.classList.add('bar','baz');

// remove : class 제거
// 해당 class 어트리뷰트가 없으면 에러 없이 무시된다.
$box.remove('foo');

// item(index) : index에 해당하는 클래스 반환
$box.classList.item(0);

// contains(className) : 일치하는 클래스가 있는지 확인
$box.classList.contains('box'); // true

// replace(oldClassName, newClassName) : 클래스 변경
$box.classList.replace('red','blue');

// toggle(oldClassName[, force]) : 클래스가 없으면 추가하고, 있으면 제거
$box.classList.toggle('red');

// true : 강제로 추가, false: 강제로 제거
$box.classList.toggle('red',true);
$box.classList.toggle('red',false);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. 요소에 적용되어 있는 CSS 스타일 참조&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;style 프로퍼티는 인라인 스타일만 반환한다. 따라서 클래스를 적용한 스타일이나 상속을 통해 암죽적으로 적용된 스타일은 style 프로퍼티로 참조할 수 없다. HTML 요소에 적용되어 있는 모든 CSS 스타일을 참조해야 할 경우 getComputedStyle 메서드를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;window.&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;getComputedStyle&lt;span&gt;(element[, pseudo]) 메서드는 첫 번째 인수로 전달한 요소 노드에 적용되어 있는 평가된 스타일을 CSSStyleDeclaration 객체에 담아 반환한다. 평가된 스타일이란 요소 노드에 적용되어 있는 모든 스타일( 링크 스타일, 임베딩 스타일, 인라인 스타일, 자바스크립트에서 적용한 스타일, 상속된 스타일, 기본 스타일 등)이 조합되어 최종적으로 적용된 스타일을 말한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;getComputedStyle 메서드의 두 번째 인수로 :after, :before와 같은 의사 요소를 지정하는 문자열을 전달할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685518481842&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const computedStyle = window.getComputedStyle($box);

console.log(computedStyled.width); // 최종 적용된 너비&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 id=&quot;%EB%AC%B8%EC%A0%9C-1&quot; style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제1&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;1. DOMTokenList 객체의 remove 객체를 이용해 class 어트리뷰트를 제거할 때, 해당 어트리뷰트가 없으면 에러가 발생한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;2. &lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;Element.prototype.className 프로퍼티는 DOMTokenList 객체의 add 메서드를 이용해 해당 요소의 클래스를 추가할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;3. style 프로퍼티는 요소 노드에 적용되어 있는 모든 스타일 중 인라인 스타일만 반환합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제2&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;아래 코드에서 console 출력이 blue로 변경되는 방법을 2개 이상 작성해주세요.&lt;/p&gt;
&lt;pre id=&quot;code_1685519905959&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;ko&quot;&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;div class=&quot;red&quot;&amp;gt;Hello World&amp;lt;/div&amp;gt;
    &amp;lt;script&amp;gt;
      $div = document.querySelector(&quot;.red&quot;);
      
      console.log($div.className); // red
    &amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p id=&quot;%EB%AC%B8%EC%A0%9C-1&quot; style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;답&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제1(X, X, O)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. &lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;해당 어트리뷰트가 없어도 에러 없이 무시된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. classList에 대한 설명입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제2&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1685520161414&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;ko&quot;&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;div class=&quot;red&quot;&amp;gt;Hello World&amp;lt;/div&amp;gt;
    &amp;lt;script&amp;gt;
      $div = document.querySelector(&quot;.red&quot;);

      // $div.className = $div.className.replace(&quot;red&quot;, &quot;blue&quot;);

      // $div.classList.replace(&quot;red&quot;, &quot;blue&quot;);

      // [&quot;red&quot;, &quot;blue&quot;].forEach((ele) =&amp;gt; $div.classList.toggle(ele));

      console.log($div.className);
    &amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>딥다이브</category>
      <author>_차누_</author>
      <guid isPermaLink="true">https://comhwang.tistory.com/66</guid>
      <comments>https://comhwang.tistory.com/66#entry66comment</comments>
      <pubDate>Wed, 31 May 2023 00:10:28 +0900</pubDate>
    </item>
    <item>
      <title>TypeScript (Enum,Interface,Type,Class)</title>
      <link>https://comhwang.tistory.com/65</link>
      <description>&lt;h2 id=&quot;TypeScript(%ED%83%80%EC%9E%85%2C%C2%A0%ED%95%A8%EC%88%98%2C%C2%A0%EC%97%B0%EC%82%B0%EC%9E%90%3A%EC%9C%A0%EB%8B%88%EC%98%A8%2F%EC%9D%B8%ED%84%B0%EC%84%B9%EC%85%98)-1&quot; style=&quot;background-color: #ffffff; color: #353638; text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;TypeScript (Enum,Interface,Type,Class)&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;TypeScript 열거형(Enum)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript의 열거형은 특정 값의 집합을 정의할 때 사용됩니다. 문자형 열거형과 숫자형 열거형을 지원합니다. 열거형은 숫자형과 문자열형, 혹은 이 둘의 조합으로 정의될 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;열거형은 일반적으로 상수값을 대신하여 사용되므로, 타입스크립트에서는 열거형이 많이 사용됩니다. 열거형은 코드를 더욱 가독성 좋게 만들어주고, 오타와 같은 실수를 방지해 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;숫자형 열거형(Enum)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디폴트 값으로 숫자형을 사용하며, 다음과 같이 값을 지정하지 않으면 각 값은 자동으로 0부터 시작하여 1씩 증가합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685512873421&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;enum Color {
  Red = 1,
  Green = 2,
  Blue = 4,
}

let c: Color = Color.Green;
let greenValue: number = Color.Green;
let blueValue: number = Color.Blue;

console.log(c);          // 출력: 2
console.log(greenValue);  // 출력: 2
console.log(blueValue);   // 출력: 4&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;문자 열거형(Enum)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자형 열거형은 열거형의 값을 전부 다 특정 문자 또는 다른 열거형 값으로 초기화해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685512985552&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;enum Direction {
  Up = &quot;UP&quot;,
  Down = &quot;DOWN&quot;,
  Left = &quot;LEFT&quot;,
  Right = &quot;RIGHT&quot;,
}

let myDirection: Direction = Direction.Up;
console.log(myDirection); // 출력: &quot;UP&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;역 매핑(Reverse mappings)&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;역 매핑은 숫자형 열거형에만 존재하는 특징입니다. 열거형의 키로 값을 얻을 수 있고, 값으로 키를 얻을 수도 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685513154325&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;enum Enum {
    A
}
let a = Enum.A;
let nameOfA = Enum[a]; // &quot;A&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;TypeScript 인터페이스&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript에서 인터페이스는 일반적으로 타입 체크를 위해 사용이 됩니다. 인터페이스는 변수,함수, 클래스에 사용할 수 있으며, 인터페이스에 선언된 프로퍼티 또는 메서드의 구현을 강제하여 일관성을 유지하도록 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;변수와 인터페이스&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript 에서 변수를 선언할 때 인터페이스를 아래와 같이 사용할 수 있습니다. TypeScript에서 인터페이스는 객체의 구조를 정의하기 위해 주로 사용되는 예약어입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685513420084&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface User {
	name: string;
	age: number;
}


// 정상적으로 선언됩니다.
const user: User = {
	name: &quot;anna&quot;,
	age: 20
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서는 인터페이스에 정의된 프로퍼티의 순서는 지키지 않아도 되지만, 정의된 프로퍼티는 전부 작성해야 합니다. 하지만 ? 연산자를 사용하면 선택적 프로퍼티를 작성할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685513530827&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface User {
	name: string;
	age?: number;
}

// 정상적으로 선언됩니다.
const user: User = {
	name: &quot;anna&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;함수와 인터페이스&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스를 사용하여 객체의 프로퍼티 이름과 타입을 정의하고, 함수의 매개변수 타입과 반환 타입도 정의할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685513706974&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface User {
	name: string;
	age: number;
	job: string;
}

interface Greeting {
	(user: User, greeting: string): string;
}

const greet: Greeting = (user, greeting) =&amp;gt; {
	return `${greeting}, ${user.name}! Your job : ${user.job}.`;
}

const user: User = {
	name: &quot;anna&quot;,
	age: 30,
	job: &quot;developer&quot;
};

const message = greet(user, &quot;Hi&quot;);

console.log(message);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;클래스와 인터페이스&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스를 구현할 때 인터페이스에서 정의된 함수나 메서드의 매개변수 타입과 반환 값과 일치하도록 구현해야 하므로, 클래스 내부에 해당 메서드의 매개변수 타입을 다시 한번 더 명시해 주지 않으면 컴파일 에러가 발생하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685513841759&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Calculator {
	add(x: number, y: number): number;
	substract(x: number, y: number): number;
}

class SimpleCalculator implements Calculator {
	add(x: number, y:number) {
		return x + y;
	}

	substract(x: number, y: number) {
		return x - y;
	}
}

const caculator = new SimpleCalculator();

console.log(caculator.add(4, 9)); //13
console.log(caculator.substract(10, 5)); //5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;인터페이스와 상속&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스도 extends 키워드를 사용하여 기존에 존재하던 인터페이스를 상속해 확장이 가능합니다. 이렇게 하면 기존에 존재하던 인터페이스의 프로퍼티를 다른 인터페이스에 복사하는 것을 가능하게 해주며, 인터페이스의 재사용성을 높여줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685514256034&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 한 개만 상속 받는 경우
interface Person {
    name: string;
    age: number;
}

interface Developer extends Person {
    language: string;
}

const person: Developer = {
    language: &quot;TypeScript&quot;,
    age: 20,
    name: &quot;Anna&quot;,
}

// 여러 인터페이스를 상속받는 경우
interface FoodStuff {
    name: string;
}

interface FoodAmount {
    amount: number;
}

interface FoodFreshness extends FoodStuff, FoodAmount {
	   isFreshed: boolean;
}

const food = {} as FoodFreshness;

food.name = &quot;egg&quot;;
food.amount = 2;
food.isFreshed = true;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;TypeScript 타입 별칭(Type Aliases)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타입 별칭은 타입의 새로운 이름을 만드는 것입니다. 이는 새로운 이름으로 기존의 타입을 참조하는 것을 의미합니다. 타입 별칭을 이용하여 타입의 새로운 이름을 만들 때 키워드 type을 사용하여 작성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685514710745&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type MyString = string;

let str1: string = 'hello!';

// string 타입처럼 사용할 수 있습니다.
let str2: MyString = 'hello world!';


type Person = {
  id: number;
  name: string;
  email: string;
}

//Commentary 인터페이스에서 Person 타입을 참조하고 있습니다.
interface Commentary {
  id: number;
  content: string;
  user: Person;
}

//객체에서 Commentary 인터페이스를 참조하고 있습니다.
let comment1: Commentary = {
    id: 1,
    content: &quot;뭐예요?&quot;,
    user: {
        id: 1,
        name: &quot;김코딩&quot;,
        email: &quot;kimcoding@codestates.com&quot;,
    },
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;인터페이스 vs 타입 별칭&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타입 별칭은 말 그래도 타입에 새로운 이름을 부여하는 것에서 그치기 때문에 확장이 되지 않습니다. 그러나 인터페이스는 확장이 가능합니다. 인터페이스는 기존의 인터페이스 및 타입 별칭으로 만들어진 타입 둘 다 상속할 수 있기 때문에, 유연한 코드 작성을 위해서는 인터페이스로 만들어서 필요할 때마다 확장할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;TypeScript 타입 추론(Type interface)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript는 정적타입을 지원하는 프로그래밍 언어입니다. 정적타입 시스템을 사용하면 코드의 안정성을 높이고 디버깅을 용이하게 할 수 있습니다. 타입 추론은 변수나 함수의 타입을 선언하지 않아도 TypeScript가 자동으로 유추하는 기능입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;최적 공통 타입(Best common type)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript는 여러 표현식에서 타입 추론이 발생할 때, 해당 표현식의 타입을 사용하여 &lt;b&gt;최적 공통 타입&lt;/b&gt;을 계산합니다. 최적 공통 타입은 각 후보 타입을 고려하여, 모든 후보의 타입을 포함할 수 있는 타입을 선택합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685515490541&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// number와 null 을 포함하는 타입이 선택됨
let x = [0, 1, null];&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;문맥상의 타이핑(Contextual Typing)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문맥상의 타이핑(타입 결정)은 코드의 위치(문맥)을 기준으로 일어납니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685515455542&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 만약 a,b가 number타입이면 반환값도 number로 추론
function add(a, b) {
  return a + b;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;타입 추론의 장단점&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;코드의 가독성 향상&lt;/li&gt;
&lt;li&gt;개발 생산성 향상&lt;/li&gt;
&lt;li&gt;오류 발견 용이성&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;타입 추론이 잘못도리 경우 코드 오류 발생&lt;/li&gt;
&lt;li&gt;명시적인 타입 지정이 필요한 경우가 있음
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;타입 추론만으로 부족한 경우(복잡한 함수나 객체 등)에는 명시적으로 타입 지정이 필요할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;TypeScript 클래스&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript의 클래스는 JavaScript의 클래스와 비슷하지만 몇 가지 추가된 기능이 있습니다. 예를 들어 클래스의 속성과 메서드에 대한 타입을 명시할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685515696845&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Person {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  greet(): void {
    console.log(`안녕하세요, 제 이름은 ${this.name}이고, ${this.age}살 입니다.`);
  }
}

const person = new Person('Alice', 30);
person.greet(); // &quot;안녕하세요, 제 이름은 Alice이고, 30살 입니다.&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;클래스와 상속&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;extends 키워드를 사용하여 기존에 존재하던 클래스를 상속받아 확장하여 새로운 클래스를 만들 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685515774877&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Animal {
    move(distanceInMeters: number): void {
        console.log(`${distanceInMeters}m 이동했습니다.`);
    }
}

class Dog extends Animal {
    speak(): void {
        console.log(&quot;멍멍!&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;public, private 키워드&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 클래스 내에 선언된 멤버는 외부로 공개되는 것이 기본이지만, public 키워드를 사용해 공개된다고 명시적으로 표시해 줄 수 있습니다. 혹은 외부에 드러내지 않을 멤버가 있다면 private 키워드로 명시해 주면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685516037614&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Person {
  public name: string;
  private age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  greet(): void {
    console.log(`안녕하세요, 제 이름은 ${this.name}이고, ${this.age}살 입니다.`);
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;readonly 키워드&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;readonly 키워드를 사용하여 프로퍼티를 읽기 전용으로 만들 수 있습니다. 읽기 전용 프로퍼티들은 선언 또는 생성자에서 초기화해야 합니다. readonly 값은 변경할 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685516108222&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Mydog {
    readonly name: string;
    constructor(theName: string) {
        this.name = theName;
    }
}
let spooky = new Mydog(&quot;스푸키&quot;);
spooky.name = &quot;멋진 스푸키&quot;; // 에러&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;TypeScript 제네릭&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타입스크립트의 제네릭은 코드 재사용성을 높이고 타입 안정성을 보장하는 기능입니다. 제네릭을 사용하면 함수나 클래스를 작성할 때, 사용될 데이터의 타입을 미리 지정하지 않고, 이후에 함수나 클래스를 호출할 때 인자로 전달된 데이터의 타입에 따라 자동으로 타입을 추론하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685579250571&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function printLog&amp;lt;T&amp;gt;(text: T): T {
	return text;
}

const str = printLog&amp;lt;string&amp;gt;('hello')

// 타입 추론 기능을 활용한 작성 방법
const str2 = printLog('hello')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;T는 유저가 준 파라미터의 타입을 캡처하고, 이 정보를 나중에 사용할 수 있게 합니다. 여기에서는 T를 반환 타입으로 다시 사용합니다. 따라서 파라미터와 반환 타입이 같은 타입을 사용하고 있는 것을 확인할 수 있습니다. printLog 함수는 제네릭으로 타입을 불문하고 동작합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;인터페이스와 제네릭&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1685579793580&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Item&amp;lt;T&amp;gt; {
	name: T;
	stock: number;
	selected: boolean;
}

const obj: Item&amp;lt;string&amp;gt; = { 
	name: &quot;T-shirts&quot;,
	stock: 2, 
	selected: false
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;클래스와 제네릭&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제네릭을 사용하는 TypeScript에서 팩토리를 생성할 때 생성자 함수로 클래스 타입을 참조해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685579890717&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class GenericNumber&amp;lt;T&amp;gt; {
    zeroValue: T;
    add: (x: T, y: T) =&amp;gt; T;
}

let myGenericNumber = new GenericNumber&amp;lt;number&amp;gt;();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;제네릭 타입 변수&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;제네릭에 타입을 줘서 유연하게 함수의 타입을 정의해 줄 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685580075841&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function printLog&amp;lt;T&amp;gt;(text: T[]): T[] {
	console.log(text.length);
	return text;
}

// 조금 더 명시적으로 작성
function printLog&amp;lt;T&amp;gt;(text: Array&amp;lt;T&amp;gt;): Array&amp;lt;T&amp;gt; {
	console.log(text.length);
	return text;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;제네릭 제약 조건&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;제네릭에 타입을 줘서 유연하게 함수의 타입을 정의해 줄 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685583395043&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface TextLength {
	length: number;
}

// 타입을 정의하지 않고도 length 속성 허용하기
function printLog&amp;lt;T extends TextLength&amp;gt;(text: T): T {
	console.log(text.length);
	return text;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685583433059&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Item&amp;lt;T&amp;gt; {
	name: T;
	stock: number;
	selected: boolean;
}

// key 키워드를 통한 제약
function printLog&amp;lt;T extends keyof Item&amp;gt;(text: T): T {
	return text;
}

printLog('name'); //정상
pirntLog('key'); //에러&lt;/code&gt;&lt;/pre&gt;</description>
      <category>프론트엔드/Section4</category>
      <author>_차누_</author>
      <guid isPermaLink="true">https://comhwang.tistory.com/65</guid>
      <comments>https://comhwang.tistory.com/65#entry65comment</comments>
      <pubDate>Tue, 30 May 2023 17:02:41 +0900</pubDate>
    </item>
    <item>
      <title>TypeScript (타입, 함수, 연산자:유니온/인터섹션)</title>
      <link>https://comhwang.tistory.com/64</link>
      <description>&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;TypeScript(타입,&amp;nbsp;함수,&amp;nbsp;연산자:유니온/인터섹션)&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #262f40; text-align: start;&quot;&gt;TypeScript는 마이크로소프트에서 개발한 JavaScript의 상위 집합(Superset) 언어입니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TypeScript는 정적타입 검사 기능을 제공하며, 코드의 가독성과 유지&amp;nbsp; 보수성을 높여줍니다. 이를 통해 런타임 에러를 최소화하고, 코드 작성 시간을 단축하며, 협업&amp;nbsp; 시 코드의 가독성을 높일 수 있습니다.&lt;/li&gt;
&lt;li&gt;TypeScript는 ES6 문법을 포함한 최신 JavaScript 문법을 지원하며, 인터페이스, 제네릭, 데코레이터 등의 기능을 제공하여 객체 지향 프로그래밍을 보다 쉽게 할 수 있도록 도와줍니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;CRA(Create-React-App) + Typescript&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 터미널에서 프로젝트 생성&lt;/p&gt;
&lt;pre id=&quot;code_1685423255062&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ npx create-react-app [프로젝트 이름] --template typescript&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. tsconfig.json 내용 커스텀&lt;/p&gt;
&lt;pre id=&quot;code_1685423514537&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//tsconfig.json
//compilerOptions 내의 속성은 자유롭게 커스텀 할 수 있습니다.
{
  &quot;compilerOptions&quot;: {
    &quot;target&quot;: &quot;es6&quot;,
    &quot;module&quot;: &quot;commonjs&quot;,
    &quot;sourceMap&quot;: true,
    &quot;outDir&quot;: &quot;./dist&quot;
  },
  &quot;include&quot;: [
    &quot;src/**/*&quot;
  ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 필요한 프리셋과 라이브러리 설치&lt;/p&gt;
&lt;pre id=&quot;code_1685423558556&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ npm i -D @babel/core @babel/preset-env @babel/preset-typescript @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint prettier eslint-plugin-prettier&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. .eslintrc.js 파일 생성하여 커스텀&lt;/p&gt;
&lt;pre id=&quot;code_1685423590892&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;module.exports = {
  root: true,
  env: {
    browser: true,
    node: true,
    jest: true,
  },
  extends: [
    'plugin:@typescript-eslint/eslint-recommended',
    'plugin:@typescript-eslint/recommended',
  ],
  plugins: ['prettier', '@typescript-eslint'],
  rules: {
    'prettier/prettier': [
      'error',
      {
        singleQuote: true,
        tabWidth: 2,
        printWidth: 80,
        bracketSpacing: true,
        arrowParens: 'avoid',
      },
    ],
    '@typescript-eslint/no-explicit-any': 'off',
    '@typescript-eslint/explicit-function-return-type': 'off',
    'prefer-const': 'off',
  },
  parserOptions: {
    parser: '@typescript-eslint/parser',
  },
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;TypeScript 타입&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript는 JavaScript와 거의 동일한 데이터 타입을 지원합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. Boolean 타입&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 기본적인 데이터 타입으로, JavaScript에서도 마찬가지로 boolean 값이라고 불리는 참,거짓 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685424094861&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let isShow: boolean = true;
let isDone: boolean = false;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. Number 타입&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;JavaScript와 마찬가지로 정수와 실수의 구분 없이 Number 타입 하나로 표기합니다. TypeScript는 이 외에도 추가로 bigint를 지원합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685424151385&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let number1: number = 5;
let number2: number = 0.7;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. String 타입&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;큰 따옴표나 작은 따옴표를 사용하여 문자열 데이터를 표현합니다. 또한 백틱을 사용한 문자열인 템플릿 리터럴을 사용하면 여러 줄에 걸쳐 문자열을 작성할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685424217146&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let firstName: string = &quot;coding&quot;;
let lastName: string = 'kim';
let longString: string = `Kimcoding is a developer.
He is 20 years old.`&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. Array 타입&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;두 가지 방법으로 배열 타입을 선언해 사용할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685424253259&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//첫 번째 방법
let items: string[] = [&quot;apple&quot;, &quot;banana&quot;, &quot;grape&quot;];

//두 번째 방법
let numberList: Array&amp;lt;number&amp;gt; = [4, 7, 100];&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. 튜플 타입&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;튜플 타입을 사용하면 요소의 타입과 개수가 고정된 배열을 표현할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685424317561&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let user: [string, number, boolean] = [&quot;kimcoding&quot;, 20, true];&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;6. 객체 타입&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;TypeScript에서도 객체는 원시 타입이 아닌 타입을 나타냅니다. JavaScript의 원시 타입에는 ( number, string, boolean, undefined, null, symbol ) 이 있습니다. TypeScript에서는 object 타입은 모든 객체를 수용하는 타입으로, 객체의 프로퍼티 타입들이 any로 지정되기 때문에 어떠한 프로퍼티라도 추가할 수 있습니다. 하지만 타입 안정성을 보장하지 않기 때문에 편하지만, 추천하는 방법은 아닙니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;따라서 객체의 프로퍼티 타입들은 각기 명시해 주는 것이 훨씬 좋습니다. 객체는 이런 방식으로 key-value 에 구체적인 타입까지도 지정할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685424536769&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let obj: object = {};

let user: {name: string, age: number} = {
	name: &quot;kimcoding&quot;,
	age: 20
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;7. Any 타입&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;타입 검사를 하지 않고자 할 때 any 타입을 사용할 수 있습니다. any 타입을 사용하게 되면 변수에 값을 재할당하는 경우 타입을 명시한 변수와 달리 타입에 구애받지 않고 값을 재할당할 수 있게 됩니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;또한 any 타입은 타입의 일부만 알고, 전체를 알지 못할 때 유용합니다. 예를 들어 여러 타입이 섞인 배열을 받고자 할 때 유용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685424764178&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let maybe: any = 4;

let list: any[] = [1, true, &quot;free&quot;];&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;TypeScript 함수&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript에서 함수를 표현할 때는 매개변수의 타입과 반환 타입을 명시해야 합니다. 각 매개변수에 해당하는 타입을 작성한 뒤, 변환되는 타입을 괄호 뒤에 작성을 해줘야 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685425184283&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//named function
function add(x: number, y: number):number {
	return x + y;
}

//arrow function
let add = (x: number, y: number): number =&amp;gt; {
	return x + y;
}

//no return
let printAnswer = (): void =&amp;gt; {
	console.log(&quot;YES&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 TypeScript는 JavaScript와 달리 매개변수의 개수에 맞춰 전달인자를 전달해야 합니다. 만약 개발자가 전달인자를 전달하지 않거나, undefined 를 전달했을 때 할당될 매개변수의 값을 정해놓을 수도 있습니다. 이는 JavaScript에서의 default parameter와 같은 동작을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹은 선택적 매개변수를 원한다면 매개변수의 이름 끝에 ?를 붙임으로써 해결할 수도 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685425440981&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 매개변수가 1,2개 일때는 정상적으로 작동합니다.
let greeting = (firstName: string, lastName=&quot;kim&quot;): string =&amp;gt; {
	return `hello, ${firstName} ${lastName}`;
}

let greeting = (firstName: string, lastName?: string): string =&amp;gt; {
	return `hello, ${firstName} ${lastName}`;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;TypeScript의 연산자 활용 타입&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript는 연산자를 이용해 타입을 정할 수 있습니다. JavaScript에서도 보았던 ||(OR) 연산자나 &amp;amp;&amp;amp;(AND)와 같은 연산자를 이용하여 만들 수 있습니다. 또한 | 연산자를 이용한 타입을 유니온 타입이라고 하며, &amp;amp; 연산자를 이용한 타입은 인터섹션 타입이라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;유니온(Union) 타입&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;유니온 타입은 둘 이상의 타입을 합쳐서 만들어진 새로운 타입입니다. | 연산자를 이용하며, 자바스크립트의 || 연산자와 같이 `A이거나 B이다`라는 의미의 타입입니다. 유니온 타입은 다양한 타입의 값을 처리해야 하는 경우 유용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685426292778&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function printValue(value: number|string): void {
  ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;유니온 타입의 장점&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유니온 타입을 사용하면 타입을 추론할 수 있기 때문에, 타입에 관련된 API를 쉽게 자동완성으로 얻어낼 수 있습니다.&lt;/li&gt;
&lt;li&gt;코드를 이해하기 쉽게 만들어주며, 가독성을 높일 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;유니온 타입 사용 시 유의할 점&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유니온 타입인 값이 있으면, 유니온에 있는 모든 타입에 공통인 멤버들에만 접근할 수 있기 때문에 유의해야 합니다.&lt;/li&gt;
&lt;li&gt;공통 프로퍼티 외에 나머지 프로퍼티에도 접근하고 싶다면 타입 가드를 사용해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1685430001293&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Developer {
  name: string;
  skill: string;
}

interface Person {
  name: string;
  age: number;
}

// 공통 프로퍼티인 name에만 접근 가능합니다.
function askSomeone(someone: Developer | Person) {
	
    console.log(someone.name);
    
    // in 연산자는 객체의 속성 이름과 함께 사용하여
    // 해당 속성이 객체 내에 존재하는지 여부를 검사합니다.
    if ('skill' in someone) {
    	console.log(someone.skill);
    }

    if ('age' in someone) {
    	console.log(someone.age);
    }
}

//유니온 타입은 전달인자를 전달할 때 선택지가 생깁니다.
askSomeone({name: '김코딩', skill: '웹 개발'});
askSomeone({name: '김코딩', age: 20});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;인터섹션(Intersection) 타입&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터섹션은 둘 이상의 타입을 결합하여 새로운 타입을 만드는 방법입니다. &amp;amp; 연산자를 사용하여 표현합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685430236527&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// string, number, boolean 타입을 전부 받을 수 있습니다
let value: string &amp;amp; number &amp;amp; boolean;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터섹션으로 타입을 연결해 하나의 단일 타입으로 표현할 수 있기 때문에, 타입 가드가 필요하지 않습니다. 그러나 전달인자를 전달할 때 선택지가 생기는 유니온 타입과 반대로, 인터섹션 타입은 모든 프로퍼티를 전부 보내줘야만 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685430378007&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function askSomeone(someone: Developer &amp;amp; Person) {
	//타입 가드를 사용하지 않아도 모든 프로퍼티에 접근할 수 있습니다.
    console.log(someone.age);
    console.log(someone.name);
    console.log(someone.skill);
}

//그러나 인터섹션 타입으로 결합하게 된다면 전달인자를 전달할 때 선택지가 없습니다.
askSomeone({name: '김코딩', skill: '웹 개발', age:20});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프론트엔드/Section4</category>
      <category>typescript</category>
      <category>유니온과 인터섹션</category>
      <category>타입스크립트</category>
      <author>_차누_</author>
      <guid isPermaLink="true">https://comhwang.tistory.com/64</guid>
      <comments>https://comhwang.tistory.com/64#entry64comment</comments>
      <pubDate>Tue, 30 May 2023 00:36:16 +0900</pubDate>
    </item>
    <item>
      <title>[딥다이브] 39장 DOM(6.DOM 조작 ~ 7.어트리뷰트)</title>
      <link>https://comhwang.tistory.com/63</link>
      <description>&lt;h2 id=&quot;39%EC%9E%A5%20DOM(3.%EB%85%B8%EB%93%9C%20%ED%83%90%EC%83%89%20~%205.%EC%9A%94%EC%86%8C%20%EB%85%B8%EB%93%9C%EC%9D%98%20%ED%85%8D%EC%8A%A4%ED%8A%B8%20%EC%A1%B0%EC%9E%91)-1&quot; style=&quot;background-color: #ffffff; color: #353638; text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;39장&amp;nbsp;DOM(6.DOM&amp;nbsp;조작&amp;nbsp;~&amp;nbsp;7.어트리뷰트)&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h2 id=&quot;3.%20%EB%85%B8%EB%93%9C%20%ED%83%90%EC%83%89-1&quot; style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;6. DOM 조작&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DOM 조작은 새로운 노드를 생성하여 DOM에 추가하거나 기존 노드를 삭제 또는 교체하는 것을 말한다. DOM 조작에 의해 DOM에 새로운 노드가 추가되거나 삭제되면 리플로우와 리페인트가 발생하는 원인이 되므로 성능에 영향을 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. innerHTML&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Element.prototype.innerHTML 프로퍼티는 setter와 getter 모두 존재하는 접근자 프로퍼티로서 요소 노드의 HTML 마크업을 취득하거나 변경한다. 요소 노드의 innerHTML 프로퍼티를 참조하면 요소 노드의 콘텐츠 영역(시작 태그와 종료 태그 사이) 내에 포함된 모든 HTML 마크업을 문자열로 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 살펴본 textContent 프로퍼티는 HTML 마크업을 무시하고 텍스타만 반환하지만 innerHTML 프로퍼티는&amp;nbsp; HTML 마크업이 포함된 문자열을 그대로 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685342153217&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// getter : $foo 요소의 콘텐츠 영역 내의 HTML 마크업을 문자열로 취득
console.log(document.getElementById('foo').innerHTML);

// setter : HTML 마크업이 파싱되어 요소 노드의 자식 노드로 DOM에 반영된다
document.getElementById('foo').innerHTML = '수정될 &amp;lt;span&amp;gt;부분&amp;lt;/span&amp;gt;'
document.getElementById('foo').innerHTML = '' // 노드 삭제&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자로부터 입력받은 데이터를 그대로 innerHTML 프로퍼티에 할당하는 것은 크로스 사이트 스크립팅 공격에 취약하므로 위험하다. HTML 마크업 내에 자바스크립트 악성 코드가 포함되어 있다면 파싱 과정에 그대로 실행될 가능성이 있기 때문이다. 이처럼 구현이 간단하고 직관적이지만 크로스 사이트 스크립팅 공격에 취약하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685342492756&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const $foo = document.getElementById('foo')
// $foo.innerHTML =  $foo.innerHTM + '추가할 구문';  와 같이 작동
$foo.innerHTML += '추가할 구문'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 해당 코드처럼 innerHTML에 새로운 요소를 삽입하면 새롭게 추가할 요소만 생성하여 추가하는 것이 아닌, 기존의 자식 노드까지 모두 제가하고 다시 처음부터 새롭게 자식 노드를 생성하여 DOM에 반영하기 때문에 효율적이지 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. insertAdjacentHTML 메서드&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Element.prototype.insertAdjacentHTML(position, DomString) 메서드는 기존 요소를 제거하지 않으면서 위치를 지정해 새로운 요소를 삽입한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;insertAdjacentHTML 메서드는 두 번째 인수로 전달한 HTML 마크업 문자열을 파싱하고, 그 결과로 생성된 노드를 첫 번째 인수로 전달한 위치에 삽입하여 DOM에 반영한다.&lt;/p&gt;
&lt;pre id=&quot;code_1685345642572&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
&amp;lt;!-- beforebegin --&amp;gt;
&amp;lt;div  id='foo'&amp;gt;
&amp;lt;!-- afterbegin --&amp;gt;
foo
&amp;lt;!-- beforeend --&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;!-- afterend --&amp;gt;
...

$foo.insertAdjacentHTML('beforeend','&amp;lt;p&amp;gt;추가할 문자열&amp;lt;/p&amp;gt;');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;nsertAdjacentHTML&lt;span&gt; 메서드는 기존 요소에는 영향을 주지 않고 새롭게 삽입될 요소만을 파싱하여 자식 요소로 추가하므로 기존의 자식 노드르 모두 제거하고 다시&amp;nbsp; 처음부터 새롭게 자식 노드를 생성하여 자식 요소로 추가하는 innerHTML 프로퍼티보다 효율적이고 빠르다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. 노드 생성과 추가&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;요소 노드 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Document.prototype.createElement(tagName) 메서드는 요소 노드를 생성하여 반환한다. createElement 메서드의 매개변수 tagName 에는 태그 이름을 나타내는 문자열을 인수로 전달한다.&lt;/p&gt;
&lt;pre id=&quot;code_1685346087825&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const $li = document.createElement('li');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;텍스트 노드 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Document.prototype.createTextNode(text) 메서드는 텍스트 노드를 생성하여 반환한다. createTextNode 메서드의 매개변수 text 에는 텍스트 노드의 값으로 사용할 문자열을 인수로 전달한다.&lt;/p&gt;
&lt;pre id=&quot;code_1685346185446&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const textNode = document.createTextNode('text');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;텍스트 노드를 요소 노드의 자식 노드로 추가&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Document.prototype.appendChild(childNode) 메서드는 매개변수 childNode에게 인수로 전달한 노드를 appendChild 메서드를 호출한 노드의 마지막 자식 노드로 추가한다.&lt;/p&gt;
&lt;pre id=&quot;code_1685346249990&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$li.appendChild(textNode);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;요소 노드를 DOM에 추가&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node.prototype.appendChild&amp;nbsp; 메서드를 사용하여 텍스트 노드와 부자 관계로 연결한 요소 노드를 #foo 요소 노드의 마지막 자식 요소로 추가한다.&lt;/p&gt;
&lt;pre id=&quot;code_1685346405924&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$foo.appendChild($li)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. 복수의 노드 생성과 추가&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 개의 요소 노드를 생성하여 DOM에 추가할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685346718750&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const $fragment = document.createDocumentFragment();

['Apple','Banana','Orange'].forEach(text =&amp;gt; {
	const $li = document.createElement('li');
    const textNode = document.createTextNode(text);
    
    $li.appendChild(textNode);
    $fragment.appendChild($li);
})

$foo.appendChild($fragment);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제처럼 DocumentFragment 노드를 사용하면 하나씩 추가할 경우 발생하는 리플로우와 리페인트가 여러번 발생하는 것을 방지할 수 있고,불필요한 컨테이너 요소가 DOM에 추가되는 부작용을 방지할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. 노드 삽입&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;마지막 노드로 추가&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node.prototype.appendChild 메서드는 인수로 전달받은 노드를 자신을 호출한&amp;nbsp; 노드의 마지막 자식 노드로 DOM에 추가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;지정한 위치에 노드 삽입&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node.prototype.insertBefore(newNode, childNode) 메서든느 첫 번째 인수로 전달받은 노드를 두 번째 인수로 전달받은 노드 앞에 삽입한다.&lt;/p&gt;
&lt;pre id=&quot;code_1685347591694&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// $li 요소 노드를 $foo 요소 노드의 마지막 자식 요소 앞에 삽입
$foo.insertBefore($li, $foo.lastElementChild);
// $li 요소 노드를 $foo 요소 노드의 마지막 자식 노드로 추가
$foo.insertBefore($li, null);&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;6. 노드 이동&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DOM에 이미 존재하는 노드를 appendChild 또는 insertBefore 메서드를 사용하여 DOM에 다시 추가하면 현재 위치에서 노드를 제거하고 새로운 위치에 노드를 추가한다. 즉 노드가 이동한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685351521508&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;ko&quot;&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;ul id=&quot;fruits&quot;&amp;gt;
      &amp;lt;li&amp;gt;Apple&amp;lt;/li&amp;gt;
      &amp;lt;li&amp;gt;Banana&amp;lt;/li&amp;gt;
      &amp;lt;li&amp;gt;Orange&amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
    &amp;lt;script&amp;gt;
      const $fruits = document.getElementById(&quot;fruits&quot;);

      // 이미 존재하는 요소 노드 취득
      const [$apple, $banana, ] = $fruits.children;

      // 이미 존재하는 요소 노드를 $fruits 요소 노드의 마지막 노드로 이동
      $fruits.appendChild($apple); // Banana - Orange - Apple

      // 이미 존재하는 요소 노드를 $fruits 요소 노드의 마지막 자식 노드 앞으로 이동
      $fruits.insertBefore($banana, $fruits.lastElementChild); // Orange - Banana - Apple
    &amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;7. 노드 복사&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node.prototype.cloneNode([deep: true | false]) 메서드는 노드의 사본을 생성하여 반환한다. 매개변수 deep에 true를 인수로 전달하면 노드를 깊은 복사하여 모든 자손 노드가 포함된 사본을 생성하고, false를 인수로 전달하거나 생략하면 노드를 얕은 복사하여 노드 자신만의 사본을 생성한다. 얕은 복사로 생성된 요소 노드는 자손 노드를 복사하지 않으므로 텍스트 노드도 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685360496281&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;ko&quot;&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;ul id=&quot;fruits&quot;&amp;gt;
      &amp;lt;li&amp;gt;Apple&amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
    &amp;lt;script&amp;gt;
      const $fruits = document.getElementById(&quot;fruits&quot;);
      const $apple = $fruits.firstElementChild;

      // 얕은 복사 : 텍스트 노드가 없는 사본이 생성된다.
      const $shallowClone = $apple.cloneNode();
      $shallowClone.textContent = &quot;Banana&quot;;
      $fruits.appendChild($shallowClone);

      // 깊은 복사 : 모든 자손 노드가 포함된 사본을 생성
      const $deepClone = $fruits.cloneNode(true);
      $fruits.appendChild($deepClone);
    &amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;8. 노드 교체&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node.ptototype.replaceChild(newChild, oldChild) 메서드는 자신을 호출한 노드의 자식 노드를 다른 노드로 교체한다.첫 번째 매개변수 newChilde에는 교체할 새로운 노드를 인수로 전달하고, 두 번째 매개변수 oldChild에는 이미 존재하는 굧체될 노드를 인수로 전달한다. oldChild 매개변수에 인수로 전달한 노드는 replaceChild 메서드를 호출한 노드의 자식 노드이어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685360696784&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 기존 노드와 교체할 요소 노드를 생성
const $newChild = document.createElement('li');
$newChild.textContent = 'Banana';

// $fruits 요소 노드의 첫 번째 자식  요소 노드를 $newChild 요소 노드로 교체
$fruits.replaceChild($newChild, $fruits.firstElementChild);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;9. 노드 삭제&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node.prototype.removeChild(child) 메서드는 child 매개변수에 인수로 전달한 노드를 DOM에서 삭제한다. 인수로 전달한 노드는 removeChild 메서드를 호출한 노드의 자식 노드이어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685360792520&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// $fruits 요소 노드의 마지막 요소를 DOM에서 삭제
$fruits.removeChild($fruits.lastElementChild);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;3.%20%EB%85%B8%EB%93%9C%20%ED%83%90%EC%83%89-1&quot; style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;7. 어트리뷰트&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 어트리뷰트 노드와 attributes 프로퍼티&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML 문서의 구성 요소인 HTML 요소는 여러 개의 어트리뷰트(속성)을 가질 수 있습니다. HTML 요소의 동작을 제어하기 위한 추가적인 정보를 제공하는 HTML 어트리뷰트는 HTML 요소의 시작 태그에 &lt;b&gt;어트리뷰트 이름 = '어트리뷰트 값'&amp;nbsp;&lt;/b&gt;형식으로 정의합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글로벌 어트리뷰트(id, class, style 등)와 이벤트 핸들러 어트리뷰터(onclick, onchange 등)는 모든 HTML 요소에서 공통적으로 사용할 수 있지만 특정 HTML 요소에만 한정적으로 사용 가능한 어트리뷰트도 있다. input 요소에만 사용할 수 있는 type, value, checked 어트리뷰트 등이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML 문서가 파싱될 때 HTML 요소의 어트리뷰트는 어트리뷰트 노드로 변환되어 요소 노드와 연결된다. 이때 HTML 어트리뷰트당 하나의 어트리뷰트 노드가 생성된다. 즉, 위 input 요소는 3개의 어트리뷰트가 있으므로 3개의 어트리뷰트 노드가 생성된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 요소 노드의 모든 어트리뷰트 노드는 요소 노드의 Element.prototype.attributes 프로퍼티로 취득할 수 있다. attribute 프로퍼티는 getter만 존재하는 읽기 전용 접근자 프로퍼티이며, 요소 노드의 모든 어트리뷰트 노드의 참조가 담긴 NameNodeMap 객체를 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685361756981&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// &amp;lt;input id='user' type='text' value='22'&amp;gt;

const {attributes} = document.getElementById('user');

// NamedNodeMap {0: id, 1: type, 2: value, id: id, type: type, value: value, length: 3}
console.log(attributes);

console.log(attributes.id.value); // user&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. HTML 어트리뷰트 조작&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요소&amp;nbsp; 노드의 attributes 프로퍼티는 getter만 존재하는 읽기 전용 접근자 프로퍼티이므로 HTML 어트리뷰트 값을 취득할 수 있지만 변경할 수는 없다. 또한 attributes.id.value 와 같이 attributes 프로퍼티를 통해야만 HTML 어트리뷰트 값을 취득할 수 있기 때문에 불편하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Element.prototype.getAttribute/setAttribute 메서드를 사용하면 attributes 프로퍼티를 통하지 않고 요소 노드에서 메서드를 통해 직접 HTML 어트리뷰트 값을 취득하거나 변경할 수 있어서 편리하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 HTML 어트리뷰트가 존재하는지 확인하려면 Element.prototype.hasAttribute 메서드를 사용하고, 삭제하려면 Element.prototype.removeAttribute 메서드를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685362121384&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const $foo = document.getElementById('foo');

// value 어트리뷰트 값을 취득
const $fooValue = $foo.getAttribute('value');

// value 어트리뷰트 값을 변경
$foo.setAttribute('value','foo');

// value 어트리뷰트 존재 확인 : true/false 반환
if($foo.hasAttribute('value')) {
	// value 어트리뷰트 삭제
	$foo.removeAttribute('foo');
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. HTML 어트리뷰트 vs DOM 프로퍼티&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요소 노드 객체에는 HTML 어트리뷰트에 대응하는 프로퍼티가 존재한다. 이 DOM 프로퍼티들은 HTML 어트리뷰트 값을 초기값으로 가지고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML 어트리뷰트는 DOM에서 중복 관리하고 있지 않다. HTML 어트리뷰트의 역할을 HTML 요소의 초기 상태를 지정하는 것이다. 즉, HTML 어트리뷰트 값은 HTML 요소의 초기 상태를 의미하여 이는 변하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685362383840&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;input id='user' type='text' value='22'&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 input이 있을 때, input 요소의 요소 노드가 생성되어 첫 렌더링이 끝난 시점까지 어트리뷰트 노드의 어트리뷰트 값과 요소 노드ㅡ이 value 프로퍼티에 할당된 값은 HTML 어트리뷰트 값과 동일하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 첫 렌더링 이후 사용자가 input 요소에 무언가를 입력하기 시작하면 상황이 달라진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요소 노드는 상태(state)를 가지고 있다. 요소 노드는 사용자의 입력에 의해 변화하는, 살아있는 것이다. 사용자가 input 요소의 입력 필드에 'foo'라는 값을 입력한 경우, input 요소 노드는 사용자의 입력에 의해 변경된 최신 상태를 관리해야 하는 것은 물론 HTML 어트리뷰트로 지정한 초기 상태도 관리해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 요소 노드는 2개의 상태, 즉 초기 상태와 최신 상태를 관리해야 한다. 요소 노드의 초기 상태는 어트리뷰트 노드가 관리하며, 요소 노드의 최신 상태는 DOM 프로퍼티가 관리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;` 어트리뷰트 노드&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;HTML 어트리뷰트로 지정한 HTML 요소의 초기 상태는 어트리뷰트 노드에서 관리한다.&amp;nbsp;&lt;/b&gt;어트리뷰트 노드에서 관리하는 어트리뷰트 값은 사용자의 입력에 의해 상태가 변경되어도 변하지 않고 HTML 어트리뷰트로 지정한 HTML 요소의 초기 상태를 그대로 유지한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어트리뷰트 노드가 관리하는 초기 상태 값을 취득하거나 변경하려면 getAttribute/setAttribute 메서드를 사용한다. getAttribute 메서드로 취득한 값은 어트리뷰트 노드에서 관리하는 HTML 요소에 지정한 어트리뷰트 값, 즉 초기 상태 값이다. HTML 요소에 지정한 어트리뷰트 값은 사용자의 입력에 의해 변하지 않으므로 결과는 언제나 동일하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;` DOM 프로퍼티&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 입력한 최신 상태는 HTML 어트리뷰트에 대응하는 요소 노드의 DOM 프로퍼티가 관리한다. DOM 프로퍼티는 사용자의 입력에 의한 상태 변화에 반응하여 언제나 최신 상태를 유지한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DOM 프로퍼티로 취득한 값은 HTML 요소의 최신 상태 값을 의미한다. 이 최신 상태 값은 사용자의 입력에 의해 언제든지 동적으로 변경되어 최신 상태를 유지한다. 이에 반해, getAttribute 메서드로 취득한 HTML 어트리뷰트 값, 즉 초기 상태 값은 변하지 않고 유지된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;` HTML 어트리뷰트와 DOM 프로퍼티의 대응 관계&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;id 어트리뷰트와 id 프로퍼티는 1:1 대응하며, 동일한 값으로 연동한다.&lt;/li&gt;
&lt;li&gt;input 요소의 value 어트리뷰트는 value 프로퍼티와 1:! 대응한다. 하지만 value 어트리뷰트는 초기 상태를, value 프로퍼티는 최신 상태를 갖는다.&lt;/li&gt;
&lt;li&gt;class 어트리뷰트는 className, classList 프로퍼티와 대응한다.&lt;/li&gt;
&lt;li&gt;for 어트리뷰트는 htmlFor 프로퍼티와 1:1 대응한다.&lt;/li&gt;
&lt;li&gt;td 요소의 colspan 어트리뷰트는 대응하는 프로퍼티가 존재하지 않는다.&lt;/li&gt;
&lt;li&gt;textContent 프로퍼티는 대응하는 어트리뷰트가 존재하지 않는다.&lt;/li&gt;
&lt;li&gt;어트리뷰트 이름은 대소문자를 구별하지 않지만 대응하는 프로퍼티 키는 카멜 케이스를 따른다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;` DOM 프로퍼티 값의 타입&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;getAttribute 메서드로 취득한 어트리뷰트 값은 언제나 문자열이다. 하지만 DOM 프로퍼티로 취득한 최신 상태 값은 문자열이 아닐 수도 있다. 예를 들어, checkbox 요소의 checked 어트리뷰트 값은 문자열이지만 checked 프로퍼티 값은 불리언 타입이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. data 어트리뷰트와 dataset 프로퍼티&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;data 어트리뷰트와 dataset 프로퍼티를 사용하면 HTML 요소에 정의한 사용자 정의 어트리뷰트와 자바스크립트 간에 데이터를 교환할 수 있다. data 어트리뷰트는 data-user-id, data-role과 같이 data- 접두사 다음에 임의의 이름을 붙여 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;data 어트리뷰트의 값은 HTMLElement.dataset 프로퍼티로 취득할 수 있다. dataset 프로퍼티는 HTML 요소의 모든 data 어트리뷰트의 정보를 제공하는 DOMStringMap 객체를 반환한다. DOMStringMap 객체를 반환한다. DOMStringMap 객체는 data 어트리뷰트의 data- 접두사 다음에 붙인 임의의 이름을 카멜 케이스로 변환한 프로퍼티로 가지고 있다. 이 프로퍼티로 data 어트리뷰트의 앖을 취득하거나 변경할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 id=&quot;%EB%AC%B8%EC%A0%9C-1&quot; style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;문제&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제1&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;1. insertAdjacentHTML&lt;span&gt; 메서드는 innerHTML메서드보다 효율적이고 빠르며, 크로스 사이트 스크립핑 공격에도 취약하지 않다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. cloneNode 메서드로 요소를 얕은 복사하면, 텍스트 노드를 포함한 사본이 생성되지만 자식 노드들은 복사되지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. HTML 문서가 파싱될 때 HTML 요소의 어트리뷰트는 어트리뷰트 노드로 변환되어 요소 노드와 연결되는데, 이때 어트리뷰트당 하나의 어트리뷰트 노드가 생성된다.(4개의 어트리뷰트가 있으면 4개의 어트리뷰트 노드가 생성된다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제2&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드의 결과가 화면에 어떻게 출력되는지 작성해주세요. (글머리/문단 부호는 생략하셔도 됩니다)&lt;/p&gt;
&lt;pre id=&quot;code_1685372295916&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;ko&quot;&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;ul id=&quot;numbers&quot;&amp;gt;
      &amp;lt;li&amp;gt;one&amp;lt;/li&amp;gt;
      &amp;lt;li&amp;gt;two&amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
    &amp;lt;script&amp;gt;
      const $numbers = document.getElementById(&quot;numbers&quot;);
      const $one = $numbers.firstElementChild;

      const $copy = $numbers.cloneNode();
      $numbers.appendChild($copy);

      $one.insertAdjacentHTML(&quot;afterbegin&quot;, &quot;hi &quot;);
    &amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제3&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;li 요소 중 id 가 존재하는 li의 id를 삭제해주세요.(removeAttribute)&lt;/p&gt;
&lt;pre id=&quot;code_1685373633681&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;ko&quot;&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;ul id=&quot;numbers&quot;&amp;gt;
      &amp;lt;li id=&quot;one&quot;&amp;gt;one&amp;lt;/li&amp;gt;
      &amp;lt;li id=&quot;two&quot;&amp;gt;two&amp;lt;/li&amp;gt;
      &amp;lt;li&amp;gt;three&amp;lt;/li&amp;gt;
      &amp;lt;li id=&quot;four&quot;&amp;gt;four&amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
    &amp;lt;script&amp;gt;
      $numbers = document.getElementById(&quot;numbers&quot;);
    &amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p id=&quot;%EB%AC%B8%EC%A0%9C-1&quot; style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;답&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제1(X, X, O)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. innerHTML 프로퍼티와 마찬가지로 insertAdjacentHTML&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; 메서드는 HTML 마크업 문자열을 파싱하므로 크로스 사이트 스크립핑 공격에 취약하다&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 얕은 복사하면 텍스트 노드가 없는 사본이 생성됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제2&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt;&amp;bull; hi one&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt;&amp;bull; two&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1685372842665&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;ko&quot;&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;ul id=&quot;numbers&quot;&amp;gt;
      &amp;lt;li&amp;gt;one&amp;lt;/li&amp;gt;
      &amp;lt;li&amp;gt;two&amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
    &amp;lt;script&amp;gt;
      const $numbers = document.getElementById(&quot;numbers&quot;);
      const $one = $numbers.firstElementChild;

      // 얕은 복사로 텍스트 노드가 없는 사본이 생성됩니다.
      const $copy = $numbers.cloneNode();
      $numbers.appendChild($copy);

      // afterbegin은 두 번째 인수로 전달 된 hi를 시작 태그 바로 뒤에 위치시킵니다.
      $one.insertAdjacentHTML(&quot;afterbegin&quot;, &quot;hi &quot;);
    &amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제3&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1685373591514&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$numbers = document.getElementById(&quot;numbers&quot;);

// 방법1
const numbers = [...$numbers.children];
for (ele of numbers) {
	ele.removeAttribute(&quot;id&quot;);
}

// 방법2
for (ele of $numbers.children) {
	ele.removeAttribute(&quot;id&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>딥다이브</category>
      <author>_차누_</author>
      <guid isPermaLink="true">https://comhwang.tistory.com/63</guid>
      <comments>https://comhwang.tistory.com/63#entry63comment</comments>
      <pubDate>Mon, 29 May 2023 16:53:51 +0900</pubDate>
    </item>
    <item>
      <title>[딥다이브] 39장 DOM(3.노드 탐색 ~ 5.요소 노드의 텍스트 조작)</title>
      <link>https://comhwang.tistory.com/62</link>
      <description>&lt;h2 id=&quot;39%EC%9E%A5%C2%A0DOM(1.%EB%85%B8%EB%93%9C~2.%EC%9A%94%EC%86%8C%C2%A0%EB%85%B8%EB%93%9C%C2%A0%EC%B7%A8%EB%93%9D)-1&quot; style=&quot;background-color: #ffffff; color: #353638; text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;39장 DOM(3.노드 탐색 ~ 5.요소 노드의 텍스트 조작)&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;3. 노드 탐색&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;요소 노드를 취득한 다음, 취득한 요소 노드를 기점으로 DOM 트리의 노드를 옮겨 다니며 부모, 형제, 자식 노드 등을 탐색해야 할 때가 있다. DOM 트리 상의 노드를 탐색할 수 있도록 Node, Element 인터페이스는 트리 탐색 프로퍼티를 제공한다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;parentNode, previousSibling, firstChild, childNodes 프로퍼티는 Node.prototype이 제공하고, 프로퍼티 키에 Element가 포함된 previousElementSibling, nextElementSibling과 children 프로퍼티는 Element.prototype이 제공한다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;노드 탐색 프로퍼티는 모두 접근자 프로퍼티다. 단, 노드 탐색 프로퍼티는 setter 없이 getter만 존재하며 참조만 가능한 읽기 전용 접근자 프로퍼티다. 읽기 전용 접근자 프로퍼티에 값을 할당하면 아무런 에러 없이 무시된다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3-1. 공백 텍스트 노드&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;HTML 요소 사이의 스페이스, 탭, 줄바꿈(개행) 등의 공백 문자는 텍스트 노드를 생성한다. 이를 공백 텍스트 노드라고 한다.&amp;nbsp; 노드를 탐색할 때는 공백 문자가 생성한 공백 텍스트 노드에 주의해야 한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3-2. 공백 텍스트 노드&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;자식 노드를 탐색하기 위해서는 다음과 같은 노드 탐색 프로퍼티를 사용한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 32.907%; text-align: center;&quot;&gt;프로퍼티&lt;/td&gt;
&lt;td style=&quot;width: 67.093%; text-align: center;&quot;&gt;설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 32.907%;&quot;&gt;Node.prototype.childNodes&lt;/td&gt;
&lt;td style=&quot;width: 67.093%;&quot;&gt;자식 노드를 모두 탐색하여 DOM 컬렉션 객체인 NodeList에 담아 반환한다. childNodes 프로퍼티가 반환한 NodeList에는 요소 노드뿐만 아니라 텍스트 노드도 포함되어 있을 수 있다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 32.907%;&quot;&gt;Element.prototype.children&lt;/td&gt;
&lt;td style=&quot;width: 67.093%;&quot;&gt;자식 노드 중에서 요소 노드만 모두 탐색하여 DOM 컬렉션 객체인 HTMLCollection 에 담아 반환한다. children 프로퍼티가 반환한 HTMLCollection에는 텍스트 노드가 포함되지 않는다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 32.907%;&quot;&gt;Node.prototype.firstChild&lt;/td&gt;
&lt;td style=&quot;width: 67.093%;&quot;&gt;첫 번째 자식 노드를 반환한다. firstChild 프로퍼티가 반환한 노드는 텍스트 노드이거나 요소 노드이다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 32.907%;&quot;&gt;Node.prototype.lastChild&lt;/td&gt;
&lt;td style=&quot;width: 67.093%;&quot;&gt;마지막 자식 노드를 반환한다. lastChild 프로퍼티가 반환한 노드는 텍스트 노드이거나 요소 노드이다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 32.907%;&quot;&gt;Element.prototype.firstElementChild&lt;/td&gt;
&lt;td style=&quot;width: 67.093%;&quot;&gt;첫 번째 자식 요소 노드를 반환한다. firstElementChild 프로퍼티는 요소 노드만 반환한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 32.907%;&quot;&gt;Element.prototype.lastElementChild&lt;/td&gt;
&lt;td style=&quot;width: 67.093%;&quot;&gt;마지막 자식 요소 노드를 반환한다.lastElementChild 프로퍼티는 요소 노드만 반환한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3-3. 자식 노드 존재 확인&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;자식 노드가 존재하는지 확인하려면 Node.prototype.hasChildNodes 메서드를 사용한다. hasChildNodes 메서드는 자식 노드가 존재하면 true, 자식 노드가 존재하지 않으면 false를 반환한다. 단, hasChildeNodes 메서드는 childNodes 프로퍼티와 마찬가지로 텍스트 노드를 포함하여 자식 노드의 존재를 확인한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;자식 노드 중에 텍스트 노드가 아닌 요소 노드가 존재하는지 확인하려면 hasChildNodes 메서드 대신 children.length 또는 Element 인터페이스의 childElementCount 프로퍼티를 사용한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3-4. 자식 노드 존재 확인&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요소 노드의 텍스트 노드는 요소 노드의 자식 노드다. 따라서 요소 노드의 텍스트 노드는 firstChild 프로퍼티로 접근할 수 있다. firstChild 프로퍼티는 첫 번째 자식 노드를 반환한다. firstChild 프로퍼티가 반환한 노드는 텍스트 노드이거나 요소 노드다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3-5. 부모 노드 탐색&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부모 노드를 탐색하려면 Node.prototype.parentNode 프로퍼티를 사용한다. 텍스트 노드는 DOM 트리의 최종단 노드인 리프 노드이므로 부모 노드가 텍스트 노드인 경우는 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3-6. 형제 노드 탐색&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;부모 노드가 같은 형제 노드를 탐색하려면 다음과 같은 노드 탐색 프로퍼티를 사용한다. 단, 어트리뷰트 노드는 요소 노드와 연결되어 있지만 부모 노드가 같은 형제 노드가 아니기 때문에 반환되지 않는다. 즉, 아래 프로퍼티는 텍스트 노드 또는 요소 노드만 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 38.4883%; text-align: center;&quot;&gt;프로퍼티&lt;/td&gt;
&lt;td style=&quot;width: 61.5117%; text-align: center;&quot;&gt;설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 38.4883%;&quot;&gt;Node.prototype.previousSibling&lt;/td&gt;
&lt;td style=&quot;width: 61.5117%;&quot;&gt;부모 노드가 같은 형제 노드 중에서 자신의 이전 형제 노드를 탐색하여 반환한다. previousSibling 프로퍼티가 반환하는 형제 노드는 요소 노드뿐만 아니라 텍스트 노드일 수도 있다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 38.4883%;&quot;&gt;Node.prototype.nextSibling&lt;/td&gt;
&lt;td style=&quot;width: 61.5117%;&quot;&gt;부모 노드가 같은 형제 노드 중에서 자신의 다음 형제 노드를 탐색하여 반환한다. nextSibling 프로퍼티가 반환하는 형제 노드는 요소 노드뿐만 아니라 텍스트 노드일 수도 있다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 38.4883%;&quot;&gt;Element.prototype.previousElementSibling&lt;/td&gt;
&lt;td style=&quot;width: 61.5117%;&quot;&gt;부모 노드가 같은 형제 요소 노드 중에서 자신의 이전 형제 요소 노드를 탐색하여 반환한다. previousElementSibling 프로퍼티는 요소 노드만 반환한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 38.4883%;&quot;&gt;&lt;span style=&quot;background-color: #efefef; color: #333333; text-align: start;&quot;&gt;Element.prototype.nextElementSibling&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 61.5117%;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;부모 노드가 같은 형제 요소 노드&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;중에서 자신의 다음 형제 요소 노드를 탐색하여 반환한다. nextElementSibling 프로퍼티는 요소 노드만 반환한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;4. 노드 정보 취득&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;노드 객체에 대한 정보를 취득하려면 다음과 같은 노드 정보 프로퍼티를 사용한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 194px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 26.8605%; text-align: center; height: 20px;&quot;&gt;프로퍼티&lt;/td&gt;
&lt;td style=&quot;width: 73.1395%; text-align: center; height: 20px;&quot;&gt;설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 117px;&quot;&gt;
&lt;td style=&quot;width: 26.8605%; height: 117px;&quot;&gt;Node.prototype.nodeType&lt;/td&gt;
&lt;td style=&quot;width: 73.1395%; height: 117px;&quot;&gt;노드 객체의 종류, 즉 노드 타입을 나타내는 상수를 반환한다. 노드 타입 상수는 Node에 정의되어 있다.&lt;br /&gt;&lt;br /&gt;- Node.Element_NODE : 요소 노드 타입을 나타내는 상수 1을 반환&lt;br /&gt;- Node.Text_NODE : 텍스트 노드 타입을 나타내는 상수 3을 반환&lt;br /&gt;- Node.DOCUMNENT_NODE : 문서 노드 타입을 나타내는 상수 9를 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 57px;&quot;&gt;
&lt;td style=&quot;width: 26.8605%; height: 57px;&quot;&gt;Node.prototype.nodeName&lt;/td&gt;
&lt;td style=&quot;width: 73.1395%; height: 57px;&quot;&gt;노드의 이름을 문자열로 반환한다.&lt;br /&gt;&lt;br /&gt;- 요소 노드 : 대문자 문자열로 태그 이름(UL, LI 등)을 반환&lt;br /&gt;- 텍스트 노드 : 문자열 #text 를 반환&lt;br /&gt;- 문서 노드 : 문자열 #document 를 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;5. 요소 노드의 텍스트 조작&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5-1 nodeValue&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;Node.prototype.nodeValue 는 지금까지 살펴본 읽기 전용 접근자 프로퍼티와 달리 setter / getter 모두 존재하는 접근자 프로퍼티다. 따라서 nodeValue는 참조와 할당 모두 가능하다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;nodeValue 프로퍼티를 참조하면 노드 객체의 값(텍스트 노드의 텍스트)를 반환한다. 따라서 텍스트 노드가 아닌 노드는 null을 반환한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;텍스트 노드의 nodeValue 프로퍼티에 값을 할당하면 텍스트 노드의 값, 즉 텍스트를 변경할 수 있다. 따라서 요소 노드의 텍스트를 변경하려면 다음과 같은 순서의 처리가 필요하다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;텍스트를 변경할 요소 노드를 취득한 다음, 취득한 요소 노드의 텍스트 노드를 탐색한다. 텍스트 노드는 요소 노드의 자식 노드이므로 firstChild 프로퍼티를 사용하여 탐색한다.&lt;/li&gt;
&lt;li&gt;탐색한 텍스트 노드의 nodeValue 프로퍼티를 사용하여 텍스트 노드의 값을 변경한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5-2 textContent&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;Node.prototype.textContent 프로퍼티는 setter와 getter 모두 존재하는 접근자 프로퍼티로서 요소 노드의 텍스트와 모든 자손 노드의 텍스트를 모두 취득하거나 변경한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;요소 노드의 textContent 프로퍼티를 참조하면 요소 노드의 콘텐츠 영역(시작 태그와 종료 태그 사이) 내의 텍스트, 즉 요소 노드의 childNodes 프로퍼티가 반환한 모든 노드들의 텍스트 노드의 값(텍스트) 를 모두 반환한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;참고로 textContent 프로퍼티와 유사한 동작을 하는 innerText 프로퍼티가 있다. innerText 프로퍼티는 다음과 같은 이유로 사용하지 않는 것이 좋다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;innerText 프로퍼티는 CSS에 순종적이다. 예를 들어, innerText 프로퍼티는 CSS에 의해 비표시로 지정된 요소 노드의 텍스트를 반환하지 않는다.&lt;/li&gt;
&lt;li&gt;innerText 프로퍼티는 CSS를 고려해야 하므로 textContent 프로퍼티보다 느리다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>딥다이브</category>
      <author>_차누_</author>
      <guid isPermaLink="true">https://comhwang.tistory.com/62</guid>
      <comments>https://comhwang.tistory.com/62#entry62comment</comments>
      <pubDate>Wed, 24 May 2023 22:31:24 +0900</pubDate>
    </item>
    <item>
      <title>UI/UX 디자인 시스템</title>
      <link>https://comhwang.tistory.com/61</link>
      <description>&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;UI/UX&amp;nbsp;디자인&amp;nbsp;시스템&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;디자인 시스템&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디자인 시스템은 디자인 원칙부터 재사용할 수 있는 UI 패턴과 컴포넌트, 코드로 구성된 시스템을 의미합니다. 이는 전체 서비스에 효율적이고 일관된 디자인을 적용할 수 있도록 도와줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디자인 시스템은 단순한 '디자인' 가이드가 아니라, 디자인 팀과 개발팀이 업무 전반 프로세스와 방식을 일관되게 가져갈 수 있도록 도와주는 협업 '시스템'에 가깝습니다. 이를 통해 제품 개발에 관련된 인원들이 통일된 규칙하에 사용자에게 일관된 디자인과 사용성을 제공할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디자인 시스템은 제품의 특성이나 규모 혹은 구성원들의 상황에 따라, 작은 규모에서 디자인 시스템은 컴포넌트 라이브러리 역할로 충분할 수 있지만 큰 규모의 서비스의 경우 더욱 다양한 복잡한 디자인 및 개발 프로세스를 포함하게 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 디자인 시스템은 실무에서 &lt;b&gt;서비스 확장이나 다양한 디바이스 환경에 대응할 때 시간과 노력을 절약해 주는 도구&lt;/b&gt;로 작용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;디자인 시스템의 이점&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 팀간의 원활한 협업 촉진&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디자인 시스템은 PM, 디자이너, 개발자 등 여러 분야의 사람들이 공통의 기준과 프로세스를 따르는 것과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디자이너와 개발자는 문서 혹은 툴킷 형태를 기반으로 디자인 시스템을 공유해 이를 참고하며 서로의 작업에 대한 이해를 높일 수 있습니다. 따라서 프로젝트의 진행 속도가 빨라지며, 팀원 간의 소통과 협업이 원활해집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 일관성 있는 사용자 경험 제공&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디자인 시스템에 따라 제품이 만들어지면, 사용자들은 시간이 지남에 따라 서비스의 일관된 디자인에 점점 익숙해지기 때문에, 인터페이스를 사용하는 데 걸리는 시간이 점점 줄어듭니다. 사용자는 일관성 있는 UI를 경험하면서 서비스를 더 쉽게 이해하고 사용할 수 있게 됩니다. 결국 이는 전반적인 사용자 만족도를 향상하는 결과를 가져옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 효율적인 디자인 및 개발 과정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디자인 시스템에서 특정 컴포넌트의 다양한 상태(기본 상태, 포커스 상태, 에러 상태 등)에 대한 디자인 가이드라인 및 컴포넌트 라이브러리를 미리 정의한다면 디자인과 개발 과정에서 효율성을 크게 향상할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 개발자의 디자인 관련 업무를 줄여주기 때문에 비즈니스 로직 혹은 성능 최적화와 같은 더 크고 복잡한 문제에 개발자가 집중할 수 있도록 도와줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 브랜드 인지도 강화&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코카콜라를 떠올리면 빨간색 로고가 생각나는 것과 같이, 사용자들이 일관된 디자인을 인지하게 되면 그 제품이나 브랜드에 대한 인지도와 신뢰도가 높아지게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 위해 디자인 시스템을 도입해 브랜드의 개성과 가치를 표현하는 색상, 타이포그래피, 아이콘, 이미지 등의 요소를 통일할 수 있습니다. 따라서 사용자들은 제품이나 서비스를 사용하면서 브랜드와 연결되는 느낌을 받게 됩니다.이를 통해 사용자에게 일관된 브랜드 이미지를 제공하여 기업의 브랜드 가치와 시장에서의 경쟁력을 향상할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;디자인 시스템을 도입하기 좋은 시기&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 제품군 및 기능의 확장&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서로 다른 프로젝트에서 일관성 있는 디자인을 적용하고 싶을 때 디자인 시스템을 도입해 재사용할 수 있는 컴포넌트를 공유함으로써 작업의 효율을 높일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 관련된 인원이 늘어날 때&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스와 관련된 인원이 늘어날수록 서로 다르게 만들어 낸 솔루션과 스타일이 추가되면 점차 사용자 경험이 상이하게 됩니다. 따라서 서비스를 만드는 디자이너 및 이해관계자가 많아진다면, 디자인 시스템 구축을 고려할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 채널의 확장&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오프라인 채널이 온라인으로 확장되거나 다양한 기기에 동일한 서비스를 제공하게 되는 경우가 있습니다. 이때 서로 다른 채널에서 공통의 디자인을 적용한다면 일관된 사용자 경험을 제공할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;디자인 시스템 구축하기&lt;/b&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;디자인 원칙 정의&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;프로젝트의 목표 및 브랜드 가치를 고려하여 설정&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;제품 검토&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;공통 컴포넌트 및 패턴 찾기&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스타일 가이드 개발&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;색상, 글꼴, 아이콘, 간격 등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;컴포넌트 디자인 및 문서화&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;컴포넌트 디자인 완성 후 사용 방법 및 세부 사항 문서화&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;디자인 시스템 구현&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;디자인 시스템의 요소를 사용해 개발자가 실제 서비스에 구현&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;지속적인 유지보수 및 업데이트&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;기존 구성 요소의 개선, 사용자 피드백 반영&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;디자인 시스템을 위한 도구들&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. &lt;a style=&quot;background-color: #ffffff; color: #0366d6; text-align: left;&quot; href=&quot;https://www.figma.com/&quot;&gt;&lt;b&gt;Figma&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. &lt;a style=&quot;background-color: #ffffff; color: #0366d6; text-align: left;&quot; href=&quot;https://tokens.studio/&quot;&gt;&lt;b&gt;Tokens Studio for Figma (Figma Tokens)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. &lt;a style=&quot;background-color: #ffffff; color: #0366d6; text-align: left;&quot; href=&quot;https://www.sketch.com/&quot;&gt;&lt;b&gt;Sketch&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. &lt;a style=&quot;background-color: #ffffff; color: #0366d6; text-align: left;&quot; href=&quot;https://storybook.js.org/&quot;&gt;&lt;b&gt;Storybook&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. &lt;a style=&quot;background-color: #ffffff; color: #0366d6; text-align: left;&quot; href=&quot;https://www.invisionapp.com/design-system-manager&quot;&gt;&lt;b&gt;InVision Design System Manager (DSM)&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. &lt;a style=&quot;background-color: #ffffff; color: #0366d6; text-align: left;&quot; href=&quot;https://zeplin.io/&quot;&gt;&lt;b&gt;Zeplin&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Atomic Design&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존의 웹 디자인 방식은 각 페이지마다 디자인 요소를 개별적으로 만들고 관리하는 방식이었습니다. 하지만 프로젝트 규모가 커질수록 관리가 어려워지고, 일관성을 유지하기 어려워졌습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 문제를 해결하기 위해 아토믹 디자인(Atomic Design)이라는 개념이 등장하였습니다. 아토믹 디자인은 UI를 물질의 가장 작은 단위인 원자(atom)처럼 최대한 쪼개고, 그것들을 조합하고 점짐적으로 확장시켜 일관성 있는 디자인 시스템을 구축하는 것을 목표로 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;630&quot; data-origin-height=&quot;262&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4hOkz/btshbucIvev/574sFH8PtphiiAW1yAiLxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4hOkz/btshbucIvev/574sFH8PtphiiAW1yAiLxk/img.png&quot; data-alt=&quot;출처:&amp;amp;amp;nbsp; https://atomicdesign.bradfrost.com/chapter-2/#the-part-and-the-whole&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4hOkz/btshbucIvev/574sFH8PtphiiAW1yAiLxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4hOkz%2FbtshbucIvev%2F574sFH8PtphiiAW1yAiLxk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;630&quot; height=&quot;262&quot; data-origin-width=&quot;630&quot; data-origin-height=&quot;262&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:&amp;amp;nbsp; https://atomicdesign.bradfrost.com/chapter-2/#the-part-and-the-whole&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아토믹 디자인의 구성 요소로는 원자(atom)에서 시작해, 분자(molecule), 유기체(organism), 템플릿(template), 페이지(page)가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 구성 요소는 웹을 여러 부분이 모인 하나의 전체이자, 동시에 여러 부분으로 이루어진 집합으로 이루어진 집합으로 이해하는 접근 방식(Mental model)에 가깝습니다. 이러한 접근 방식은 UI를 체계적이고 재사용 가능한 모듈로 구성하도록 도와줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;아토믹 디자인의 장점&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 모듈화와 재사용성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아토믹 디자인은 작은 단위의 구성요소를 만들고, 이를 조합하여 더 큰 단위의 구성 요소를 생성하는 방식으로 진행됩니다. 이렇게 모듈화된 구성 요소는 쉽게 재사용할 수 있어 개발 시간을 단축시키고 코드의 중복을 줄입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 유지보수의 편리함&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹사이트나 애플리케이션의 변경이나 업데이트가 필요할 때, 각 구성 요소를 개별적으로 수정하기 쉽고 이러한 변경이 전체 시스템에 영향을 미치지 않습니다. 이는 프로젝트의 유지 보수를 편리하게 만들어 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 확장성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아토믹 디자인을 적용한다면 새로운 기능이나 페이지를 추가할 때 유연한 확장이 가능합니다. 이미 만들어진 구성 요소를 조합하여 새로운 기능을 구현하거나, 필요한 경우 기존 구성 요소를 확장하여 새로운 버전을 만들 수 있기 때문입니다. 이를 통해 프로젝트의 확장성이 높아지며, 새로운 요구 사항이 생겼을 때 더 빠르게 대응할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;같이 읽으면 좋은 글&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://yozm.wishket.com/magazine/detail/1531/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://yozm.wishket.com/magazine/detail/1531/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1684892744007&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Atomic Design Pattern의 Best Practice 여정기 | 요즘IT&quot; data-og-description=&quot;좋은 폴더 구조에 관한 이야기는 개발자들 간의 끊임없는 떡밥입니다. 정답이 있지 않고 프로젝트의 특징이나 크기, 주관적인 해석에 따라 정말 여러 가지 방법들이 존재하기 때문입니다. 마치 &quot; data-og-host=&quot;yozm.wishket.com&quot; data-og-source-url=&quot;https://yozm.wishket.com/magazine/detail/1531/&quot; data-og-url=&quot;https://yozm.wishket.com/magazine/detail/1531/yozm.wishket.com/magazine/detail/1531/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/LBwet/hySKEvaEZl/1jDhpSfZl1m85Q7503ZKKk/img.png?width=1022&amp;amp;height=768&amp;amp;face=0_0_1022_768,https://scrap.kakaocdn.net/dn/EzzfO/hySKyBIUN5/7CxtWjEkhoZkb8kEnQ8Jck/img.png?width=1022&amp;amp;height=768&amp;amp;face=0_0_1022_768&quot;&gt;&lt;a href=&quot;https://yozm.wishket.com/magazine/detail/1531/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://yozm.wishket.com/magazine/detail/1531/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/LBwet/hySKEvaEZl/1jDhpSfZl1m85Q7503ZKKk/img.png?width=1022&amp;amp;height=768&amp;amp;face=0_0_1022_768,https://scrap.kakaocdn.net/dn/EzzfO/hySKyBIUN5/7CxtWjEkhoZkb8kEnQ8Jck/img.png?width=1022&amp;amp;height=768&amp;amp;face=0_0_1022_768');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Atomic Design Pattern의 Best Practice 여정기 | 요즘IT&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;좋은 폴더 구조에 관한 이야기는 개발자들 간의 끊임없는 떡밥입니다. 정답이 있지 않고 프로젝트의 특징이나 크기, 주관적인 해석에 따라 정말 여러 가지 방법들이 존재하기 때문입니다. 마치&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;yozm.wishket.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>프론트엔드/Section4</category>
      <author>_차누_</author>
      <guid isPermaLink="true">https://comhwang.tistory.com/61</guid>
      <comments>https://comhwang.tistory.com/61#entry61comment</comments>
      <pubDate>Wed, 24 May 2023 09:19:46 +0900</pubDate>
    </item>
  </channel>
</rss>