<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>김수정 블로그</title>
    <link>https://rlatnwjd.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Fri, 22 May 2026 14:02:41 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>suudong</managingEditor>
    <item>
      <title>[Cypress] social로그인 테스트 방법</title>
      <link>https://rlatnwjd.tistory.com/36</link>
      <description>&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;cy.origin()을 사용한 방법&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;수동으로 소셜 로그인 흐름을 시뮬레이션&lt;/b&gt;: 이 방법은 Cypress 테스트 코드에서 소셜 인증 흐름을 직접 시뮬레이션&lt;br /&gt;즉, 사용자의 행동을 모방하여 소셜 로그인 버튼을 클릭하고, 로그인 페이지로 이동하며, 사용자 인증 및 권한 부여를 처리&lt;br /&gt;이는 테스트 코드를 작성하고 관리하는 데 더 많은 작업을 필요로 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;유연성 및 사용자 정의 가능&lt;/b&gt;: 수동으로 테스트를 작성하기 때문에 테스트 코드에 필요한 모든 사용자 정의 및 유연성을 추가할 수 있습니다.&lt;br /&gt;&lt;a href=&quot;https://docs.cypress.io/guides/end-to-end-testing/social-authentication#__docusaurus_skipToContent_fallback&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.cypress.io/guides/end-to-end-testing/social-authentication#__docusaurus_skipToContent_fallback&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;cypress-social-logins를 사용한 방법&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;자동 소셜 로그인 흐름&lt;/b&gt;: cypress-social-logins는 Cypress 플러그인으로 소셜 로그인 흐름을 자동화하는 기능을 제공&lt;br /&gt;이를 사용하면 소셜 로그인 버튼을 클릭하고, 소셜 로그인 페이지로 이동하고, 사용자 인증 및 권한 부여를 자동으로 처리할 수 있습니다. 따라서 테스트 코드 작성 및 유지 보수에 대한 노력이 줄어듭니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;간편한 설정 및 사용&lt;/b&gt;: cypress-social-logins를 사용하면 각 소셜 로그인 제공자에 대한 설정을 간단하게 추가하고 테스트 코드에서 cy.loginBySocialAuth() 명령을 사용하여 소셜 로그인을 호출할 수 있습니다.&lt;br /&gt;&lt;a href=&quot;https://github.com/lirantal/cypress-social-logins&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/lirantal/cypress-social-logins&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <author>suudong</author>
      <guid isPermaLink="true">https://rlatnwjd.tistory.com/36</guid>
      <comments>https://rlatnwjd.tistory.com/36#entry36comment</comments>
      <pubDate>Fri, 10 May 2024 11:38:12 +0900</pubDate>
    </item>
    <item>
      <title>[Cypress] Cypress에서 비동기 처리를 수행하는 방법</title>
      <link>https://rlatnwjd.tistory.com/35</link>
      <description>&lt;div style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-scroll-anchor=&quot;false&quot; data-testid=&quot;conversation-turn-5&quot;&gt;
&lt;div&gt;
&lt;div data-message-id=&quot;557170d3-3ece-423c-b3aa-534d41f34e84&quot; data-message-author-role=&quot;assistant&quot;&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cypress의 명령 체인 내에서 then() 또는 should()을 사용하거나, cy.wrap()과 같은 명령을 사용하여 프로미스를 처리합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;then() 또는 should() 사용:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1715058618207&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;it('비동기 처리 예제', () =&amp;gt; {
  cy.visit('/some-page')
    .then(() =&amp;gt; {
      // 비동기 작업 수행
      return new Promise((resolve, reject) =&amp;gt; {
        // 예: setTimeout 사용
        setTimeout(() =&amp;gt; {
          // 비동기 작업 완료 후에는 resolve 호출
          resolve();
        }, 2000);
      });
    })
    .then(() =&amp;gt; {
      // 비동기 작업 완료 후의 동작
      cy.get('.result').should('contain', '예상 결과');
    });
});&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;cy.wrap() 사용:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1715058687004&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;it('비동기 처리 예제', () =&amp;gt; {
  // 비동기 작업을 프로미스로 래핑
  cy.wrap(new Promise((resolve, reject) =&amp;gt; {
    // 예: setTimeout 사용
    setTimeout(() =&amp;gt; {
      // 비동기 작업 완료 후에는 resolve 호출
      resolve();
    }, 2000);
  }))
  .then(() =&amp;gt; {
    // 비동기 작업 완료 후의 동작
    cy.visit('/some-page');
    cy.get('.result').should('contain', '예상 결과');
  });
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기 작업이 완료될 때까지 기다리려면, .then() 또는 .should()를 사용하여 명시적으로 비동기 작업이 완료될 때까지 대기할 수 있습니다. 또는 cy.wrap()을 사용하여 프로미스를 Cypress 체인에 래핑하여 비동기 작업을 처리할 수 있습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-scroll-anchor=&quot;false&quot; data-testid=&quot;conversation-turn-6&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-scroll-anchor=&quot;true&quot; data-testid=&quot;conversation-turn-7&quot;&gt;
&lt;div data-message-id=&quot;17986e6d-3093-4daa-865d-df9dd8667fdb&quot; data-message-author-role=&quot;assistant&quot;&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cy.wrap()은 Cypress에서 사용되는 유틸리티 함수 중 하나입니다. cy.wrap()은 값을 래핑하여 Cypress 체인으로 전달하거나, 프로미스를 Cypress 체인으로 전달하여 비동기 작업을 처리하는 데 사용됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1715058799419&quot; class=&quot;coffeescript&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;cy.wrap('Hello Cypress').then((value) =&amp;gt; {
  // 'Hello Cypress' 값을 사용하여 다른 Cypress 명령 실행
});&lt;/code&gt;&lt;/pre&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;: Cypress 체인에 값을 전달하려면 cy.wrap()을 사용하여 값을 래핑합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;프로미스 처리&lt;/b&gt;: 프로미스를 Cypress 체인으로 전달하여 비동기 작업을 처리합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1715058783837&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cy.wrap(new Promise((resolve, reject) =&amp;gt; {
  // 비동기 작업 수행
  setTimeout(() =&amp;gt; {
    resolve('Async value');
  }, 2000);
})).then((value) =&amp;gt; {
  // 비동기 작업 완료 후의 동작
  expect(value).to.equal('Async value');
});&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;cy.wrap()은 Cypress 체인 내에서 값을 전달하고 프로미스를 처리하기 위한 유용한 도구로 사용&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>suudong</author>
      <guid isPermaLink="true">https://rlatnwjd.tistory.com/35</guid>
      <comments>https://rlatnwjd.tistory.com/35#entry35comment</comments>
      <pubDate>Tue, 7 May 2024 14:13:41 +0900</pubDate>
    </item>
    <item>
      <title>[Cypress] 테스트코드 작성시 유의사항</title>
      <link>https://rlatnwjd.tistory.com/34</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;- Cypress가 직접적으로 함수가 호출되거나 컴포넌트 내부의 값을 인지하는 것은 어려울까 ?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: Cypress로 직접적으로 함수 호출을 감지하는 것은 기본적으로 어렵다. Cypress는 웹 애플리케이션의 동작을 테스트하는 데 주로 사용되며, 테스트 코드는 일반적으로 사용자의 행동 및 상호작용을 시뮬레이트하고 해당 동작에 대한 결과를 검증합니다. &lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; 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;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;대신, 함수가 호출되었음을 간접적으로 확인할 수 있습니다. 예를 들어, 함수가 호출될 때 해당 함수가 변경하는 상태나 DOM 요소의 변화를 검증할 수 있습니다. 함수가 호출되었을 때 상태가 변경되거나, 특정 DOM 요소가 생성되거나 변경되는지를 통해 함수 호출을 확인할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이를 위해 다음과 같은 접근 방식을 사용할 수 있습니다:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;함수 호출로 인한 상태 변경을 확인합니다. 예를 들어, 함수가 호출될 때 상태 값을 변경하고, 해당 상태 값을 확인하여 함수 호출을 확인할 수 있습니다.&lt;/li&gt;
&lt;li&gt;함수가 호출될 때 DOM 요소를 생성하거나 변경하고, 해당 DOM 요소의 존재 여부나 속성 등을 확인합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1714705521598&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;describe('Navbar Button Click Tests', () =&amp;gt; {
  it('Clicking on search button should display search input', () =&amp;gt; {
    cy.visit('/your-page'); // 페이지 방문
    cy.get('button').contains('Search').click(); // 검색 버튼 클릭
    cy.get('.search-wrap input').should('exist'); // 검색 창이 나타나는지 확인
  });
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;- 이렇게 검색 버튼을 클릭한 후에 검색 창이 나타나는지를 확인하여, &lt;/span&gt;onSearchButtonClick&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; 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: #0d0d0d; text-align: start;&quot;&gt;- React 컴포넌트에서 입력 값이 변경될 때 상태를 업데이트하는 예시&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1714705810720&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;describe('Input Value Change Tests', () =&amp;gt; {
  it('Should update input value and display it correctly', () =&amp;gt; {
    // 페이지 방문
    cy.visit('/your-page');

    // 입력 요소를 찾고, &quot;hello&quot;를 입력합니다.
    cy.get('input[type=&quot;text&quot;]').type('hello');

    // 입력 값이 변경되었는지 확인합니다.
    cy.get('input[type=&quot;text&quot;]').should('have.value', 'hello');

    // 다른 입력 값을 시뮬레이트해봅니다. 예: &quot;world&quot;
    cy.get('input[type=&quot;text&quot;]').clear().type('world');

    // 변경된 입력 값이 정확히 표시되는지 확인합니다.
    cy.get('input[type=&quot;text&quot;]').should('have.value', 'world');
  });
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;페이지를 방문하고, 입력 요소를 찾은 후에 &lt;/span&gt;.type()&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt; 명령을 사용하여 입력 값을 변경합니다. 그런 다음 &lt;/span&gt;.should()&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt; 명령을 사용하여 변경된 입력 값이 예상대로 표시되는지 확인합니다. 이를 통해 입력 값의 변경이 상태에 반영되고, 화면에 올바르게 표시되는지를 확인할 수 있습니다.&lt;/span&gt;&lt;/p&gt;</description>
      <author>suudong</author>
      <guid isPermaLink="true">https://rlatnwjd.tistory.com/34</guid>
      <comments>https://rlatnwjd.tistory.com/34#entry34comment</comments>
      <pubDate>Fri, 3 May 2024 12:11:48 +0900</pubDate>
    </item>
    <item>
      <title>[Cypress] 요소를 찾을 수 없는 경우</title>
      <link>https://rlatnwjd.tistory.com/33</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Expected to find element: , but never found it.&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;요소가 렌더링되지 않았을 수 있음&lt;/b&gt;: Cypress는 테스트 중에 DOM 요소를 찾으려고 할 때 해당 요소가 렌더링되어 있어야 합니다. 그렇지 않으면 요소를 찾지 못할 수 있습니다. 코드를 보면 npm start를 실행하는 beforeEach() 훅이 있습니다. 이렇게 하면 응용 프로그램이 시작되고 렌더링되기 전에 테스트가 시작될 수 있습니다. 이 경우 Cypress는 해당 요소를 찾을 수 없을 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Cypress의 기다리는 방식 이용&lt;/b&gt;: Cypress는 기본적으로 명령이 완료될 때까지 기다리지만 명시적인 기다리기 없이는 비동기적으로 로딩되는 요소를 찾는 데 문제가 발생할 수 있습니다. cy.wait()를 사용하여 요소가 완전히 로드될 때까지 기다릴 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;클래스 이름이 변경되었을 수 있음&lt;/b&gt;: 코드를 보면 React 컴포넌트의 클래스 이름을 사용하여 요소를 찾고 있습니다. 그러나 클래스 이름이 변경되었거나 템플릿이 업데이트되어 Cypress가 클래스를 올바르게 인식하지 못할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Cypress의 설정 문제&lt;/b&gt;: 가끔은 Cypress의 환경 설정 문제가 이러한 문제의 원인이 될 수 있습니다. Cypress의 설정을 확인하여 문제를 해결할 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1714638381360&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;describe('template spec', () =&amp;gt; {
  beforeEach(() =&amp;gt; {
    cy.exec('npm start');
    cy.visit('http://localhost:3000');
    cy.wait(2000);
  });


//title, descripton입력하고 체크버튼 누르면 todolist에 추가  
  it('Todo입력하기', () =&amp;gt; {
    cy.get('.buttons .addBtn').click();
    cy.get('.form input').type('제목');
    cy.get('.form textarea').type('글내용');
    cy.get('.checkBtn').click();
  })&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;cy.wait()를 사용하여 Cypress가 특정 동작이나 요소가 로드되기를 기다리도록 할 수 있습니다&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;: 페이지가 로드되기를 기다리려면 cy.wait()를 사용하여 Cypress가 페이지 로드를 기다리도록 할 수 있습니다. 예를 들어, cy.visit()로 페이지를 방문한 후에 cy.wait()를 사용하여 페이지가 완전히 로드되기를 기다릴 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714638438870&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;beforeEach(() =&amp;gt; { cy.visit('your_page_url'); cy.wait(2000); // 페이지 로드를 위해 2초간 기다림 });&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;: 어떤 요소가 화면에 나타나기를 기다리려면 cy.wait()를 사용하여 해당 요소가 로드되기를 기다릴 수 있습니다. 이것은 특히 비동기적으로 로딩되는 요소에 유용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714638474557&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;it('should wait for an element to appear', () =&amp;gt; { 
	cy.get('.your-element').should('exist'); // 해당 요소가 존재하는지 확인 cy.wait(1000);
    // 요소가 나타날 때까지 1초간 기다림
});&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이처럼 cy.wait()를 사용하여 Cypress가 특정 동작이나 요소가 로드되기를 기다리도록 설정&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;It is unsafe to chain further commands that rely on the subject after this command. It is best to split the chain, chaining again from `cy.`&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Cypress에서 명령 체인을 연속해서 사용할 때 발생합니다. 일반적으로 이것은 Cypress의 비동기 작업과 관련이 있습니다. Cypress 명령은 자체적으로 비동기적으로 실행되기 때문에, 명령 체인 내에서 뒤따르는 명령이 실행되기 전에 이전 명령이 완료되지 않을 수 있습니다. 이러한 이유로 Cypress는 명령 체인 내에서 추가적인 명령을 연결하는 것을 제한합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 에러를 해결하는 방법은 다음과 같습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 명령 분리&lt;/b&gt;: 명령 체인을 분리하고 다른 cy.로 시작하는 새로운 체인을 만듭니다. 예를 들어, 다음과 같이 체인을 분리할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714643503148&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cy.get('.element').click(); 
// 이 명령은 이전 명령이 완료될 때까지 기다립니다. 
cy.get('.other-element').should('be.visible'); 
// 새로운 체인은 이전 명령과 별개로 실행됩니다.&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;2. 콜백 함수 사용&lt;/b&gt;: 이전 명령이 완료될 때까지 기다리기 위해 .then()을 사용하여 콜백 함수를 전달할 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #000000;&quot;&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;pre id=&quot;code_1714643554996&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cy.get('.element').click().then(() =&amp;gt; { 
	cy.get('.other-element').should('be.visible'); 
	// 이 명령은 이전 명령이 완료된 후에 실행됩니다. 
});​&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;: 필요한 경우, 명령 간에 대기 시간을 추가하여 Cypress가 이전 명령이 완료될 때까지 기다리도록 합니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #000000;&quot;&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;pre id=&quot;code_1714643591364&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cy.get('.element').click(); 
// 이 명령은 이전 명령이 완료될 때까지 기다립니다. 
cy.wait(1000); // 이 명령은 대기 시간을 제공합니다. 
cy.get('.other-element').should('be.visible'); 
// 새로운 체인은 이전 명령과 별개로 실행됩니다.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <author>suudong</author>
      <guid isPermaLink="true">https://rlatnwjd.tistory.com/33</guid>
      <comments>https://rlatnwjd.tistory.com/33#entry33comment</comments>
      <pubDate>Thu, 2 May 2024 17:28:49 +0900</pubDate>
    </item>
    <item>
      <title>[React]VanilaJs 로 React Hooks 만들기</title>
      <link>https://rlatnwjd.tistory.com/32</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;- 에러상황&lt;/p&gt;
&lt;pre id=&quot;code_1714613180960&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export function createHooks(callback) {
  
  let stateContext = {current:0, states:[]};
  let memoContext = {current:0, memoValue:{}};
  
  function resetContext() {
    stateContext.current = 0;
    memoContext.current = 0;
  }

  const useState = (initState) =&amp;gt; {
    const {current, states} = stateContext;
    const _index = stateContext.current;
    //초기값 설정
    if(states.length === _index){
      states.push(initState);
    }
    //state할당하기
    const state = states[_index];
    
    const setState = (newState) =&amp;gt; {
      //기존의 state와 동일한 경우
      if(newState === state) return;
      states[_index] = newState;  
      callback();
    }
    stateContext.current+=1;
    return [state, setState];
  };

  const useMemo = (fn, refs) =&amp;gt; {
    const {current, memoValue} = memoContext;
    const key = JSON.stringify(refs);

    if (key in memoValue) {
      return memoValue[key];
    }
    const result = fn();
    memoValue[key] = result;
    return result;
  };
  return { useState, useMemo, resetContext };
}&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;setState&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt; 함수 내에서 상태가 변경되었을 때만 &lt;/span&gt;callback&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt; 함수가 호출되므로, 상태가 이전과 동일한 경우에는 렌더링이 발생하지 않아야되는데 기존코드는 state에 states[_index]의 값을 할당해줘서 newState === state가 다른주소로 인식되어서 값이 동일해도 주소값이 달라서 렌더링이 계속 발생되었음&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1714613710958&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const useState = (initState) =&amp;gt; {
    const {current, states} = stateContext;
    stateContext.current+=1;

    //초기값 설정
    if(states.length === current){
      states.push(initState);
    }
    let state = states[current]
    const setState = (newState) =&amp;gt; {
      //기존의 state와 동일한 경우
      if(newState ===  states[current]) return;
      states[current] = newState;
      callback();
    }
    

    return [state, setState];
  };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>suudong</author>
      <guid isPermaLink="true">https://rlatnwjd.tistory.com/32</guid>
      <comments>https://rlatnwjd.tistory.com/32#entry32comment</comments>
      <pubDate>Thu, 2 May 2024 10:38:37 +0900</pubDate>
    </item>
    <item>
      <title>[Javascript] 이벤트 루프</title>
      <link>https://rlatnwjd.tistory.com/31</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pvdCa/btsGqNfRPj1/ixHBkCSiFVd4tXEE30cS20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pvdCa/btsGqNfRPj1/ixHBkCSiFVd4tXEE30cS20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pvdCa/btsGqNfRPj1/ixHBkCSiFVd4tXEE30cS20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpvdCa%2FbtsGqNfRPj1%2FixHBkCSiFVd4tXEE30cS20%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;1024&quot; height=&quot;768&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;콜 스택, 메모리 힙이란?&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;자바스크립트 엔진은&lt;span&gt;&amp;nbsp;&lt;/span&gt;Memory Heap&lt;span&gt;&amp;nbsp;&lt;/span&gt;과&lt;span&gt;&amp;nbsp;&lt;/span&gt;Call Stack&lt;span&gt;&amp;nbsp;&lt;/span&gt;으로 구성되어 있습니다. 가장 유명한 것이 구글의 V8 Engine입니다. 자바스크립트는 단일 스레드 (sigle thread) 프로그래밍 언어인데, 이 의미는&lt;span&gt;&amp;nbsp;&lt;/span&gt;Call Stack이 하나&lt;span&gt;&amp;nbsp;&lt;/span&gt;라는 이야기입니다. 즉 멀티가 되지 않고, 하나씩 하나씩 처리한다는 의미입니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;콜 스택(Call Stack)&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;원시 타입(숫자 등) 데이터가 저장된다.&lt;br /&gt;실행 콘텍스트(Execution Context)를 통해&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1) 변수 식별자(이름) 저장,&lt;br /&gt;2) 스코프 체인 및 this 관리,&lt;br /&gt;3) 코드 실행 순서 관리 등을 수행.&lt;br /&gt;*실행 컨텍스트의 상세 구조 및 원리는 이 글의 범위를 넘어가므로 다루지 않습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;메모리 힙(Memory Heap)&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;참조 타입(객체 등) 데이터가 저장된다.&lt;br /&gt;메모리 할당이 일어나는 곳.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;콜 스택, 메모리 힙의 데이터 저장 구조&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;763&quot; data-origin-height=&quot;260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKmugA/btsGuNLBl3l/PRlF3HsO6DSVQHQPba3a3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKmugA/btsGuNLBl3l/PRlF3HsO6DSVQHQPba3a3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKmugA/btsGuNLBl3l/PRlF3HsO6DSVQHQPba3a3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKmugA%2FbtsGuNLBl3l%2FPRlF3HsO6DSVQHQPba3a3k%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;763&quot; height=&quot;260&quot; data-origin-width=&quot;763&quot; data-origin-height=&quot;260&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img1.daumcdn.png&quot; data-origin-width=&quot;797&quot; data-origin-height=&quot;380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bETTDa/btsGq9CMTgG/jlefjEEbdMhjFDQmAjN5Qk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bETTDa/btsGq9CMTgG/jlefjEEbdMhjFDQmAjN5Qk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bETTDa/btsGq9CMTgG/jlefjEEbdMhjFDQmAjN5Qk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbETTDa%2FbtsGq9CMTgG%2FjlefjEEbdMhjFDQmAjN5Qk%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;797&quot; height=&quot;380&quot; data-filename=&quot;img1.daumcdn.png&quot; data-origin-width=&quot;797&quot; data-origin-height=&quot;380&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-alt=&quot;자바스크립트 메모리 구조 : 콜 스택, 메모리 힙&quot; data-lightbox=&quot;lightbox&quot; data-url=&quot;https://blog.kakaocdn.net/dn/wyILC/btrdon3nQV9/yWgZ1qDmEZDwzINEm5dkf1/img.png&quot;&gt;&lt;/span&gt;자바스크립트 메모리 구조 : 콜 스택, 메모리 힙&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;1. 원시 타입 데이터(파란색 변수 a)&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 10이라는 값 자체는 원시 타입이므로 콜 스택에 저장된다.&lt;br /&gt;- 변수 a에는 10이 저장된 콜 스택 메모리의 주소값이 저장된다.&lt;br /&gt;* 변수 식별자 a 자체는 콜스택 상의 '실행 컨텍스트(Execution Context)의 렉시컬 환경(Lexical Environment)'이라는 곳에 저장된다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. 참조 타입 데이터(핑크색 변수 b, c, d)&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 배열, 객체, 함수 등은 참조 타입이므로 메모리 힙에 저장된다.&lt;br /&gt;- 참조타입 데이터가 저장된 메모리 힙의 주소값은 콜스택에 각각 저장된다.&lt;br /&gt;- 메모리힙의 주소 값이 저장된 콜 스택의 주소값은 각각 변수 b, c, d에 저장된다.&lt;br /&gt;* 마찬가지로, 변수 식별자 b, c, d 이름 자체는 콜스택 상의 '실행 컨텍스트(Execution Context)의 렉시컬 환경(Lexical Environment)'에 저장된다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 이벤트 루프&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://seokzin.tistory.com/entry/JavaScript-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84-Event-Loop?category=695590&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://seokzin.tistory.com/entry/JavaScript-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84-Event-Loop?category=695590&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712563760163&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;[JavaScript] 이벤트 루프 (Event Loop)&quot; data-og-description=&quot;JavaScript는 싱글 스레드 언어로써 한 번에 하나의 작업만 처리할 수 있습니다. 하지만 실제 웹을 보면 여러 작업들이 동시에 처리되는 것을 볼 수 있습니다. JavaScript는 어떻게 여러 작업을 처리할&quot; data-og-host=&quot;seokzin.tistory.com&quot; data-og-source-url=&quot;https://seokzin.tistory.com/entry/JavaScript-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84-Event-Loop?category=695590&quot; data-og-url=&quot;https://seokzin.tistory.com/entry/JavaScript-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84-Event-Loop&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fK8Lm/hyVJ2oe5ZX/iIJTiG6cCUVRrSPII2VnkK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400,https://scrap.kakaocdn.net/dn/YnjXS/hyVMWfBm3A/rxKVYjsr5p188oavjwLi81/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400,https://scrap.kakaocdn.net/dn/W2sDb/hyVMQ7wqYm/bFMjzrU8W3AwtLx51vXrQk/img.png?width=650&amp;amp;height=389&amp;amp;face=0_0_650_389&quot;&gt;&lt;a href=&quot;https://seokzin.tistory.com/entry/JavaScript-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84-Event-Loop?category=695590&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://seokzin.tistory.com/entry/JavaScript-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84-Event-Loop?category=695590&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fK8Lm/hyVJ2oe5ZX/iIJTiG6cCUVRrSPII2VnkK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400,https://scrap.kakaocdn.net/dn/YnjXS/hyVMWfBm3A/rxKVYjsr5p188oavjwLi81/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400,https://scrap.kakaocdn.net/dn/W2sDb/hyVMQ7wqYm/bFMjzrU8W3AwtLx51vXrQk/img.png?width=650&amp;amp;height=389&amp;amp;face=0_0_650_389');&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;[JavaScript] 이벤트 루프 (Event Loop)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;JavaScript는 싱글 스레드 언어로써 한 번에 하나의 작업만 처리할 수 있습니다. 하지만 실제 웹을 보면 여러 작업들이 동시에 처리되는 것을 볼 수 있습니다. JavaScript는 어떻게 여러 작업을 처리할&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;seokzin.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>
      <author>suudong</author>
      <guid isPermaLink="true">https://rlatnwjd.tistory.com/31</guid>
      <comments>https://rlatnwjd.tistory.com/31#entry31comment</comments>
      <pubDate>Thu, 2 May 2024 10:25:38 +0900</pubDate>
    </item>
    <item>
      <title>[React] 생활코딩_react2022</title>
      <link>https://rlatnwjd.tistory.com/30</link>
      <description>&lt;pre id=&quot;code_1713322853440&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import './App.css';
import {useState} from 'react';

function Header(props){
  return &amp;lt;header&amp;gt;
  &amp;lt;h1&amp;gt;&amp;lt;a href='/' onClick={(event) =&amp;gt; {
    event.preventDefault();
    props.onChangeMode();
  }}&amp;gt;{props.title}&amp;lt;/a&amp;gt;&amp;lt;/h1&amp;gt;
    &amp;lt;/header&amp;gt;
}

function Nav(props){
  const lis = []
  for(let i=0;i&amp;lt;props.topics.length;i++){
    let t = props.topics[i];
    lis.push(
      &amp;lt;li key={t.id}&amp;gt;
      &amp;lt;a id={t.id} href={'/read/' + t.id} onClick={(event) =&amp;gt; { //태그의 속성으로 넘기게되면 문자열로 변경
        event.preventDefault();
        props.onChangeMode(Number(event.target.id));
      }} &amp;gt;{t.title}&amp;lt;/a&amp;gt;
      &amp;lt;/li&amp;gt;
      )
  }
  return &amp;lt;nav&amp;gt;
    &amp;lt;ol&amp;gt;
      {lis}
    &amp;lt;/ol&amp;gt;
  &amp;lt;/nav&amp;gt;
}

function Article(props){
  return &amp;lt;article&amp;gt;
  &amp;lt;h2&amp;gt;{props.title}&amp;lt;/h2&amp;gt;
    {props.body}
  &amp;lt;/article&amp;gt;
}

function Create(props){
  return &amp;lt;article&amp;gt;
    &amp;lt;h2&amp;gt;Create&amp;lt;/h2&amp;gt;
    &amp;lt;form onSubmit={event =&amp;gt; {
      event.preventDefault();
      const title = event.target.title.value;
      const body = event.target.body.value;
      props.onCreate(title,body);
    }}&amp;gt;
      &amp;lt;p&amp;gt;&amp;lt;input type='text' name='title' placeholder='title' /&amp;gt;&amp;lt;/p&amp;gt;
      &amp;lt;p&amp;gt;&amp;lt;textarea name='body' placeholder='body'/&amp;gt;&amp;lt;/p&amp;gt;
      &amp;lt;p&amp;gt;&amp;lt;input type='submit' value=&quot;Create&quot;&amp;gt;&amp;lt;/input&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;/form&amp;gt;
  &amp;lt;/article&amp;gt;
}

function Update(props){
  const [title,setTitle] = useState(props.title);
  const [body, setBody] = useState(props.body);

  return &amp;lt;article&amp;gt;
    &amp;lt;h2&amp;gt;Update&amp;lt;/h2&amp;gt;
    &amp;lt;form onSubmit={event =&amp;gt; {
      event.preventDefault();
      const title = event.target.title.value;
      const body = event.target.body.value;
      props.onUpdate(title,body);
    }}&amp;gt;
      &amp;lt;p&amp;gt;&amp;lt;input type='text' name='title' placeholder='title' value={title} onChange={(event)=&amp;gt;{
        setTitle(event.target.value);
      }}/&amp;gt;&amp;lt;/p&amp;gt;
      &amp;lt;p&amp;gt;&amp;lt;textarea name='body' placeholder='body' value={body} onChange={(event) =&amp;gt; {
        setBody(event.target.body);
      }}/&amp;gt;&amp;lt;/p&amp;gt;
      &amp;lt;p&amp;gt;&amp;lt;input type='submit' value=&quot;Update&quot;&amp;gt;&amp;lt;/input&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;/form&amp;gt;
  &amp;lt;/article&amp;gt;
}

function App() {
  // const _mode = useState('WELCOME'); // useState의 초기값
  // const mode = _mode[0];
  // const setMode = _mode[1]; //값을 바꿀 때
  const [mode, setMode] = useState(&quot;WELCOME&quot;); 
  const [id, setId] = useState(null); 
  const [nextId, setNextId] = useState(4);
  const [topics,setTopics] = useState([
    {id:1, title:'html', body:'html is...' },
    {id:2, title:'css', body:'css is...' },
    {id:3, title:'js', body:'js is...' }
  ]);
  let content = null;
  let contentControl = null;

  if(mode === &quot;WELCOME&quot;) {
    content = &amp;lt;Article title=&quot;Welcome&quot; body=&quot;Hello, WEB&quot;/&amp;gt;
  } else if(mode === &quot;READ&quot;){
    let title,body = null;
    for(let i=0;i&amp;lt;topics.length;i++){
      if(topics[i].id === id){
        title = topics[i].title;
        body = topics[i].body;
      }
    }
    content = &amp;lt;Article title={title} body={body}/&amp;gt;
    contentControl= &amp;lt;&amp;gt;
    &amp;lt;li&amp;gt;&amp;lt;a href={'/update' + id} onClick={(event) =&amp;gt; {
      event.preventDefault();
      setMode(&quot;UPDATE&quot;)
    }}&amp;gt;Update&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
    &amp;lt;input type='button' value=&quot;Delete&quot; onClick={() =&amp;gt; {
      const newTopics =[];
      for(let i=0;i&amp;lt;topics.length;i++){
        if(topics[i].id !== id){
          newTopics.push(topics[i]);
        }
      }
      setTopics(newTopics);
      setMode(&quot;WELCOME&quot;);
    }}/&amp;gt;
    &amp;lt;/&amp;gt;
  } else if(mode === &quot;CREATE&quot;){
    content = &amp;lt;Create onCreate={(_title, _body) =&amp;gt; { 
      const newTopic = {id:nextId, title:_title, body: _body}
      const newTopics = [...topics];
      newTopics.push(newTopic);
      setTopics(newTopics);
      setMode(&quot;READ&quot;);
      setId(nextId);
      setNextId(nextId+1);
    }}/&amp;gt;
  } else if(mode === &quot;UPDATE&quot;){
    let title,body = null;
    for(let i=0;i&amp;lt;topics.length;i++){
      if(topics[i].id === id){
        title = topics[i].title;
        body = topics[i].body;
      }
    }
    content = &amp;lt;Update title={title} body={body} onUpdate={(title,body)=&amp;gt;{
      const newTopics = [...topics];
      const updatedTopic = {id:id, title:title, body:body}
      for(let i=0;i&amp;lt;newTopics.length;i++){
        if(newTopics[i].id === id){
          newTopics[i] = updatedTopic;
          break;
        }
      }
      setTopics(newTopics);
    }} /&amp;gt;
  }

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;Header title=&quot;REACT&quot; onChangeMode={() =&amp;gt; {
        setMode(&quot;WELCOME&quot;);
      }} /&amp;gt;
      &amp;lt;Header/&amp;gt;
      &amp;lt;Nav topics={topics} onChangeMode={(_id) =&amp;gt; {
        setMode(&quot;READ&quot;);
        setId(_id);
      }}/&amp;gt;
      {content}
      &amp;lt;ul&amp;gt;
        &amp;lt;li&amp;gt;
          &amp;lt;a href='/create' onClick={event =&amp;gt; {
        event.preventDefault();
        setMode(&quot;CREATE&quot;);
          }}&amp;gt;
            Create
          &amp;lt;/a&amp;gt;
        &amp;lt;/li&amp;gt;
        {contentControl}
      &amp;lt;/ul&amp;gt;
      
    &amp;lt;/div&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>React</category>
      <author>suudong</author>
      <guid isPermaLink="true">https://rlatnwjd.tistory.com/30</guid>
      <comments>https://rlatnwjd.tistory.com/30#entry30comment</comments>
      <pubDate>Wed, 17 Apr 2024 12:01:27 +0900</pubDate>
    </item>
    <item>
      <title>[CSS] px em rem, max min -width</title>
      <link>https://rlatnwjd.tistory.com/29</link>
      <description>&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;px (pixels): 픽셀은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;디지털 화면에 표시되는 가장 작은 단위&lt;/b&gt;이다.&lt;br /&gt;&lt;b&gt;고정된 크기&lt;/b&gt;를 가지며, 따라서 다른 요소나 설정에 영향을 받지 않는다.&lt;/li&gt;
&lt;li&gt;em: em 단위는 상대적인 단위로, 해당 요소의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;부모 요소의 글꼴 크기에 상대적&lt;/b&gt;이다.&lt;br /&gt;예를 들어, 부모 요소의 글꼴 크기가 16픽셀이고 자식 요소의 글꼴 크기가 1em으로 설정되면, 자식 요소의 글꼴 크기도 16픽셀이 된다. 만약 자식 요소의 글꼴 크기가 2em으로 설정되면, 그것은 부모요소의 두 배인 32픽셀이 됩니다.&lt;/li&gt;
&lt;li&gt;rem (root em): rem도 상대적인 단위지만, &lt;b&gt;HTML 문서 최상단 루트(root)요소()의 글꼴 크기에 기반&lt;/b&gt;한다. 이렇게 하면 사이트 전체에서 일관된 스타일링을 쉽게 유지할 수 있다.&lt;/li&gt;
&lt;li&gt;vw (viewport width) : 하나의 vw는 뷰포트 너비의 1%이다. 예를 들어, 뷰포트 너비가 500px일 때, width:50vw;는 해당 요소가 화면 너비의 절반(250px)을 차지하도록 한다.&lt;/li&gt;
&lt;li&gt;vh (viewport height) : 마찬가지로 하나의 vh는 뷰포트 높이의 1%이다. 예를 들어, 뷰포트 높이가 800px일 때, height:20vh;는 해당 요소가 화면높이의 5분의 1(160px)을 차지하도록 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 상대 단위 : &lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;고정되지 않고 어떤 기준에 따라 유동적으로 바뀌는 길이를 나타내는 단위 ex) &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;em, rem, %, vw, vh&lt;/span&gt;&lt;span style=&quot;color: #212529; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;&lt;span&gt;&lt;b&gt;- 절대 단위 :&lt;/b&gt; &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;어떤 상황에서든 항상 고정된 길이를 나타내는 단위 ex) &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;&lt;span&gt;px&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;&lt;span&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: #212529; text-align: start;&quot;&gt;웹은 디바이스나 사용자 환경에 따라 콘텐츠 크기가 유동적으로 변하기 때문에 절대 단위를 사용하면 콘텐츠의 유연성이 저하&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;rem,em 모두 상대적인 단위이지만 em의 경우 부모요소에게 영향을 받기 때문에 실제 몇 px로 변환될지에 영향을 주는 변수가 많아져서 스타일된 요소의 경우 재사용이 어려워지거나 유지보수가 힘들어지는 경향이 있을 수 있음 따라서 rem을 권장&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;브레이크 포인트(breakpoint)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 화면 크기 범위&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모바일: 320px ~ 480px&lt;/li&gt;
&lt;li&gt;태블릿: 481px ~ 768px&lt;/li&gt;
&lt;li&gt;작은 데스크탑: 769px ~ 1024px&lt;/li&gt;
&lt;li&gt;대형 데스크탑: 1025px 이상&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Min-width (모바일) : &quot;모바일 우선(Mobile First)&quot;&lt;span style=&quot;color: #212529; text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;접근 방식을 사용하면 작은 화면 크기부터 시작하여 점진적으로 대형화면에 맞게 스타일링&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1713320456113&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@media (min-width: 1000px) {
	body {
		background: gold;
	}
}
//min-width(최소 width)가 1000px, 즉 1000px 이상인 경우에 적용되는 코드&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;Max-width(&lt;span&gt;웹&lt;/span&gt;) : &lt;span style=&quot;color: #323228; text-align: start;&quot;&gt;데스크탑용의 가장 큰 화면 사이즈의 레이아웃을 기본으로 하고, 점차 축소하는 형태로 CSS를 작성&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1713320467378&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@media (max-width: 1000px) {
	body {
		background: gold;
	}
}
//max-width(최대 width)가 1000px, 즉 1000px 이하인 경우에 적용되는 코드&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CSS</category>
      <author>suudong</author>
      <guid isPermaLink="true">https://rlatnwjd.tistory.com/29</guid>
      <comments>https://rlatnwjd.tistory.com/29#entry29comment</comments>
      <pubDate>Wed, 17 Apr 2024 11:23:26 +0900</pubDate>
    </item>
    <item>
      <title>[CSS] Selector 선택자</title>
      <link>https://rlatnwjd.tistory.com/28</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 태그 선택자&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1713316182149&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&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;- id 선택자&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1713316131784&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#id명 { 속성: 속성값; }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;433&quot; data-origin-height=&quot;426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brUnZr/btsGHlaD1jm/vWo3yDaJTWIc8gCBr9WhqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brUnZr/btsGHlaD1jm/vWo3yDaJTWIc8gCBr9WhqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brUnZr/btsGHlaD1jm/vWo3yDaJTWIc8gCBr9WhqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrUnZr%2FbtsGHlaD1jm%2FvWo3yDaJTWIc8gCBr9WhqK%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;433&quot; height=&quot;426&quot; data-origin-width=&quot;433&quot; data-origin-height=&quot;426&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- class 선택자&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1713316109384&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.class명 { 속성: 속성값; }&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;pre id=&quot;code_1713315911392&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;선택자1 &amp;gt; 선택자2 {
    속성: 속성값;
}

// 선택자1이 부모 element, 선택자2가 자식 element
// 부모 태그 하위에 있는 선택자2에 해당하는 모든 자식 태그에 스타일을 적용&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;428&quot; data-origin-height=&quot;309&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8zaF8/btsGHtl5gIe/HfJ1jDoOJvYgfbRmwa4Fp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8zaF8/btsGHtl5gIe/HfJ1jDoOJvYgfbRmwa4Fp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8zaF8/btsGHtl5gIe/HfJ1jDoOJvYgfbRmwa4Fp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8zaF8%2FbtsGHtl5gIe%2FHfJ1jDoOJvYgfbRmwa4Fp1%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;428&quot; height=&quot;309&quot; data-origin-width=&quot;428&quot; data-origin-height=&quot;309&quot;/&gt;&lt;/span&gt;&lt;/figure&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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 자손 선택자&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1713315851074&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;선택자1 선택자2 {
    속성: 속성값;
}
// 선택자1 이 부모 element, 선택자2가 자손 element
// 부모 태그 하위에 있는 선택자2에 해당하는 모든 자손 태그에 스타일을 적용&lt;/code&gt;&lt;/pre&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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 다중 조건 선택자&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;논리 연산자 &lt;b&gt;and&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1713316004628&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;선택자1선택자2 {
    속성: 속성값;
}
// 선택자끼리 띄어쓰기 없이 붙여서 쓰면 and와 같습니다
// 선택자1과 선택자2를 모두 만족하는 엘리먼트들에게 해당 style을 적용

태그이름#아이디 { 속성1:속성값; 속성2:속성값; } 
태그이름.클래스명 { 속성1:속성값; 속성2:속성값; }
.클래스명#아이디 { 속성1:속성값; 속성2:속성값; }&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;or&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1713316057303&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;선택자1, 선택자2 {
    속성: 속성값;
}

// 선택자끼리 쉼표로 구분
// 선택자1과 선택자2 중 어느 하나라도 만족하는 엘리먼트들에게 해당 style을 적용

#아이디, .클래스명{ 속성1:속성값; 속성2:속성값; } 
태그이름, .클래스명{ 속성1:속성값; 속성2:속성값; }&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;CSS 적용의 우선순위&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;속성 값 뒤에 !important를 붙인 속성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;HTML의 각 태그에서 style을 직접 지정한 속성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;id selector&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;class selector&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;tag selector&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;상위 객체에 의해 상속된 속성&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors#combinators_and_separators&quot;&gt;결합자와 구분자&lt;/a&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;+(&amp;nbsp;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Next-sibling_combinator&quot;&gt;다음 형제 결합자&lt;/a&gt; ) &lt;b&gt;: &lt;/b&gt;+는 두 개의 선택자를 분리하고 첫 번째 요소&lt;span&gt;&amp;nbsp;&lt;/span&gt;바로&lt;span&gt;&amp;nbsp;&lt;/span&gt;뒤에 있고 둘 다 동일한 부모의 자식인 경우에만 두 번째 요소와 일치 ,&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b; text-align: start;&quot;&gt;앞에서 지정한 요소의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;바로 다음&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b; text-align: start;&quot;&gt;에 위치하는 형제 요소만 선택&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;424&quot; data-origin-height=&quot;505&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cW8OIP/btsGGOj6kth/QYxJ53uwbJ8OOx7iaCXZ4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cW8OIP/btsGGOj6kth/QYxJ53uwbJ8OOx7iaCXZ4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cW8OIP/btsGGOj6kth/QYxJ53uwbJ8OOx7iaCXZ4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcW8OIP%2FbtsGGOj6kth%2FQYxJ53uwbJ8OOx7iaCXZ4k%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;424&quot; height=&quot;505&quot; data-origin-width=&quot;424&quot; data-origin-height=&quot;505&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;gt;(&amp;nbsp;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Child_combinator&quot;&gt;하위 결합자&lt;/a&gt; ) : 자식&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;연결자&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;gt;)는 두 CSS 선택자 사이에 배치됩니다. 첫 번째 선택기와 일치하는 요소의 직계 하위 요소인 두 번째 선택기와 일치하는 요소만 일치&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;416&quot; data-origin-height=&quot;348&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vVOMa/btsGHIcm1to/jg1Q8ieGRyYDyfUB8kZxk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vVOMa/btsGHIcm1to/jg1Q8ieGRyYDyfUB8kZxk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vVOMa/btsGHIcm1to/jg1Q8ieGRyYDyfUB8kZxk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvVOMa%2FbtsGHIcm1to%2Fjg1Q8ieGRyYDyfUB8kZxk0%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;416&quot; height=&quot;348&quot; data-origin-width=&quot;416&quot; data-origin-height=&quot;348&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;||(&amp;nbsp;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Column_combinator&quot;&gt;열 조합자&lt;/a&gt; ) : 열&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;연결자&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(&lt;span&gt;&amp;nbsp;&lt;/span&gt;||)는 두 CSS 선택자 사이에 배치됩니다. 첫 번째 선택기와 일치하는 열 요소에 속하는 두 번째 선택기와 일치하는 요소만 일치&lt;/li&gt;
&lt;li&gt;~(&amp;nbsp;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Subsequent-sibling_combinator&quot;&gt;후속 형제 결합자&lt;/a&gt; ): (&lt;span&gt;&amp;nbsp;&lt;/span&gt;~, 물결표)는 두 개의 선택기를 분리하고&lt;span&gt;&amp;nbsp;&lt;/span&gt;첫 번째 요소(반드시 바로는 아님) 뒤에 오는 두 번째 요소의&lt;span&gt;&amp;nbsp;&lt;/span&gt;모든 인스턴스 와 일치하며 동일한 상위 요소를 공유&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;440&quot; data-origin-height=&quot;446&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/u6pOr/btsGEVkbs43/5ck6QkdPK2AVfmlhS1BqzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/u6pOr/btsGEVkbs43/5ck6QkdPK2AVfmlhS1BqzK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/u6pOr/btsGEVkbs43/5ck6QkdPK2AVfmlhS1BqzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fu6pOr%2FbtsGEVkbs43%2F5ck6QkdPK2AVfmlhS1BqzK%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;440&quot; height=&quot;446&quot; data-origin-width=&quot;440&quot; data-origin-height=&quot;446&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot; &quot;(&amp;nbsp;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Descendant_combinator&quot;&gt;하위 결합자&lt;/a&gt; ) : &lt;b&gt;일반적으로 단일 공백(&quot; &quot;) 문자로 표시되는 하위 조합자는&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;두&lt;span&gt;&amp;nbsp;&lt;/span&gt;개의 선택기를 결합하여 두 번째 선택기와 일치하는 요소에 일치하는 조상(부모, 부모의 부모, 부모의 부모의 부모 등) 요소가 있는 경우 두 번째 선택기와 일치하는 요소가 선택&lt;/li&gt;
&lt;li&gt;|(&amp;nbsp;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Namespace_separator&quot;&gt;네임스페이스 구분 기호&lt;/a&gt; ) : 네임&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;스페이스 구분 기호&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(&lt;span&gt;&amp;nbsp;&lt;/span&gt;|)는 선택기를 네임스페이스에서 분리하여&lt;span&gt;&amp;nbsp;&lt;/span&gt;유형 선택기에 대한&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Glossary/Namespace&quot;&gt;네임스페이스 또는 네임스페이스 부족을 식별&lt;/a&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;:not()&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;부정(negation) CSS 가상 클래스 :not(X)는 인수로 간단한 선택자(selector) X를 취하는 기능 표기법&lt;/li&gt;
&lt;li&gt;인수로 표시되지 않은 요소와 일치&lt;/li&gt;
&lt;li&gt;X는 다른 부정 선택자를 포함해서는 안 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;411&quot; data-origin-height=&quot;554&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvDSvs/btsGFkDURQp/1foSoQG2y3zUWAlmCFnX4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvDSvs/btsGFkDURQp/1foSoQG2y3zUWAlmCFnX4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvDSvs/btsGFkDURQp/1foSoQG2y3zUWAlmCFnX4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcvDSvs%2FbtsGFkDURQp%2F1foSoQG2y3zUWAlmCFnX4k%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;411&quot; height=&quot;554&quot; data-origin-width=&quot;411&quot; data-origin-height=&quot;554&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;:first-child&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;CSS&amp;nbsp;:first-child&amp;nbsp;의사 클래스는 형제 요소 중 제일 첫 요소&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;nth-child()&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&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;CSS&amp;nbsp;:nth-child() : 의사 클래스는 형제 사이에서의 순서에 따라 요소를 선택&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1713317706751&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* 목록의 두 번째 &amp;lt;li&amp;gt; 선택 */
li:nth-child(2) {
  color: lime;
}

/* 임의의 그룹에서 네 번째에 위치하는 모든 요소 선택 */
:nth-child(4n) {
  color: lime;
}&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;span style=&quot;background-color: #ffffff; color: #1b1b1b; text-align: start;&quot;&gt;주어진 특성의 존재 여부나 그 값에 따라 요소를 선택&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1713317516496&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[attr]
attr이라는 이름의 특성을 가진 요소를 선택합니다.
[attr=value]
attr이라는 이름의 특성값이 정확히 value인 요소를 선택합니다.
[attr~=value]
attr이라는 이름의 특성값이 정확히 value인 요소를 선택합니다. attr 특성은 공백으로 구분한 여러 개의 값을 가지고 있을 수 있습니다.
[attr|=value]
attr이라는 특성값을 가지고 있으며, 그 특성값이 정확히 value이거나 value로 시작하면서 -(U+002D) 문자가 곧바로 뒤에 따라 붙으면 이 요소를 선택합니다. 보통 언어 서브코드(en-US, ko-KR 등)가 일치하는지 확인할 때 사용합니다.
[attr^=value]
attr이라는 특성값을 가지고 있으며, 접두사로 value가 값에 포함되어 있으면 이 요소를 선택합니다.
[attr$=value]
attr이라는 특성값을 가지고 있으며, 접미사로 value가 값에 포함되어 있으면 이 요소를 선택합니다.
[attr*=value]
attr이라는 특성값을 가지고 있으며, 값 안에 value라는 문자열이 적어도 하나 이상 존재한다면 이 요소를 선택합니다.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;432&quot; data-origin-height=&quot;353&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bd4mIW/btsGFzAYhf6/qlikZuVl6cXtpREJQqKvak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bd4mIW/btsGFzAYhf6/qlikZuVl6cXtpREJQqKvak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bd4mIW/btsGFzAYhf6/qlikZuVl6cXtpREJQqKvak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbd4mIW%2FbtsGFzAYhf6%2FqlikZuVl6cXtpREJQqKvak%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;432&quot; height=&quot;353&quot; data-origin-width=&quot;432&quot; data-origin-height=&quot;353&quot;/&gt;&lt;/span&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;:enabled &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;CSS&amp;nbsp;:enabled&amp;nbsp;의사 클래스는 모든 활성 요소를 나타냅니다. 활성 요소란 활성(선택, 클릭, 입력 등등)하거나 포커스를 받을 수 있는 요소를 말합니다. 반대 상태인 비활성 요소도 존재&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;427&quot; data-origin-height=&quot;329&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOFhF1/btsGEjTbY7f/EKtvw6UB6b8VUfijMQ46wK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOFhF1/btsGEjTbY7f/EKtvw6UB6b8VUfijMQ46wK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOFhF1/btsGEjTbY7f/EKtvw6UB6b8VUfijMQ46wK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOFhF1%2FbtsGEjTbY7f%2FEKtvw6UB6b8VUfijMQ46wK%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;427&quot; height=&quot;329&quot; data-origin-width=&quot;427&quot; data-origin-height=&quot;329&quot;/&gt;&lt;/span&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>CSS</category>
      <author>suudong</author>
      <guid isPermaLink="true">https://rlatnwjd.tistory.com/28</guid>
      <comments>https://rlatnwjd.tistory.com/28#entry28comment</comments>
      <pubDate>Wed, 17 Apr 2024 10:37:39 +0900</pubDate>
    </item>
    <item>
      <title>[React] 컴포넌트, 컴포넌트 생명주기</title>
      <link>https://rlatnwjd.tistory.com/27</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 함수 컴포넌트와 클래스 컴포넌트&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1713173134180&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Welcome(props) {
  return &amp;lt;h1&amp;gt;Hello, {props.name}&amp;lt;/h1&amp;gt;;
}&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_1713173187492&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Welcome extends React.Component {
  render() {
    return &amp;lt;h1&amp;gt;Hello, {this.props.name}&amp;lt;/h1&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;- 컴포넌트 생명주기 메서드&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;컴포넌트 클래스에서 특별한 메서드를 선언하여 컴포넌트가 마운트되거나 언마운트 될 때 일부 코드 작동&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkiFZZ/btsGCo0TfDG/maVfwr9cGMouy0KJWdfAyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkiFZZ/btsGCo0TfDG/maVfwr9cGMouy0KJWdfAyk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkiFZZ/btsGCo0TfDG/maVfwr9cGMouy0KJWdfAyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkiFZZ%2FbtsGCo0TfDG%2FmaVfwr9cGMouy0KJWdfAyk%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;1280&quot; height=&quot;520&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;520&quot;/&gt;&lt;/span&gt;&lt;/figure&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;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;b&gt;componentDidMount()&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;메서드는 컴포넌트 출력물이 DOM에 렌더링 된 후에 실행&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #282c34; color: #ffffff; text-align: start;&quot; data-language=&quot;jsx&quot;&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;  componentDidMount() {
    this.timerID = setInterval(
        () =&amp;gt; this.tick(),      
        1000    
    );  
   }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Mouting : Dom이생성되고 웹 브라우저상에 나타나는 것&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;React는 컴포넌트를 마운팅할 때 순서대로 4가지 내장 메소드를 호출하게 된다. &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;render() 메소드는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #ff0000; text-align: start;&quot;&gt;항상 호출&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; 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: #212529; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;으로 호출&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;constructor()&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;getDerivedStateFromProps()&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;render()&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;componentDidMount()&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. constructor(props) : 컴포넌트를 새로 만들 때마다 먼저 호출되는 클래스 생성자 메소드&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;constructor() 메소드는 props 라고도 불리며, super(props) 를 가장 먼저 호출해야 한다. state 와 다른 초기 값들을 세팅한다. super(props) 는 부모의 constructor 메소드를 초기화하고, 부모로부터 상속받은 메소드들을 컴포넌트로 하여금 사용할 수 있도록 해준다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2. getDerivedStateFromProps&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;props&lt;span&gt;&amp;nbsp;&lt;/span&gt;에 있는 값을&lt;span&gt;&amp;nbsp;&lt;/span&gt;state&lt;span&gt;&amp;nbsp;&lt;/span&gt;에 넣을 때 사용하는 메소드&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;컴포넌트 마운트 또는 업데이트에서 render 메소드를 호출하기 전에 호출되며 시간의 흐름에 따라 변하는 props를 state에 동기화하기 위해 존재하는 메소드&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;DOM에서 요소들이 랜더링 되기 직전에 호출되며, 최초의 props 에 기반한 state 객체를 저장한다. state 를 인자로 받고, state 가 변하면 객체를 반환한다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;static과 함께 선언되어야 하며 메소드 내부에서는 this를 통한 인스턴스 접근이 불가하다. 또한, props를 이용하여 생성한 객체를 반환함으로써 props를 state에 동기화한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;❌ React에서 이 메소드를 권장하지 않음!&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;3. render : 필수값이며, DOM에 HTML을 표현함.&lt;br /&gt;jsx를 반환 (배열, null 등 다른 요소 반환 가능)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;컴포넌트 마운트 또는 업데이트에서 호출되며,&lt;span&gt;&amp;nbsp;&lt;/span&gt;shouldComponentUpdate()&lt;span&gt;&amp;nbsp;&lt;/span&gt;가 false를 반환하는 경우에 호출되지 않는다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;UI 렌더링을 위해 필요한 메소드로 React Element를 반환한다. 컴포넌트의 상태를 변경하지 않아야 하며, 호출될 때마다 동일한 결과를 반환해야 하고 브라우저와 직접적인 상호작용을 하지 않아야 한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;4. componentDidMount: 컴포넌트가 웹 브라우저상에 나타난 후 호출하는 메소드&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;라이브러리 또는 프레임워크 함수 호출, 이벤트 등록,&lt;span&gt;&amp;nbsp;&lt;/span&gt;setTimeout,&lt;span&gt;&amp;nbsp;&lt;/span&gt;setInterval, 네트워크 요청 등의 비동기 작업을 처리하기에 적절한 메소드.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;setState()를 호출하는 경우도 있지만, 추가 렌더링이 발생하여 성능 저하로 이루어질 수 있으므로 주의해야 함. (+ 무한루프)&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;componentWillUnmount() : &lt;b&gt;컴포넌트가 DOM을 제거하거나 DOM 상에서 완전히 제거(Unmount)될 때&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 컴포넌트가 언마운트되기 직전에 호출. 즉, 컴포넌트가 사라지기 전에 마지막으로 작업할 수 있는 메소드&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- componentDidMount()에서 설정한 모든 비동기 작업(이벤트, 타이머, 직접 생성한 DOM)에 대하여 정리를 해주어야 한다. 또한, 해당 컴포넌트는 리렌더링 되지 않으므로&lt;span&gt;&amp;nbsp;&lt;/span&gt;setState를 호출하면 안 됌&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;라이프-사이클-이벤트-실행-순서&quot;&gt;&lt;b&gt;라이프 사이클 이벤트 실행 순서&lt;/b&gt; : constructor()를 포함한 라이프 사이클 실행 순서
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;constructor()&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 엘리먼트를 생성하여 기본 state와 prop을 설정할 때 실행된다.&lt;/li&gt;
&lt;li&gt;componentWillMount()&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 컴포넌트를 DOM에 삽입하기 전 실행&lt;/li&gt;
&lt;li&gt;render()&lt;/li&gt;
&lt;li&gt;componentDidMount()&lt;span&gt;&amp;nbsp;&lt;/span&gt;: DOM에 삽입되어 렌더링이 완료된 후 실행&lt;/li&gt;
&lt;li&gt;componentWillReceiveProps(nextProps)&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 컴포넌트가 props를 받기 직전 실행&lt;/li&gt;
&lt;li&gt;shouldComponentUpdate(nextProps, nextState)&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 컴포넌트가 갱신되기 전 실행. 랜더링 유무 설정 가능&lt;/li&gt;
&lt;li&gt;componentWillUpdate(nextProps, nextState)&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 컴포넌트가 갱신되기 직전 실행&lt;/li&gt;
&lt;li&gt;render()&lt;/li&gt;
&lt;li&gt;componentDidUpdate(prevProps, prevState)&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 컴포넌트가 갱신된 후에 실행&lt;/li&gt;
&lt;li&gt;componentWillUnmount()&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 컴포넌트를 DOM에서 제거하기 전 실행&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;React는 엘리먼트를 먼저 렌더링(=&lt;span&gt;&amp;nbsp;&lt;/span&gt;render()함수 호출)하고 나서 DOM에 추가한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1713173057887&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from &quot;react&quot;;

class LifeCycle extends React.Component {
    constructor(props) {
        super(props)
    }

// 랜더링 전
    componentWillMount () {
//  this.setState() 사용 가능
    }

// 랜더링render() {
// this.setState() 사용 불가// 랜더링 과정 중에 상태에 대해서 수정은 불가하다// 비동기 작업이기 때문에 결과에 대해서 보장 받지 못한다.return(&amp;lt;&amp;gt;&amp;lt;/&amp;gt;)
    }


// 랜더링 후 업데이트가 필요한 경우 로직 작성
    componentDidMount () {
// this.setState() 사용 가능

    }

// 메모리 누수 방지 초기화
    componentWillUnmount () {
// this.setState()사용 불가// 해당 하는 객체가 더이상 필요 없어 삭제 되는 과정이기 때문
    }
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>React</category>
      <author>suudong</author>
      <guid isPermaLink="true">https://rlatnwjd.tistory.com/27</guid>
      <comments>https://rlatnwjd.tistory.com/27#entry27comment</comments>
      <pubDate>Mon, 15 Apr 2024 18:45:01 +0900</pubDate>
    </item>
  </channel>
</rss>