<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>개발일지</title>
    <link>https://maloveforme.tistory.com/</link>
    <description>게임 및 개발에 대한 일지</description>
    <language>ko</language>
    <pubDate>Mon, 20 Jul 2026 17:30:38 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>nowkoes</managingEditor>
    <item>
      <title>[코틀린] 코틀린 기초 - 변수, 자료형</title>
      <link>https://maloveforme.tistory.com/298</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Kotlin Basic - Variables, Baisc Types&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;개요&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　어떤 언어든, 변수와 기본 자료형은 중요하다. &lt;span style=&quot;color: #ee2323;&quot;&gt;프로그램은 결국 데이터를 받아서 처리하고 결과를 내는 과정&lt;/span&gt;이므로, 사용자와 상호작용하는 가장 기본 단위인 변수와 자료형이 중요한 것이다. &lt;span style=&quot;background-color: #9feec3;&quot;&gt;변수(Variable)&lt;/span&gt;는 &lt;span style=&quot;color: #006dd7;&quot;&gt;데이터를 저장하기 위한 &amp;lsquo;공간&amp;rsquo;&lt;/span&gt;이며, &lt;span style=&quot;background-color: #9feec3;&quot;&gt;자료형(Type)&lt;/span&gt;은 그 &lt;span style=&quot;color: #006dd7;&quot;&gt;공간에 어떤 종류의 데이터를 담을 수 있는지를 결정&lt;/span&gt;한다. 예를 들어 정수, 실수, 문자, 논리형 등 다양한 자료형이 존재하며, 각각의 자료형은 메모리 사용량과 연산 방식이 다르다. 따라서 변수와 자료형을 올바르게 이해하고 사용하는 것은 효율적인 메모리 관리와 정확한 연산 수행의 기초가 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;　&lt;span style=&quot;color: #000000;&quot;&gt;또한, 변수와 자료형 개념은 상위 수준의 개념인 클래스, 객체, 컬렉션, 함수형 프로그래밍을 이해하기 위한 기반이 된다. 즉, 프로그래밍 언어를 배우는 첫 단계에서 변수와 자료형을 학습하는 것은 단순히 데이터를 저장하는 법을 배우는 것을 넘어, 이후의 모든 논리적 사고와 프로그램 구조 설계의 출발점이 되는 것이다. &lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;본문&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;변수(Variable)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　 앞서 설명한 대로, 프로그램은 데이터를 입력받아 처리하고 결과를 출력한다. 이 과정에서 데이터를 잠시라도 저장하려면 공간이 필요하다. 하지만 컴퓨터의 공간은 수많은 주소로 이루어져 있고, 각 공간은 0x7FFD23A0과 같은 복잡한 숫자로 표현되기 때문에 사람이 직접 다루기 어렵다. 따라서 프로그래밍 언어는 이러한 메모리 주소에 사람이 이해하기 쉬운 이름을 붙일 수 있도록 해주는데, 이를 변수(variable)라고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　코틀린에서는 이러한 변수를 크게 두 종류로 구분한다. 첫 번째는 &lt;span style=&quot;color: #006dd7;&quot;&gt;한 번 값을 할당하면 변경할 수 없는 읽기 전용 변수&lt;/span&gt; &lt;span style=&quot;background-color: #9feec3;&quot;&gt;val&lt;/span&gt;이다. 코틀린에서는 기본적으로 변수를 val로 선언하는 것을 권장한다. 이는 불필요한 실수나 버그를 예방하기 위한 언어 철학이다. &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;반대로, &lt;span style=&quot;color: #006dd7;&quot;&gt;값을 자유롭게 바꿀 수 있는 변수&lt;/span&gt;는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;var&lt;/span&gt;로 선언한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　예를 들어, 게임 계정을 생각해 보자. ID는 한 번 정하면 바꾸지 않는 고유한 식별자고, 비밀번호는 사용자가 원할 때 변경할 수 있다. 이를 코틀린 문법으로 표현하면 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1760353462610&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val ID = &quot;malove&quot;
var PW = &quot;tistory&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　여기서 PW는 변경이 가능하지만, ID를 다시 할당하려고 하면 컴파일 오류가 발생한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1760353513583&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;PW = &quot;tistory1&quot;
ID = &quot;forme&quot; // Error: Val cannot be reassigned&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;자료형(Types)&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;　컴퓨터는 기본적으로 모든 데이터를 0과 1의 조합으로 저장한다. 이러한 이진수만으로는 그 값이 숫자인지, 문자인지, 참/거짓인지 구분할 수 없다. 예를 들어, 01000001이라는 숫자는 10진수 정수로 보면 65, ASCII 코드로 보면 'A'로, 둘 다 맞지만 어떻게 해석하냐에 따라 의미가 달라진다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　이러한 혼란을 막기 위해 프로그래밍 언어는 변수가 어떤 종류의 데이터를 저장하는지 명시하도록 강제한다. 이것이 바로 자료형이다. 즉, 자료형은 데이터의 성격과 사용 방법을 컴파일러에게 알려주는 규칙이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　코틀린에서는 기본 자료형을 크게 다섯 종류로 구분한다. 이를 표로 나타내면 다음과 같다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 106px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 21px;&quot;&gt;종류&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 21px;&quot;&gt;자료형&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 21px;&quot;&gt;예시&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;정수형&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;Byte, Short, Int, Long, &lt;br /&gt;UByte, UShort, UInt, ULong&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;val age: Int = 27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;실수형&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;Float, Double&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;val temp: Float = 36.5f&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;문자형&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;Char&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;val grade : Char = 'A'&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;문자열형&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;String&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;val name: String = &quot;Allice&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;논리형&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;Boolean&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;val isActive: Boolean = true&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;※ 정수형 자료형 앞에 U라는 접두사가 붙으면 Unsigned, 즉 부호가 없는 양수를 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　코틀린에서는 이러한 자료형을 자동으로 추론(&lt;span style=&quot;background-color: #9feec3;&quot;&gt;Type Interface&lt;/span&gt;)하는 것을 지원한다. 즉, 콜론을 이용해 자료형을 명시하지 않아도, &lt;span style=&quot;color: #006dd7;&quot;&gt;컴파일러가 대입된 값으로부터 자동으로 자료형을 추론&lt;/span&gt;한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　예를 들어, 다음 두 선언은 동일하게 동작한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1760354285277&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val my_age: Int = 27
val your_age = 27 // 컴파일러가 자동으로 Int로 추론&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;요약&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;변수&lt;br /&gt;&lt;/b&gt;1. 정의: 데이터를 저장하기 위한 이름이 있는 메모리 공간&lt;br /&gt;2. 종류&lt;br /&gt;　① val: 읽기 전용 변수&lt;br /&gt;　② var: 변경 가능 변수&lt;br /&gt;&lt;br /&gt;&lt;b&gt;자료형&lt;/b&gt;&lt;br /&gt;1. 정의: 변수에 어떤 종류의 데이터를 저장할 수 있는지를 정의하는 규칙&lt;br /&gt;2. 종류&lt;br /&gt;　① 정수형: Byte, Short, Int, Long, UByte, UShort, UInt, ULong&lt;br /&gt;　② 실수형: Float, Double&lt;br /&gt;　③ 문자형: Char&lt;br /&gt;　④ 문자열: String&lt;br /&gt;　⑤ 논리형: Boolean&lt;/blockquote&gt;</description>
      <category>Language/Kotlin</category>
      <category>Kotlin</category>
      <category>types</category>
      <category>VARIABLE</category>
      <category>변수</category>
      <category>자료형</category>
      <category>코틀린</category>
      <author>nowkoes</author>
      <guid isPermaLink="true">https://maloveforme.tistory.com/298</guid>
      <comments>https://maloveforme.tistory.com/298#entry298comment</comments>
      <pubDate>Mon, 13 Oct 2025 20:21:40 +0900</pubDate>
    </item>
    <item>
      <title>[코틀린] 코틀린 기초 - Hello World!</title>
      <link>https://maloveforme.tistory.com/297</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Kotlin Basic - Hello World!&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;개요&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;442&quot; data-origin-height=&quot;166&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEBok1/btsQGTDwoT1/SF4tDOJQt7oWfwEWkIMx9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEBok1/btsQGTDwoT1/SF4tDOJQt7oWfwEWkIMx9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEBok1/btsQGTDwoT1/SF4tDOJQt7oWfwEWkIMx9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEBok1%2FbtsQGTDwoT1%2FSF4tDOJQt7oWfwEWkIMx9K%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;442&quot; height=&quot;166&quot; data-origin-width=&quot;442&quot; data-origin-height=&quot;166&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　코틀린(Kotlin)은 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;JVM(Java Virtual Machine)&lt;/span&gt; 기반으로 동작하는 프로그래밍 언어로, Java와 유사하지만 더 간결한 문법과 다양한 기능을 제공한다. 구글이 2017년부터 안드로이드 공식 언어로 지정하면서 현재는 안드로이드 앱 개발에서 사실상 표준으로 자리 잡았다. 즉, &lt;span style=&quot;color: #ee2323;&quot;&gt;안드로이드 애플리케이션을 만들고자 한다면 반드시 학습해야 할 언어&lt;/span&gt; 중 하나라 할 수 있다(물론 Java로도 개발이 가능하다). 이번 글에서는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;기본적인 개발 환경을 구축하고, Hello World 문자열을 출력하는 시간&lt;/span&gt;을 가져보겠다.&amp;nbsp;&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;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;JVM&lt;/span&gt;: &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;소스 파일을 바이트코드로 변환해 운영체제와 CPU에 맞게 실행해 주는 가상 머신&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;본문&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;개발 환경&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;329&quot; data-origin-height=&quot;135&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIjFm7/btsQG2UILYh/KbscBRapoGlaOyraYUnpP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIjFm7/btsQG2UILYh/KbscBRapoGlaOyraYUnpP1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIjFm7/btsQG2UILYh/KbscBRapoGlaOyraYUnpP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIjFm7%2FbtsQG2UILYh%2FKbscBRapoGlaOyraYUnpP1%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;329&quot; height=&quot;135&quot; data-origin-width=&quot;329&quot; data-origin-height=&quot;135&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　개발 환경은 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://www.jetbrains.com/idea/download/?section=windows&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Intelij IDEA&lt;/a&gt;를 개발 도구(IDE)로 사용하고, &lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://kotlinlang.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Kotlin&lt;/a&gt; 2.2.20 버전을 기반으로 구축&lt;/span&gt;하였다. 해당 에디터는 코틀린을 개발한 JetBrains에서 제공하는 공식 IDE로, 코틀린 개발에 최적화된 다양한 기능(코드 자동 완성, 디버깅, 빌드 관리 등)을 제공한다.&amp;nbsp;&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;설치 주소는 하이퍼링크로 삽입해 두었으니, 개발 환경이 구축되지 않았으면 해당 사이트에 접속해 에디터와 코틀린을 설치하면 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Hello World&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;1. 스크립트 생성&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　 어떤 프로그래밍 언어를 배우든, 먼저 Hello World 문자열을 출력하는 것부터 시작한다. 이는 입문자가 언어의 기본 코드 구조를 이해하고, 개발 환경이 정상적으로 세팅되어 있는지 확인할 수 있는 초석이 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kzf4J/btsQGse5xe3/KxkIO6QQyOAOvA1IPUcuek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kzf4J/btsQGse5xe3/KxkIO6QQyOAOvA1IPUcuek/img.png&quot; data-origin-width=&quot;1636&quot; data-origin-height=&quot;1001&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.4448%; margin-right: 10px;&quot; data-widthpercent=&quot;50.03&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kzf4J/btsQGse5xe3/KxkIO6QQyOAOvA1IPUcuek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fkzf4J%2FbtsQGse5xe3%2FKxkIO6QQyOAOvA1IPUcuek%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;1636&quot; height=&quot;1001&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVZmm0/btsQGT4C9vs/v1JuGMuudBg5hNWFKUjKKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVZmm0/btsQGT4C9vs/v1JuGMuudBg5hNWFKUjKKK/img.png&quot; data-origin-width=&quot;1631&quot; data-origin-height=&quot;999&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;49.97&quot; style=&quot;width: 49.3924%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVZmm0/btsQGT4C9vs/v1JuGMuudBg5hNWFKUjKKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVZmm0%2FbtsQGT4C9vs%2Fv1JuGMuudBg5hNWFKUjKKK%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;1631&quot; height=&quot;999&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;[메인 메뉴 &amp;rarr; 파일&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&amp;rarr; 새로 만들기&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&amp;rarr; Kotlin Notebook / Kotlin 스크립트]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　우선 Intelij IDEA를 실행하고, 좌측 상단에 &lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;lt;파일&amp;gt;을 클릭해 &amp;lt;새로 만들기&amp;gt;를 누른 후 &amp;lt;Kotlin Notebook&amp;gt; 혹은 &amp;lt;Kotlin 스크립트&amp;gt;를 생성&lt;/span&gt;하자. 여기서 메뉴에 나와있는 만들 수 있는 요소들은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&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;/li&gt;
&lt;li&gt;&lt;b&gt;모듈&lt;/b&gt;: 프로젝트 안에서 독립적인 코드 단위. 큰 프로젝트에서 기능별로 나누거나, 공통 라이브러리를 관리할 때 사용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Kotlin 스크립트&lt;/b&gt;: Kotlin으로 작성된 스크립트 파일. 실험용 코드, 빠른 테스트, 작은 유틸리티를 작성할 때 사용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Kotlin Notebook&lt;/b&gt;: Jupyter Notebook처럼 셀 단위(코드를 여러 개의 작은 셀로 나누어 전체 코드를 실행하지 않고 부분만 실행할 수 있게 하는 단위)로 코드를 작성하고 실행할 수 있는 환경. 단계별 실행과 결과 확인이 필요할 경우 사용&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　우리는 여기서 스크립트나 노트북을 선택할 것이다. 둘 중 어느 것을 사용해도 크게 상관이 없으니, 본인이 원하는 방식을 고르면 된다. 학습용으로는 스크립트나 노트북 모두 가능하며, 본인의 선호에 따라 선택하면 된다. 필자는 학습 내용을 날짜별로 기록하고 정리하기 위해 Kotlin Notebook을 선택했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;2. 코드 작성&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;279&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLcShb/btsQI0nMh8W/ltuqclNrsXTx5VgArTiNS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLcShb/btsQI0nMh8W/ltuqclNrsXTx5VgArTiNS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLcShb/btsQI0nMh8W/ltuqclNrsXTx5VgArTiNS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLcShb%2FbtsQI0nMh8W%2FltuqclNrsXTx5VgArTiNS0%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;1600&quot; height=&quot;279&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;279&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;[Hello World! 코드 작성&lt;span style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　그후, 에디터 창에 다음과 같이 코드를 작성한다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1758459149257&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;fun main()
{
    println(&quot;Hello World!&quot;)
}

main()

// 실행 결과: Hello World!&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　위 코드는 코틀린 언어의 몇 가지 중요한 특징을 알 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;&lt;b&gt;fun&lt;/b&gt;: 함수를 선언할 때 사용하는 키워드. 코틀린에서는 모든 코드를 함수 안에서 실행함.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;main()&lt;/b&gt;: 프로그램의 시작점 역할을 하는 함수. 콘솔 프로그램은 main() 함수부터 실행됨.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;{ }&lt;/b&gt;: 함수의 본문을 정의하는 중괄호. 실행할 명령어들을 이 안에 작성함.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;세미콜론&lt;/b&gt;: 자바와 달리 코틀린에서는 문장 끝에 세미콜론을 사용하지 않음.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;요약&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;코틀린&lt;/b&gt;&lt;br /&gt;1. 정의: JVM 기반으로 동작하는 프로그래밍 언어&lt;br /&gt;2. 특징&lt;br /&gt;　① 안드로이드 애플리케이션을 만들기 위해 학습해야 하는 언어&lt;br /&gt;　② 간결한 문법 지향&lt;/blockquote&gt;</description>
      <category>Language/Kotlin</category>
      <category>Hello World</category>
      <category>Kotlin</category>
      <category>코틀린</category>
      <author>nowkoes</author>
      <guid isPermaLink="true">https://maloveforme.tistory.com/297</guid>
      <comments>https://maloveforme.tistory.com/297#entry297comment</comments>
      <pubDate>Sun, 21 Sep 2025 22:03:36 +0900</pubDate>
    </item>
    <item>
      <title>[임베디드] 신호와 주파수</title>
      <link>https://maloveforme.tistory.com/296</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&amp;lt;본 게시글은 &quot;&lt;a href=&quot;https://recipes.tistory.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;임베디드 레시피&lt;/a&gt;&quot; 책을 기반으로 작성하였습니다&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Signal and Frequency&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;개요&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;603&quot; data-origin-height=&quot;296&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c7cysU/btsJWgMfvVu/KTrWovXCkZAfZQi98g5k91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c7cysU/btsJWgMfvVu/KTrWovXCkZAfZQi98g5k91/img.png&quot; data-alt=&quot;시간 축의 펄스파(위)와 주파수 축의 펄스파(아래)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c7cysU/btsJWgMfvVu/KTrWovXCkZAfZQi98g5k91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc7cysU%2FbtsJWgMfvVu%2FKTrWovXCkZAfZQi98g5k91%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;603&quot; height=&quot;296&quot; data-origin-width=&quot;603&quot; data-origin-height=&quot;296&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;시간 축의 펄스파(위)와 주파수 축의 펄스파(아래)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　임베디드 시스템은 다양한 신호를 처리하며, 센서로부터 입력된 데이터를 분석하고 필터링하여 제어 명령을 생성하기도 한다. 단적으로 오실로스코프로 측정하는 그래프도 신호의 일종이고, 수학 시간에 그렸던 함수들의 그래프도 신호의 일종이다. 이러한 신호에 대한 이해를 하는 것은 공학적인 측면에서 중요하다고 할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　이때 주파수는 새로운 시선을 제공한다. 시간 영역에서 복잡하게 보이는 신호도 주파수 영역으로 변환하면 단순한 주파수 성분들의 조합으로 분석할 수 있다. 이를 통해 신호의 성분을 쉽게 이해하고, 불필요한 노이즈를 제거하거나 원하는 주파수 대역을 강조할 수도 있다. &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번 시간에는 이러한 기초 개념을 중점적으로 다루어 보겠다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;본문&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;b&gt;Signals&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;568&quot; data-origin-height=&quot;258&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xT2PZ/btsJYaDw6mG/CLF2wM83lpyup7QtF45gW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xT2PZ/btsJYaDw6mG/CLF2wM83lpyup7QtF45gW1/img.png&quot; data-alt=&quot;출처: 위키피디아&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xT2PZ/btsJYaDw6mG/CLF2wM83lpyup7QtF45gW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxT2PZ%2FbtsJYaDw6mG%2FCLF2wM83lpyup7QtF45gW1%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;568&quot; height=&quot;258&quot; data-origin-width=&quot;568&quot; data-origin-height=&quot;258&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: 위키피디아&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;　&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;신호(Signal)&lt;/b&gt;&lt;/span&gt;는 &lt;span style=&quot;color: #006dd7;&quot;&gt;시간에 따라 변하는 물리적인 양&lt;/span&gt;을 의미한다. 임베디스 시스템에서는 아날로그 신호와 디지털 신호가 주로 사용된다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;　&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;아날로그(Analog) 신호&lt;/b&gt;&lt;/span&gt;는 &lt;span style=&quot;color: #006dd7;&quot;&gt;AC(교류)와 DC(직류)로 이루어진 연속적인 값을 갖는 신호&lt;/span&gt;를 의미한다. 여기서 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;교류&lt;/b&gt;&lt;/span&gt;는 &lt;span style=&quot;color: #006dd7;&quot;&gt;극성이 바뀌는 신호&lt;/span&gt;를 의미하고, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;직류&lt;/b&gt;&lt;/span&gt;는 &lt;span style=&quot;color: #006dd7;&quot;&gt;극성이 바뀌지 않고 일정한 상태의 신호&lt;/span&gt;를 의미한다.&amp;nbsp;&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;즉, 교류는 전류나 전압이 시간이 지남에 따라 방향이 주기적으로 바뀌고, 직류는 전류나 전압이 일정한 방향으로만 흐르는 것을 의미&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&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;994&quot; data-origin-height=&quot;597&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5oBdq/btsJWAXZfJE/qyzpno7eQxxHbxIFAN8ub0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5oBdq/btsJWAXZfJE/qyzpno7eQxxHbxIFAN8ub0/img.png&quot; data-alt=&quot;이산적인 펄스파(위), 노이즈가 추가된 펄스파(아래)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5oBdq/btsJWAXZfJE/qyzpno7eQxxHbxIFAN8ub0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5oBdq%2FbtsJWAXZfJE%2Fqyzpno7eQxxHbxIFAN8ub0%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;994&quot; height=&quot;597&quot; data-origin-width=&quot;994&quot; data-origin-height=&quot;597&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이산적인 펄스파(위), 노이즈가 추가된 펄스파(아래)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;　&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;디지털(Digital) 신호&lt;/b&gt;&lt;/span&gt;는 &lt;span style=&quot;color: #006dd7;&quot;&gt;대부분 DC 성분으로 이루어진 0과 1의 이산적인 신호&lt;/span&gt;다. 이상적인 디지털 신호는 깨끗하게 0과 1로 구분되어 출력되는 것이 목표이지만, 실제 환경에서는 Bounce라고 불리는 노이즈가 끼어 신호가 불안정해질 수 있습니다. 이러한 노이즈로 인해 위의 그래프와 같이 신호가 이상적으로 표현되지 않고, 특정 구간에서 값이 불규칙하게 흔들리는 현상이 발생한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　만약 실제 통신 과정에서 이러한 노이즈가 발생한다면 임계값(Threshold)을 이용해 이를 기준으로 1과 0을 나누면 된다. 하지만 위의 그래프와 같이 노이즈가 심해 그 임계값을 넘어버리면 신호가 왜곡되어 원하는 출력과 결과가 달라지는 상황이 발생한다. 이를 해결하기 위해 우리는 주파수를 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 style=&quot;text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Frequency&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;736&quot; data-origin-height=&quot;305&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vZ2V6/btsJZezOtrj/euBrjzz8VxGBW7AJQqKVT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vZ2V6/btsJZezOtrj/euBrjzz8VxGBW7AJQqKVT0/img.png&quot; data-alt=&quot;출처: 삼성반도체이야기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vZ2V6/btsJZezOtrj/euBrjzz8VxGBW7AJQqKVT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvZ2V6%2FbtsJZezOtrj%2FeuBrjzz8VxGBW7AJQqKVT0%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;736&quot; height=&quot;305&quot; data-origin-width=&quot;736&quot; data-origin-height=&quot;305&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: 삼성반도체이야기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;주파수(Frequency)&lt;/b&gt;&lt;/span&gt;는 사전적으로 &lt;span style=&quot;color: #006dd7;&quot;&gt;진동운동에서 단위 시간당 같은 것이 일어난 횟수&lt;/span&gt;를 의미한다. 만약 3Hz의 주파수를 갖는다고 하면, 1초 동안 동일한 진동이 세 번 일어난다는 것을 의미하고, 주기는 주파수의 역수인 333ms가 된다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Fourier_transform_time_and_frequency_domains_(small).gif&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;240&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dhvZdE/btsJX5Kqljg/13LukkxZkB3RvSEkB0cHOK/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dhvZdE/btsJX5Kqljg/13LukkxZkB3RvSEkB0cHOK/img.gif&quot; data-alt=&quot;출처: 위키피디아&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dhvZdE/btsJX5Kqljg/13LukkxZkB3RvSEkB0cHOK/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/dhvZdE/btsJX5Kqljg/13LukkxZkB3RvSEkB0cHOK/img.gif&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;300&quot; height=&quot;240&quot; data-filename=&quot;Fourier_transform_time_and_frequency_domains_(small).gif&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;240&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: 위키피디아&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　이런 주파수는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;푸리에 트랜스폼(Fourier Transform)&lt;/b&gt;&lt;/span&gt;을 이용해 새로운 관점에서 문제를 해석할 때 중요한 역할을 한다. 해당 개념은 쉽게 생각해서 &lt;span style=&quot;color: #006dd7;&quot;&gt;모든 신호는 여러 개의 주기 함수의 합으로 나타낼 수 있으며, 이는 곧 시간 축에서의 신호를 주파수 별로 분리해 준다는&lt;/span&gt; 것이다.&amp;nbsp;&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;푸리에 트랜스폼에 대한 설명은 &lt;a href=&quot;https://maloveforme.tistory.com/251&quot; target=&quot;_blank&quot; rel=&quot;noopener&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1189&quot; data-origin-height=&quot;397&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9rt6U/btsJZLcS1WQ/KEcnTOuhVT9AleWd8K9FZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9rt6U/btsJZLcS1WQ/KEcnTOuhVT9AleWd8K9FZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9rt6U/btsJZLcS1WQ/KEcnTOuhVT9AleWd8K9FZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9rt6U%2FbtsJZLcS1WQ%2FKEcnTOuhVT9AleWd8K9FZ1%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;1189&quot; height=&quot;397&quot; data-origin-width=&quot;1189&quot; data-origin-height=&quot;397&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　해당 노이즈 신호를 예로 들어보자. 이를 시간 축에서 노이즈를 필터링하려니 쉽지 않아 보인다. 하지만 이를 주파수 축으로 바꿔(Fourier Transform을 적용) 보면 다음과 같이 나온다. 이해하기 쉽게 노이즈가 타지 않은 깨끗한 신호와 비교해서 표시했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;1186&quot; data-origin-height=&quot;396&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AsZSO/btsJ0boC4Z6/sMZUZH6QdOz2YFKjJIAboK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AsZSO/btsJ0boC4Z6/sMZUZH6QdOz2YFKjJIAboK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AsZSO/btsJ0boC4Z6/sMZUZH6QdOz2YFKjJIAboK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAsZSO%2FbtsJ0boC4Z6%2FsMZUZH6QdOz2YFKjJIAboK%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;1186&quot; height=&quot;396&quot; data-origin-width=&quot;1186&quot; data-origin-height=&quot;396&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　해당 그래프를 보면, 노이즈가 탄 신호가 원래 신호와 비교해서 고주파수 성분이 많은 것을 알 수 있다. 일반적으로 노이즈는 고주파수 성분이기 때문에, 해당 부분에 필터를 씌우고, 임계값을 기준으로 0과 1로 이진화하면 신호를 복원할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;1866&quot; data-origin-height=&quot;321&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IFt6J/btsJZRqyDPY/jgmKfkQju0jYWJWIg8Puik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IFt6J/btsJZRqyDPY/jgmKfkQju0jYWJWIg8Puik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IFt6J/btsJZRqyDPY/jgmKfkQju0jYWJWIg8Puik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIFt6J%2FbtsJZRqyDPY%2FjgmKfkQju0jYWJWIg8Puik%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;1866&quot; height=&quot;321&quot; data-origin-width=&quot;1866&quot; data-origin-height=&quot;321&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;　&lt;span style=&quot;color: #000000;&quot;&gt;사실 신호와 주파수는 굉장히 복잡하고 어려운 내용이다. 하지만 임베디드 시스템을 이해하는 관점에서는 위와 같이 간략한 개념정도만 파악하고 있으면 큰 어려움은 없을 것으로 예상한다. 혹시 위와 같은 그래프를 그려낸 과정이 궁금하면 아래 접은 글을 확인하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1728378685428&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import numpy as np
import matplotlib.pyplot as plt
from scipy.fft import fft, ifft

# 0과 1로 이루어진 펄스파 생성
t = np.linspace(0, 1, 500, endpoint=False)
pulse_wave = np.where((t &amp;gt;= 0.4) &amp;amp; (t &amp;lt; 0.6), 1, 0)

# 노이즈 추가
noise = np.random.normal(0, 0.2, pulse_wave.shape)
noisy_signal = pulse_wave + noise

# 푸리에 변환 (FFT)
fft_signal = fft(noisy_signal)
fft_pulse = fft(pulse_wave)

# 주파수 성분 필터링 (고주파 제거)
freqs = np.fft.fftfreq(len(t), d=t[1] - t[0])
fft_filtered = np.where(np.abs(freqs) &amp;lt; 50, fft_signal, 0)

# 역 푸리에 변환 (IFFT)
recovered_signal = ifft(fft_filtered)

# 복원된 신호를 0.5 기준으로 0과 1로 이진화
binary_signal = np.where(recovered_signal.real &amp;gt;= 0.5, 1, 0)

# 그래프 그리기
plt.figure(figsize=(12, 12))

plt.subplot(6, 1, 1)
plt.plot(t, pulse_wave)
plt.title(&quot;Original Pulse Wave&quot;)

plt.subplot(6, 1, 2)
plt.plot(t, noisy_signal)
plt.title(&quot;Noisy Signal&quot;)

plt.subplot(6, 1, 3)
plt.plot(freqs[:len(freqs)//2], np.abs(fft_pulse[:len(freqs)//2]))
plt.title(&quot;Original Pulse Wave Frequency Spectrum&quot;)

plt.subplot(6, 1, 4)
plt.plot(freqs[:len(freqs)//2], np.abs(fft_signal[:len(freqs)//2]))
plt.title(&quot;Noisy Signal Frequency Spectrum&quot;)

plt.subplot(6, 1, 5)
plt.plot(t, recovered_signal.real)
plt.title(&quot;Recovered Signal after Filtering&quot;)

plt.subplot(6, 1, 6)
plt.plot(t, binary_signal)
plt.title(&quot;Binary Signal (Thresholded at 0.5)&quot;)

plt.tight_layout()
plt.show()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;span style=&quot;color: #ee2323;&quot;&gt;요약&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;신호&lt;/b&gt;: 시간에 따라 변하는 물리적인 양&lt;br /&gt;&lt;b&gt;아날로그 신호&lt;/b&gt;: 연속적인 신호&lt;br /&gt;&lt;b&gt;디지털 신호&lt;/b&gt;: 0과 1로 이루어진 이산적인 신호&lt;br /&gt;&lt;b&gt;AC(교류)&lt;/b&gt;: 극성이 바뀌는 신호&lt;br /&gt;&lt;b&gt;DC(직류)&lt;/b&gt;: 극성이 바뀌지 않는 신호&lt;br /&gt;&lt;br /&gt;&lt;b&gt;주파수&lt;/b&gt;: 단위 시간당 같은 것이 일어난 횟수&lt;br /&gt;&lt;b&gt;주기&lt;/b&gt;: 한 번 진동하는 데 걸리는 시간 (주파수의 역수)&lt;br /&gt;&lt;b&gt;푸리에 변환&lt;/b&gt;: 시간 축의 정보를 주파수 축의 정보로 변환&lt;br /&gt;-&amp;gt; 모든 신호는 여러 개의 주기 함수의 합으로 나타낼 수 있음&lt;/blockquote&gt;</description>
      <category>CS/임베디드</category>
      <category>Embedded</category>
      <category>Fourier</category>
      <category>fourier transfrom</category>
      <category>Frequency</category>
      <category>signals</category>
      <category>신호</category>
      <category>임베디드</category>
      <category>주파수</category>
      <category>푸리에</category>
      <category>푸리에 변환</category>
      <author>nowkoes</author>
      <guid isPermaLink="true">https://maloveforme.tistory.com/296</guid>
      <comments>https://maloveforme.tistory.com/296#entry296comment</comments>
      <pubDate>Tue, 8 Oct 2024 18:22:06 +0900</pubDate>
    </item>
    <item>
      <title>[임베디드] 엔디안 방식의 이해(2) with CAN Message</title>
      <link>https://maloveforme.tistory.com/295</link>
      <description>&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;본문&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Big-endian&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;216&quot; data-origin-height=&quot;214&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lUa7b/btsJRrTUFsR/GKghDM4lb2TV4tKVe9Sep0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lUa7b/btsJRrTUFsR/GKghDM4lb2TV4tKVe9Sep0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lUa7b/btsJRrTUFsR/GKghDM4lb2TV4tKVe9Sep0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlUa7b%2FbtsJRrTUFsR%2FGKghDM4lb2TV4tKVe9Sep0%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;216&quot; height=&quot;214&quot; data-origin-width=&quot;216&quot; data-origin-height=&quot;214&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;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;빅 엔디안 방식&lt;/b&gt;&lt;/span&gt;은&lt;span&gt; &lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;큰 값을 먼저 저장하는 방식&lt;/span&gt;이다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예를 들어, 1234라는 숫자에서 1이 가장 중요한 숫자(MSB)가 되는 방식이다. 빅 엔디안에서는 이 작은 값이 메모리의 앞쪽에 저장되고, 작은 값(LSB)이 나중에 저장된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　이 방식은 사람이&lt;span style=&quot;color: #ee2323;&quot;&gt; 숫자를 읽는 방식과 동일하게 데이터를 저장&lt;/span&gt;하기 때문에, 디버깅이나 사람이 데이터를 직관적으로 이해하기에 매우 용이하다. 예를 들어, 32비트 정수 0x12345678을 빅 엔디안 방식으로 저장하면 메모리 상에 12 34 56 78 순서로 저장되며, 이는 우리가 숫자를 읽는 순서와 일치한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　빅 엔디안 방식은 &lt;span style=&quot;color: #ee2323;&quot;&gt;네트워크 프로토콜에서 표준&lt;/span&gt;적으로 사용되는데, 이를 &quot;네트워크 바이트 오더&quot;라고 부른다. 이 덕분에 네트워크 통신에서 일관성을 유지할 수 있으며, 다른 시스템 간의 데이터 교환 시 변환 과정 없이 바로 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　그러나 빅 엔디안 방식은 메모리에서 작은 단위로 데이터를 읽을 때 비효율적일 수 있다. 특히, x86과 같은 리틀 엔디안 아키텍처에서 빅 엔디안 데이터를 처리할 경우, 추가적인 변환 과정이 필요하므로 성능에 약간의 영향을 줄 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Big Endian Parsing (1) - 16진수 배열에 특정 비트 추출하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;612&quot; data-origin-height=&quot;57&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4MuYt/btsJQWmtj1O/beie8JHvSzTkDGzCT8YKV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4MuYt/btsJQWmtj1O/beie8JHvSzTkDGzCT8YKV1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4MuYt/btsJQWmtj1O/beie8JHvSzTkDGzCT8YKV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4MuYt%2FbtsJQWmtj1O%2Fbeie8JHvSzTkDGzCT8YKV1%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;612&quot; height=&quot;57&quot; data-origin-width=&quot;612&quot; data-origin-height=&quot;57&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　예를 들어, 다음과 같은 CAN Message가 Big Endian 방식으로 수신되었다고 가정해 보자. 이때 offset은 0이고 factor는 1이라고 가정한다. 여기서 5번 비트부터 12번 비트까지의 값은 얼마일까?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;601&quot; data-origin-height=&quot;82&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brGvyQ/btsJQ4Lqhs6/0AKPWRQ1DWaOZp176gNCWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brGvyQ/btsJQ4Lqhs6/0AKPWRQ1DWaOZp176gNCWK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brGvyQ/btsJQ4Lqhs6/0AKPWRQ1DWaOZp176gNCWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrGvyQ%2FbtsJQ4Lqhs6%2F0AKPWRQ1DWaOZp176gNCWK%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;601&quot; height=&quot;82&quot; data-origin-width=&quot;601&quot; data-origin-height=&quot;82&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　빅 엔디안은 큰 값이 먼저 저장되기 때문에 메모리엔 다음과 같이 저장될 것이다. 이때 특정 비트들의 값을 추출하는 것을 목적으로 하고 있으므로, 16진수를 2진수로 변환해 준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;607&quot; data-origin-height=&quot;104&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxv7du/btsJRdauRWE/lbNiyg8kkBzZosqczxcklK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxv7du/btsJRdauRWE/lbNiyg8kkBzZosqczxcklK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxv7du/btsJRdauRWE/lbNiyg8kkBzZosqczxcklK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbxv7du%2FbtsJRdauRWE%2FlbNiyg8kkBzZosqczxcklK%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;607&quot; height=&quot;104&quot; data-origin-width=&quot;607&quot; data-origin-height=&quot;104&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　여기서 5번 비트부터 12번 비트까지 값을 추출하면 다음과 같다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;610&quot; data-origin-height=&quot;117&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zcXMo/btsJRyrU78A/712bjiKurMkekWWwcSDzj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zcXMo/btsJRyrU78A/712bjiKurMkekWWwcSDzj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zcXMo/btsJRyrU78A/712bjiKurMkekWWwcSDzj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzcXMo%2FbtsJRyrU78A%2F712bjiKurMkekWWwcSDzj1%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;610&quot; height=&quot;117&quot; data-origin-width=&quot;610&quot; data-origin-height=&quot;117&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　즉, 0000 0001(2) = 1(10)이다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Big Endian Parsing (2) - 16진수 배열에 특정 비트 삽입하기&lt;/b&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;601&quot; data-origin-height=&quot;78&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ouvHF/btsJSoBYAFK/UYUKuCPm6KjMg1hpdhI701/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ouvHF/btsJSoBYAFK/UYUKuCPm6KjMg1hpdhI701/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ouvHF/btsJSoBYAFK/UYUKuCPm6KjMg1hpdhI701/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FouvHF%2FbtsJSoBYAFK%2FUYUKuCPm6KjMg1hpdhI701%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;601&quot; height=&quot;78&quot; data-origin-width=&quot;601&quot; data-origin-height=&quot;78&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번에는 빈 문자열 배열에 5번 비트부터 12번 비트까지 90이라는 10진수 값을 넣어 보자. Big Endian Parsing(1)과 마찬가지로 offset은 0이고 factor는 1이라고 가정한다. 그리고 각 문자열에 괄호로 된 숫자는 문자열 배열의 인덱스를 의미한다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　빅 엔디안 방식이므로 순서를 바꿔줄 필요가 없다. 특정 비트에 값을 넣기 위해 2진수로 변환해 주자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;603&quot; data-origin-height=&quot;103&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KIcz3/btsJQU3jUTm/8ypznEqLKvjSwXIzUPiDCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KIcz3/btsJQU3jUTm/8ypznEqLKvjSwXIzUPiDCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KIcz3/btsJQU3jUTm/8ypznEqLKvjSwXIzUPiDCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKIcz3%2FbtsJQU3jUTm%2F8ypznEqLKvjSwXIzUPiDCk%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;603&quot; height=&quot;103&quot; data-origin-width=&quot;603&quot; data-origin-height=&quot;103&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　그리고 아래와 같이 5번 비트부터 12번 비트까지 90을 2진수로 변환한 값인 0101 1010(2)을 차례대로 넣고 16진수로 변환해 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;614&quot; data-origin-height=&quot;130&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bw7Kbm/btsJQD1VqfR/K04FlTSgCrP1M3SL7BXkP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bw7Kbm/btsJQD1VqfR/K04FlTSgCrP1M3SL7BXkP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bw7Kbm/btsJQD1VqfR/K04FlTSgCrP1M3SL7BXkP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbw7Kbm%2FbtsJQD1VqfR%2FK04FlTSgCrP1M3SL7BXkP0%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;614&quot; height=&quot;130&quot; data-origin-width=&quot;614&quot; data-origin-height=&quot;130&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　여기서 바이트 순서를 반대로 적용하면 최종적으로 메시지는 다음과 같이 0x02, 0xD0, 0x00, 0x00으로 구성된다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;코드 구현&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　해당 내용을 Python 코드로 작성하면 다음과 같다. 파이썬의 문법을 크게 쓰지 않고 비트 연산이 주를 이루고 있기 때문에, 로직을 잘 파악하고 있다면 C언어로 변환하는 것도 크게 어렵지 않을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727684137960&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def update_data_big_endian(data, value, start_bit, bit_length, factor):
    value = int(value / factor)
    data = bytearray(data)

    for i in range(bit_length):
        bit_value = (value &amp;gt;&amp;gt; (bit_length - 1 - i)) &amp;amp; 1
        byte_index = (start_bit + i) // 8
        bit_index = 7 - ((start_bit + i) % 8) 

        if bit_value:
            data[byte_index] |= (1 &amp;lt;&amp;lt; bit_index)
        else:
            data[byte_index] &amp;amp;= ~(1 &amp;lt;&amp;lt; bit_index)

    return data

message = [0x00, 0x00, 0x00, 0x00]  
start_bit = 5
bit_length = 8  
value = 90  # 0101 1010

updated_message = update_data_big_endian(message, value, start_bit, bit_length, 1)

print([hex(x) for x in updated_message])&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;216&quot; data-origin-height=&quot;20&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKD3il/btsJQ2GZmzn/cFvoclzUUpvOF6lSFe6UgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKD3il/btsJQ2GZmzn/cFvoclzUUpvOF6lSFe6UgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKD3il/btsJQ2GZmzn/cFvoclzUUpvOF6lSFe6UgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKD3il%2FbtsJQ2GZmzn%2FcFvoclzUUpvOF6lSFe6UgK%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;216&quot; height=&quot;20&quot; data-origin-width=&quot;216&quot; data-origin-height=&quot;20&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1727684203821&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def get_value_from_hex_big_endian(data, start_bit, bit_length, factor=1):
    full_value = 0
    for i in range(len(data)):
        full_value |= data[i] &amp;lt;&amp;lt; ((len(data) - 1 - i) * 8)

    mask = (1 &amp;lt;&amp;lt; bit_length) - 1
    extracted_value = (full_value &amp;gt;&amp;gt; (len(data) * 8 - start_bit - bit_length)) &amp;amp; mask
  
    return extracted_value * factor

if __name__ == &quot;__main__&quot;:
    message = [0x40, 0x0B, 0x00, 0x01]  
    start_bit = 5
    bit_length = 8
    factor = 1

    extracted_value = get_value_from_hex_big_endian(message, start_bit, bit_length, factor)

    print(f&quot;Extracted Value: {extracted_value}&quot;)  
    print(f&quot;Extracted Value (binary): {bin(extracted_value)}&quot;)&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;227&quot; data-origin-height=&quot;37&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qAKKy/btsJRfe7h1g/nma8aAgNHN1a8A2iQuG14k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qAKKy/btsJRfe7h1g/nma8aAgNHN1a8A2iQuG14k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qAKKy/btsJRfe7h1g/nma8aAgNHN1a8A2iQuG14k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqAKKy%2FbtsJRfe7h1g%2Fnma8aAgNHN1a8A2iQuG14k%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;227&quot; height=&quot;37&quot; data-origin-width=&quot;227&quot; data-origin-height=&quot;37&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;</description>
      <category>CS/임베디드</category>
      <category>Big Endian</category>
      <category>endianness</category>
      <category>빅엔디안</category>
      <category>엔디안</category>
      <author>nowkoes</author>
      <guid isPermaLink="true">https://maloveforme.tistory.com/295</guid>
      <comments>https://maloveforme.tistory.com/295#entry295comment</comments>
      <pubDate>Mon, 30 Sep 2024 17:17:23 +0900</pubDate>
    </item>
    <item>
      <title>[파이썬] 에러 로깅 클래스</title>
      <link>https://maloveforme.tistory.com/294</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Error Logging&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;개요&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;942&quot; data-origin-height=&quot;555&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bt93rK/btsJNFdmxia/uByzzxbKPjOedMT3icONVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bt93rK/btsJNFdmxia/uByzzxbKPjOedMT3icONVk/img.png&quot; data-alt=&quot;출처: https://docs.python.org/3/library/logging.html&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bt93rK/btsJNFdmxia/uByzzxbKPjOedMT3icONVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbt93rK%2FbtsJNFdmxia%2FuByzzxbKPjOedMT3icONVk%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;942&quot; height=&quot;555&quot; data-origin-width=&quot;942&quot; data-origin-height=&quot;555&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://docs.python.org/3/library/logging.html&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　 파이썬으로 프로그램을 개발하여 exe 파일로 빌드한 후 테스트할 때, 종종 콘솔창을 제외한 형태로 실행 파일을 만들곤 한다. 하지만 이 경우 오류가 발생하더라도 콘솔창이 없어 문제를 파악하기가 어렵다. 이러한 실행 파일의 런타임 환경 등에서 &lt;span style=&quot;color: #006dd7;&quot;&gt;발생하는 오류를 기록하기 위해 사용하는 모듈&lt;/span&gt;이 바로&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt; logging&lt;/b&gt;&lt;/span&gt;이다. 이번 시간에는 이 logging 모듈을 활용해, 프로그램 실행 중 에러가 발생하면 같은 디렉터리에 에러 내용을 담은 텍스트 파일을 자동으로 생성하는 클래스를 구현해 보겠다. &lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;본문&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　로깅 모듈을 통해 에러를 검출하고 처리하기 위한 최소한의 구성 요소는 다음과 같다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. &lt;b&gt;로그 레벨&lt;/b&gt;: 로깅 모듈에서는 로그를 다음과 같은 레벨로 나눈다. 로그를 남길 메시지의 특성에 따라 아래의 다섯 가지 레벨 중 하나를 선택하면 된다.&amp;nbsp;&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;DEBUG: 디버깅 메시지. 세부적인 정보를 남기고 싶을 때 주로 사용&lt;/li&gt;
&lt;li&gt;INFO: 일반적인 정보 메시지&lt;/li&gt;
&lt;li&gt;WARNING: 경고 수준의 메시지. 프로그램이 정상적으로 동작하지만 주의가 필요한 상황을 알림&lt;/li&gt;
&lt;li&gt;ERROR: 오류가 발생했을 때의 메시지. 문제로 인해 프로그램의 일부 기능이 제대로 동작하지 않을 때 사용&lt;/li&gt;
&lt;li&gt;CRITICAL: 치명적인 오류 메시지. 프로그램이 더 이상 실행될 수 없는 상황&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. &lt;b&gt;로그 설정&lt;/b&gt;: 오류를 기록하려면 먼저 로그 파일을 설정해야 한다. 가장 기본적인 구성은 logging.basicConfig() 함수를 사용하여 파일에 로그를 저장하는 방식이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727393829174&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;logging.basicConfig(
    filename='error_log.txt',  # 로그 파일명
    level=logging.ERROR,       # ERROR 이상의 로그만 기록
    format='%(asctime)s %(levelname)s: %(message)s'  # 로그 형식
)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. &lt;b&gt;예외 처리&lt;/b&gt;: 프로그램에서 예외가 발생했을 때의 동작을 정의하는 부분이다. 예를 들어, 예외 상황이 발생했을 경우 경고창을 띄우고 앞서 설정한 로그 파일에 내용을 덮어 씌우는 형태로 쓸 수 있다. 이때 예외가 발생한 위치나 더 상세한 트레이스백(Traceback) 정보가 필요하면 exc_info 옵션을 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727394180903&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def log_exception(exc_type, exc_value, exc_traceback):
    if issubclass(exc_type, KeyboardInterrupt):
        sys.__excepthook__(exc_type, exc_value, exc_traceback)
        return

    logging.error(
        &quot;An unhandled exception occurred&quot;,
        exc_info=(exc_type, exc_value, exc_traceback)
    )

    tkinter.messagebox.showerror(
        &quot;Error&quot;,
        &quot;An unexpected error occurred. Please check error_log.txt.&quot;
    )
    sys.exit(1)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. &lt;b&gt;hook 설정&lt;/b&gt;: hook는 &lt;span style=&quot;color: #006dd7;&quot;&gt;프로그래밍에서 특정 이벤트가 발생할 때 실행되도록 미리 정의된 함수나 동작&lt;/span&gt;을 의미한다. 즉, 기본적으로 프로그램의 흐름에 개입할 수 있도록 설계된 지점이다. 파이썬에서는 프로그램 전역에서 발생하는 미처리된 예외를 처리하는 hook로 sys.excepthook를 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727394013052&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sys.excepthook = ErrorLogging.log_exception # hook 지정&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;　필자의 경우엔 해당 내용들을 담아 클래스로 만들어 개발 중인 프로그램에 임포트하여 사용하고 있다. 이때 굳이 객체로 만들 필요는 없으므로 정적 클래스처럼 동작하게 메서드들을 static 키워드로 선언하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1727394336185&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import logging
import tkinter
import sys
import tkinter.messagebox

class ErrorLogging:
    @staticmethod
    def setup_logging(log_filename='error_log.txt'):
        logging.basicConfig(
            filename=log_filename,
            level=logging.ERROR,
            format='%(asctime)s %(levelname)s: %(message)s'
        )
    
    @staticmethod
    def log_exception(exc_type, exc_value, exc_traceback):
        if issubclass(exc_type, KeyboardInterrupt):
            sys.__excepthook__(exc_type, exc_value, exc_traceback)
            return

        logging.error(
            &quot;An unhandled exception occurred&quot;,
            exc_info=(exc_type, exc_value, exc_traceback)
        )

        tkinter.messagebox.showerror(
            &quot;Error&quot;,
            &quot;An unexpected error occurred. Please check error_log.txt.&quot;
        )
        sys.exit(1)

    @staticmethod
    def setup_exception_hook():
        sys.excepthook = ErrorLogging.log_exception&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　해당 클래스를 이용해 예외 적인 상황을 만들어 보면 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727394380405&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import logging
import tkinter
import sys
import tkinter.messagebox

class ErrorLogging:
    @staticmethod
    def setup_logging(log_filename='error_log.txt'):
        logging.basicConfig(
            filename=log_filename,
            level=logging.ERROR,
            format='%(asctime)s %(levelname)s: %(message)s'
        )
    
    @staticmethod
    def log_exception(exc_type, exc_value, exc_traceback):
        if issubclass(exc_type, KeyboardInterrupt):
            sys.__excepthook__(exc_type, exc_value, exc_traceback)
            return

        logging.error(
            &quot;An unhandled exception occurred&quot;,
            exc_info=(exc_type, exc_value, exc_traceback)
        )

        tkinter.messagebox.showerror(
            &quot;Error&quot;,
            &quot;An unexpected error occurred. Please check error_log.txt.&quot;
        )
        sys.exit(1)

    @staticmethod
    def setup_exception_hook():
        sys.excepthook = ErrorLogging.log_exception

if __name__ == &quot;__main__&quot;:
    ErrorLogging.setup_logging()
    ErrorLogging.setup_exception_hook()

    print(asdfknxvxcv)&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;621&quot; data-origin-height=&quot;144&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBRu8A/btsJNBP2g0N/6OGgWSHf2gvtHxX49cDaf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBRu8A/btsJNBP2g0N/6OGgWSHf2gvtHxX49cDaf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBRu8A/btsJNBP2g0N/6OGgWSHf2gvtHxX49cDaf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBRu8A%2FbtsJNBP2g0N%2F6OGgWSHf2gvtHxX49cDaf1%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;621&quot; height=&quot;144&quot; data-origin-width=&quot;621&quot; data-origin-height=&quot;144&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;요약&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;logging&lt;/b&gt;&lt;br /&gt;1. 정의: 로그를 기록하는 데 사용되는 모듈&lt;br /&gt;2. 옵션&lt;br /&gt;　a. 로그 레벨: 오류를 기록하는 레벨&lt;br /&gt;　b. 로그 설정: logging.basicConfig()로 로그 파일 이름, 로그 레벨, 형식을 설정&lt;br /&gt;　c. 예외 처리: try-except 구문에서 발생하는 예외를 logging.error(), 사용자 정의 함수 등으로 기록&lt;br /&gt;　d. sys.excepthook: 프로그램 전역에서 발생하는 미처리 예외를 자동으로 기록하도록 설정&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Language/Python</category>
      <category>error</category>
      <category>Log</category>
      <category>logging</category>
      <category>Python</category>
      <category>로그</category>
      <category>로깅</category>
      <category>예외 처리</category>
      <category>예외처리</category>
      <category>파이썬</category>
      <author>nowkoes</author>
      <guid isPermaLink="true">https://maloveforme.tistory.com/294</guid>
      <comments>https://maloveforme.tistory.com/294#entry294comment</comments>
      <pubDate>Sat, 28 Sep 2024 00:00:28 +0900</pubDate>
    </item>
    <item>
      <title>[파이썬] GUI(tkinter) 멀티스레딩 with CAN Message</title>
      <link>https://maloveforme.tistory.com/293</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;GUI Multithreading&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;개요&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;528&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NSXEX/btsJNMpu73t/UnsurAjF5K93Tre65kmVpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NSXEX/btsJNMpu73t/UnsurAjF5K93Tre65kmVpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NSXEX/btsJNMpu73t/UnsurAjF5K93Tre65kmVpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNSXEX%2FbtsJNMpu73t%2FUnsurAjF5K93Tre65kmVpK%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;1198&quot; height=&quot;528&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;528&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　지난 파이썬 tkinter를 다루는 &lt;a href=&quot;https://maloveforme.tistory.com/291&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;게시글&lt;/a&gt;엔 화면의 배율에 따라 위젯들의 크기가 동적으로 변하는 것에 대해 학습하였다. 이번 시간에는 특정 이벤트가 발생할 때마다 해당 내역을 업데이트 방법에 대한 내용을 다뤄보도록 하겠다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;본문&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;개념&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;　 &lt;span style=&quot;color: #000000;&quot;&gt;본격적인 내용에 들어가기에 앞서, 동기/비동기, 동시성/병렬성, 그리고 멀티쓰레딩/멀티프로세싱의 개념을 알고 있으면 이해가 훨씬 수월하다. 필자는 이 개념들을 &lt;a href=&quot;https://techblog-history-younghunjo1.tistory.com/570&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;해당 블로그&lt;/a&gt;를 통해 참고했으며, 만약 아직 해당 개념에 대한 이해가 부족하다면, 블로그 등을 통해 먼저 확인하는 것을 추천한다. 다만, 이 개념들이 다소 복잡하고 어려울 수 있지만, 실무에서 이를 구현하는 데 있어 반드시 완벽한 이해가 필요하지는 않다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;813&quot; data-origin-height=&quot;292&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdiCSC/btsJNeNEAUk/UjuONpxNDukV5Kp9tn5l31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdiCSC/btsJNeNEAUk/UjuONpxNDukV5Kp9tn5l31/img.png&quot; data-alt=&quot;출처: https://www.geeksforgeeks.org/python-after-method-in-tkinter/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdiCSC/btsJNeNEAUk/UjuONpxNDukV5Kp9tn5l31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdiCSC%2FbtsJNeNEAUk%2FUjuONpxNDukV5Kp9tn5l31%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;813&quot; height=&quot;292&quot; data-origin-width=&quot;813&quot; data-origin-height=&quot;292&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://www.geeksforgeeks.org/python-after-method-in-tkinter/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　오늘의 목표는 'CAN Message가 수신될 때마다, 메시지와 매핑된 라벨의 text를 업데이트'하는 것이다. 일반적으로 tkinter에서&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;after()라는&lt;/b&gt;&lt;/span&gt; 함수를 이용하여 동시성을 제공한다. 즉, Tkinter의 이벤트 루프를 사용하여, &lt;span style=&quot;color: #006dd7;&quot;&gt;지정된 시간 이후에 함수 호출을 예약&lt;/span&gt;하는 메커니즘이다. 만약 정해진 시간마다 데이터가 수신된다면 해당 함수를 이용해도 되지만, CAN에서 수신되는 메시지는 '이벤트가 발생할 때마다' 수신되기 때문에 이를 이용하면 수신에 지연이 생긴다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;946&quot; data-origin-height=&quot;504&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FpGs2/btsJMDG32U0/k7AKhI81fWiHRP67UA20c0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FpGs2/btsJMDG32U0/k7AKhI81fWiHRP67UA20c0/img.png&quot; data-alt=&quot;https://docs.python.org/3/library/threading.html&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FpGs2/btsJMDG32U0/k7AKhI81fWiHRP67UA20c0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFpGs2%2FbtsJMDG32U0%2Fk7AKhI81fWiHRP67UA20c0%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;946&quot; height=&quot;504&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;504&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://docs.python.org/3/library/threading.html&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 　 따라서 threading 모듈을 사용하여 수신 작업을 별도의 스레드에서 처리해야 한다. 기존의 after() 함수는 호출 시간을 명시적으로 지정해야 하는 단점이 있었지만, threading을 사용하면 이벤트가 발생할 때마다 CAN 메시지를 실시간으로 수신할 수 있다. 이를 통해 메시지 수신 후 즉시 해당 메시지에 맞는 라벨의 텍스트를 업데이트하도록 구현하는 것을 목표로 했다. &lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구현&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1727338123511&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class CanBus:
    def __init__(self):
        self.init_class_variable()
        self.init()

    def init_class_variable(self):
        self.bus = None
        self.id, self.signal = None, None
    
    def init(self):
        self.bus = can.interface.Bus(interface='slcan', channel=Common.find_serial_port(), bitrate=500000)

    def shutdown(self):
        if self.bus:
            self.bus.shutdown()
            self.bus = None

    def receive(self):
        message = self.bus.recv(timeout=0.1)
        if message:
            self.id = message.arbitration_id
            self.signal = message.data&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;　CAN bus를 slcan protocol로 연결해 주는 CanBus 클래스다. 메시지를 수신받으면 id와 signal로 분리시켜 놓았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1727338170506&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class MainUI:
    def __init__(self):
        self.init_class_variable()
        self.init_root_configure()
        self.init_main_ui()
        self.init_main_frame()
        self.init_main_label()

    def init_class_variable(self):
        self.root = tk.Tk()
        self.ratio = common.Common.get_display_ratio()
        self.width, self.height = int(1200/self.ratio), int(500/self.ratio)
        self.frames = {}
        self.labels = []

    def init_root_configure(self):
        self.root.grid_columnconfigure(0, weight=1)
        self.root.grid_columnconfigure(1, weight=1)
        self.root.grid_rowconfigure(0, weight=1)

    def init_main_ui(self):
        self.root.title(&quot;example for multithreading and tkinter&quot;)
        self.root.geometry(f&quot;{self.width}x{self.height}&quot;)
        self.root.resizable(False, False)

    def init_main_frame(self):
        for i in range(2):
            frame = tk.Frame(self.root, bg='lightblue')
            frame.grid(row=0, column=i, sticky=&quot;nsew&quot;)
            self.frames[f&quot;frame{i}&quot;] = frame  

    def init_main_label(self):
        for i in range(2):
            for j in range(4):
                label = tk.Label(
                    self.frames[f'frame{i}'], text=f&quot;{j}번 째 라벨&quot;, font=(&quot;Helvetica&quot;, int(12/self.ratio)), width=50, height=2, anchor=&quot;w&quot;, padx=10, pady=5)
                label.grid(row=j, column=0)
                self.labels.append(label)

    def run(self):
        self.root.mainloop()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　UI를 구현한 MainUI 클래스다. 저번 시간에 배웠던 배율에 맞게 반응형 GUI를 구현하였고, 라벨을 8개 배치해 두었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1727335952654&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Updater:
    def __init__(self, ui: MainUI, bus : CanBus):
        self.init_class_variable(ui, bus)
        self.ui.root.protocol(&quot;WM_DELETE_WINDOW&quot;, self.stop)

    def init_class_variable(self, ui, bus):
        self.ui = ui
        self.can = bus
        self.running = True
        self.stop_threading = threading.Event()
        self.messages = {}
        self.update_labels = {}
        self.cnt = 0

    def update_label(self, key):
        if self.cnt &amp;lt; len(self.ui.labels):
            if key not in self.update_labels:
                self.update_labels[key] = self.ui.labels[self.cnt]
                self.cnt += 1

    def receive_thread(self):
        while self.running and not self.stop_threading.is_set():
            try:
                self.can.receive()
                id = self.can.id
                signal = self.can.signal

                if id and signal:
                    self.update_label(id)
                    if id in self.update_labels:
                        self.update_labels[id].config(
                            text=f&quot;Signal: &quot; + &quot; &quot;.join(f&quot;{byte:02x}&quot; for byte in signal)
                        )

            except Exception as e:
                print(f&quot;Error receiving CAN message: {e}&quot;)
                break

    def run(self):
        self.thread = threading.Thread(target=self.receive_thread)
        self.thread.start()
        self.ui.run()

    def stop(self):
        self.running = False
        self.stop_threading.set()  
        self.can.shutdown()  
        if self.thread.is_alive():
            self.thread.join()
        self.ui.root.destroy() 

if __name__ == &quot;__main__&quot;:
    bus = CanBus()
    ui = MainUI()
    main = Updater(ui, bus)
    main.run()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　UI를 업데이트시켜 주는 Updater 클래스다. 여기서 핵심적으로 봐야 할 부분은 receive_thread다. 대기 시간을 따로 설정하지 않고, 메시지가 수신될 때마다 update_label 함수를 호출하여 동일한 id를 가진 라벨이 있는지 확인한 후, 해당 라벨의 text config를 바꿔주는 식으로 구현하였다. 이때 멀티 스레드는 안전하게 종료하는 부분이 중요하므로, 스레드 종료 시 스레드에 할당된 이벤트를 종료하게 구현하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;총합본&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1727338925429&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import common
import tkinter as tk
import can
from common import Common
import threading

class CanBus:
    def __init__(self):
        self.init_class_variable()
        self.init()

    def init_class_variable(self):
        self.bus = None
        self.id, self.signal = None, None
    
    def init(self):
        self.bus = can.interface.Bus(interface='slcan', channel=Common.find_serial_port(), bitrate=500000)

    def shutdown(self):
        if self.bus:
            self.bus.shutdown()
            self.bus = None

    def receive(self):
        message = self.bus.recv(timeout=0.1)
        if message:
            self.id = message.arbitration_id
            self.signal = message.data

class MainUI:
    def __init__(self):
        self.init_class_variable()
        self.init_root_configure()
        self.init_main_ui()
        self.init_main_frame()
        self.init_main_label()

    def init_class_variable(self):
        self.root = tk.Tk()
        self.ratio = common.Common.get_display_ratio()
        self.width, self.height = int(1200/self.ratio), int(500/self.ratio)
        self.frames = {}
        self.labels = []

    def init_root_configure(self):
        self.root.grid_columnconfigure(0, weight=1)
        self.root.grid_columnconfigure(1, weight=1)
        self.root.grid_rowconfigure(0, weight=1)

    def init_main_ui(self):
        self.root.title(&quot;example for multithreading and tkinter&quot;)
        self.root.geometry(f&quot;{self.width}x{self.height}&quot;)
        self.root.resizable(False, False)

    def init_main_frame(self):
        for i in range(2):
            frame = tk.Frame(self.root, bg='lightblue')
            frame.grid(row=0, column=i, sticky=&quot;nsew&quot;)
            self.frames[f&quot;frame{i}&quot;] = frame  

    def init_main_label(self):
        for i in range(2):
            for j in range(4):
                label = tk.Label(
                    self.frames[f'frame{i}'], text=f&quot;{j}번 째 라벨&quot;, font=(&quot;Helvetica&quot;, int(12/self.ratio)), width=50, height=2, anchor=&quot;w&quot;, padx=10, pady=5)
                label.grid(row=j, column=0)
                self.labels.append(label)

    def run(self):
        self.root.mainloop()

class Updater:
    def __init__(self, ui: MainUI, bus : CanBus):
        self.init_class_variable(ui, bus)
        self.ui.root.protocol(&quot;WM_DELETE_WINDOW&quot;, self.stop)

    def init_class_variable(self, ui, bus):
        self.ui = ui
        self.can = bus
        self.running = True
        self.stop_threading = threading.Event()
        self.messages = {}
        self.update_labels = {}
        self.cnt = 0

    def update_label(self, key):
        if self.cnt &amp;lt; len(self.ui.labels):
            if key not in self.update_labels:
                self.update_labels[key] = self.ui.labels[self.cnt]
                self.cnt += 1

    def receive_thread(self):
        while self.running and not self.stop_threading.is_set():
            try:
                self.can.receive()
                id = self.can.id
                signal = self.can.signal

                if id and signal:
                    self.update_label(id)
                    if id in self.update_labels:
                        self.update_labels[id].config(
                            text=f&quot;Signal: &quot; + &quot; &quot;.join(f&quot;{byte:02x}&quot; for byte in signal)
                        )

            except Exception as e:
                print(f&quot;Error receiving CAN message: {e}&quot;)
                break

    def run(self):
        self.thread = threading.Thread(target=self.receive_thread)
        self.thread.start()
        self.ui.run()

    def stop(self):
        self.running = False
        self.stop_threading.set()  
        self.can.shutdown()  
        if self.thread.is_alive():
            self.thread.join()
        self.ui.root.destroy() 

if __name__ == &quot;__main__&quot;:
    bus = CanBus()
    ui = MainUI()
    main = Updater(ui, bus)
    main.run()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;기타&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　앞서 언급했지만 멀티 스레드는 복잡한 개념이다. 특히 파이썬의 경우 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;GIL(Global Interpreter Lock)&lt;/b&gt;&lt;/span&gt;이라는 규칙으로 인해 CPU 바운드 작업에서 멀티스레딩의 효율성이 떨어질 수 있다. 그러나 I/O 바운드 작업에서는 멀티스레딩이 효과적일 수 있다. 이러한 부분을 잘 인지하고 자신의 프로젝트 성격에 맞게 멀티스레딩을 구현하는 것이 중요하다. 이 게시글만으로 모든 내용을 다루기 힘들기 때문에 추가로 참고할 수 있는 자료를 소개한다. &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;color: #000000;&quot;&gt;&lt;b&gt;GIL&lt;/b&gt;: Understanding the Python GIL (David Beazley)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;tkinter threading&lt;/b&gt;: &lt;a href=&quot;https://www.geeksforgeeks.org/how-to-use-thread-in-tkinter-python/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;geeksforgeeks&lt;/a&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a href=&quot;https://www.notion.so/24-09-26-10ae102e3be880aeaee8e463d8531a6f?pvs=4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;Notion 자료 정리(with Chat GPT)&lt;/b&gt;&lt;/a&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Language/Python</category>
      <category>GUI</category>
      <category>multi threading</category>
      <category>Python</category>
      <category>tkinter</category>
      <category>UI</category>
      <category>동시성</category>
      <category>멀티 스레딩</category>
      <category>파이썬</category>
      <author>nowkoes</author>
      <guid isPermaLink="true">https://maloveforme.tistory.com/293</guid>
      <comments>https://maloveforme.tistory.com/293#entry293comment</comments>
      <pubDate>Fri, 27 Sep 2024 00:00:19 +0900</pubDate>
    </item>
    <item>
      <title>[임베디드] 엔디안 방식의 이해(1) with CAN Message</title>
      <link>https://maloveforme.tistory.com/292</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Endianness&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;개요&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;421&quot; data-origin-height=&quot;230&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kG8x1/btsJLcDlYtf/MpMKc2NFR59gJdqSu1Drd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kG8x1/btsJLcDlYtf/MpMKc2NFR59gJdqSu1Drd1/img.png&quot; data-alt=&quot;출처: https://agilescientific.com/blog/2017/3/31/little-endian-is-legal&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kG8x1/btsJLcDlYtf/MpMKc2NFR59gJdqSu1Drd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkG8x1%2FbtsJLcDlYtf%2FMpMKc2NFR59gJdqSu1Drd1%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;421&quot; height=&quot;230&quot; data-origin-width=&quot;421&quot; data-origin-height=&quot;230&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://agilescientific.com/blog/2017/3/31/little-endian-is-legal&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;엔디안(Endianness)&lt;/b&gt;&lt;/span&gt;은 컴퓨터 시스템에서 &lt;span style=&quot;color: #006dd7;&quot;&gt;데이터를 메모리나 전송 매체에 저장할 때, 그 배열 순서를 결정하는 개념&lt;/span&gt;이다. 즉, 엔디안은 숫자나 다중 바이트 데이터(예: 16비트, 32비트, 64비트 등)를 저장하거나 전송할 때, 어떤 순서로 배열할 것인지를 나타낸다. 이 순서는 시스템의 하드웨어 구조에 따라 달라지며, 특히 메모리, 파일 포맷, 네트워크 통신 등에서 중요한 역할을 한다. 엔디안은 크게 빅 엔디안(Big-endian)과 리틀 엔디안(Little-endian)으로 나뉜다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　엔디안이 중요한 이유는 &lt;span style=&quot;color: #ee2323;&quot;&gt;시스템 간 데이터 전송 시 엔디안의 차이는 호환성 문제&lt;/span&gt;를 일으킬 수 있기 때문이다. 따라서 데이터 전송 표준(예: 네트워크에서는 주로 빅 엔디안을 사용)이나 프로토콜에 따라 엔디안 변환이 필요하다. 현대의 프로세서나 소프트웨어 환경에서는 대부분 이러한 차이를 자동으로 처리하지만, 임베디드 시스템이나 저수준 프로그래밍에서는 여전히 중요한 고려 사항이다. 이번 시간에는 엔디안의 종류 중 하나인 리틀 엔디안을 살펴보고, 16진수 배열에서 각 엔디안 방식을 적용하여 값을 처리하는 방법을 알아보도록 하겠다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;본문&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Little-endian&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;219&quot; data-origin-height=&quot;197&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MI5IN/btsJL9shZOh/WcPlyQAkSeUuzw1u2NrOfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MI5IN/btsJL9shZOh/WcPlyQAkSeUuzw1u2NrOfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MI5IN/btsJL9shZOh/WcPlyQAkSeUuzw1u2NrOfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMI5IN%2FbtsJL9shZOh%2FWcPlyQAkSeUuzw1u2NrOfK%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;219&quot; height=&quot;197&quot; data-origin-width=&quot;219&quot; data-origin-height=&quot;197&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;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;리틀 엔디안 방식&lt;/b&gt;&lt;/span&gt;은 &lt;span style=&quot;color: #006dd7;&quot;&gt;작은 값을 먼저 저장하는 방식&lt;/span&gt;이다. &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예를 들어, 1234라는 숫자에서 4가 가장 덜 중요한 숫자(LSB)가 되는 방식이다. 리틀 엔디안에서는 이 작은 값이 메모리의 앞쪽에 저장되고, 큰 값(MSB)이 나중에 저장된다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　이 방식은 &lt;span style=&quot;color: #ee2323;&quot;&gt;메모리에서 작은 단위의 데이터에 접근할 때 효율적&lt;/span&gt;이다. 특히, 16비트나 32비트 데이터를 처리할 때, 리틀 엔디안 방식에서는 하위 바이트부터 바로 접근할 수 있기 때문에 메모리 접근 성능이 뛰어나다. 또한, 대부분의 현대 컴퓨터 아키텍처, 특히 x86 아키텍처는 리틀 엔디안을 기본으로 사용하기 때문에 이러한 시스템에서 빠르고 변환이 필요하지 않아 효율적이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　하지만 리틀 엔디안은 &lt;span style=&quot;color: #ee2323;&quot;&gt;숫자를 거꾸로 저장하기 때문에 사람이 읽거나 디버깅할 때 직관적이지 않아 혼동&lt;/span&gt;을 줄 수 있다. 또한, 네트워크 프로토콜은 대부분 빅 엔디안을 사용하기 때문에, 리틀 엔디안 데이터를 네트워크에서 사용하려면 변환이 필요하여 추가적인 처리 과정을 거쳐야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Little Endian Parsing (1) - 16진수 배열에 특정 비트 추출하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;561&quot; data-origin-height=&quot;44&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ShmPc/btsJM6VSaQQ/cehitFA8E9Lk1Lqq0lKB01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ShmPc/btsJM6VSaQQ/cehitFA8E9Lk1Lqq0lKB01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ShmPc/btsJM6VSaQQ/cehitFA8E9Lk1Lqq0lKB01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FShmPc%2FbtsJM6VSaQQ%2FcehitFA8E9Lk1Lqq0lKB01%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;561&quot; height=&quot;44&quot; data-origin-width=&quot;561&quot; data-origin-height=&quot;44&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　예를 들어, 다음과 같은 CAN Message가 Little Endian 방식으로 수신되었다고 가정해 보자. 이때 offset은 0이고 factor는 1이라고 가정한다. 여기서 5번 비트부터 12번 비트까지의 값은 얼마일까?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;560&quot; data-origin-height=&quot;63&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ehb5m/btsJNe7fwm0/GxRGcb53BP9RfzvTcXn6U1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ehb5m/btsJNe7fwm0/GxRGcb53BP9RfzvTcXn6U1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ehb5m/btsJNe7fwm0/GxRGcb53BP9RfzvTcXn6U1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEhb5m%2FbtsJNe7fwm0%2FGxRGcb53BP9RfzvTcXn6U1%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;560&quot; height=&quot;63&quot; data-origin-width=&quot;560&quot; data-origin-height=&quot;63&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　리틀 엔디안은 작은 값이 먼저 저장되기 때문에 메모리엔 다음과 같이 저장될 것이다. 이때 특정 비트에 값을 넣는 것을 목적으로 하고 있으므로 16진수를 2진수로 변환해 준다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;653&quot; data-origin-height=&quot;100&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpO3hm/btsJNBVtCAG/B8kSxmr6fQcsCPOVcHgoY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpO3hm/btsJNBVtCAG/B8kSxmr6fQcsCPOVcHgoY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpO3hm/btsJNBVtCAG/B8kSxmr6fQcsCPOVcHgoY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcpO3hm%2FbtsJNBVtCAG%2FB8kSxmr6fQcsCPOVcHgoY0%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;653&quot; height=&quot;100&quot; data-origin-width=&quot;653&quot; data-origin-height=&quot;100&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　여기서 5번 비트부터 12번 비트까지 값을 추출하면 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;651&quot; data-origin-height=&quot;134&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dqnDS8/btsJLv32qUm/x5upDw5LKkCcMJe7vB9yK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dqnDS8/btsJLv32qUm/x5upDw5LKkCcMJe7vB9yK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dqnDS8/btsJLv32qUm/x5upDw5LKkCcMJe7vB9yK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdqnDS8%2FbtsJLv32qUm%2Fx5upDw5LKkCcMJe7vB9yK0%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;651&quot; height=&quot;134&quot; data-origin-width=&quot;651&quot; data-origin-height=&quot;134&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　즉, 0101 1010(2) = 90이 된다.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Little Endian Parsing (2) - 16진수 배열에 특정 비트 삽입하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;660&quot; data-origin-height=&quot;82&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CgSsI/btsJLJA21I2/sZQooHACeru0DFpW0dyCxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CgSsI/btsJLJA21I2/sZQooHACeru0DFpW0dyCxK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CgSsI/btsJLJA21I2/sZQooHACeru0DFpW0dyCxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCgSsI%2FbtsJLJA21I2%2FsZQooHACeru0DFpW0dyCxK%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;660&quot; height=&quot;82&quot; data-origin-width=&quot;660&quot; data-origin-height=&quot;82&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번에는 빈 문자열 배열에 5번 비트부터 12번 비트까지 90이라는 10진수 값을 넣어 보자. Little Endian Parsing(1)과 마찬가지로 offset은 0이고 factor는 1이라고 가정한다. 그리고 각 문자열에 괄호로 된 숫자는 문자열 배열의 인덱스를 의미한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;661&quot; data-origin-height=&quot;88&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SqEoV/btsJL8tuHUW/tc95yQfLK1KCRNr1Bm90eK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SqEoV/btsJL8tuHUW/tc95yQfLK1KCRNr1Bm90eK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SqEoV/btsJL8tuHUW/tc95yQfLK1KCRNr1Bm90eK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSqEoV%2FbtsJL8tuHUW%2Ftc95yQfLK1KCRNr1Bm90eK%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;661&quot; height=&quot;88&quot; data-origin-width=&quot;661&quot; data-origin-height=&quot;88&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　리틀 엔디안 방식이므로 순서를 바꿔주고, 특정 비트에 값을 넣기 위해 2진수로 변환해 주자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;659&quot; data-origin-height=&quot;112&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgOLXl/btsJLYxU3g5/KfsktasxyZOWFi35wtRK61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgOLXl/btsJLYxU3g5/KfsktasxyZOWFi35wtRK61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgOLXl/btsJLYxU3g5/KfsktasxyZOWFi35wtRK61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgOLXl%2FbtsJLYxU3g5%2FKfsktasxyZOWFi35wtRK61%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;659&quot; height=&quot;112&quot; data-origin-width=&quot;659&quot; data-origin-height=&quot;112&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　그리고 아래와 같이 5번 비트부터 12번 비트까지 90을 2진수로 변환한 값인 0101 1010(2)을 차례대로 넣고 16진수로 변환해 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;663&quot; data-origin-height=&quot;182&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dkCDMj/btsJLJA41Vx/vCHTkKhTsxtkiHarnIXxx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dkCDMj/btsJLJA41Vx/vCHTkKhTsxtkiHarnIXxx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dkCDMj/btsJLJA41Vx/vCHTkKhTsxtkiHarnIXxx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdkCDMj%2FbtsJLJA41Vx%2FvCHTkKhTsxtkiHarnIXxx0%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;663&quot; height=&quot;182&quot; data-origin-width=&quot;663&quot; data-origin-height=&quot;182&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　여기서 바이트 순서를 반대로 적용하면 최종적으로 메시지는 다음과 같이 0x40, 0x0B, 0x00, 0x00으로 구성된다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;코드 구현&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　해당 내용을 Python 코드로 작성하면 다음과 같다. 파이썬의 문법을 크게 쓰지 않고 비트 연산이 주를 이루고 있기 때문에, 로직을 잘 파악하고 있다면 C언어로 변환하는 것도 크게 어렵지 않을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1727325462049&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 16진수 배열의 특정 비트에 값을 넣는 예제

def update_data(data, value, start_bit, bit_length, factor):
    value = int(value / factor)
    data = bytearray(data)

    for i in range(bit_length):
        bit_value = (value &amp;gt;&amp;gt; i) &amp;amp; 1
        byte_index = (start_bit + i) // 8 
        bit_index = (start_bit + i) % 8 

        if bit_value:
            data[byte_index] |= (1 &amp;lt;&amp;lt; bit_index)   
        else:
            data[byte_index] &amp;amp;= ~(1 &amp;lt;&amp;lt; bit_index)  

    return data

message = [0x00, 0x00, 0x00, 0x00]  
start_bit = 5
bit_length = 8  
value = 90 

updated_message = update_data(message, value, start_bit, bit_length, 1)

print([hex(x) for x in updated_message])&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;209&quot; data-origin-height=&quot;20&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c4cdyU/btsJLZKofiO/4XGH80YERf4tDZsBMW8wKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c4cdyU/btsJLZKofiO/4XGH80YERf4tDZsBMW8wKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c4cdyU/btsJLZKofiO/4XGH80YERf4tDZsBMW8wKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc4cdyU%2FbtsJLZKofiO%2F4XGH80YERf4tDZsBMW8wKK%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;209&quot; height=&quot;20&quot; data-origin-width=&quot;209&quot; data-origin-height=&quot;20&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;　&lt;/p&gt;
&lt;pre id=&quot;code_1727325972695&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def get_value_from_hex(data, start_bit, bit_length, factor=1):
    full_value = 0
    for i in range(len(data)):
        full_value |= data[i] &amp;lt;&amp;lt; (i * 8)  
    
    mask = (1 &amp;lt;&amp;lt; bit_length) - 1
    extracted_value = (full_value &amp;gt;&amp;gt; start_bit) &amp;amp; mask
  
    return extracted_value * factor

if __name__ == &quot;__main__&quot;:
    message = [0x40, 0x0B, 0x00, 0x01]  
    start_bit = 5
    bit_length = 8
    factor = 1

    extracted_value = get_value_from_hex(message, start_bit, bit_length, factor)

    print(f&quot;Extracted Value: {extracted_value}&quot;)  
    print(f&quot;Extracted Value (binary): {bin(extracted_value)}&quot;)&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;312&quot; data-origin-height=&quot;33&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TQ4fp/btsJNf6qgtb/2Ql14JZs8Aq8rBFNQtqotK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TQ4fp/btsJNf6qgtb/2Ql14JZs8Aq8rBFNQtqotK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TQ4fp/btsJNf6qgtb/2Ql14JZs8Aq8rBFNQtqotK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTQ4fp%2FbtsJNf6qgtb%2F2Ql14JZs8Aq8rBFNQtqotK%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;312&quot; height=&quot;33&quot; data-origin-width=&quot;312&quot; data-origin-height=&quot;33&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;</description>
      <category>CS/임베디드</category>
      <category>Embedded</category>
      <category>Endian</category>
      <category>endianness</category>
      <category>little endlian</category>
      <category>little-endian</category>
      <category>Memory</category>
      <category>리틀 엔디안</category>
      <category>메모리</category>
      <category>엔디안</category>
      <category>임베디드</category>
      <author>nowkoes</author>
      <guid isPermaLink="true">https://maloveforme.tistory.com/292</guid>
      <comments>https://maloveforme.tistory.com/292#entry292comment</comments>
      <pubDate>Thu, 26 Sep 2024 13:48:51 +0900</pubDate>
    </item>
    <item>
      <title>[파이썬] 반응형 GUI</title>
      <link>https://maloveforme.tistory.com/291</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;화면 해상도(DPI) 인식&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;개요&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;690&quot; data-origin-height=&quot;407&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HmWii/btsJInciQvI/WoKufjdEu4NJtkXNKLucF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HmWii/btsJInciQvI/WoKufjdEu4NJtkXNKLucF1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HmWii/btsJInciQvI/WoKufjdEu4NJtkXNKLucF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHmWii%2FbtsJInciQvI%2FWoKufjdEu4NJtkXNKLucF1%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;690&quot; height=&quot;407&quot; data-origin-width=&quot;690&quot; data-origin-height=&quot;407&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　GUI 프로그램을 개발할 때는 다양한 디스플레이 환경을 고려해야 한다. 예를 들어, 동일한 1920 x 1080 해상도에서도 디스플레이 배율에 따라 프로그램의 크기와 배치가 달라질 수 있다. 따라서 디스플레이 해상도와 배율을 적절히 반영하는 것이 중요하다. 이전에 &lt;a href=&quot;https://maloveforme.tistory.com/283&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;C# WinForm&lt;/a&gt;에서는 이를 다뤘지만, 이번에는 파이썬을 사용해 디스플레이 환경을 고려하는 방법을 살펴보도록 하겠다. &lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;본문&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;ctypes&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;802&quot; data-origin-height=&quot;428&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rQXAG/btsJG3ziV08/KaKGUcpXFRXGcnjLIRm6kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rQXAG/btsJG3ziV08/KaKGUcpXFRXGcnjLIRm6kk/img.png&quot; data-alt=&quot;출처: https://docs.python.org/3/library/ctypes.html&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rQXAG/btsJG3ziV08/KaKGUcpXFRXGcnjLIRm6kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrQXAG%2FbtsJG3ziV08%2FKaKGUcpXFRXGcnjLIRm6kk%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;802&quot; height=&quot;428&quot; data-origin-width=&quot;802&quot; data-origin-height=&quot;428&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://docs.python.org/3/library/ctypes.html&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;ctypes&lt;/b&gt;&lt;/span&gt;는 &lt;span style=&quot;color: #006dd7;&quot;&gt;파이썬에서는 외부 C 라이브러리에 쉽게 접근할 수 있게 해주는 모듈&lt;/span&gt;이다. C와 파이썬은 서로 다른 데이터 타입을 사용하지만, ctypes는 파이썬 타입을 C 데이터 타입에 매핑하는 기능을 제공한다. 일반적으로 플랫폼 의존적인 기능에 대한 직접적인 접근과 정확성을 이유로, &lt;span style=&quot;color: #ee2323;&quot;&gt;운영 체제의 네이티브 API에 접근하기 위해 자주 사용&lt;/span&gt;한다. Windows의 경우 user32.dll에서 디스플레이에 대한 정보를 제공하기 때문에 이를 이용해 보도록 하겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1727047387851&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import ctypes

def get_screen_resolution():
    user32 = ctypes.windll.user32
    user32.SetProcessDPIAware()  
    screen_width = user32.GetSystemMetrics(0) 
    screen_height = user32.GetSystemMetrics(1)  
    return screen_width, screen_height

def get_display_ratio():
    user32 = ctypes.windll.user32
    gdi32 = ctypes.windll.gdi32
    ctypes.windll.shcore.SetProcessDpiAwareness(2) 

    hdc = user32.GetDC(0)
    dpi_x = gdi32.GetDeviceCaps(hdc, 88)
    user32.ReleaseDC(0, hdc)

    scaling_factor = dpi_x / 96.0  

    return scaling_factor

width, height = get_screen_resolution()
ratio = get_display_ratio()
print(f&quot;현재 디스플레이 해상도: {width}x{height}\n배율: {ratio}&quot;)&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;240&quot; data-origin-height=&quot;32&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vL2Kx/btsJIV0SEPC/zxshzwOKatxY60kVTxQUh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vL2Kx/btsJIV0SEPC/zxshzwOKatxY60kVTxQUh0/img.png&quot; data-alt=&quot;출력&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vL2Kx/btsJIV0SEPC/zxshzwOKatxY60kVTxQUh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvL2Kx%2FbtsJIV0SEPC%2FzxshzwOKatxY60kVTxQUh0%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;240&quot; height=&quot;32&quot; data-origin-width=&quot;240&quot; data-origin-height=&quot;32&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출력&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;get_screen_resolution&lt;/b&gt;　&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　ctypes.windll.user32는 Windows의 user32.dll 라이브러리에 접근하는 객체다. 이 객체의 SetProcessDPIAware() 함수를 통해 현재 파이썬 프로세스가 DPI-Aware(DPI 인식) 모드로 설정된다. 이 함수를 호출하면 파이썬 프로그램이 Windows의 DPI 스케일링 설정을 무시하고 실제 해상도(픽셀 단위)를 정확하게 인식하게 된다. 또한, GetSystemMetrics() 함수를 사용하면 다양한 시스템 정보를 가져올 수 있는데, 인수에 따라 반환되는 정보가 달라진다. 예를 들어, &lt;span style=&quot;color: #ee2323;&quot;&gt;0은 화면의 가로 해상도, 1은 화면의 세로 해상도&lt;/span&gt;를 의미한다. 그러나 DPI 배율을 직접적으로 반환하지는 않으며, 해상도를 기반으로 간접적으로 계산할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;get_display_ratio&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　ctypes.windll.gdi32는 그래픽 장치와 관련된 작업을 처리하는 Windows의 gdi32.dll 라이브러리에 접근하는 객체다. GetDC() 함수는 화면의 디바이스 컨텍스트(Device Context) 핸들을 가져오는데, 인수로 0을 전달하면 전체 화면에 대한 핸들을 가져온다. 디바이스 컨텍스트는 그래픽 장치의 속성이나 상태를 가져오고 설정할 수 있도록 해주는 개념이다. &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;디바이스 컨텍스트를 사용한 후에는 시스템 자원을 해제하기 위해 ReleaseDC()를 호출하여 자원을 반환&lt;/span&gt;&lt;/b&gt;해야 한다. gdi32 객체의 GetDeviceCaps() 함수를 사용하면 디바이스 컨텍스트에서 가로 방향 DPI 값을 가져올 수 있다. 인수 88은 가로 DPI를 의미하는 상수다. 마지막으로, &lt;span style=&quot;color: #ee2323;&quot;&gt;현재 DPI 값을 Windows의 기본 DPI인 96으로 나누면 현재 화면의 배율을 계산&lt;/span&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;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예시&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1497&quot; data-origin-height=&quot;923&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tDvtU/btsJIh4ubZO/dKw16lkAUqBAWEWkFkXdd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tDvtU/btsJIh4ubZO/dKw16lkAUqBAWEWkFkXdd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tDvtU/btsJIh4ubZO/dKw16lkAUqBAWEWkFkXdd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtDvtU%2FbtsJIh4ubZO%2FdKw16lkAUqBAWEWkFkXdd0%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;1497&quot; height=&quot;923&quot; data-origin-width=&quot;1497&quot; data-origin-height=&quot;923&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　 다음과 같이 1500x1000 크기의 GUI가 있다고 가정해 보자. 이 GUI를 1920x1080 해상도를 사용하는 동일한 디스플레이에서 배율을 달리하면 다음과 같은 결과를 볼 수 있다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;1898&quot; data-origin-height=&quot;1029&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Eq6cG/btsJHXryzh6/xA7zt97jfxz4BPAvvJZS0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Eq6cG/btsJHXryzh6/xA7zt97jfxz4BPAvvJZS0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Eq6cG/btsJHXryzh6/xA7zt97jfxz4BPAvvJZS0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEq6cG%2FbtsJHXryzh6%2FxA7zt97jfxz4BPAvvJZS0K%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;1898&quot; height=&quot;1029&quot; data-origin-width=&quot;1898&quot; data-origin-height=&quot;1029&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　 &lt;span style=&quot;color: #ee2323;&quot;&gt;만약 배율이 120%로 설정된 경우, 화면 내에서 UI 요소들이 20% 더 크게 표시된다. 이렇게 되면 실제 해상도는 그대로지만, 마치 1600x900 해상도에서 동작하는 것처럼 UI 요소가 커지면서 일부 내용이 화면에서 잘리거나 보이지 않을 수 있다&lt;/span&gt;. 이처럼 고해상도 디스플레이에서는 배율 설정에 따른 영향을 고려해야 한다. 이러한 문제를 해결하기 위해, 앞서 구현한 get_display_ratio 함수를 활용할 수 있다. 이 함수는 화면의 DPI 배율을 계산하여, UI의 크기 조정에 활용할 수 있다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1727048918556&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import ctypes
import tkinter as tk

def get_display_ratio():
    user32 = ctypes.windll.user32
    gdi32 = ctypes.windll.gdi32
    ctypes.windll.shcore.SetProcessDpiAwareness(2) 

    hdc = user32.GetDC(0)
    dpi_x = gdi32.GetDeviceCaps(hdc, 88)
    user32.ReleaseDC(0, hdc)

    scaling_factor = dpi_x / 96.0  

    return scaling_factor

ratio = get_display_ratio()
width, height = int(1500/ratio), int(1000/ratio)

root = tk.Tk()
root.geometry(f&quot;{width}x{height}&quot;)
[tk.Label(root, text=f&quot;{i}번 째 라벨&quot;, font=(&quot;Helvetica&quot;, 50)).pack() for i in range(5)]

root.mainloop()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　위 코드에서는 get_display_ratio() 함수를 통해 현재 화면의 배율을 계산하고, 1500x1000 크기의 GUI를 배율에 맞춰 조정한 크기로 설정한다. 배율을 고려함으로써 UI가 너무 작거나 잘리는 문제를 방지할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;필자의 경우, 위치와 크기 관련 코드를 작성할 때는 항상 배율을 고려하여 변수로 처리하고, 이를 DPI 배율로 나눠 크기를 조정하는 방식을 사용하고 있다. 이를 통해 다양한 배율 환경에서도 일관된 UI를 유지할 수 있다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;요약&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;반응형 GUI&lt;br /&gt;1. ctypes 라이브러리를 통해 user32.dll, gdi32.dll 등의 OS Native API 호출&lt;br /&gt;2. DPI 값을 이용해 크기를 조정&lt;/blockquote&gt;</description>
      <category>Language/Python</category>
      <category>dpi</category>
      <category>GUI</category>
      <category>Python</category>
      <category>Resolution</category>
      <category>tkinter</category>
      <category>반응형</category>
      <category>배율</category>
      <category>파이썬</category>
      <category>해상도</category>
      <author>nowkoes</author>
      <guid isPermaLink="true">https://maloveforme.tistory.com/291</guid>
      <comments>https://maloveforme.tistory.com/291#entry291comment</comments>
      <pubDate>Mon, 23 Sep 2024 08:54:48 +0900</pubDate>
    </item>
    <item>
      <title>[C#] 타입(1) 값 형식의 변수</title>
      <link>https://maloveforme.tistory.com/290</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&amp;lt;본 카테고리는 &quot;닷넷 정복 C#&quot; 책을 기반으로 작성하였습니다&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;값 타입&lt;/b&gt;&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;개요&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;467&quot; data-origin-height=&quot;284&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zEHSB/btsIUKAohK2/PAl0He1ivQeQW38KbsEcA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zEHSB/btsIUKAohK2/PAl0He1ivQeQW38KbsEcA1/img.png&quot; data-alt=&quot;C#에서 사용하는 타입의 분류&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zEHSB/btsIUKAohK2/PAl0He1ivQeQW38KbsEcA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzEHSB%2FbtsIUKAohK2%2FPAl0He1ivQeQW38KbsEcA1%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;467&quot; height=&quot;284&quot; data-origin-width=&quot;467&quot; data-origin-height=&quot;284&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;C#에서 사용하는 타입의 분류&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;타입(Type)&lt;/b&gt;&lt;/span&gt;은 &lt;span style=&quot;color: #006dd7;&quot;&gt;변수의 형식&lt;/span&gt;이며 길이나 값을 해석하는 방식을 결정한다. 즉, &lt;span style=&quot;color: #006dd7;&quot;&gt;데이터의 특성을 정의하고, 해당 데이터를 어떻게 저장하고 조작할지 결정&lt;/span&gt;하는 중요한 요인이다. C#에서는 위의 표와 같이 타입을 &lt;span style=&quot;color: #ee2323;&quot;&gt;크게 값 타입과 참조 타입으로 나눌 수 있다&lt;/span&gt;. 값과 참조에 대해 깊게 고찰해봐야 하지만, 이는 추후에 다루기로 하고, 값 타입의 변수들에 대해 먼저 알아보자.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;본문&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;값 타입&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;값 타입(Value Type)&lt;/b&gt;&lt;/span&gt;이란 &lt;span style=&quot;color: #006dd7;&quot;&gt;스택에 할당되며 변수가 직접 값을 가지는 형식&lt;/span&gt;을 의미한다. 일반적으로 크기가 작고 길이가 일정한 값을 저장하며, &lt;span style=&quot;color: #ee2323;&quot;&gt;선언하는 즉시 기억 장소에 할당&lt;/span&gt;되어 바로 사용할 수 있다. 또한 값 타입은 클래스의 멤버나 메서드의 지역 변수로 선언될 수 있으며, 다른 언어들과 마찬가지로 자료형과 이름으로 선언하고, 선언과 동시에 초기화할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1722921204783&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;

namespace MyCompiler 
{
    class Program 
    {
        public static void Main(string[] args) 
        {
            decimal x = 1.5;
            double y = 1.5;
            float z = 1.5f;
        }
    }
}&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;1163&quot; data-origin-height=&quot;97&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pzXzG/btsIVkVMZiw/Y53elDOU3FRcSbIRKlUrG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pzXzG/btsIVkVMZiw/Y53elDOU3FRcSbIRKlUrG1/img.png&quot; data-alt=&quot;출력 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pzXzG/btsIVkVMZiw/Y53elDOU3FRcSbIRKlUrG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpzXzG%2FbtsIVkVMZiw%2FY53elDOU3FRcSbIRKlUrG1%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;1163&quot; height=&quot;97&quot; data-origin-width=&quot;1163&quot; data-origin-height=&quot;97&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출력 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　값 타입은 크게 세 가지, &lt;span style=&quot;color: #ee2323;&quot;&gt;내장형, 열거형, 구조체&lt;/span&gt;로 나뉜다. 내장형에는 정수형, 실수형, 논리형, 문자형이 존재하는데, 유념해야 할 것은 실수형이다. C#에서 실수형은 float(4byte), double(8byte), decimal(16byte) 세 가지가 존재한다. 이때 float 형의 상수는 뒤에 f 접미사, decimal 형의 상수는 뒤에 m 접미사를 붙여야 한다. 만약 이러한 접미사를 따로 붙이지 않으면 컴파일러가 double 형으로 간주하고 에러를 띄운다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;열거형&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;　&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;열거형(Enumeration)&lt;/b&gt;&lt;/span&gt;은 &lt;span style=&quot;color: #006dd7;&quot;&gt;상수 집합에 이름을 붙여 관리하기 위해 사용하는 특별한 데이터 타입&lt;/span&gt;이다. 값이 특정 유한 집합으로 제한될 때 사용하는데, 일반적으로 관련된 상수들의 그룹을 만들고, 각 상수에 이름을 부여하여 코드의 가독성을 높이는 역할을 한다. 이때 &lt;span style=&quot;color: #ee2323;&quot;&gt;enum 키워드&lt;/span&gt;를 이용하여 사용하는데, 타입 정의문은 명령이 아니어서 끝에 세미콜론을 붙이지 않는다.&amp;nbsp;&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;C#에서는 타입 선언은 실행문과 구분된다. 실행문은 특정 작업을 수행하며, 각 실행문의 끝에는 세미콜론을 붙여 끝을 명확히 표시한다. 반면, 타입 선언은 하나의 완전한 구문 단위로 간주되며, 내부에 여러 멤버를 가질 수 있는 복잡한 구조다. 이러한 선언의 끝에 세미콜론을 붙이지 않지만 중괄호를 사용함으로써 이를 구분 짓는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1722921658437&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;

namespace MyCompiler 
{
    public class Scheduler
    {
        public void PrintDay(int day)
        {
            switch (day)
            {
                case 0:
                    Console.WriteLine(&quot;Sunday&quot;);
                    break;
                case 1:
                    Console.WriteLine(&quot;Monday&quot;);
                    break;
                case 2:
                    Console.WriteLine(&quot;Tuesday&quot;);
                    break;
                case 3:
                    Console.WriteLine(&quot;Wednesday&quot;);
                    break;
                case 4:
                    Console.WriteLine(&quot;Thursday&quot;);
                    break;
                case 5:
                    Console.WriteLine(&quot;Friday&quot;);
                    break;
                case 6:
                    Console.WriteLine(&quot;Saturday&quot;);
                    break;
                default:
                    Console.WriteLine(&quot;Invalid day&quot;);
                    break;
            }
        }
    }
    
    class Program 
    {
        public static void Main(string[] args) 
        {
            Scheduler scheduler = new Scheduler();
            scheduler.PrintDay(3); 
            scheduler.PrintDay(7); 
        }
    }
}&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;554&quot; data-origin-height=&quot;89&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kTodi/btsIWaymjUr/RJa6VCpAUGB0WkxatRUjvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kTodi/btsIWaymjUr/RJa6VCpAUGB0WkxatRUjvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kTodi/btsIWaymjUr/RJa6VCpAUGB0WkxatRUjvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkTodi%2FbtsIWaymjUr%2FRJa6VCpAUGB0WkxatRUjvk%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;554&quot; height=&quot;89&quot; data-origin-width=&quot;554&quot; data-origin-height=&quot;89&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;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;　예를 들어 다음과 같이 월요일부터 일요일까지 날짜를 출력하는 코드를 구성했다고 가정해 보자. 날짜에 인수가 정수이므로, 다른 사람이 봤을 때 이해하기 직관적이지 않다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1722921766701&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;

namespace MyCompiler 
{
    public enum Days
    {
        Sunday,    // 0
        Monday,    // 1
        Tuesday,   // 2
        Wednesday, // 3
        Thursday,  // 4
        Friday,    // 5
        Saturday   // 6
    }
    
    public class Scheduler
    {
        public void PrintDay(Days day)
        {
            switch (day)
            {
                case Days.Sunday:
                    Console.WriteLine(&quot;Sunday&quot;);
                    break;
                case Days.Monday:
                    Console.WriteLine(&quot;Monday&quot;);
                    break;
                case Days.Tuesday:
                    Console.WriteLine(&quot;Tuesday&quot;);
                    break;
                case Days.Wednesday:
                    Console.WriteLine(&quot;Wednesday&quot;);
                    break;
                case Days.Thursday:
                    Console.WriteLine(&quot;Thursday&quot;);
                    break;
                case Days.Friday:
                    Console.WriteLine(&quot;Friday&quot;);
                    break;
                case Days.Saturday:
                    Console.WriteLine(&quot;Saturday&quot;);
                    break;
                default:
                    Console.WriteLine(&quot;Invalid day&quot;);
                    break;
            }
        }
    }
    
    class Program 
    {
        public static void Main(string[] args) 
        {
            Scheduler scheduler = new Scheduler();
            scheduler.PrintDay(Days.Wednesday);
        }
    }
}&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;556&quot; data-origin-height=&quot;72&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v6VM1/btsIVip8NCP/wNuAebpHgsJtSk1p3HBBF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v6VM1/btsIVip8NCP/wNuAebpHgsJtSk1p3HBBF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v6VM1/btsIVip8NCP/wNuAebpHgsJtSk1p3HBBF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv6VM1%2FbtsIVip8NCP%2FwNuAebpHgsJtSk1p3HBBF0%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;556&quot; height=&quot;72&quot; data-origin-width=&quot;556&quot; data-origin-height=&quot;72&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;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;　반면, 날짜를 지정하는 Days라는 열거형을 선언함으로써 훨씬 코드가 간결해지고 가독성이 좋아졌다. 이때 다음과 같이 열거 타입 이름 다음에 내부 저장 타입을 지정하면 용량을 조금 아낄 수 있다는 점도 알아 두자. 이때 열거 멤버는 열거 타입 소속이어서 참조할 때마다 일일이 소속을 밝혀야 한다. 물론 using 문을 이용하여 열거형 타입의 멤버를 미리 읽는 방법도 존재하니, 상황에 맞게 활용하면 된다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;구조체&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;구조체(Structure)&lt;/b&gt;&lt;/span&gt;는&lt;span style=&quot;color: #006dd7;&quot;&gt; 타입이 다른 변수들의 집합&lt;/span&gt;이다. 이때 클래스와 유사하지만(메서드, 생성자 정의 가능, 멤버 참조 시 . 연산자 사용 등), 몇 가지 중요한 차이점이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;&lt;b&gt;값 타입&lt;/b&gt;: 멤버의 개수에 제한이 없어 굉장히 커질 수 있지만 스택에 할당되는 값 타입&lt;/li&gt;
&lt;li&gt;&lt;b&gt;상속 불가&lt;/b&gt;: 봉인되어 있어 더 이상 파생시킬 수 없으며 단독으로만 사용해야 함&lt;/li&gt;
&lt;li&gt;&lt;b&gt;대입&lt;/b&gt;: 구조체끼리의 대입은 멤버 전체를 복사하는 느린 연산&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　따라서 선언만 하면 곧바로 사용할 수 있지만, 참조 타입인 클래스와 사용 방법을 일관되게 통일하기 위해 &lt;span style=&quot;color: #ee2323;&quot;&gt;new 연산자를 쓰는 (참조 형식으로 선언하는) 방식도 지원&lt;/span&gt;한다. 그리고 전방 선언도 필요 없고, 구조체의 선언문이 Main 보다 더 뒤에 있어도 상관이 없다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1722922505526&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;

namespace MyCompiler 
{
    struct Book
    {
        public string name;
        public int price;

        public void output()
        {
            Console.WriteLine($&quot;name = {name}\nprice = {price}&quot;);
        }
    }
    
    class Program 
    {
        public static void Main(string[] args) 
        {
            Book b1;
            b1.name = &quot;A&quot;;
            b1.price = 10;
            b1.output();

            Book b2 = new Book();
            b2.name = &quot;B&quot;;
            b2.price = 20;
            b2.output();
        }
    }
}&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;548&quot; data-origin-height=&quot;130&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qLKh9/btsIWw8V0Hu/J5j2KGtEczuK0u1FkUiCK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qLKh9/btsIWw8V0Hu/J5j2KGtEczuK0u1FkUiCK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qLKh9/btsIWw8V0Hu/J5j2KGtEczuK0u1FkUiCK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqLKh9%2FbtsIWw8V0Hu%2FJ5j2KGtEczuK0u1FkUiCK1%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;548&quot; height=&quot;130&quot; data-origin-width=&quot;548&quot; data-origin-height=&quot;130&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;요약&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;C# 값 타입&lt;/b&gt;&lt;br /&gt;1. 정의: 스택에 할당되는 형식&lt;br /&gt;2. 특징: 선언하는 즉시 기억 장소에 할당&lt;br /&gt;3. 종류: 내장형(정수, 실수, 논리, 문자), 열거형, 구조체&lt;/blockquote&gt;</description>
      <category>Language/C#</category>
      <category>c#</category>
      <category>Value Type</category>
      <category>값 타입</category>
      <category>값타입</category>
      <category>변수</category>
      <author>nowkoes</author>
      <guid isPermaLink="true">https://maloveforme.tistory.com/290</guid>
      <comments>https://maloveforme.tistory.com/290#entry290comment</comments>
      <pubDate>Tue, 6 Aug 2024 14:58:25 +0900</pubDate>
    </item>
    <item>
      <title>[C#] C# 개요 및 입출력</title>
      <link>https://maloveforme.tistory.com/289</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;개요&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&amp;lt;본 카테고리는 &quot;닷넷 정복 C#&quot; 책을 기반으로 작성하였습니다&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;C# 개요&lt;/b&gt;&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;개요&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;319&quot; data-origin-height=&quot;250&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zfoJc/btsIUkuVPEq/K44mxUTnLMYjKmVoLVERk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zfoJc/btsIUkuVPEq/K44mxUTnLMYjKmVoLVERk0/img.png&quot; data-alt=&quot;출처: https://namu.wiki/w/C%23&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zfoJc/btsIUkuVPEq/K44mxUTnLMYjKmVoLVERk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzfoJc%2FbtsIUkuVPEq%2FK44mxUTnLMYjKmVoLVERk0%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;319&quot; height=&quot;250&quot; data-origin-width=&quot;319&quot; data-origin-height=&quot;250&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://namu.wiki/w/C%23&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　 C#은 Microsoft가 개발한 현대적이고 강력한 객체지향 프로그래밍 언어로, 다양한 응용 프로그램을 개발하는 데 사용된다. C#은 .NET Framework와 .NET Core(현재는 .NET 5+로 통합됨)에서 주로 사용되며, 가비지 컬렉션 기능을 내장하여 메모리 관리를 자동으로 수행한다. 다음은 C#의 주요 특징이다.&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;size18&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;C#은 클래스와 객체를 중심으로 설계된 완전한 객체지향 언어&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;size18&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;C#은 가비지 컬렉션을 통해 불필요한 메모리를 자동으로 해제&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;size18&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;포인터를 기본적으로 제공하지 않으며, 안전하지 않은 코드 영역(unsafe)에서만 포인터를 사용&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;size18&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;C#은 강력한 형식 검사와 엄격한 타입 시스템을 갖추고 있어, 컴파일 타임에 많은 오류를 잡을 수 있음&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;size18&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;.NET 라이브러리(BCL, Base Class Library)를 통해 다양한 기능을 쉽게 사용&lt;/li&gt;
&lt;li&gt;데이터 구조, 파일 입출력, 네트워킹, 데이터베이스 액세스, GUI, XML 처리, JSON 처리 등의 기능을 제공&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;size18&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;C#은 Windows뿐만 아니라, macOS, Linux에서도 실행할 수 있는 크로스 플랫폼 지원을 제공&lt;/li&gt;
&lt;li&gt;.NET Core 및 .NET 5+를 통해 다양한 플랫폼에서 애플리케이션을 개발&lt;/li&gt;
&lt;/ul&gt;
&lt;p 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;p data-ke-size=&quot;size18&quot;&gt;　오늘부터 이러한 특징을 가진 C#의 문법들에 대해 알아보는 시간을 가지도록 하자.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;본문&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;네임스페이스&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;　닷넷에서 &lt;span style=&quot;color: #ee2323;&quot;&gt;입출력 기능은 System 네임스페이스의 Console 클래스가 제공&lt;/span&gt;한다. 여기서 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;네임스페이스(namespace)&lt;/b&gt;&lt;/span&gt;란 닷넷의 방대한 공용 라이브러리인 BCL(Base Class Library)을 효율적으로 관리하기 위해 나눈 공간이라고 생각하면 된다. 즉, &lt;span style=&quot;color: #006dd7;&quot;&gt;명칭을 저장하는 장소이며 명칭의 범위를 격리시키는 역할&lt;/span&gt;을 한다. 이때 &lt;span style=&quot;color: #ee2323;&quot;&gt;C#에선 함수나 변수가 네임스페이스 안에 직접 선언될 수 없고, 클래스나 구조체의 멤버로 선언&lt;/span&gt;되어야 한다는 점 알아두자.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/S3lqj/btsIUxU3Dt9/TEXqN6JGuJhpQJMEuNXjJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/S3lqj/btsIUxU3Dt9/TEXqN6JGuJhpQJMEuNXjJk/img.png&quot; data-origin-width=&quot;552&quot; data-origin-height=&quot;325&quot; data-is-animation=&quot;false&quot; style=&quot;width: 65.566%; margin-right: 10px;&quot; data-widthpercent=&quot;66.34&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/S3lqj/btsIUxU3Dt9/TEXqN6JGuJhpQJMEuNXjJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FS3lqj%2FbtsIUxU3Dt9%2FTEXqN6JGuJhpQJMEuNXjJk%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;552&quot; height=&quot;325&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxOZUp/btsIUJgIy1H/EMVztCzHzrSdJK0LyHG1j1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxOZUp/btsIUJgIy1H/EMVztCzHzrSdJK0LyHG1j1/img.png&quot; data-origin-width=&quot;312&quot; data-origin-height=&quot;362&quot; data-is-animation=&quot;false&quot; style=&quot;width: 33.2712%;&quot; data-widthpercent=&quot;33.66&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxOZUp/btsIUJgIy1H/EMVztCzHzrSdJK0LyHG1j1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxOZUp%2FbtsIUJgIy1H%2FEMVztCzHzrSdJK0LyHG1j1%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;312&quot; height=&quot;362&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;같은 네임스페이스에서는 같은 이름의 클래스가 존재하면 에러가 뜨지만(좌), 다른 네임스페이스의 경우 상관이 없다(우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&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;495&quot; data-origin-height=&quot;145&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mOTnG/btsIV7nBcFt/zgoL35FqWES9mmvgGKRmY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mOTnG/btsIV7nBcFt/zgoL35FqWES9mmvgGKRmY1/img.png&quot; data-alt=&quot;네임스페이스 안에 필드나 메서드 같은 멤버를 포함하면 에러가 뜬다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mOTnG/btsIV7nBcFt/zgoL35FqWES9mmvgGKRmY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmOTnG%2FbtsIV7nBcFt%2FzgoL35FqWES9mmvgGKRmY1%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;495&quot; height=&quot;145&quot; data-origin-width=&quot;495&quot; data-origin-height=&quot;145&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;네임스페이스 안에 필드나 메서드 같은 멤버를 포함하면 에러가 뜬다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;b&gt;using 문&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　고유한 네임스페이스 안에서 명칭을 자유롭게 만들 수 있다는 것은 분명 장점이다. 하지만 협업을 하던지, 혹은 프로젝트를 진행하다 보면 명칭을 참조하는 문장이 필연적으로 길어진다. 이로 인해 번거로움과 오타 발생 확률이 높아져 오히려 생산성이 떨어질 수 있다. 그래서 &lt;span style=&quot;color: #006dd7;&quot;&gt;긴 참조문을 짧게 쓸 수 있는&lt;/span&gt; &lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;using 문장&lt;/span&gt;&lt;/b&gt;이 제공된다. &lt;span style=&quot;color: #ee2323;&quot;&gt;using 다음에 참조할 네임스페이스 명을 적으면 컴파일러가 using 선언된 네임스페이스를 항상 참조&lt;/span&gt;한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhnmlk/btsIUTQ3n8s/FEn3NREkjjg47sUJ6j4QKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhnmlk/btsIUTQ3n8s/FEn3NREkjjg47sUJ6j4QKK/img.png&quot; data-origin-width=&quot;771&quot; data-origin-height=&quot;228&quot; data-is-animation=&quot;false&quot; style=&quot;width: 70.8117%; margin-right: 10px;&quot; data-widthpercent=&quot;71.64&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhnmlk/btsIUTQ3n8s/FEn3NREkjjg47sUJ6j4QKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbhnmlk%2FbtsIUTQ3n8s%2FFEn3NREkjjg47sUJ6j4QKK%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;771&quot; height=&quot;228&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Lz8yi/btsIVHQfhz6/JWIkMVxaK8muX1cpkJbxd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Lz8yi/btsIVHQfhz6/JWIkMVxaK8muX1cpkJbxd1/img.png&quot; data-origin-width=&quot;356&quot; data-origin-height=&quot;266&quot; data-is-animation=&quot;false&quot; style=&quot;width: 28.0255%;&quot; data-widthpercent=&quot;28.36&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Lz8yi/btsIVHQfhz6/JWIkMVxaK8muX1cpkJbxd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLz8yi%2FbtsIVHQfhz6%2FJWIkMVxaK8muX1cpkJbxd1%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;356&quot; height=&quot;266&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;using문을 사용하기 전(좌)과 후(우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;입출력&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;　입출력 기능을 사용하려면 앞서 언급했던 using문을 이용해 System 선언을 해주고, Console 메서드를 통해 모니터에 문자열을 출력하고 키보드 등으로부터 입력을 받을 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1722850600993&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;

namespace ex
{
    class ex1
    {
        static void Main(string[] args)
        {
            Console.Write(&quot;Hello&quot;);
            Console.Write(&quot; World!\n&quot;);
            Console.WriteLine(&quot;Hello &quot; + &quot;World!&quot;);

            string str = &quot;World!&quot;;
            Console.WriteLine($&quot;Hello {str}&quot;);
        }
    }
}&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;355&quot; data-origin-height=&quot;122&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6pSYu/btsIWaR8NyL/99AXuuqnAXkUQYqA2DBiU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6pSYu/btsIWaR8NyL/99AXuuqnAXkUQYqA2DBiU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6pSYu/btsIWaR8NyL/99AXuuqnAXkUQYqA2DBiU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6pSYu%2FbtsIWaR8NyL%2F99AXuuqnAXkUQYqA2DBiU1%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;355&quot; height=&quot;122&quot; data-origin-width=&quot;355&quot; data-origin-height=&quot;122&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;size18&quot;&gt;　&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;　C#에서 주로 사용하는 &lt;span style=&quot;color: #006dd7;&quot;&gt;출력 메서드&lt;/span&gt;는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Write&lt;/b&gt;&lt;/span&gt; 혹은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;WriteLine&lt;/b&gt;&lt;/span&gt;이다. 전자는 &lt;span style=&quot;color: #006dd7;&quot;&gt;줄 바꿈을 지원하지 않고, 후자는 자동으로 줄을 바꾸어준다&lt;/span&gt;. 이때 여러 개의 변수를 한 번에 출력할 때는 문자열과 + 연산자를 사용하여 연결하거나, 문자열 리터럴 앞에 $를 붙이는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;보간(Interpolation)&lt;/b&gt;&lt;/span&gt;을 사용할 수도 있다. 이 외에 형식을 지정하거나, 자릿수와 정밀도 등을 설정할 수도 있으니, 해당 내용은 공식 문서를 참조하면 좋을 것 같다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1722850928945&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;

namespace ex
{
    class ex1
    {
        static void Main(string[] args)
        {
            Console.Write(&quot;Write your age: &quot;);
            int age = Convert.ToInt32(Console.ReadLine());

            Console.Write(&quot;Write your last name: &quot;);
            string name = Console.ReadLine();

            Console.WriteLine($&quot;age: {age}, last name: {name}&quot;);
        }
    }
}&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;354&quot; data-origin-height=&quot;123&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d30vZ7/btsIUhE0UiD/bivVNeovR7lowmGGUbLUa0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d30vZ7/btsIUhE0UiD/bivVNeovR7lowmGGUbLUa0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d30vZ7/btsIUhE0UiD/bivVNeovR7lowmGGUbLUa0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd30vZ7%2FbtsIUhE0UiD%2FbivVNeovR7lowmGGUbLUa0%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;354&quot; height=&quot;123&quot; data-origin-width=&quot;354&quot; data-origin-height=&quot;123&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;　콘솔의 &lt;span style=&quot;color: #006dd7;&quot;&gt;입력 메서드&lt;/span&gt;는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;ReadLine()&lt;/b&gt;&lt;/span&gt;이다. &lt;span style=&quot;color: #ee2323;&quot;&gt;문자열로 입력받기 때문에 만약 다른 자료형이 필요하다면 문자열로 받은 후 변환&lt;/span&gt;해서 사용해야 한다. 만약 문자열이나 정수 등의 자료형이 아닌 &lt;span style=&quot;color: #006dd7;&quot;&gt;키 자체를 입력받을 때&lt;/span&gt;는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;ReadKey()&lt;/b&gt;&lt;/span&gt;라는 메서드를 호출해야 한다. 키 하나만 입력받기 때문에 엔터키를 누르지 않아도 즉시 리턴된다. 해당 내용은 추후에 반복문과 연계해서 설명해 주도록 하겠다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;요약&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;C# 입출력&lt;br /&gt;1. 입력: Console.ReadLine()&lt;br /&gt;2. 출력: Console.WriteLine(), Console.Write()&lt;/blockquote&gt;</description>
      <category>Language/C#</category>
      <category>c#</category>
      <category>console</category>
      <category>READ</category>
      <category>System</category>
      <category>Write</category>
      <category>닷넷</category>
      <category>입출력</category>
      <category>콘솔</category>
      <author>nowkoes</author>
      <guid isPermaLink="true">https://maloveforme.tistory.com/289</guid>
      <comments>https://maloveforme.tistory.com/289#entry289comment</comments>
      <pubDate>Mon, 5 Aug 2024 18:54:25 +0900</pubDate>
    </item>
  </channel>
</rss>