<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Software Engineer</title>
    <link>https://s-engineer.tistory.com/</link>
    <description>English &amp;amp; Software Engineering Blog - Sean</description>
    <language>ko</language>
    <pubDate>Mon, 27 Jul 2026 19:32:34 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>J-sean</managingEditor>
    <image>
      <title>Software Engineer</title>
      <url>https://tistory1.daumcdn.net/tistory/2983016/attach/de381f1a7fbc408183cc2309d781486d</url>
      <link>https://s-engineer.tistory.com</link>
    </image>
    <item>
      <title>[Solidworks] Tap Thread 나사산 표시</title>
      <link>https://s-engineer.tistory.com/728</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;솔리드웍스에서 주석 나사산을 표시해 보자. 실제 모델을 깎아서 구현하는 나사산이 아닌 그림으로만 표시하는 나사산이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1210&quot; data-origin-height=&quot;1172&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSY5fa/dJMcafU3bLu/cdIqaoedqnuYGuSlQtC4Mk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSY5fa/dJMcafU3bLu/cdIqaoedqnuYGuSlQtC4Mk/img.png&quot; data-alt=&quot;화면에 나사산이 표시되도록 Document Properties - Detailing에서 Cosmetic threads와 Shaded cosmetic threads를 선택한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSY5fa/dJMcafU3bLu/cdIqaoedqnuYGuSlQtC4Mk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSY5fa%2FdJMcafU3bLu%2FcdIqaoedqnuYGuSlQtC4Mk%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;1210&quot; height=&quot;1172&quot; data-origin-width=&quot;1210&quot; data-origin-height=&quot;1172&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;화면에 나사산이 표시되도록 Document Properties - Detailing에서 Cosmetic threads와 Shaded cosmetic threads를 선택한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1583&quot; data-origin-height=&quot;979&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oOPZj/dJMcaiRJ35J/G2Nt374dLOCoUugYC5mqq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oOPZj/dJMcaiRJ35J/G2Nt374dLOCoUugYC5mqq1/img.png&quot; data-alt=&quot;Cosmetic threads는 1번 화살표가 가리키는 실선을 표시하고 Shaded cosmetic threads는 2번 화살표가 가리키는 음영 나사산을 표시한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oOPZj/dJMcaiRJ35J/G2Nt374dLOCoUugYC5mqq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoOPZj%2FdJMcaiRJ35J%2FG2Nt374dLOCoUugYC5mqq1%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;1583&quot; height=&quot;979&quot; data-origin-width=&quot;1583&quot; data-origin-height=&quot;979&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Cosmetic threads는 1번 화살표가 가리키는 실선을 표시하고 Shaded cosmetic threads는 2번 화살표가 가리키는 음영 나사산을 표시한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;603&quot; data-origin-height=&quot;1676&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dcb5pC/dJMcahL1SOf/Mnmzt1FDdJkd18D8iX59PK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dcb5pC/dJMcahL1SOf/Mnmzt1FDdJkd18D8iX59PK/img.png&quot; data-alt=&quot;Hole Wizard로 나사산을 만들 땐 Hole Type에 있는 두 가지 탭 중 하나를 선택해야 Options에 나사산 관련 옵션이 표시된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dcb5pC/dJMcahL1SOf/Mnmzt1FDdJkd18D8iX59PK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdcb5pC%2FdJMcahL1SOf%2FMnmzt1FDdJkd18D8iX59PK%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;1676&quot; data-origin-width=&quot;603&quot; data-origin-height=&quot;1676&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Hole Wizard로 나사산을 만들 땐 Hole Type에 있는 두 가지 탭 중 하나를 선택해야 Options에 나사산 관련 옵션이 표시된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;1667&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfHMjp/dJMcajiOsqh/wWawJchZM6kKyyMlXOMkrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfHMjp/dJMcajiOsqh/wWawJchZM6kKyyMlXOMkrk/img.png&quot; data-alt=&quot;Insert - Annotations - Cosmetic Thread...에서도 나사산을 만들 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfHMjp/dJMcajiOsqh/wWawJchZM6kKyyMlXOMkrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfHMjp%2FdJMcajiOsqh%2FwWawJchZM6kKyyMlXOMkrk%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;838&quot; height=&quot;1667&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;1667&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Insert - Annotations - Cosmetic Thread...에서도 나사산을 만들 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1370&quot; data-origin-height=&quot;1211&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7ahAv/dJMcadQlzUz/rhuxO8nC8QkUU227rfC9eK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7ahAv/dJMcadQlzUz/rhuxO8nC8QkUU227rfC9eK/img.png&quot; data-alt=&quot;만약 나사산이 표시되지 않는다면 View Top Level Annotations가 선택되어 있는지 확인하자.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7ahAv/dJMcadQlzUz/rhuxO8nC8QkUU227rfC9eK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7ahAv%2FdJMcadQlzUz%2FrhuxO8nC8QkUU227rfC9eK%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;1370&quot; height=&quot;1211&quot; data-origin-width=&quot;1370&quot; data-origin-height=&quot;1211&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;만약 나사산이 표시되지 않는다면 View Top Level Annotations가 선택되어 있는지 확인하자.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CAD</category>
      <category>SolidWorks</category>
      <category>tap</category>
      <category>thread</category>
      <category>나사</category>
      <category>나사산</category>
      <category>솔리드웍스</category>
      <category>음영</category>
      <category>표시</category>
      <author>J-sean</author>
      <guid isPermaLink="true">https://s-engineer.tistory.com/728</guid>
      <comments>https://s-engineer.tistory.com/728#entry728comment</comments>
      <pubDate>Sun, 26 Jul 2026 23:10:45 +0900</pubDate>
    </item>
    <item>
      <title>[C#] Asynchronously Write DateTime and Value Text File 시간, 값 데이터 텍스트 파일 비동기 쓰기</title>
      <link>https://s-engineer.tistory.com/727</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;시간과 임의의 값을 비동기적으로 텍스트 파일로 저장하고 확인해 보자.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;867&quot; data-origin-height=&quot;548&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAB3Md/dJMcadCFsRf/Lx9Q3wp41WxRt0518Iif11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAB3Md/dJMcadCFsRf/Lx9Q3wp41WxRt0518Iif11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAB3Md/dJMcadCFsRf/Lx9Q3wp41WxRt0518Iif11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAB3Md%2FdJMcadCFsRf%2FLx9Q3wp41WxRt0518Iif11%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;867&quot; height=&quot;548&quot; data-origin-width=&quot;867&quot; data-origin-height=&quot;548&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;pre id=&quot;code_1784533109236&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;namespace DateTimeValue
{
    public partial class Form1 : Form
    {
        private readonly string filePath = &quot;output.txt&quot;;        
        readonly Random random = new Random();

        public Form1()
        {
            InitializeComponent();

            button1.Click += Button1_Click;
            button2.Click += Button2_Click;
        }

        // 비동기적으로 파일에 현재 시간과 랜덤 값을 기록하는 버튼 클릭 이벤트 핸들러
        // 비동기 메서드는 Task를 반환하는게 좋지만 이벤트 핸들러는 void를 반환해야 하므로 어쩔 수 없이 async void를 사용
        private async void Button1_Click(object? sender, EventArgs e)
        {
            try
            {
                // 버튼 클릭 시 버튼을 비활성화하여 중복 클릭 방지
                button1.Enabled = false; // 버튼 비활성화

                FileStream fileStream = new FileStream (
                    filePath,
                    FileMode.Append,  // 파일이 없으면 새로 생성하고, 있으면 이어쓰기
                    FileAccess.Write, // 쓰기 전용
                    FileShare.Read); // 다른 프로세스가 파일을 읽을 수 있도록 허용, 내가 쓰는 동안 다른 프로세스는 읽기 가능
                
                using (StreamWriter writer = new StreamWriter(fileStream, System.Text.Encoding.UTF8))
                {
                    for (int i = 0; i &amp;lt; 5; i++)
                    {
                        await writer.WriteLineAsync(DateTime.Now.ToString(&quot;yyyyMMdd-HHmmss&quot;) + &quot; &quot; + random.Next());
                        // 비동기적으로 파일에 기록
                        await writer.FlushAsync();
                        // 비동기적으로 버퍼를 파일에 기록

                        // 비동기적으로 1초 대기
                        await Task.Delay(1000);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($&quot;오류 발생: {ex.Message}&quot;);
            }
            finally
            {
                button1.Enabled = true; // 버튼 활성화
            }
        }

        private async void Button2_Click(object? sender, EventArgs e)
        {
            listBox1.Items.Clear(); // 기존 항목 제거
            try
            {
                FileStream fileStream = new FileStream(
                    filePath,
                    FileMode.Open, // 파일이 없으면 예외 발생
                    FileAccess.Read, // 읽기 전용
                    FileShare.ReadWrite); // 다른 프로세스가 파일을 읽을 수 있도록 허용, 내가 읽는 동안 다른 프로세스도 읽기/쓰기 가능

                using (StreamReader reader = new StreamReader(fileStream, System.Text.Encoding.UTF8))
                {
                    string? line;
                    while ((line = await reader.ReadLineAsync()) != null)
                    {
                        //listBox1.Items.Add(line);

                        // 공백 문자를 기준으로 분리
                        string[] parts = line.Split(' ');
                        if (parts.Length == 2)
                        {
                            listBox1.Items.Add(&quot;시간: &quot; + DateTime.ParseExact(parts[0], &quot;yyyyMMdd-HHmmss&quot;, null) + &quot;\t값: &quot; + parts[1]);
                            // ParseExact() 세번째 인자를 null로 주면 현재 문화권의 형식으로 해석, InvariantCulture를 주면 문화권에 상관없이 해석
                        }
                        else
                        {
                            listBox1.Items.Add(&quot;Error&quot;);
                        }
                    }
                }
            }
            catch (FileNotFoundException)
            {
                MessageBox.Show($&quot;{filePath} 파일이 존재하지 않습니다.&quot;);
            }
            catch (Exception ex)
            {
                MessageBox.Show($&quot;오류 발생: {ex.Message}&quot;);
            }            
        }
    }
}&lt;/code&gt;&lt;/pre&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;804&quot; data-origin-height=&quot;497&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cq2Cbb/dJMcaazlJHl/vYtbNJD9hCufKpFRFBksQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cq2Cbb/dJMcaazlJHl/vYtbNJD9hCufKpFRFBksQk/img.png&quot; data-alt=&quot;Record 버튼을 클릭해 로그 파일을 생성하고 Show 버튼을 클릭해 원하는 로그 파일을 선택하면 리스트 박스에 로그가 표시된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cq2Cbb/dJMcaazlJHl/vYtbNJD9hCufKpFRFBksQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcq2Cbb%2FdJMcaazlJHl%2FvYtbNJD9hCufKpFRFBksQk%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;804&quot; height=&quot;497&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;497&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Record 버튼을 클릭해 로그 파일을 생성하고 Show 버튼을 클릭해 원하는 로그 파일을 선택하면 리스트 박스에 로그가 표시된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래프를 추가해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;871&quot; data-origin-height=&quot;549&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c3MCno/dJMcab54xv6/jKK9LV92BMdzQSS4xS8zLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c3MCno/dJMcab54xv6/jKK9LV92BMdzQSS4xS8zLk/img.png&quot; data-alt=&quot;Graph 버튼을 추가한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c3MCno/dJMcab54xv6/jKK9LV92BMdzQSS4xS8zLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc3MCno%2FdJMcab54xv6%2FjKK9LV92BMdzQSS4xS8zLk%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;871&quot; height=&quot;549&quot; data-origin-width=&quot;871&quot; data-origin-height=&quot;549&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Graph 버튼을 추가한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1784616955643&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System.Diagnostics;

namespace DateTimeValue
{
    public partial class Form1 : Form
    {
        internal string filePath = string.Empty; // Form2에서 접근할 수 있도록 internal로 선언
        readonly Random random = new Random();

        public Form1()
        {
            InitializeComponent();

            button1.Click += Button1_Click;
            button2.Click += Button2_Click;
            button3.Click += Button3_Click;
        }

        // 비동기적으로 파일에 현재 시간과 랜덤 값을 기록하는 버튼 클릭 이벤트 핸들러
        // 비동기 메서드는 Task를 반환하는게 좋지만 이벤트 핸들러는 void를 반환해야 하므로 어쩔 수 없이 async void를 사용
        private async void Button1_Click(object? sender, EventArgs e)
        {
            try
            {
                // 버튼 클릭 시 버튼을 비활성화하여 중복 클릭 방지
                button1.Enabled = false; // 버튼 비활성화

                int count = 120; // 테스트를 위해 120회(120초)만 기록
                string mm = string.Empty;
                string now = string.Empty;
                bool needNewFile = false; // 새로운 파일 생성 여부를 나타내는 플래그

                while (true)
                {
                    filePath = DateTime.Now.ToString(&quot;yyyyMMdd-HHmmss&quot;) + &quot;.txt&quot;; // 파일 이름을 현재 시간으로 설정                    
                    mm = Path.GetFileName(filePath).Substring(11, 2); // 파일 이름에서 '분'만 추출

                    FileStream fileStream = new FileStream(
                        filePath,
                        FileMode.Append,  // 파일이 없으면 새로 생성하고, 있으면 이어쓰기
                        FileAccess.Write, // 쓰기 전용
                        FileShare.Read); // 다른 프로세스가 파일을 읽을 수 있도록 허용, 내가 쓰는 동안 다른 프로세스는 읽기 가능

                    using (StreamWriter writer = new StreamWriter(fileStream, System.Text.Encoding.UTF8))
                    {
                        while (true)
                        {
                            now = DateTime.Now.ToString(&quot;yyyyMMdd-HHmmss&quot;);
                            if (now.Substring(11, 2) != mm) // 현재 '분'이 파일 이름의 '분'과 다르면
                            {
                                needNewFile = true;
                                break; // 루프 종료하여 새로운 파일 생성
                            }

                            await writer.WriteLineAsync(now + &quot; &quot; + random.Next(1, 11)); // 1부터 10까지의 랜덤 값을 기록
                            // 비동기적으로 파일에 기록
                            await writer.FlushAsync();
                            // 비동기적으로 버퍼를 파일에 기록

                            await Task.Delay(1000);
                            // 비동기적으로 1초 대기

                            count--;
                            if (count &amp;lt; 0)
                                break; // 기록 횟수가 0이 되면 루프 종료
                            Debug.WriteLine($&quot;남은 기록 횟수: {count}&quot;);
                        }
                    }

                    // needNewFile보다 count를 먼저 확인하여 무한 루프를 방지
                    if (count &amp;lt; 0)
                    {
                        break; // 무한 루프 종료
                    }
                    if (needNewFile)
                    {
                        needNewFile = false; // 새로운 파일 생성 여부 플래그 초기화
                        continue; // 새로운 파일 생성 루프 시작
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($&quot;오류 발생: {ex.Message}&quot;);
            }
            finally
            {
                button1.Enabled = true; // 버튼 활성화
            }
        }

        private async void Button2_Click(object? sender, EventArgs e)
        {
            FileDialog fileDialog = new OpenFileDialog();
            fileDialog.InitialDirectory = Application.StartupPath; // 실행 파일이 있는 폴더 경로
            fileDialog.Filter = &quot;텍스트 파일 (*.txt)|*.txt|모든 파일 (*.*)|*.*&quot;;
            fileDialog.Title = &quot;파일 선택&quot;;
            fileDialog.DefaultExt = &quot;txt&quot;;

            if (fileDialog.ShowDialog() == DialogResult.OK)
                filePath = fileDialog.FileName;
            else
                return; // 파일 선택 취소 시 종료

            listBox1.Items.Clear(); // 기존 항목 제거

            try
            {
                FileStream fileStream = new FileStream(
                    filePath,
                    FileMode.Open, // 파일이 없으면 예외 발생
                    FileAccess.Read, // 읽기 전용
                    FileShare.ReadWrite); // 다른 프로세스가 파일을 읽을 수 있도록 허용, 내가 읽는 동안 다른 프로세스도 읽기/쓰기 가능

                using (StreamReader reader = new StreamReader(fileStream, System.Text.Encoding.UTF8))
                {
                    string? line;
                    while ((line = await reader.ReadLineAsync()) != null)
                    {
                        //listBox1.Items.Add(line);

                        // 공백 문자를 기준으로 문자열 분리
                        string[] parts = line.Split(' ');
                        if (parts.Length == 2)
                        {
                            listBox1.Items.Add(&quot;시간: &quot; + DateTime.ParseExact(parts[0], &quot;yyyyMMdd-HHmmss&quot;, null) + &quot;\t값: &quot; + parts[1]);
                            // ParseExact() 세번째 인자를 null로 주면 현재 문화권의 형식으로 해석, InvariantCulture를 주면 문화권에 상관없이 해석
                        }
                        else
                        {
                            listBox1.Items.Add(&quot;Error&quot;);
                        }
                    }
                }
            }
            catch (FileNotFoundException)
            {
                MessageBox.Show($&quot;{filePath} 파일이 존재하지 않습니다.&quot;);
            }
            catch (Exception ex)
            {
                MessageBox.Show($&quot;오류 발생: {ex.Message}&quot;);
            }
        }

        private void Button3_Click(object? sender, EventArgs e)
        {
            Form2 dlg = new Form2();
            dlg.Owner = this; // Form1을 Form2의 소유자로 설정
            // 아니면 아래 if문에서 dlg.ShowDialog(this) 명령으로 Form1을 Form2의 소유자로 설정할 수도 있다
            if (dlg.ShowDialog() == DialogResult.OK)
                ; // Form2에서 OK 버튼을 클릭하면 처리할 내용 작성

            dlg.Close();
            dlg.Dispose();
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Visual Studio - Project - Add Form(Windows Forms)... 을 클릭하고 Form을 하나 추가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;866&quot; data-origin-height=&quot;552&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c2mFm7/dJMcadQhlg1/uJVlhJI0n4r90KoICdjGkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c2mFm7/dJMcadQhlg1/uJVlhJI0n4r90KoICdjGkK/img.png&quot; data-alt=&quot;버튼을 하나 배치한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c2mFm7/dJMcadQhlg1/uJVlhJI0n4r90KoICdjGkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc2mFm7%2FdJMcadQhlg1%2FuJVlhJI0n4r90KoICdjGkK%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;866&quot; height=&quot;552&quot; data-origin-width=&quot;866&quot; data-origin-height=&quot;552&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;버튼을 하나 배치한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2012&quot; data-origin-height=&quot;1909&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DVjis/dJMcadQhlrQ/n8oA77JdWnM00QDKk3qwY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DVjis/dJMcadQhlrQ/n8oA77JdWnM00QDKk3qwY1/img.png&quot; data-alt=&quot;NuGet Package Manager - LiveChartsCore.SkiaSharpView.WinForms 를 설치한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DVjis/dJMcadQhlrQ/n8oA77JdWnM00QDKk3qwY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDVjis%2FdJMcadQhlrQ%2Fn8oA77JdWnM00QDKk3qwY1%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;2012&quot; height=&quot;1909&quot; data-origin-width=&quot;2012&quot; data-origin-height=&quot;1909&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;NuGet Package Manager - LiveChartsCore.SkiaSharpView.WinForms 를 설치한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1784617301714&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using LiveChartsCore;
using LiveChartsCore.Defaults;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.WinForms;

using System.Collections.ObjectModel;
using System.Diagnostics;

namespace DateTimeValue
{
    public partial class Form2 : Form
    {
        private readonly ObservableCollection&amp;lt;DateTimePoint&amp;gt; values = new ObservableCollection&amp;lt;DateTimePoint&amp;gt;();

        public Form2()
        {
            InitializeComponent();

            button1.DialogResult = DialogResult.OK; // 버튼 클릭 시 DialogResult를 OK로 설정
            this.Load += Form2_Load; // Form2 로드 이벤트에 핸들러 추가                        
        }

        private async void Form2_Load(object? sender, EventArgs e)
        {
            Form1? parent = Owner as Form1; // Form1 인스턴스를 가져옴

            if (parent != null)
                if (string.IsNullOrEmpty(parent.filePath))
                {
                    // 파일 경로가 설정되지 않은 경우, 메시지 박스를 표시하고 종료
                    MessageBox.Show(&quot;파일 경로가 설정되지 않았습니다.&quot;);
                    // Form2 종료
                    Close();
                }
                else
                {
                    try
                    {
                        FileStream fileStream = new FileStream(
                            parent.filePath,
                            FileMode.Open, // 파일이 없으면 예외 발생
                            FileAccess.Read, // 읽기 전용
                            FileShare.ReadWrite); // 다른 프로세스가 파일을 읽을 수 있도록 허용, 내가 읽는 동안 다른 프로세스도 읽기/쓰기 가능

                        using (StreamReader reader = new StreamReader(fileStream, System.Text.Encoding.UTF8))
                        {
                            string? line;
                            while ((line = await reader.ReadLineAsync()) != null)
                            {
                                //listBox1.Items.Add(line);

                                // 공백 문자를 기준으로 분리
                                string[] parts = line.Split(' ');
                                if (parts.Length == 2)
                                {
                                    values.Add(new DateTimePoint(DateTime.ParseExact(parts[0], &quot;yyyyMMdd-HHmmss&quot;, null), double.Parse(parts[1])));
                                    // ParseExact() 세번째 인자를 null로 주면 현재 문화권의 형식으로 해석, InvariantCulture를 주면 문화권에 상관없이 해석
                                }
                                else
                                {
                                    Debug.WriteLine($&quot;잘못된 형식의 데이터: {line}&quot;);
                                }
                            }

                            ISeries[] series = new ISeries[]
                            {
                                new LineSeries&amp;lt;DateTimePoint&amp;gt;
                                {
                                    Values = values,
                                    Fill = null
                                }
                            };

                            CartesianChart cartesianChart = new CartesianChart
                            {
                                Series = series,
                                ZoomMode = LiveChartsCore.Measure.ZoomAndPanMode.X,
                                Location = new System.Drawing.Point(0, 0),
                                Size = new System.Drawing.Size(800, 300),
                                Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom,
                                // X축 설정
                                XAxes = new Axis[]
                                {
                                    //new Axis
                                    //{
                                    //    Labeler = value =&amp;gt; new DateTime((long)value).ToString(&quot;HH:mm:ss&quot;),
                                    //    MinStep = TimeSpan.FromSeconds(1).Ticks // 1초 단위 (Ticks 단위)
                                    //    // MinStep을 설정하면 축의 최소 간격을 지정할 수 있는데 DateTimePoint 데이터를 사용하는
                                    //    // 경우에는 제대로 동작하지 않는다. 이 경우에는 DateTimeAxis를 사용하는 것이 더 적합하다.
                                    //}

                                    // 1초 단위 축 생성 및 DateTime 포맷터 지정
                                    // 위 주석 처리된 Axis를 직접 생성하는 것보다 DateTimeAxis를 사용하는 것이 더 간단하고 직관적이다
                                    new DateTimeAxis(TimeSpan.FromSeconds(1), date =&amp;gt; date.ToString(&quot;HH:mm:ss&quot;))
                                    //{
                                    //    Name = &quot;Time&quot;,
                                    //    MinStep = TimeSpan.FromSeconds(2).Ticks, // 최소 2초 간격 유지를 원하는 경우
                                    //    LabelsRotation = 15 // 라벨 회전 각도
                                    //}
                                },
                                // Y축 설정
                                //YAxes = new Axis[]
                                //{
                                //    new Axis
                                //    {
                                //        Labeler = value =&amp;gt; value.ToString(&quot;F2&quot;) // 소수점 2자리까지 표시
                                //    }
                                //}
                            };

                            Controls.Add(cartesianChart);
                        }
                    }
                    catch (FileNotFoundException)
                    {
                        MessageBox.Show($&quot;{parent.filePath} 파일이 존재하지 않습니다.&quot;);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show($&quot;오류 발생: {ex.Message}&quot;);
                    }
                }
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트를 빌드하고 실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;497&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WLuNx/dJMcagTRyNI/NkJgGKYC4NjIIzDyVfwv4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WLuNx/dJMcagTRyNI/NkJgGKYC4NjIIzDyVfwv4K/img.png&quot; data-alt=&quot;Record 버튼을 클릭해 로그 파일을 생성하고 Show 버튼을 클릭해 원하는 로그 파일을 선택하면 리스트 박스에 로그가 표시된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WLuNx/dJMcagTRyNI/NkJgGKYC4NjIIzDyVfwv4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWLuNx%2FdJMcagTRyNI%2FNkJgGKYC4NjIIzDyVfwv4K%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;804&quot; height=&quot;497&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;497&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Record 버튼을 클릭해 로그 파일을 생성하고 Show 버튼을 클릭해 원하는 로그 파일을 선택하면 리스트 박스에 로그가 표시된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;497&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/X8QiF/dJMcafAD5OJ/GvSi3fP8rHQYTZHIcV1S9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/X8QiF/dJMcafAD5OJ/GvSi3fP8rHQYTZHIcV1S9K/img.png&quot; data-alt=&quot;Form1에서 Graph 버튼을 클릭하면 Form2가 열리고 그래프가 표시된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/X8QiF/dJMcafAD5OJ/GvSi3fP8rHQYTZHIcV1S9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FX8QiF%2FdJMcafAD5OJ%2FGvSi3fP8rHQYTZHIcV1S9K%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;804&quot; height=&quot;497&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;497&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Form1에서 Graph 버튼을 클릭하면 Form2가 열리고 그래프가 표시된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;497&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kIsbx/dJMcajiJ3cB/hGqXorn0mi7b5kkaHkHrOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kIsbx/dJMcajiJ3cB/hGqXorn0mi7b5kkaHkHrOk/img.png&quot; data-alt=&quot;마우스로 Zooming 및 Panning을 할 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kIsbx/dJMcajiJ3cB/hGqXorn0mi7b5kkaHkHrOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkIsbx%2FdJMcajiJ3cB%2FhGqXorn0mi7b5kkaHkHrOk%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;804&quot; height=&quot;497&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;497&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;마우스로 Zooming 및 Panning을 할 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://s-engineer.tistory.com/682&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;2026.04.20 - [C#] - [LiveCharts] 설치 및 기본 차트 그리기&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>C#</category>
      <category>Asynchronously</category>
      <category>Datetime</category>
      <category>TEXT</category>
      <category>UTF8</category>
      <category>날짜</category>
      <category>비동기</category>
      <category>시간</category>
      <category>쓰기</category>
      <category>텍스트</category>
      <category>파일</category>
      <author>J-sean</author>
      <guid isPermaLink="true">https://s-engineer.tistory.com/727</guid>
      <comments>https://s-engineer.tistory.com/727#entry727comment</comments>
      <pubDate>Mon, 20 Jul 2026 16:44:28 +0900</pubDate>
    </item>
    <item>
      <title>[CFMEGA2] Serial Communication 시리얼 통신</title>
      <link>https://s-engineer.tistory.com/726</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;CFMEGA2는 2개의 RS232 통신 채널이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터와 USB로 연결하고 시리얼 통신을 하는 경우는 아래 링크의 예와 같이 그냥 Serial 클래스를 사용하면 되지만 RS232 통신을 위한 핀(TX, RX, SG)을 직접 사용해 통신하는 경우는 Serial1, Serial2 클래스를 사용해야 한다.&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: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://s-engineer.tistory.com/252&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2021.03.24 - [Embedded] - Digital Temperature Sensor DS18B20 with Arduino - 아두이노 방수 온도 센서&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;569&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbggzc/dJMcafgeU5k/KGkXlmCTxESsrAGqm4aY81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbggzc/dJMcafgeU5k/KGkXlmCTxESsrAGqm4aY81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbggzc/dJMcafgeU5k/KGkXlmCTxESsrAGqm4aY81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbbggzc%2FdJMcafgeU5k%2FKGkXlmCTxESsrAGqm4aY81%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;800&quot; height=&quot;569&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;569&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2268&quot; data-origin-height=&quot;3556&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/O1K0q/dJMcaftIgYh/rhbtndN30eo8lU6Piq4f9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/O1K0q/dJMcaftIgYh/rhbtndN30eo8lU6Piq4f9K/img.png&quot; data-alt=&quot;Serial1(Tx1, Rx1, SG)에 연결&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/O1K0q/dJMcaftIgYh/rhbtndN30eo8lU6Piq4f9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FO1K0q%2FdJMcaftIgYh%2FrhbtndN30eo8lU6Piq4f9K%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;2268&quot; height=&quot;3556&quot; data-origin-width=&quot;2268&quot; data-origin-height=&quot;3556&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Serial1(Tx1, Rx1, SG)에 연결&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1783585050678&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;OneWire.h&amp;gt;
#include &amp;lt;DallasTemperature.h&amp;gt;
#include &amp;lt;LowPower.h&amp;gt;

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
#define TEMPERATURE_PRECISION 9 // Lower resolution

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&amp;amp;oneWire);

int numberOfDevices; // Number of temperature devices found
uint8_t sensor[3][8] = { { 0x28, 0xB8, 0x22, 0x94, 0x65, 0x25, 0x06, 0x5F},
                         { 0x28, 0xBB, 0x38, 0x60, 0x65, 0x25, 0x06, 0xB8},
                         { 0x28, 0x82, 0xBD, 0x0B, 0x92, 0x25, 0x06, 0x29} };

void setup(void)
{
  // start Serial1 port
  Serial1.begin(9600);
  
  // Start up the library
  sensors.begin();

  // Grab a count of devices on the wire
  numberOfDevices = sensors.getDeviceCount();

  // locate devices on the bus
  Serial1.print(&quot;Locating devices... &quot;);
  Serial1.print(&quot;Found &quot;);
  Serial1.print(numberOfDevices, DEC);
  Serial1.println(&quot; devices.&quot;);

  // report parasite power requirements
  Serial1.print(&quot;Parasite power is: &quot;);
  if (sensors.isParasitePowerMode())
    Serial1.println(&quot;ON&quot;);
  else
    Serial1.println(&quot;OFF&quot;);
  
  Serial1.print(&quot;Setting resolution to &quot;);
  Serial1.println(TEMPERATURE_PRECISION, DEC);

  // set the resolution to 9 bit per device
  for (uint8_t i = 0; i &amp;lt; numberOfDevices; i++){
    if (!sensors.setResolution(sensor[i], TEMPERATURE_PRECISION))
      Serial1.print(&quot;Failed to set resolution&quot;);
  }
  
  for (uint8_t i = 0; i &amp;lt; numberOfDevices; i++){
    Serial1.print(&quot;Sensor &quot;);
    Serial1.print(i);
    Serial1.print(&quot; Resolution: &quot;);
    Serial1.println(sensors.getResolution(sensor[i]), DEC);
  }  
}

// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress, uint8_t id)
{
  float tempC = sensors.getTempC(deviceAddress);
  if (tempC == DEVICE_DISCONNECTED_C)
  {
    Serial1.println(&quot;Error: Could not read temperature data&quot;);
    return;
  }
  Serial1.print(id);
  Serial1.print(&quot;: &quot;);
  Serial1.print(tempC);  
  Serial1.println(&quot;&amp;deg;C&quot;);
}

void loop (void)
{
  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  sensors.requestTemperatures();

  for (uint8_t i = 0; i &amp;lt; numberOfDevices; i++){
    printTemperature(sensor[i], i);
  }
  Serial1.println(&quot;-----------&quot;);
  Serial1.flush();
  // Serial1.print()가 종료되어도 데이터를 전송하는데 시간이 걸린다.
  // 데이터를 다 보내기도 전에 LowPower.powerDown()가 실행되면 아두이노가 바로 잠들어 버린다.
  // 아두이노가 잠들기 전에 Serial1.flush()로 시리얼 버퍼에 남은 데이터를 모두 전송해야 한다.
  // digitalWrite() 등으로 LED나 다른 하드웨어를 작동시키고 있었다면 delay(100) 같은 명령으로
  // 반응할 수 있는 최소한의 시간을 주어야 한다.

  LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF);
  // SLEEP_1S: 아두이노를 1초 동안 잠들게 한다.
  // ADC_OFF: 잠자는 동안 아날로그 센서를 읽는 기능(ADC)을 꺼서 전기를 아낀다.
  // BOD_OFF: 저전압 감지 기능(BrownOut Detection)을 꺼서 전기를 더 많이 아낀다.
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Serial1 클래스를 사용해 코드를 작성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;563&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rpfC7/dJMcadiqpRH/FAqEZIvL4wk9iGDYQikvCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rpfC7/dJMcadiqpRH/FAqEZIvL4wk9iGDYQikvCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rpfC7/dJMcadiqpRH/FAqEZIvL4wk9iGDYQikvCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrpfC7%2FdJMcadiqpRH%2FFAqEZIvL4wk9iGDYQikvCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;563&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;563&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>Embedded</category>
      <category>arduino</category>
      <category>cfmega</category>
      <category>cfmega2</category>
      <category>Communication</category>
      <category>Serial</category>
      <category>산업용</category>
      <category>시리얼</category>
      <category>아두이노</category>
      <category>통신</category>
      <author>J-sean</author>
      <guid isPermaLink="true">https://s-engineer.tistory.com/726</guid>
      <comments>https://s-engineer.tistory.com/726#entry726comment</comments>
      <pubDate>Thu, 9 Jul 2026 17:19:23 +0900</pubDate>
    </item>
    <item>
      <title>[Hugging Face] Datasets 데이터셋</title>
      <link>https://s-engineer.tistory.com/725</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Hugging Face Datasets 라이브러리를 사용해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1783246303841&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import datasets

dataset = datasets.load_dataset(&quot;jaehy12/news3&quot;)
print(dataset)&lt;/code&gt;&lt;/pre&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;1730&quot; data-origin-height=&quot;980&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFJLu4/dJMcahSu2We/hYoxGRuy2FBOm6dK8qrbf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFJLu4/dJMcahSu2We/hYoxGRuy2FBOm6dK8qrbf1/img.png&quot; data-alt=&quot;처음 실행하면 데이터셋을 다운로드한다. C:\Users\Sean\.cache\huggingface\hub\datasets--msarmi9--korean-english-multitarget-ted-talks-task&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFJLu4/dJMcahSu2We/hYoxGRuy2FBOm6dK8qrbf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFJLu4%2FdJMcahSu2We%2FhYoxGRuy2FBOm6dK8qrbf1%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;1730&quot; height=&quot;980&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;980&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;처음 실행하면 데이터셋을 다운로드한다. C:\Users\Sean\.cache\huggingface\hub\datasets--msarmi9--korean-english-multitarget-ted-talks-task&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1783247893974&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import datasets

dataset = datasets.load_dataset(&quot;msarmi9/korean-english-multitarget-ted-talks-task&quot;)
print(dataset[&quot;train&quot;])
print(dataset[&quot;train&quot;].features)
print(dataset[&quot;train&quot;][0])
print(&quot;-&quot;*50)
print(dataset[&quot;validation&quot;])
print(dataset[&quot;validation&quot;].features)
print(dataset[&quot;validation&quot;][0])&lt;/code&gt;&lt;/pre&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;1730&quot; data-origin-height=&quot;560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r5UqZ/dJMcac4Lv4a/0LBQBFmLVuR8gIkHFDgZnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r5UqZ/dJMcac4Lv4a/0LBQBFmLVuR8gIkHFDgZnK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r5UqZ/dJMcac4Lv4a/0LBQBFmLVuR8gIkHFDgZnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr5UqZ%2FdJMcac4Lv4a%2F0LBQBFmLVuR8gIkHFDgZnK%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;1730&quot; height=&quot;560&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;560&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;pre id=&quot;code_1783248981091&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import datasets

# train, valudation, test 데이터셋 직접 만들기
data_dict = {
	&quot;train&quot;: [
		{&quot;text&quot;: &quot;I love programming.&quot;, &quot;label&quot;: 1},
		{&quot;text&quot;: &quot;Python is my favorite language.&quot;, &quot;label&quot;: 1},
		{&quot;text&quot;: &quot;I hate bugs in my code.&quot;, &quot;label&quot;: 0},
		{&quot;text&quot;: &quot;Debugging is a frustrating process.&quot;, &quot;label&quot;: 0},
		{&quot;text&quot;: &quot;I enjoy solving complex problems.&quot;, &quot;label&quot;: 1},
		{&quot;text&quot;: &quot;I dislike syntax errors.&quot;, &quot;label&quot;: 0},
		{&quot;text&quot;: &quot;I find coding to be a rewarding experience.&quot;, &quot;label&quot;: 1},
		{&quot;text&quot;: &quot;I get frustrated when my code doesn't work.&quot;, &quot;label&quot;: 0},
		{&quot;text&quot;: &quot;I love learning new programming languages.&quot;, &quot;label&quot;: 1},
		{&quot;text&quot;: &quot;I find it challenging to debug my code.&quot;, &quot;label&quot;: 0}
	],
	&quot;validation&quot;: [
		{&quot;text&quot;: &quot;I enjoy writing clean and efficient code.&quot;, &quot;label&quot;: 1},
		{&quot;text&quot;: &quot;I find it difficult to understand complex algorithms.&quot;, &quot;label&quot;: 0},
		{&quot;text&quot;: &quot;I love collaborating with other developers.&quot;, &quot;label&quot;: 1},
		{&quot;text&quot;: &quot;I get frustrated when I encounter unexpected errors.&quot;, &quot;label&quot;: 0},
		{&quot;text&quot;: &quot;I enjoy learning new programming paradigms.&quot;, &quot;label&quot;: 1}
	],
	&quot;test&quot;: [
		{&quot;text&quot;: &quot;I find it rewarding to solve challenging coding problems.&quot;, &quot;label&quot;: 1},
		{&quot;text&quot;: &quot;I dislike spending hours debugging my code.&quot;, &quot;label&quot;: 0},
		{&quot;text&quot;: &quot;I love exploring new programming frameworks.&quot;, &quot;label&quot;: 1},
		{&quot;text&quot;: &quot;I get frustrated when I can't find a solution to a coding problem.&quot;, &quot;label&quot;: 0},
		{&quot;text&quot;: &quot;I enjoy optimizing my code for better performance.&quot;, &quot;label&quot;: 1}
	]
}

# 데이터셋을 Hugging Face Datasets 라이브러리의 DatasetDict로 변환
dataset = datasets.DatasetDict({
	&quot;train&quot;: datasets.Dataset.from_list(data_dict[&quot;train&quot;]),
	&quot;validation&quot;: datasets.Dataset.from_list(data_dict[&quot;validation&quot;]),
	&quot;test&quot;: datasets.Dataset.from_list(data_dict[&quot;test&quot;])
})

# 데이터셋 확인
print(dataset)
print(dataset[&quot;train&quot;].features)
print(dataset[&quot;train&quot;][0])

# 파일로 저장
dataset.save_to_disk(&quot;my_dataset&quot;)&lt;/code&gt;&lt;/pre&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;1730&quot; data-origin-height=&quot;644&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6hPQ1/dJMcafmXDXT/Zw4PIOidO2kmuf111kC0H1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6hPQ1/dJMcafmXDXT/Zw4PIOidO2kmuf111kC0H1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6hPQ1/dJMcafmXDXT/Zw4PIOidO2kmuf111kC0H1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6hPQ1%2FdJMcafmXDXT%2FZw4PIOidO2kmuf111kC0H1%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;1730&quot; height=&quot;644&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;644&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;246&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKyYSU/dJMcaiqnI36/VZCFJjrELYq90BwKtBHlm1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKyYSU/dJMcaiqnI36/VZCFJjrELYq90BwKtBHlm1/img.png&quot; data-alt=&quot;프로젝트 폴더\my_dataset&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKyYSU/dJMcaiqnI36/VZCFJjrELYq90BwKtBHlm1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKyYSU%2FdJMcaiqnI36%2FVZCFJjrELYq90BwKtBHlm1%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;1064&quot; height=&quot;246&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;246&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로젝트 폴더\my_dataset&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1783250337834&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import datasets

# train, valudation, test 데이터셋 직접 만들기
data_dict = {
	&quot;text&quot;: [
		&quot;I love programming.&quot;,
		&quot;Python is my favorite language.&quot;,
		&quot;I hate bugs in my code.&quot;,
		&quot;Debugging is a frustrating process.&quot;,
		&quot;I enjoy solving complex problems.&quot;,
		&quot;I dislike syntax errors.&quot;,
		&quot;I find coding to be a rewarding experience.&quot;,
		&quot;I get frustrated when my code doesn't work.&quot;,
		&quot;I love learning new programming languages.&quot;,
		&quot;I find it challenging to debug my code.&quot;,
		&quot;I enjoy writing clean and efficient code.&quot;,
		&quot;I find it difficult to understand complex algorithms.&quot;,
		&quot;I love collaborating with other developers.&quot;,
		&quot;I get frustrated when I encounter unexpected errors.&quot;,
		&quot;I enjoy learning new programming paradigms.&quot;,
		&quot;I find it rewarding to solve challenging coding problems.&quot;,
		&quot;I dislike spending hours debugging my code.&quot;,
		&quot;I love exploring new programming frameworks.&quot;,
		&quot;I get frustrated when I can't find a solution to a coding problem.&quot;,
		&quot;I enjoy optimizing my code for better performance.&quot;
	],
	&quot;label&quot;: [1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1]
}

# 데이터를 Hugging Face Datasets 형식으로 변환
dataset = datasets.Dataset.from_dict(data_dict)
# 데이터셋 확인
print(dataset)
print(dataset[0])  # 첫 번째 데이터 확인
print(&quot;-&quot;*50)

# 데이터셋을 train, test로 분리
split_dataset = dataset.train_test_split(test_size=0.2)
train_dataset = split_dataset[&quot;train&quot;]
test_dataset = split_dataset[&quot;test&quot;]

# 데이터셋 확인
print(train_dataset)
print(train_dataset[0])  # 첫 번째 train 데이터 확인
print(&quot;-&quot;*50)
print(test_dataset)
print(test_dataset[0])  # 첫 번째 test 데이터 확인&lt;/code&gt;&lt;/pre&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;1182&quot; data-origin-height=&quot;588&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AETZQ/dJMcafUMFCs/JA74KZxaimmNddZxNOX3Wk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AETZQ/dJMcafUMFCs/JA74KZxaimmNddZxNOX3Wk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AETZQ/dJMcafUMFCs/JA74KZxaimmNddZxNOX3Wk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAETZQ%2FdJMcafUMFCs%2FJA74KZxaimmNddZxNOX3Wk%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;1182&quot; height=&quot;588&quot; data-origin-width=&quot;1182&quot; data-origin-height=&quot;588&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://huggingface.co/docs/datasets/index&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Datasets&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI, ML, DL</category>
      <category>data</category>
      <category>DataSet</category>
      <category>face</category>
      <category>FINE</category>
      <category>hugging</category>
      <category>tuning</category>
      <category>딥러닝</category>
      <category>인공지능</category>
      <category>튜닝</category>
      <category>파인</category>
      <author>J-sean</author>
      <guid isPermaLink="true">https://s-engineer.tistory.com/725</guid>
      <comments>https://s-engineer.tistory.com/725#entry725comment</comments>
      <pubDate>Sun, 5 Jul 2026 19:58:07 +0900</pubDate>
    </item>
    <item>
      <title>[Hugging Face] Hugging Face Python Libraries 허깅 페이스 파이썬 라이브러리</title>
      <link>https://s-engineer.tistory.com/724</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;허깅 페이스 파이썬 라이브러리를 사용해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1783173945442&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import huggingface_hub

huggingface_hub.login(token=&quot;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&quot;)

# 로그인 후 사용자 정보 가져오기
user_info = huggingface_hub.whoami()
print(user_info['fullname'])

# 로그아웃
huggingface_hub.logout()&lt;/code&gt;&lt;/pre&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;692&quot; data-origin-height=&quot;140&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BBJWr/dJMcai4VhGJ/dAKSwwU5LYaHXTskjkr9F1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BBJWr/dJMcai4VhGJ/dAKSwwU5LYaHXTskjkr9F1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BBJWr/dJMcai4VhGJ/dAKSwwU5LYaHXTskjkr9F1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBBJWr%2FdJMcai4VhGJ%2FdAKSwwU5LYaHXTskjkr9F1%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;692&quot; height=&quot;140&quot; data-origin-width=&quot;692&quot; data-origin-height=&quot;140&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;pre id=&quot;code_1783175795762&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from huggingface_hub import InferenceClient

# 기본 질문-응답(question answering) 모델을 사용하여 질문에 대한 답변 생성
client = InferenceClient(token=&quot;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&quot;)
answer = client.question_answering(question=&quot;What is the capital of France?&quot;,
								   context=&quot;France is a country in Europe. Its capital is Paris.&quot;)
print(answer)
#print(answer.answer)

# 대화(conversational) 모델을 사용하여 대화 생성
client = InferenceClient(token=&quot;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&quot;,
						 model=&quot;Qwen/Qwen2.5-7B-Instruct&quot;)
messages = [{&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;프랑스의 수도는 어디야?&quot;}]
answer = client.chat_completion(messages=messages, max_tokens=100)
print(answer)
#print(answer.choices[0].message.content)

# 이미지 생성(text-to-image) 모델을 사용하여 텍스트를 기반으로 이미지 생성
client = InferenceClient(token=&quot;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&quot;,
						 model=&quot;stabilityai/stable-diffusion-xl-base-1.0&quot;)
image = client.text_to_image(&quot;A beautiful sunset over the mountains.&quot;)
image.save(&quot;sunset.png&quot;)&lt;/code&gt;&lt;/pre&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;1730&quot; data-origin-height=&quot;280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csOmyu/dJMcafgbrjY/X9Zt8kcd1PIwn2sk7cjZI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csOmyu/dJMcafgbrjY/X9Zt8kcd1PIwn2sk7cjZI0/img.png&quot; data-alt=&quot;모델에 따라 답변 및 여러 가지 정보가 생성된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csOmyu/dJMcafgbrjY/X9Zt8kcd1PIwn2sk7cjZI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsOmyu%2FdJMcafgbrjY%2FX9Zt8kcd1PIwn2sk7cjZI0%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;1730&quot; height=&quot;280&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;280&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모델에 따라 답변 및 여러 가지 정보가 생성된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;sunset.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cm0i7j/dJMcadbsOU4/YoQzeOtv7vucFqj22NcneK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cm0i7j/dJMcadbsOU4/YoQzeOtv7vucFqj22NcneK/img.png&quot; data-alt=&quot;텍스트에 따른 이미지를 생성한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cm0i7j/dJMcadbsOU4/YoQzeOtv7vucFqj22NcneK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcm0i7j%2FdJMcadbsOU4%2FYoQzeOtv7vucFqj22NcneK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;1024&quot; data-filename=&quot;sunset.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;텍스트에 따른 이미지를 생성한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block; text-align: center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-7506419418365672&quot; data-ad-slot=&quot;5217671153&quot;&gt;&lt;/ins&gt;
&lt;script&gt;     (adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1783229951513&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from transformers import AutoModelForCausalLM

model = AutoModelForCausalLM.from_pretrained(&quot;Qwen/Qwen3-0.6B&quot;, dtype=&quot;auto&quot;, device_map=&quot;auto&quot;)
# 미리 학습된 인과적 언어 모델을 로드한다.
print(model._get_name())&lt;/code&gt;&lt;/pre&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;1730&quot; data-origin-height=&quot;532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IQ6tB/dJMcabEMrc7/CnJ3J6iARXlvNnxmZUh4O0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IQ6tB/dJMcabEMrc7/CnJ3J6iARXlvNnxmZUh4O0/img.png&quot; data-alt=&quot;처음 실행하면 모델을 다운로드받고 이름을 출력한다. (C:\Users\Sean\.cache\huggingface\hub\models--Qwen--Qwen3-0.6B)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IQ6tB/dJMcabEMrc7/CnJ3J6iARXlvNnxmZUh4O0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIQ6tB%2FdJMcabEMrc7%2FCnJ3J6iARXlvNnxmZUh4O0%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;1730&quot; height=&quot;532&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;532&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;처음 실행하면 모델을 다운로드받고 이름을 출력한다. (C:\Users\Sean\.cache\huggingface\hub\models--Qwen--Qwen3-0.6B)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IVftl/dJMcahygUmb/SbQyPlFdDF0JXynJAbC7Z0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IVftl/dJMcahygUmb/SbQyPlFdDF0JXynJAbC7Z0/img.png&quot; data-alt=&quot;다음 실행부터는 다운로드된 모델을 로딩만 한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IVftl/dJMcahygUmb/SbQyPlFdDF0JXynJAbC7Z0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIVftl%2FdJMcahygUmb%2FSbQyPlFdDF0JXynJAbC7Z0%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;1730&quot; height=&quot;168&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;168&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;다음 실행부터는 다운로드된 모델을 로딩만 한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1783230631116&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path=&quot;Qwen/Qwen3-0.6B&quot;)
# 미리 학습된 모델의 토크나이저를 불러오는 코드이다. &quot;Qwen/Qwen3-0.6B&quot;는 모델의 이름을 나타낸다.

result = tokenizer(&quot;Hello, how are you?&quot;, return_tensors=&quot;pt&quot;)
# pt: PyTorch를 나타내며, return_tensors=&quot;pt&quot;는 토큰화된 결과를 PyTorch 텐서 형식으로 반환하도록 지정하는 것이다.
print(result)&lt;/code&gt;&lt;/pre&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;1730&quot; data-origin-height=&quot;532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bq8XVv/dJMcagMW6tO/MqOYdMF81KVN1qS1skQfik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bq8XVv/dJMcagMW6tO/MqOYdMF81KVN1qS1skQfik/img.png&quot; data-alt=&quot;처음 실행 시 필요한 파일을 다운로드한다. 이후 실행 시 마지막 결과만 출력된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bq8XVv/dJMcagMW6tO/MqOYdMF81KVN1qS1skQfik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbq8XVv%2FdJMcagMW6tO%2FMqOYdMF81KVN1qS1skQfik%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;1730&quot; height=&quot;532&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;532&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;처음 실행 시 필요한 파일을 다운로드한다. 이후 실행 시 마지막 결과만 출력된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1783217975173&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path=&quot;Qwen/Qwen2.5-7B-Instruct&quot;)
# 미리 학습된 모델의 토크나이저를 불러오는 코드이다. &quot;Qwen/Qwen2.5-7B-Instruct&quot;는 모델의 이름을 나타낸다.

result = tokenizer(&quot;Hello, how are you?&quot;, return_tensors=&quot;pt&quot;)
# pt: PyTorch를 나타내며, return_tensors=&quot;pt&quot;는 토큰화된 결과를 PyTorch 텐서 형식으로 반환하도록 지정하는 것이다.
print(result)&lt;/code&gt;&lt;/pre&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;1730&quot; data-origin-height=&quot;560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mIEum/dJMcag0mmOt/x3fK28lMYoBNkJncXm0kZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mIEum/dJMcag0mmOt/x3fK28lMYoBNkJncXm0kZ1/img.png&quot; data-alt=&quot;다른 모델을 사용했지만 토큰화 결과는 같다. (같은 Qwen 모델이라 그런거 같다)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mIEum/dJMcag0mmOt/x3fK28lMYoBNkJncXm0kZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmIEum%2FdJMcag0mmOt%2Fx3fK28lMYoBNkJncXm0kZ1%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;1730&quot; height=&quot;560&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;560&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;다른 모델을 사용했지만 토큰화 결과는 같다. (같은 Qwen 모델이라 그런거 같다)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;LGAI-EXAONE 모델을 사용하면 토큰화 결과가 달라진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1783231043311&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path=&quot;LGAI-EXAONE/EXAONE-4.0-1.2B&quot;)
result = tokenizer(&quot;Hello, how are you?&quot;, return_tensors=&quot;pt&quot;)
print(result)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;616&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMAa5R/dJMcah59FP9/behDz8oAwe0ZGOaDEZQAe0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMAa5R/dJMcah59FP9/behDz8oAwe0ZGOaDEZQAe0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMAa5R/dJMcah59FP9/behDz8oAwe0ZGOaDEZQAe0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMAa5R%2FdJMcah59FP9%2FbehDz8oAwe0ZGOaDEZQAe0%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;1730&quot; height=&quot;616&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;616&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block; text-align: center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-7506419418365672&quot; data-ad-slot=&quot;5217671153&quot;&gt;&lt;/ins&gt;
&lt;script&gt;     (adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1783218595395&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path=&quot;Qwen/Qwen2.5-7B-Instruct&quot;)
# 미리 학습된 모델의 토크나이저를 불러오는 코드이다. &quot;Qwen/Qwen2.5-7B-Instruct&quot;는 모델의 이름을 나타낸다.

result = tokenizer(&quot;Hello, how are you?&quot;, return_tensors=&quot;pt&quot;)
# pt: PyTorch를 나타내며, return_tensors=&quot;pt&quot;는 토큰화된 결과를 PyTorch 텐서 형식으로 반환하도록 지정하는 것이다.
print(result)

result = tokenizer.encode(&quot;Hello, how are you?&quot;, return_tensors=&quot;pt&quot;)
# encode() 메서드는 입력 텍스트를 토큰화하고, 토큰 ID만 반환하는 메서드이다.
print(result)&lt;/code&gt;&lt;/pre&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;1574&quot; data-origin-height=&quot;168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Vzm35/dJMcabdFkaw/ZZ3Kzi5HKxexnKiuALCgd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Vzm35/dJMcabdFkaw/ZZ3Kzi5HKxexnKiuALCgd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Vzm35/dJMcabdFkaw/ZZ3Kzi5HKxexnKiuALCgd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVzm35%2FdJMcabdFkaw%2FZZ3Kzi5HKxexnKiuALCgd0%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;1574&quot; height=&quot;168&quot; data-origin-width=&quot;1574&quot; data-origin-height=&quot;168&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;pre id=&quot;code_1783218892094&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path=&quot;Qwen/Qwen2.5-7B-Instruct&quot;)
# 미리 학습된 모델의 토크나이저를 불러오는 코드이다. &quot;Qwen/Qwen2.5-7B-Instruct&quot;는 모델의 이름을 나타낸다.

result = tokenizer.encode(&quot;Hello, how are you?&quot;, return_tensors=&quot;pt&quot;)
# encode() 메서드는 입력 텍스트를 토큰화하고, 토큰 ID만 반환하는 메서드이다.
print(result)

result = tokenizer.decode(result[0], skip_special_tokens=True)
# decode() 메서드는 토큰 ID를 다시 텍스트로 변환하는 메서드이다.
# clean_up_tokenization_spaces=True 옵션은 토큰화 과정에서 생긴 불필요한 공백을 제거하는 옵션이다.
print(result)&lt;/code&gt;&lt;/pre&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;692&quot; data-origin-height=&quot;168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bn7QWm/dJMcajpcySh/QxqAynoXUiEyCB8MY7JshK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bn7QWm/dJMcajpcySh/QxqAynoXUiEyCB8MY7JshK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bn7QWm/dJMcajpcySh/QxqAynoXUiEyCB8MY7JshK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbn7QWm%2FdJMcajpcySh%2FQxqAynoXUiEyCB8MY7JshK%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;692&quot; height=&quot;168&quot; data-origin-width=&quot;692&quot; data-origin-height=&quot;168&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;pre id=&quot;code_1783233669373&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from transformers import AutoModelForCausalLM, AutoTokenizer

model_name = &quot;LGAI-EXAONE/EXAONE-4.0-1.2B&quot;
model = AutoModelForCausalLM.from_pretrained(model_name, dtype=&quot;bfloat16&quot;, device_map=&quot;auto&quot;)
tokenizer = AutoTokenizer.from_pretrained(model_name)

prompt = &quot;네가 얼마나 대단한지 설명해 봐&quot;

messages = [
    {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: prompt}
]
inputs = tokenizer.apply_chat_template(
    messages,
    tokenize=True,
    add_generation_prompt=True,
    return_tensors=&quot;pt&quot;,
    return_dict=True
).to(model.device)
# .to(model.device): 모델이 실행되는 장치(GPU 또는 CPU)로 입력 데이터를 이동시키는 역할을 함.

output = model.generate(
    **inputs,
    max_new_tokens=256,
    do_sample=False,
)
# **inputs의 의미: inputs 딕셔너리의 키-값 쌍을 언패킹하여 model.generate 함수에 전달하는 것.
# 즉, inputs 딕셔너리의 각 항목이 model.generate 함수의 인자로 전달됨.
# do_sample=False의 의미: 모델이 생성할 텍스트를 결정할 때 무작위성을 배제하고,
# 가장 가능성이 높은 토큰을 선택하도록 설정하는 것.

print(tokenizer.decode(output[0]))&lt;/code&gt;&lt;/pre&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;1730&quot; data-origin-height=&quot;588&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdJcOG/dJMcafUMzTU/XSw0qyxi3n1NokfYl8sXm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdJcOG/dJMcafUMzTU/XSw0qyxi3n1NokfYl8sXm0/img.png&quot; data-alt=&quot;EXAONE&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdJcOG/dJMcafUMzTU/XSw0qyxi3n1NokfYl8sXm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdJcOG%2FdJMcafUMzTU%2FXSw0qyxi3n1NokfYl8sXm0%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;1730&quot; height=&quot;588&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;588&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;EXAONE&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1783233888084&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from transformers import AutoModelForCausalLM, AutoTokenizer

model_name = &quot;QWen/Qwen3-0.6B&quot;
model = AutoModelForCausalLM.from_pretrained(model_name, dtype=&quot;bfloat16&quot;, device_map=&quot;auto&quot;)
tokenizer = AutoTokenizer.from_pretrained(model_name)

prompt = &quot;네가 얼마나 대단한지 설명해 봐&quot;

messages = [
    {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: prompt}
]
inputs = tokenizer.apply_chat_template(
    messages,
    tokenize=True,
    add_generation_prompt=True,
    return_tensors=&quot;pt&quot;,
    return_dict=True
).to(model.device)
# .to(model.device): 모델이 실행되는 장치(GPU 또는 CPU)로 입력 데이터를 이동시키는 역할을 함.

output = model.generate(
    **inputs,
    max_new_tokens=256,
    do_sample=False,
)
# **inputs의 의미: inputs 딕셔너리의 키-값 쌍을 언패킹하여 model.generate 함수에 전달하는 것.
# 즉, inputs 딕셔너리의 각 항목이 model.generate 함수의 인자로 전달됨.
# do_sample=False의 의미: 모델이 생성할 텍스트를 결정할 때 무작위성을 배제하고,
# 가장 가능성이 높은 토큰을 선택하도록 설정하는 것.

print(tokenizer.decode(output[0]))&lt;/code&gt;&lt;/pre&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;1730&quot; data-origin-height=&quot;532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kJ6dH/dJMb991kEKt/q6hkUAT9uKdPmOGUQjax8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kJ6dH/dJMb991kEKt/q6hkUAT9uKdPmOGUQjax8K/img.png&quot; data-alt=&quot;QWen&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kJ6dH/dJMb991kEKt/q6hkUAT9uKdPmOGUQjax8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkJ6dH%2FdJMb991kEKt%2Fq6hkUAT9uKdPmOGUQjax8K%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;1730&quot; height=&quot;532&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;532&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;QWen&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block; text-align: center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-7506419418365672&quot; data-ad-slot=&quot;5217671153&quot;&gt;&lt;/ins&gt;
&lt;script&gt;     (adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1783236949578&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from transformers import pipeline

generator = pipeline(task='text-generation', model='LGAI-EXAONE/EXAONE-4.0-1.2B')
# EXAONE과 같은 인스트럭션(대화형) 튜닝 모델은 챗 템플릿 형식으로 프롬프트를 전달해야 올바른 답변이 나온다.
messages = [
    {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;한국의 수도는 어디야?&quot;}
]

# return_full_text=False를 주면 질문은 제외하고 생성된 답변만 반환한다.
result = generator(messages, return_full_text=False)

print(result)
#print(result[0]['generated_text'])&lt;/code&gt;&lt;/pre&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;1730&quot; data-origin-height=&quot;364&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUyJsX/dJMcahLMGSD/m5WNL1CmOeXo5Tj2VL10ZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUyJsX/dJMcahLMGSD/m5WNL1CmOeXo5Tj2VL10ZK/img.png&quot; data-alt=&quot;EXAONE&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUyJsX/dJMcahLMGSD/m5WNL1CmOeXo5Tj2VL10ZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUyJsX%2FdJMcahLMGSD%2Fm5WNL1CmOeXo5Tj2VL10ZK%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;1730&quot; height=&quot;364&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;364&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;EXAONE&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1783236914372&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from transformers import pipeline

generator = pipeline(task='text-generation', model='QWen/Qwen3-0.6B')
messages = [
    {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;한국의 수도는 어디야?&quot;}
]

# return_full_text=False를 주면 질문은 제외하고 생성된 답변만 반환한다.
result = generator(messages, return_full_text=False)

print(result)
#print(result[0]['generated_text'])&lt;/code&gt;&lt;/pre&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;1730&quot; data-origin-height=&quot;476&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vy4E3/dJMcagszQuh/RcqVsom71QngwF1VuXSzmK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vy4E3/dJMcagszQuh/RcqVsom71QngwF1VuXSzmK/img.png&quot; data-alt=&quot;QWen&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vy4E3/dJMcagszQuh/RcqVsom71QngwF1VuXSzmK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fvy4E3%2FdJMcagszQuh%2FRcqVsom71QngwF1VuXSzmK%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;1730&quot; height=&quot;476&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;476&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;QWen&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://huggingface.co/docs/huggingface_hub/v1.22.0/en/index&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Hub Python Library&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://huggingface.co/docs/transformers/v5.13.0/en/index&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Transformers&lt;/a&gt;&amp;nbsp; &lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://huggingface.co/docs/transformers/v5.13.0/en/fast_tokenizers&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Tokenizers&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://huggingface.co/docs/datasets/index&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Datasets&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI, ML, DL</category>
      <category>face</category>
      <category>hugging</category>
      <category>Library</category>
      <category>Python</category>
      <category>Transformers</category>
      <category>라이브러리</category>
      <category>인공지능</category>
      <category>트랜스포머</category>
      <category>파이썬</category>
      <category>페이스</category>
      <author>J-sean</author>
      <guid isPermaLink="true">https://s-engineer.tistory.com/724</guid>
      <comments>https://s-engineer.tistory.com/724#entry724comment</comments>
      <pubDate>Sat, 4 Jul 2026 22:43:52 +0900</pubDate>
    </item>
    <item>
      <title>[CFMEGA2] Hardware SPI Communication Pin</title>
      <link>https://s-engineer.tistory.com/723</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;CFMEGA2는 노이즈 보호를 위해 8개(5, 6, 7, 8, 9, 11, 12, 42)의 지정된 GPIO 단자만 나와 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;569&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccFjBy/dJMcahZdia4/zbWKwd3S2ecbLIkhb9AX21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccFjBy/dJMcahZdia4/zbWKwd3S2ecbLIkhb9AX21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccFjBy/dJMcahZdia4/zbWKwd3S2ecbLIkhb9AX21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FccFjBy%2FdJMcahZdia4%2FzbWKwd3S2ecbLIkhb9AX21%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;800&quot; height=&quot;569&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;569&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하드웨어 SPI 핀이 필요하다면 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://comfilewiki.co.kr/ko/doku.php?id=faduino:modularfaduino:ethernet:index&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CF-SHIELD&lt;/a&gt;&lt;/span&gt;를 연결해야 한다. 소프트웨어 SPI 통신을 한다면 아무 GPIO 핀을 이용해도 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;488&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bq9tgt/dJMcaiKySvr/tOD8vbrxK7c3WqWGoMpGHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bq9tgt/dJMcaiKySvr/tOD8vbrxK7c3WqWGoMpGHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bq9tgt/dJMcaiKySvr/tOD8vbrxK7c3WqWGoMpGHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbq9tgt%2FdJMcaiKySvr%2FtOD8vbrxK7c3WqWGoMpGHK%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;500&quot; height=&quot;488&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;488&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CF-SHIELD는 CFMEGA2에 나와 있지 않은 4번, 10번 GPIO 및 하드웨어 SPI 통신 핀, 그리고 몇 개의 전원선을 가져온다. 그 외의 다른 핀들은 연결되지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Embedded</category>
      <category>arduino</category>
      <category>cf-shield</category>
      <category>cfmega2</category>
      <category>Communication</category>
      <category>SPI</category>
      <category>아두이노</category>
      <category>통신</category>
      <author>J-sean</author>
      <guid isPermaLink="true">https://s-engineer.tistory.com/723</guid>
      <comments>https://s-engineer.tistory.com/723#entry723comment</comments>
      <pubDate>Sun, 28 Jun 2026 14:08:38 +0900</pubDate>
    </item>
    <item>
      <title>[CFMEGA2] OMRON E8Y Pressure Sensor 압력 센서</title>
      <link>https://s-engineer.tistory.com/722</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;CFMEGA2에서 OMRON E8Y 압력 센서를 사용해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;779&quot; data-origin-height=&quot;735&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EWb4a/dJMcadvEqVk/4GYIgmFu0FUUKT2ToYx3b1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EWb4a/dJMcadvEqVk/4GYIgmFu0FUUKT2ToYx3b1/img.png&quot; data-alt=&quot;정확히 이 모델을 사용한 건 아니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EWb4a/dJMcadvEqVk/4GYIgmFu0FUUKT2ToYx3b1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEWb4a%2FdJMcadvEqVk%2F4GYIgmFu0FUUKT2ToYx3b1%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;779&quot; height=&quot;735&quot; data-origin-width=&quot;779&quot; data-origin-height=&quot;735&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;정확히 이 모델을 사용한 건 아니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1782389525940&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// CFMEGA2에서 A0~A3은 0~20mA 전류값을 0~1023의 디지털 값으로 변환한다. (Analog to Digital Converter)
// OMRON E8Y 압력 센서는 압력에 따라 4~20mA의 아날로그 전류를 출력한다.
//
// 4mA의 ADC 값: 약 204 (1023의 20%)
// 20mA의 ADC 값: 1023
//
// 그럼 이론적으로는 CFMEGA2에서 204~1023의 값을 감지할 것이다. (범위: 819)
// 하지만 압력 센서를 연결하고 압력을 가하지 않은 상태의 값을 확인해 보면 195,
// 센서가 감지할 수 있는 최대 압력을 가한 상태의 값을 확인해 보면 985가 나온다. (범위: 790)
//
// 실제 값에 맞게 보정해 주어야 한다.

const int sensorPin = A0;  // 0~20mA 전용 입력 핀에 연결 (회색 선).
const float maxPressure = 1000.0f; // 압력 센서 데이터시트에 기재된 최대 측정 압력값. (1,000Pa)
const float maxCurrent = 20.0f; // 압력 센서 데이터시트에 기재된 최대 측정 전류값.
const int initialADCValue = 195; // 압력이 없을때 ADC 값으로 195가 들어온다.
const int maxADCValue = 985; // 최대 압력일때 ADC 값으로 985가 들어온다.

void setup() {
  Serial.begin(9600);
  Serial.println(&quot;----------- CFMEGA2 Pressure Measure Start -----------&quot;);
}

void loop() {
  int adcValue = analogRead(sensorPin);
  
  // 센서 단선 또는 전원 오류 확인 (4mA 미만 확인)
  // 오차를 감안해 ADC 값이 190(약 3.7mA) 미만으로 떨어지면 오류로 간주
  if (adcValue &amp;lt; 190) {
    Serial.println(&quot;Error: Weak Sensor Signal. Check the sensor or the cable.&quot;);
  } else {
    // ADC 값(204~1023)을 압력(0~maxPressure)으로 비례 변환
    float pressure = (adcValue - initialADCValue) * (maxPressure / (maxADCValue - initialADCValue));
    // 값 보정: 실제 센서에 압력이 전혀 안 걸려 있을 때 출력되는 전류가 정확히
    // 4mA(ADC 204)가 아닐 수 있다. 초기값이 미세하게 맞지 않는다면 initialADCValue 값을
    // 실제 측정된 초기 ADC 값으로 조금씩 수정하여 보정한다.
    // 내 경우엔 195다. 최대 압력이 걸렸을때는 1023이 아니라 985다.

    // 센서에서 현재 출력되는 전류(mA) 역산
    float current_mA = adcValue * (maxCurrent / maxADCValue);
    
    Serial.print(&quot;adc: &quot;);
    Serial.print(adcValue);
    Serial.print(&quot;  |  Current: &quot;);
    Serial.print(current_mA, 2); // 소수점 둘째 자리까지 출력
    Serial.print(&quot; mA  |  Pressure: &quot;);
    Serial.print(pressure, 2);
    Serial.println(&quot; Pa&quot;);
  }
  
  delay(1000); // 1초 대기
}&lt;/code&gt;&lt;/pre&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;1581&quot; data-origin-height=&quot;324&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMemSp/dJMb99NBwe3/RkAKnmGqzxswlvILgQzqkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMemSp/dJMb99NBwe3/RkAKnmGqzxswlvILgQzqkK/img.png&quot; data-alt=&quot;센서 데이터가 표시된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMemSp/dJMb99NBwe3/RkAKnmGqzxswlvILgQzqkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMemSp%2FdJMb99NBwe3%2FRkAKnmGqzxswlvILgQzqkK%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;1581&quot; height=&quot;324&quot; data-origin-width=&quot;1581&quot; data-origin-height=&quot;324&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;센서 데이터가 표시된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block; text-align: center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-7506419418365672&quot; data-ad-slot=&quot;5217671153&quot;&gt;&lt;/ins&gt;
&lt;script&gt;     (adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번엔 아스키 문자가 아닌 바이너리 데이터를 전달해 보자.&lt;/p&gt;
&lt;pre id=&quot;code_1782479783360&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const int sensorPin = A0;  // 0~20mA 전용 입력 핀에 연결 (회색 선)
const float maxPressure = 1000.0f; // 압력 센서 데이터시트에 기재된 최대 측정 압력값
const float maxCurrent = 20.0f; // 압력 센서 데이터시트에 기재된 최대 측정 전류값
const int initialADCValue = 195; // 압력이 없을때 ADC 값으로 195가 들어온다.
const int maxADCValue = 985; // 최대 압력일때 ADC 값으로 985가 들어온다.

void setup() {
  Serial.begin(9600);
  //Serial.println(&quot;----------- CFMEGA2 Pressure Measure Start -----------&quot;);
}

void loop() {
  int adcValue = analogRead(sensorPin);
  
  // 센서 단선 또는 전원 오류 확인 (4mA 미만 확인)
  // 오차를 감안해 ADC 값이 190(약 3.7mA) 미만으로 떨어지면 오류로 간주
  if (adcValue &amp;lt; 190) {
    Serial.println(&quot;Error: Weak Sensor Signal. Check the sensor or the cable.&quot;);
  } else {
    // ADC 값(204~1023)을 압력(0~maxPressure)으로 비례 변환
    float pressure = (adcValue - initialADCValue) * (maxPressure / (maxADCValue - initialADCValue));
    // 값 보정: 실제 센서에 압력이 전혀 안 걸려 있을 때 출력되는 전류가 정확히
    // 4mA(ADC 204)가 아닐 수 있다. 초기값이 미세하게 맞지 않는다면 initialADCValue 값을
    // 실제 측정된 초기 ADC 값으로 조금씩 수정하여 보정한다.
    // 내 경우엔 195다. 최대 압력이 걸렸을때는 1023이 아니라 985다.

    // 센서에서 현재 출력되는 전류(mA) 역산
    float current_mA = adcValue * (maxCurrent / maxADCValue);
    
    //Serial.print(&quot;adc: &quot;);
    //Serial.print(adcValue);
    //Serial.print(&quot;  |  Current: &quot;);
    //Serial.print(current_mA, 2); // 소수점 둘째 자리까지 출력
    //Serial.print(&quot; mA  |  Pressure: &quot;);
    //Serial.print(pressure, 2);
    //Serial.println(&quot; Pa&quot;);
    
    // CFMEGA2(Arduino)의 int는 2바이트(16비트) 크기를 가진다.
    Serial.write(highByte((int)pressure)); // 상위 1바이트(8비트) 먼저 전송
    Serial.write(lowByte((int)pressure)); // 하위 1바이트(8비트) 이어서 전송
  }
  
  delay(1000); // 1초 대기
}&lt;/code&gt;&lt;/pre&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;1581&quot; data-origin-height=&quot;325&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cosEdo/dJMcaaeLy78/97EaOY9bp5XwBNkJGoBkak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cosEdo/dJMcaaeLy78/97EaOY9bp5XwBNkJGoBkak/img.png&quot; data-alt=&quot;아스키 문자가 아닌 바이너리 데이터이기 때문에 Arduino IDE의 Serial Monitor를 통해 확인하면 알 수 없는 문자가 표시된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cosEdo/dJMcaaeLy78/97EaOY9bp5XwBNkJGoBkak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcosEdo%2FdJMcaaeLy78%2F97EaOY9bp5XwBNkJGoBkak%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;1581&quot; height=&quot;325&quot; data-origin-width=&quot;1581&quot; data-origin-height=&quot;325&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;아스키 문자가 아닌 바이너리 데이터이기 때문에 Arduino IDE의 Serial Monitor를 통해 확인하면 알 수 없는 문자가 표시된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1014&quot; data-origin-height=&quot;938&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0bjkn/dJMcaaTlhaV/9Jgbak0j3Eh73aSCM0g8ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0bjkn/dJMcaaTlhaV/9Jgbak0j3Eh73aSCM0g8ck/img.png&quot; data-alt=&quot;시리얼 통신용 프로그램을 사용하면 바이너리 데이터를 직접 확인할 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0bjkn/dJMcaaTlhaV/9Jgbak0j3Eh73aSCM0g8ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0bjkn%2FdJMcaaTlhaV%2F9Jgbak0j3Eh73aSCM0g8ck%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;1014&quot; height=&quot;938&quot; data-origin-width=&quot;1014&quot; data-origin-height=&quot;938&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;시리얼 통신용 프로그램을 사용하면 바이너리 데이터를 직접 확인할 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1초당 2바이트씩 데이터를 읽는다. 처음 4초간은 압력이 없기 때문에 00 01이 4번 입력되고 5초에 177 Pa의 압력이 가해져 00 B1이 입력되었다.&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;센서가 출력하는 전류값이나 CFMEGA2가 읽는 전류값은 높은 정밀도를 가질 수 없을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;압력이 없을 때 센서를 통해 CFMEGA2에 들어온 ADC값이 처음엔 195였는데 몇 번 테스트하는 과정에서 196으로 바뀌었고 변환 과정을 거쳐 압력은 1로 표시되었다.&amp;nbsp; 최대 압력일 때 ADC값도 최초 985에서 986으로 바뀌었다. 986은 변환식을 통해 1001이 된다.&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;예) (h): HEX, (d): DEC&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;■ 00 01(h): 1(d)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;■ 00 B1(h): 177(d)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;■ 01 20(h): 288(d)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;■ 03 E9(h): 1001(d)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Embedded</category>
      <category>arduino</category>
      <category>cfmega2</category>
      <category>omron</category>
      <category>sensor</category>
      <category>센서</category>
      <category>아두이노</category>
      <category>압력</category>
      <category>차압</category>
      <author>J-sean</author>
      <guid isPermaLink="true">https://s-engineer.tistory.com/722</guid>
      <comments>https://s-engineer.tistory.com/722#entry722comment</comments>
      <pubDate>Thu, 25 Jun 2026 21:25:33 +0900</pubDate>
    </item>
    <item>
      <title>[vLLM] WSL에서 vLLM 서버 실행하고 사용하기</title>
      <link>https://s-engineer.tistory.com/721</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;아래 링크와 같이 WSL에 설치한 vLLM 서버를 실행하고 사용해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://s-engineer.tistory.com/720&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2026.06.19 - [AI, ML, DL] - [vLLM] WSL 에서 vLLM 설치 및 간단한 실행&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1336&quot; data-origin-height=&quot;504&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpBEU2/dJMcag6ZQHp/COdJFEZcyjX0CguqTSbAkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpBEU2/dJMcag6ZQHp/COdJFEZcyjX0CguqTSbAkk/img.png&quot; data-alt=&quot;Background에서 서버를 실행하고 프로세스를 확인.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpBEU2/dJMcag6ZQHp/COdJFEZcyjX0CguqTSbAkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpBEU2%2FdJMcag6ZQHp%2FCOdJFEZcyjX0CguqTSbAkk%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;1336&quot; height=&quot;504&quot; data-origin-width=&quot;1336&quot; data-origin-height=&quot;504&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Background에서 서버를 실행하고 프로세스를 확인.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;■ 서버 실행하기 (Foreground에서 실행된다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VLLM_USE_FLASHINFER_SAMPLER=0&amp;nbsp;python3&amp;nbsp;-m&amp;nbsp;vllhttp://m.entrypoints.openai.api_server&amp;nbsp;--model&amp;nbsp;LGAI-EXAONE/EXAONE-Deep-2.4B-AWQ&amp;nbsp;--trust_remote_code&amp;nbsp;True&amp;nbsp;--gpu_memory_utilization=0.7&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;■ 서버 실행하기 (Background에서 실행되고 vllm.log 파일에 로그가 기록된다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VLLM_USE_FLASHINFER_SAMPLER=0&amp;nbsp;python3&amp;nbsp;-m&amp;nbsp;vllhttp://m.entrypoints.openai.api_server&amp;nbsp;--model&amp;nbsp;LGAI-EXAONE/EXAONE-Deep-2.4B-AWQ&amp;nbsp;--trust_remote_code&amp;nbsp;True&amp;nbsp;--gpu_memory_utilization=0.7&amp;nbsp;&amp;gt;&amp;nbsp;vllm.log&amp;nbsp;2&amp;gt;&amp;amp;1&amp;nbsp;&amp;amp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VLLM_USE_FLASHINFER_SAMPLER=0은 vLLM이 다음 토큰을 선택(샘플링)할 때 FlashInfer 라이브러리의 고속 커널을 사용하지 않고, PyTorch/Triton 기반의 기본 내장 샘플러를 사용하도록 강제하는 환경 변수 설정이다. 내 시스템에선 이 옵션 없이는 실행할 수 없었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;■ 백그라운드에서 동작중인 서버 프로세스 확인 (백그라운드에서&amp;nbsp;동작하는&amp;nbsp;프로세스&amp;nbsp;중&amp;nbsp;vllm이라는&amp;nbsp;문자열과&amp;nbsp;VLLM이라는&amp;nbsp;문자열을&amp;nbsp;검색한다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ps&amp;nbsp;-ef&amp;nbsp;|&amp;nbsp;grep&amp;nbsp;-E&amp;nbsp;&quot;vllm|VLLM&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;■ 백그라운드 서버 종료&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pkill&amp;nbsp;-f&amp;nbsp;vllhttp://m.entrypoints.openai.api_server&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block; text-align: center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-7506419418365672&quot; data-ad-slot=&quot;5217671153&quot;&gt;&lt;/ins&gt;
&lt;script&gt;     (adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동작중인 서버를 이용해보자. 아래 코드를 작성하고 실행한다.&lt;/p&gt;
&lt;pre id=&quot;code_1782016955500&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from openai import OpenAI

# vLLM 서버 주소 설정 (기본 포트 8000)
client = OpenAI(
    base_url=&quot;http://localhost:8000/v1&quot;,
    api_key=&quot;vllm-token&quot; # api_key는 아무 문자열이나 넣어도 된다.
)

# 단발성 답변 받기 (General Request)
print(&quot;=== 일반 답변 요청 ===&quot;)
response = client.chat.completions.create(
    model=&quot;LGAI-EXAONE/EXAONE-Deep-2.4B-AWQ&quot;,  # 동작중인 서버의 모델 이름과 일치해야 한다.
    messages=[
        {&quot;role&quot;: &quot;system&quot;, &quot;content&quot;: &quot;당신은 친절한 AI 도우미입니다.&quot;},
        {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;인공지능과 거대언어모델(LLM)의 차이점을 한 문장으로 설명해줘.&quot;}
    ],
    temperature=0.2,
    top_p=0.95,
    max_tokens=1024
)

print(response.choices[0].message.content)

print()

# 실시간 스트리밍 답변 받기 (Streaming Request)
print(&quot;=== 스트리밍 답변 요청 ===&quot;)
stream = client.chat.completions.create(
    model=&quot;LGAI-EXAONE/EXAONE-Deep-2.4B-AWQ&quot;,
    messages=[
        {&quot;role&quot;: &quot;system&quot;, &quot;content&quot;: &quot;당신은 친절한 AI 요리사 도우미 입니다.&quot;},
        {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;맛있는 김치찌개를 끓이는 비법을 짧게 알려줘.&quot;}
    ],
    temperature=0.2,
    top_p=0.95,
    max_tokens=1024,
    stream=True, # 스트리밍 활성화
)

for chunk in stream:
    if chunk.choices[0].delta.content is not None:
        print(chunk.choices[0].delta.content, end=&quot;&quot;, flush=True)

print()&lt;/code&gt;&lt;/pre&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;1392&quot; data-origin-height=&quot;1176&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxtHX9/dJMb99Nw5OP/p5zgw5Ap8GYQ7kuIj6ixkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxtHX9/dJMb99Nw5OP/p5zgw5Ap8GYQ7kuIj6ixkK/img.png&quot; data-alt=&quot;답변 첫 부분에 빈 줄과 &amp;amp;lt;/thought&amp;amp;gt; 태그가 따라 나온다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxtHX9/dJMb99Nw5OP/p5zgw5Ap8GYQ7kuIj6ixkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxtHX9%2FdJMb99Nw5OP%2Fp5zgw5Ap8GYQ7kuIj6ixkK%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;1392&quot; height=&quot;1176&quot; data-origin-width=&quot;1392&quot; data-origin-height=&quot;1176&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;답변 첫 부분에 빈 줄과 &amp;lt;/thought&amp;gt; 태그가 따라 나온다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;불필요한 태그를 제거해 보자.&lt;/p&gt;
&lt;pre id=&quot;code_1782016579726&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from openai import OpenAI

# vLLM 서버 주소 설정 (기본 포트 8000)
client = OpenAI(
    base_url=&quot;http://localhost:8000/v1&quot;,
    api_key=&quot;vllm-token&quot; # api_key는 아무 문자열이나 넣어도 된다.
)

# 단발성 답변 받기 (General Request)
print(&quot;=== 일반 답변 요청 ===&quot;)
response = client.chat.completions.create(
    model=&quot;LGAI-EXAONE/EXAONE-Deep-2.4B-AWQ&quot;,  # 동작중인 서버의 모델 이름과 일치해야 한다.
    messages=[
        {&quot;role&quot;: &quot;system&quot;, &quot;content&quot;: &quot;당신은 친절한 AI 도우미입니다.&quot;},
        {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;인공지능과 거대언어모델(LLM)의 차이점을 한 문장으로 설명해줘.&quot;}
    ],
    temperature=0.2,
    top_p=0.95,
    max_tokens=1024
)

#print(response.choices[0].message.content) # 태그 포함 답변 출력
content = response.choices[0].message.content

# &amp;lt;/thought&amp;gt; 태그가 포함되어 있다면 분할 처리
if &quot;&amp;lt;/thought&amp;gt;&quot; in content:
    # thought_process: 모델이 생각한 과정 (필요시 사용)
    # final_answer: 사용자가 원하는 최종 답변
    thought_process, final_answer = content.split(&quot;&amp;lt;/thought&amp;gt;&quot;, 1)
    #print(&quot;=== [AI의 생각 과정] ===&quot;)
    #print(thought_process.replace(&quot;&amp;lt;thought&amp;gt;&quot;, &quot;&quot;).strip()) # 시작 태그가 남아있다면 제거
    print(final_answer.strip())
else:
    # 태그가 없는 일반적인 경우 그대로 출력
    print(content)

print()

# 실시간 스트리밍 답변 받기 (Streaming Request)
print(&quot;=== 스트리밍 답변 요청 ===&quot;)
stream = client.chat.completions.create(
    model=&quot;LGAI-EXAONE/EXAONE-Deep-2.4B-AWQ&quot;,
    messages=[
        {&quot;role&quot;: &quot;system&quot;, &quot;content&quot;: &quot;당신은 친절한 AI 요리사 도우미 입니다.&quot;},
        {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;맛있는 김치찌개를 끓이는 비법을 짧게 알려줘.&quot;}
    ],
    temperature=0.2,
    top_p=0.95,
    max_tokens=1024,
    stream=True, # 스트리밍 활성화
)

# 실시간 문자열에서 불필요한 &amp;lt;/thought&amp;gt; 태그 처리를 위한 변수 선언
full_text = &quot;&quot;
has_passed_thought = False

for chunk in stream:
    if chunk.choices[0].delta.content is not None:
        #print(chunk.choices[0].delta.content, end=&quot;&quot;, flush=True) # 태그 포함 답변 출력

        token = chunk.choices[0].delta.content
        full_text += token  # 들어오는 토큰을 전체 버퍼에 누적

        # &amp;lt;/thought&amp;gt; 태그가 지나갔는지 확인
        if not has_passed_thought:
            if &quot;&amp;lt;/thought&amp;gt;&quot; in full_text:
                # 태그가 끝나는 지점을 찾아 그 이후의 텍스트만 추출
                _, final_start_text = full_text.split(&quot;&amp;lt;/thought&amp;gt;&quot;, 1)
                has_passed_thought = True
                
                # 태그 뒤에 공백이나 줄바꿈이 있다면 깔끔하게 지우고 첫 출력
                first_output = final_start_text.lstrip()
                if first_output:
                    print(first_output, end=&quot;&quot;, flush=True)
            else:
                # 아직 &amp;lt;/thought&amp;gt; 태그가 나오기 전(생각 중)이라면 화면에 출력하지 않고 건너뛴다.
                continue
        else:
            # 만약 앞서 출력된 내용이 아직 아무것도 없다면 (sys.stdout이 비어있음)
            # 다음에 들어오는 토큰들도 첫 글자가 나올 때까지 앞쪽 공백/줄바꿈을 계속 지워준다.
            if not full_text.split(&quot;&amp;lt;/thought&amp;gt;&quot;, 1)[1].lstrip():
                # 여전히 공백이나 줄바꿈만 들어오는 상태이므로 출력하지 않고 스킵.
                continue
                
            # 글자가 들어오기 시작하면, 그 시점의 토큰부터 그대로 출력.
            # (단, 공백이 섞여 들어왔을 수 있으므로 첫 진입 토큰만 lstrip 처리)
            if len(full_text.split(&quot;&amp;lt;/thought&amp;gt;&quot;, 1)[1].lstrip()) == len(token):
                print(token.lstrip(), end=&quot;&quot;, flush=True)
            else:
                print(token, end=&quot;&quot;, flush=True)

print()&lt;/code&gt;&lt;/pre&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;1392&quot; data-origin-height=&quot;980&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EBylr/dJMcahrmDG6/7qSvZ1QHK5Pm9sPvZ4LaeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EBylr/dJMcahrmDG6/7qSvZ1QHK5Pm9sPvZ4LaeK/img.png&quot; data-alt=&quot;불필요한 태그 없이 깔끔하게 정리되었다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EBylr/dJMcahrmDG6/7qSvZ1QHK5Pm9sPvZ4LaeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEBylr%2FdJMcahrmDG6%2F7qSvZ1QHK5Pm9sPvZ4LaeK%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;1392&quot; height=&quot;980&quot; data-origin-width=&quot;1392&quot; data-origin-height=&quot;980&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;불필요한 태그 없이 깔끔하게 정리되었다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block; text-align: center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-7506419418365672&quot; data-ad-slot=&quot;5217671153&quot;&gt;&lt;/ins&gt;
&lt;script&gt;     (adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 WSL에 서버를 실행한 상태에서 네이티브 윈도우에서도 위와 동일한 코드로 LLM을 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아니면 WSL에서 hostname -I 명령으로 확인한 IP 주소값을 base_url에 넣어도 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1782017609160&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from openai import OpenAI

# vLLM 서버 주소 설정 (기본 포트 8000)
client = OpenAI(
    base_url=&quot;http://localhost:8000/v1&quot;,
    #base_url=&quot;http://172.21.167.101:8000/v1&quot;,
    api_key=&quot;vllm-token&quot; # api_key는 아무 문자열이나 넣어도 된다.
)

# 단발성 답변 받기 (General Request)
print(&quot;=== 일반 답변 요청 ===&quot;)
response = client.chat.completions.create(
    model=&quot;LGAI-EXAONE/EXAONE-Deep-2.4B-AWQ&quot;,  # 동작중인 서버의 모델 이름과 일치해야 한다.
    messages=[
        {&quot;role&quot;: &quot;system&quot;, &quot;content&quot;: &quot;당신은 친절한 AI 도우미입니다.&quot;},
        {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;인공지능과 거대언어모델(LLM)의 차이점을 한 문장으로 설명해줘.&quot;}
    ],
    temperature=0.2,
    top_p=0.95,
    max_tokens=1024
)

print(response.choices[0].message.content)

print()

# 실시간 스트리밍 답변 받기 (Streaming Request)
print(&quot;=== 스트리밍 답변 요청 ===&quot;)
stream = client.chat.completions.create(
    model=&quot;LGAI-EXAONE/EXAONE-Deep-2.4B-AWQ&quot;,
    messages=[
        {&quot;role&quot;: &quot;system&quot;, &quot;content&quot;: &quot;당신은 친절한 AI 요리사 도우미 입니다.&quot;},
        {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;맛있는 김치찌개를 끓이는 비법을 짧게 알려줘.&quot;}
    ],
    temperature=0.2,
    top_p=0.95,
    max_tokens=1024,
    stream=True, # 스트리밍 활성화
)

for chunk in stream:
    if chunk.choices[0].delta.content is not None:
        print(chunk.choices[0].delta.content, end=&quot;&quot;, flush=True)

print()&lt;/code&gt;&lt;/pre&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;1112&quot; data-origin-height=&quot;1036&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxX34J/dJMcabLtWUZ/JTStRrkqvDrDqRJgavtya1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxX34J/dJMcabLtWUZ/JTStRrkqvDrDqRJgavtya1/img.png&quot; data-alt=&quot;네이티브 윈도우에서 WSL 서버 사용.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxX34J/dJMcabLtWUZ/JTStRrkqvDrDqRJgavtya1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxX34J%2FdJMcabLtWUZ%2FJTStRrkqvDrDqRJgavtya1%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;1112&quot; height=&quot;1036&quot; data-origin-width=&quot;1112&quot; data-origin-height=&quot;1036&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;네이티브 윈도우에서 WSL 서버 사용.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LG AI Research의 공식 가이드에 따르면 EXAONE Deep 모델은 시스템 프롬프트를 지원하지 않거나 권장하지 않는다. 시스템 프롬프트를 넣으면 모델이 지시사항을 무시하거나 추론(&amp;lt;thought&amp;gt;)을 시작하지 못하고 엉뚱한 답변을 낼 확률이 높아진다. 요리사 같은 페르소나는 아래와 같이 user 메시지 안에 녹여내자.&lt;/p&gt;
&lt;pre id=&quot;code_1782017892727&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;response = client.chat.completions.create(
    model=&quot;LGAI-EXAONE/EXAONE-Deep-2.4B-AWQ&quot;,
    messages=[
        # 시스템 프롬프트를 없애고 유저 메시지에 역할을 녹여낸다.
        {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;당신은 친절한 AI 도우미입니다. 인공지능과 거대언어모델(LLM)의 차이점을 한 문장으로 설명해줘.&quot;}
    ],
    temperature=0.2,
    top_p=0.95,
    max_tokens=1024
)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI, ML, DL</category>
      <category>Linux</category>
      <category>LLM</category>
      <category>openai</category>
      <category>Server</category>
      <category>vllm</category>
      <category>WSL</category>
      <category>딥러닝</category>
      <category>서버</category>
      <category>인공지능</category>
      <author>J-sean</author>
      <guid isPermaLink="true">https://s-engineer.tistory.com/721</guid>
      <comments>https://s-engineer.tistory.com/721#entry721comment</comments>
      <pubDate>Sun, 21 Jun 2026 13:59:35 +0900</pubDate>
    </item>
    <item>
      <title>[vLLM] WSL에서 vLLM 설치 및 간단한 실행</title>
      <link>https://s-engineer.tistory.com/720</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;WSL에서 &lt;a href=&quot;https://vllm.ai/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;vLLM&lt;/span&gt;&lt;/a&gt;을 사용해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;■&amp;nbsp;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/windows/wsl/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;WSL&lt;/span&gt;&lt;/a&gt;을 설치한다.&amp;nbsp;운영체제는 우분투 24.04를 설치한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우분투 26.04는 파이썬 3.14가 설치되어 있는데 현재 파이토치가 파이썬 3.13까지만 지원하기 때문에 파이토치 설치가 귀찮아진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;924&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ibbw8/dJMcaaZ0F4c/NwPRl8krvfwk71p1TXgDV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ibbw8/dJMcaaZ0F4c/NwPRl8krvfwk71p1TXgDV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ibbw8/dJMcaaZ0F4c/NwPRl8krvfwk71p1TXgDV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIbbw8%2FdJMcaaZ0F4c%2FNwPRl8krvfwk71p1TXgDV0%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;1730&quot; height=&quot;924&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;924&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;■ pip3를 설치한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sudo apt update&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sudo apt upgrade&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sudo apt install python3-pip&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pip3 --version (정상 설치 확인)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;924&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/R9tQj/dJMcadPUL4u/pmbomVlbFcWKsePDuf40j1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/R9tQj/dJMcadPUL4u/pmbomVlbFcWKsePDuf40j1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/R9tQj/dJMcadPUL4u/pmbomVlbFcWKsePDuf40j1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FR9tQj%2FdJMcadPUL4u%2FpmbomVlbFcWKsePDuf40j1%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;1730&quot; height=&quot;924&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;924&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;■ 파이썬 가상환경을 만들어 주는 venv를 설치한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sudo apt install python3-venv&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;924&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dyaj5w/dJMcadiaVaz/kKBlNgYMlo4Qku7VnrMkKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dyaj5w/dJMcadiaVaz/kKBlNgYMlo4Qku7VnrMkKk/img.png&quot; data-alt=&quot;가상환경 생성 및 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dyaj5w/dJMcadiaVaz/kKBlNgYMlo4Qku7VnrMkKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdyaj5w%2FdJMcadiaVaz%2FkKBlNgYMlo4Qku7VnrMkKk%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;1730&quot; height=&quot;924&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;924&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가상환경 생성 및 확인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;924&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byiX9g/dJMcaaTgazY/5F4I8zjyHRQ7bhfmnNa3bk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byiX9g/dJMcaaTgazY/5F4I8zjyHRQ7bhfmnNa3bk/img.png&quot; data-alt=&quot;가상환경 활성화&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byiX9g/dJMcaaTgazY/5F4I8zjyHRQ7bhfmnNa3bk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyiX9g%2FdJMcaaTgazY%2F5F4I8zjyHRQ7bhfmnNa3bk%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;1730&quot; height=&quot;924&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;924&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가상환경 활성화&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;■ venv-vllm 디렉토리에 가상환경을 생성하고 활성화한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;python3 -m venv venv-vllm&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;source venv-vllm/bin/activate&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block; text-align: center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-7506419418365672&quot; data-ad-slot=&quot;5217671153&quot;&gt;&lt;/ins&gt;
&lt;script&gt;     (adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&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;1730&quot; data-origin-height=&quot;924&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mw5bL/dJMcad3spOy/ANNfPqrTk3lKR9s3TK7WNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mw5bL/dJMcad3spOy/ANNfPqrTk3lKR9s3TK7WNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mw5bL/dJMcad3spOy/ANNfPqrTk3lKR9s3TK7WNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmw5bL%2FdJMcad3spOy%2FANNfPqrTk3lKR9s3TK7WNK%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;1730&quot; height=&quot;924&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;924&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;■&amp;nbsp;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://pytorch.kr/get-started/locally/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;파이토치를 설치&lt;/a&gt;&lt;/span&gt;한다. (CUDA 12.4)&lt;br /&gt;pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;924&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCh2YF/dJMcahdND7V/1vquK07AcADVGYceNKw2C1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCh2YF/dJMcahdND7V/1vquK07AcADVGYceNKw2C1/img.png&quot; data-alt=&quot;vllm을 설치하면 많은 프로그램이 설치된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCh2YF/dJMcahdND7V/1vquK07AcADVGYceNKw2C1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCh2YF%2FdJMcahdND7V%2F1vquK07AcADVGYceNKw2C1%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;1730&quot; height=&quot;924&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;924&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;vllm을 설치하면 많은 프로그램이 설치된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;■ vLLM을 설치한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pip3 install vllm&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;924&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2KRoZ/dJMcahrl1kZ/VMPeKr5A5Ge0LQM51ca5y1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2KRoZ/dJMcahrl1kZ/VMPeKr5A5Ge0LQM51ca5y1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2KRoZ/dJMcahrl1kZ/VMPeKr5A5Ge0LQM51ca5y1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2KRoZ%2FdJMcahrl1kZ%2FVMPeKr5A5Ge0LQM51ca5y1%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;1730&quot; height=&quot;924&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;924&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;■ vLLM을 실행하기 위해 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://developer.nvidia.com/cuda-toolkit-archive&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CUDA Toolkit을 설치&lt;/a&gt;&lt;/span&gt;한다. (Cuda Toolkit 12.4)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;wget&amp;nbsp;https://developer.download.nvidia.com/compute/cuda/12.4.0/local_installers/cuda_12.4.0_550.54.14_linux.run&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sudo sh cuda_12.4.0_550.54.14_linux.run&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 명령을 실행하면 잠시 멈춘 것처럼 시간이 좀 걸린다. 그리고 accept를 입력하고 다음 화면에서 CUDA Toolkit 12.4가 선택된 상태에서 Install을 선택한다. Driver는 옵션에 없었지만 있다면 선택해제한다. Driver를 설치하는 것이 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;924&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y5f6W/dJMcaglBYU8/Dgu2oZEUSsDjzDQ29InvbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y5f6W/dJMcaglBYU8/Dgu2oZEUSsDjzDQ29InvbK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y5f6W/dJMcaglBYU8/Dgu2oZEUSsDjzDQ29InvbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy5f6W%2FdJMcaglBYU8%2FDgu2oZEUSsDjzDQ29InvbK%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;1730&quot; height=&quot;924&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;924&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치가 끝나면 아래와 같이 환경 변수를 등록한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;nano ~/.bashrc 실행하고 파일&amp;nbsp;끝에&amp;nbsp;아래&amp;nbsp;내용&amp;nbsp;추가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;export&amp;nbsp;PATH=/usr/local/cuda-12.4/bin${PATH:+:${PATH}} &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;export&amp;nbsp;LD_LIBRARY_PATH=/usr/local/cuda-12.4/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;source ~/.bashrc 실행 (이 명령을 실행하고 나면 파이썬 가상환경이 풀린다)&lt;br /&gt;nvcc --version 명령을 실행하면 버전이 표시된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block; text-align: center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-7506419418365672&quot; data-ad-slot=&quot;5217671153&quot;&gt;&lt;/ins&gt;
&lt;script&gt;     (adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;■ vLLM에서 LGAI EXAON 모델을 사용하는 예&lt;/p&gt;
&lt;pre id=&quot;code_1781844299372&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import os

# vLLM에서 FlashInfer 기반의 고속 셈플링(Sampling) 기능을 끄고, 안정적인 PyTorch 네이티브(기본)
# 셈플링 방식으로 되돌리기(Fallback).
os.environ[&quot;VLLM_USE_FLASHINFER_SAMPLER&quot;] = &quot;0&quot;
# vLLM은 내부적으로 가속 연산을 위해 FlashInfer라는 라이브러리를 사용하는데 이 라이브러리는
# NVIDIA Turing 아키텍처(Compute Capability sm75) 이상의 GPU에서만 작동한다. 사용하는 그래픽카드가
# 소형 모델 구동용(VRAM 8GB 수준)이면서 sm75보다 낮은 구형 아키텍처(예: GTX 10시리즈인 Pascal 아키텍처 sm61 등)
# 이면 문제가 발생한다.
# 해결 방법: vllm 패키지를 로드하기 전에 os.environ을 통해 FlashInfer 가속 비활성화하기

from vllm import LLM, SamplingParams

def main():
    # 모델 로드
    llm = LLM(
        model=&quot;LGAI-EXAONE/EXAONE-Deep-2.4B-AWQ&quot;, 
        trust_remote_code=True, 
        gpu_memory_utilization=0.7
    )
# vLLM은 기본적으로 GPU 메모리의 90%(0.9)를 미리 할당하기 때문에, 낮은 성능의 GPU에서는
# OOM(메모리 부족) 에러를 방지하거나 다른 프로세스와 GPU를 나누어 쓰려면 gpu_memory_utilization
# 옵션이 필수적이다.

    # 파라미터 설정
    sampling_params = SamplingParams(
        temperature=0.0,
        top_p=0.95,
        max_tokens=1024,
        repetition_penalty=1.1
    )

    # 질문 리스트
    raw_questions = [
        &quot;대한민국의 수도는 어디인가요?&quot;,
        &quot;인공지능은 무엇인가요?&quot;
    ]

    # vLLM 공식 Chat Template 적용
    prompts = []
    tokenizer = llm.get_tokenizer()
    for q in raw_questions:
        messages = [{&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: q}]
        formatted_prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
        prompts.append(formatted_prompt)

    # 텍스트 생성
    outputs = llm.generate(prompts, sampling_params)

    # 결과 출력 (내장함수로 태그 뒤쪽만 추출)
    for i, output in enumerate(outputs):
        prompt = raw_questions[i]
        # output.prompt로 프롬프트를 추출할 수도 있지만 불필요한 태그가 많이 따라온다. 정제과정이 필요.
        generated_text = output.outputs[0].text
        
        # &amp;lt;/thought&amp;gt; 태그가 존재한다면 그 태그 뒷부분([1])만 추출한다
        if &quot;&amp;lt;/thought&amp;gt;&quot; in generated_text:
            clean_answer = generated_text.split(&quot;&amp;lt;/thought&amp;gt;&quot;)[1]
        else:
            clean_answer = generated_text

        print(f&quot;==========================================&quot;)
        print(f&quot;질문: {prompt}&quot;)
        print(f&quot;답변: {clean_answer.strip()}&quot;)
        print(f&quot;==========================================\n&quot;)

if __name__ == &quot;__main__&quot;:
    main()&lt;/code&gt;&lt;/pre&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;1730&quot; data-origin-height=&quot;924&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cequW8/dJMcaiqcW4e/karK0UOkmE64aA5gzpHUd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cequW8/dJMcaiqcW4e/karK0UOkmE64aA5gzpHUd0/img.png&quot; data-alt=&quot;EXAON 모델이 다운로드되어 있지 않다면 다운로드하느라 이 화면에서 시간이 좀 걸린다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cequW8/dJMcaiqcW4e/karK0UOkmE64aA5gzpHUd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcequW8%2FdJMcaiqcW4e%2FkarK0UOkmE64aA5gzpHUd0%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;1730&quot; height=&quot;924&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;924&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;EXAON 모델이 다운로드되어 있지 않다면 다운로드하느라 이 화면에서 시간이 좀 걸린다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서는 토큰 없이 허가되지 않은 접근을 하고 있기 때문에 다운로드가 느리다고 한다. 토큰을 받고 빠르게 다운로드하는 방법은 맨 아래 내용을 참고하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;1204&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cY31oy/dJMcacKmlcN/dCnDaC86ma4iI5ACEYzKzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cY31oy/dJMcacKmlcN/dCnDaC86ma4iI5ACEYzKzk/img.png&quot; data-alt=&quot;최종 결과 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cY31oy/dJMcacKmlcN/dCnDaC86ma4iI5ACEYzKzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcY31oy%2FdJMcacKmlcN%2FdCnDaC86ma4iI5ACEYzKzk%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;1730&quot; height=&quot;1204&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;1204&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;최종 결과 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block; text-align: center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-7506419418365672&quot; data-ad-slot=&quot;5217671153&quot;&gt;&lt;/ins&gt;
&lt;script&gt;     (adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&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;2024&quot; data-origin-height=&quot;4564&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dc17YF/dJMcadoPHHD/dwaeu1Upm3XrhXwKYkkYdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dc17YF/dJMcadoPHHD/dwaeu1Upm3XrhXwKYkkYdK/img.png&quot; data-alt=&quot;다시 실행하면 모델을 다운로드하는 과정이 없다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dc17YF/dJMcadoPHHD/dwaeu1Upm3XrhXwKYkkYdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdc17YF%2FdJMcadoPHHD%2Fdwaeu1Upm3XrhXwKYkkYdK%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;2024&quot; height=&quot;4564&quot; data-origin-width=&quot;2024&quot; data-origin-height=&quot;4564&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;다시 실행하면 모델을 다운로드하는 과정이 없다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1781846578649&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import os
os.environ[&quot;VLLM_USE_FLASHINFER_SAMPLER&quot;] = &quot;0&quot;

from vllm import LLM, SamplingParams

def main():
    llm = LLM(
        model=&quot;LGAI-EXAONE/EXAONE-Deep-2.4B-AWQ&quot;, 
        trust_remote_code=True, 
        gpu_memory_utilization=0.7
    )

    sampling_params = SamplingParams(
        temperature=0.0,
        top_p=0.95,
        max_tokens=1024,
        repetition_penalty=1.1
    )

    raw_questions = [
        &quot;대한민국의 수도는 어디인가요?&quot;,
        &quot;인공지능에 대해 한 문장으로 요약해줘.&quot;
    ]

    prompts = []
    tokenizer = llm.get_tokenizer()
    for q in raw_questions:
        messages = [{&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: q}]
        formatted_prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
        prompts.append(formatted_prompt)

    outputs = llm.generate(prompts, sampling_params)

    for i, output in enumerate(outputs):
        prompt = raw_questions[i]
        generated_text = output.outputs[0].text
        
        if &quot;&amp;lt;/thought&amp;gt;&quot; in generated_text:
            clean_answer = generated_text.split(&quot;&amp;lt;/thought&amp;gt;&quot;)[1]
        else:
            clean_answer = generated_text

        print(f&quot;==========================================&quot;)
        print(f&quot;질문: {prompt}&quot;)
        print(f&quot;답변: {clean_answer.strip()}&quot;)
        print(f&quot;==========================================\n&quot;)

    print(outputs)

if __name__ == &quot;__main__&quot;:
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;짧은 답변이 나오도록 질문을 바꾸고 전체 결과가 출력되도록 print(outputs) 명령을 추가했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2050&quot; data-origin-height=&quot;1008&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZoblR/dJMcahY7aAl/MsUbsjs0jvkuyqzmpk5Pf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZoblR/dJMcahY7aAl/MsUbsjs0jvkuyqzmpk5Pf1/img.png&quot; data-alt=&quot;마지막에 outputs의 내용이 출력되었다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZoblR/dJMcahY7aAl/MsUbsjs0jvkuyqzmpk5Pf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZoblR%2FdJMcahY7aAl%2FMsUbsjs0jvkuyqzmpk5Pf1%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;2050&quot; height=&quot;1008&quot; data-origin-width=&quot;2050&quot; data-origin-height=&quot;1008&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;마지막에 outputs의 내용이 출력되었다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;[RequestOutput(request_id=0, prompt='[|system|][|endofturn|]\n[|user|]대한민국의 수도는 어디인가요?\n[|assistant|]&amp;lt;thought&amp;gt;\n', prompt_token_ids=[420, 453, 47982, 453, 422, 361, 560, 420, 453, 14719, 453, 422, 36437, 730, 8952, 657, 4083, 798, 7799, 392, 560, 420, 453, 1167, 8659, 453, 422, 389, 52040, 391, 560], encoder_prompt=None, encoder_prompt_token_ids=None, prompt_logprobs=None, outputs=[CompletionOutput(index=0, text='\n&amp;lt;/thought&amp;gt;\n\n 대한민국의 수도는 서울(Seoul)입니다.', token_ids=[560, 2240, 52040, 391, 560, 560, 9971, 730, 8952, 657, 2879, 369, 8078, 10103, 370, 10996, 375, 361], routed_experts=None, cumulative_logprob=None, logprobs=None, finish_reason=stop, stop_reason=None)], finished=True, metrics=None, lora_request=None, num_cached_tokens=0), RequestOutput(request_id=1, prompt='[|system|][|endofturn|]\n[|user|]인공지능에 대해 한 문장으로 요약해줘.\n[|assistant|]&amp;lt;thought&amp;gt;\n', prompt_token_ids=[420, 453, 47982, 453, 422, 361, 560, 420, 453, 14719, 453, 422, 41595, 22427, 2373, 2409, 764, 13742, 13456, 16399, 999, 15887, 375, 560, 420, 453, 1167, 8659, 453, 422, 389, 52040, 391, 560], encoder_prompt=None, encoder_prompt_token_ids=None, prompt_logprobs=None, outputs=[CompletionOutput(index=0, text='\n&amp;lt;/thought&amp;gt;\n\n인간의 intelligence를 computer로 구현하는 것.', token_ids=[560, 2240, 52040, 391, 560, 560, 25284, 730, 13887, 4605, 6458, 715, 19495, 1130, 657, 924, 375, 361], routed_experts=None, cumulative_logprob=None, logprobs=None, finish_reason=stop, stop_reason=None)], finished=True, metrics=None, lora_request=None, num_cached_tokens=0)]&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block; text-align: center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-7506419418365672&quot; data-ad-slot=&quot;5217671153&quot;&gt;&lt;/ins&gt;
&lt;script&gt;     (adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 이렇게 진행하는 모델은 내부에 config.json 파일이 있어야 한다. (정확히는 gguf 포맷의 모델은 바로 사용할 수 없다는 것이다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 EXAON은 config.json 파일이 있지만 Bllossom-3B-gguf-Q4_k_M은 없다. 그래서 Bllossom-3B-gguf-Q4_k_M은 vLLM에서 바로 사용할 수 없다. (아래 &lt;u&gt;참고 1~2&lt;/u&gt;를 참고한다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1626&quot; data-origin-height=&quot;1475&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bao0wD/dJMcaaZ0aoj/Crhd6Y1D1sQKW0zEK3M5VK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bao0wD/dJMcaaZ0aoj/Crhd6Y1D1sQKW0zEK3M5VK/img.png&quot; data-alt=&quot;config.json 파일이 없다. (gguf 포맷 모델이므로)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bao0wD/dJMcaaZ0aoj/Crhd6Y1D1sQKW0zEK3M5VK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbao0wD%2FdJMcaaZ0aoj%2FCrhd6Y1D1sQKW0zEK3M5VK%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;1626&quot; height=&quot;1475&quot; data-origin-width=&quot;1626&quot; data-origin-height=&quot;1475&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;config.json 파일이 없다. (gguf 포맷 모델이므로)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1714&quot; data-origin-height=&quot;840&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cq2iCp/dJMcahrmqmf/Fb9dfuUfKMFiQPmkCAWVo1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cq2iCp/dJMcahrmqmf/Fb9dfuUfKMFiQPmkCAWVo1/img.png&quot; data-alt=&quot;config.json 파일이 없다는 에러가 발생한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cq2iCp/dJMcahrmqmf/Fb9dfuUfKMFiQPmkCAWVo1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcq2iCp%2FdJMcahrmqmf%2FFb9dfuUfKMFiQPmkCAWVo1%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;1714&quot; height=&quot;840&quot; data-origin-width=&quot;1714&quot; data-origin-height=&quot;840&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;config.json 파일이 없다는 에러가 발생한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1626&quot; data-origin-height=&quot;1475&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/u04t5/dJMcacQ1ztz/JSUUcDfrC0IcFE2hNAEgPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/u04t5/dJMcacQ1ztz/JSUUcDfrC0IcFE2hNAEgPK/img.png&quot; data-alt=&quot;config.json 파일이 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/u04t5/dJMcacQ1ztz/JSUUcDfrC0IcFE2hNAEgPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fu04t5%2FdJMcacQ1ztz%2FJSUUcDfrC0IcFE2hNAEgPK%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;1626&quot; height=&quot;1475&quot; data-origin-width=&quot;1626&quot; data-origin-height=&quot;1475&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;config.json 파일이 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1626&quot; data-origin-height=&quot;1475&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKhbHR/dJMcacXPdKn/dz9Il2AYX0c6t1kkyxgwGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKhbHR/dJMcacXPdKn/dz9Il2AYX0c6t1kkyxgwGK/img.png&quot; data-alt=&quot;config.json 파일이 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKhbHR/dJMcacXPdKn/dz9Il2AYX0c6t1kkyxgwGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKhbHR%2FdJMcacXPdKn%2Fdz9Il2AYX0c6t1kkyxgwGK%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;1626&quot; height=&quot;1475&quot; data-origin-width=&quot;1626&quot; data-origin-height=&quot;1475&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;config.json 파일이 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block; text-align: center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-7506419418365672&quot; data-ad-slot=&quot;5217671153&quot;&gt;&lt;/ins&gt;
&lt;script&gt;     (adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 참고 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;■ Hugging Face에서 (Bllossom-3B-gguf-Q4_K_M) 모델 다운로드하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hf 명령어를 사용한다. huggingface-cli는 더 이상 사용하지 않는다. 위 과정을 진행했다면 hf(Hugging Face Hub CLI)는 이미 설치되어 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2162&quot; data-origin-height=&quot;616&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/becNHe/dJMcabLtIFC/0P6kPzqW2SG2WorKcxnJFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/becNHe/dJMcabLtIFC/0P6kPzqW2SG2WorKcxnJFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/becNHe/dJMcabLtIFC/0P6kPzqW2SG2WorKcxnJFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbecNHe%2FdJMcabLtIFC%2F0P6kPzqW2SG2WorKcxnJFK%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;2162&quot; height=&quot;616&quot; data-origin-width=&quot;2162&quot; data-origin-height=&quot;616&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬 가상화 환경을 시작한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hf&amp;nbsp;auth&amp;nbsp;login &lt;br /&gt;Paste an access token 옵션을 선택하고 Profile - Settings - Access Tokens에서 생성한 토큰을 붙여넣는다. &lt;br /&gt;로그인이 완료된다. &lt;br /&gt;&lt;br /&gt;로그인&amp;nbsp;확인하기 &lt;br /&gt;hf&amp;nbsp;auth&amp;nbsp;whoami &lt;br /&gt;&lt;br /&gt;Bllossom-3B-gguf-Q4_K_M 모델 다운로드하기&lt;br /&gt;hf&amp;nbsp;download&amp;nbsp;Bllossom/llama-3.2-Korean-Bllossom-3B-gguf-Q4_K_M &lt;br /&gt;로그인하지 않은 상태에서 다운로드하면 느리게 진행되지만 로그인을 했으므로 빠르게 진행된다. &lt;br /&gt;&lt;br /&gt;모델 다운로드 위치 &lt;br /&gt;/home/sean/.cache/huggingface/hub/ &lt;br /&gt;예) /home/sean/.cache/huggingface/hub/models--Bllossom--llama-3.2-Korean-Bllossom-3B-gguf-Q4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 참고 2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bllossom-3B-gguf-Q4_K_M 같은 gguf 포맷 모델 저장소에는 config.json 파일이 포함되어 있지 않다. guff 파일은 모델의 가중치뿐만 아니라 토크나이저 설정, 레이어 수, 아키텍처 정보 등 config.json에 들어가는 모든 메타데이터를 단일 guff 파일 내부에 바이너리 형태로 통합하여 저장하기 때문이다. 모델의 메타데이터와 아키텍처 구조를 확인하거나 다른 라이브러리와 호환을 맞추기 위해 json 파일이 필요하다면 양자화되기 전 원본 모델 저장소인 Bllossom/llama-3.2-Korean-Bllossom-3B에 있는 config.json 및 토크나이저 설정 파일들을 사용하면 된다. (설정 파일을 직접 다운로드 받아 gguf 파일이 있는곳에 저장할 필요는 없다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1781967603463&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;llm = LLM(
        model=&quot;/home/sean/.cache/huggingface/hub/models--Bllossom--llama-3.2-Korean-Bllossom-3B-gguf-Q4_K_M/snapshots/c07b7a0f2688d1212612b653a752a0dfe4e18bae/llama-3.2-Korean-Bllossom-3B-gguf-Q4_K_M.gguf&quot;,
        # 모델은 저장된 경로와 이름을 정확히 적어준다.
        tokenizer=&quot;Bllossom/llama-3.2-Korean-Bllossom-3B&quot;,
        # 토크나이저는 저장소 이름을 적어줘도 된다.
        trust_remote_code=True,
        gpu_memory_utilization=0.7,
        dtype=&quot;float16&quot;,
    )&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 위와 같이 LLM 클래스를 생성하면 될 것 같은데, WSL에서 실행하면 계속 UVA 관련 에러가 발생한다. WSL이 아닌 리눅스를 네이티브 운영체제로 사용하는 환경에서 테스트해 봐야 할 것 같다.&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;또한 vLLM에서 gguf 포맷 모델 사용은 실험적 단계이며 특별한 제약과 조건이 있어 추천하지 않는다. vLLM은 AWQ, GPTQ, FP8 같은 GPU 네이티브 양자화 포맷에서 제대로 된 성능이 나온다. gguf 포맷 모델을 로컬 환경에서 편하고 안정적으로 사용하려면 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://s-engineer.tistory.com/712&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Ollama&lt;/a&gt;&lt;/span&gt;를 사용하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GGUF(GPT-Generated&amp;nbsp;Unified&amp;nbsp;Format)는&amp;nbsp;인공지능&amp;nbsp;모델(특히&amp;nbsp;LLM)을&amp;nbsp;개인&amp;nbsp;PC나&amp;nbsp;노트북&amp;nbsp;같은&amp;nbsp;로컬&amp;nbsp;환경에서&amp;nbsp;빠르고&amp;nbsp;효율적으로&amp;nbsp;실행하기&amp;nbsp;위해&amp;nbsp;설계된&amp;nbsp;단일&amp;nbsp;파일&amp;nbsp;모델&amp;nbsp;포맷이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3B: 모델의 매개변수가 30억 개이다. (3 Billion)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Q4: 4비트 양자화를 의미. 원래 16비트인 모델을 4비트로 압축하여 파일 용량과 메모리를 1/4로 줄였다는 뜻.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;K_M: 양자화 기법의 종류. 보통 _L(Large), _M(Medium), _S(Small) 로 나뉘며, Q4_K_M은 성능 저하를 최소화하면서 용량을 줄인 가장 대중적이고 밸런스가 좋은 기법이다.&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;■ UVA&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WSL에서&amp;nbsp;UVA는&amp;nbsp;일반적으로&amp;nbsp;엔비디아(NVIDIA)의&amp;nbsp;Unified&amp;nbsp;Virtual&amp;nbsp;Addressing(통합&amp;nbsp;가상&amp;nbsp;주소)&amp;nbsp;기술을&amp;nbsp;의미합니다. &lt;br /&gt;이는 GPU가 컴퓨터 메모리(RAM)와 GPU 자체 메모리를 하나의 주소 공간으로 다룰 수 있게 해주는 기술입니다. WSL 환경에서는 AI/머신러닝(예: PyTorch)을 구동할 때 GPU 가속을 위해 필수적으로 사용되는 핵심 기능입니다.&lt;br /&gt;&lt;br /&gt;WSL에서&amp;nbsp;UVA가&amp;nbsp;중요한&amp;nbsp;이유 &lt;br /&gt;1.&amp;nbsp;메모리&amp;nbsp;접근&amp;nbsp;단순화:&amp;nbsp;CPU&amp;nbsp;메모리와&amp;nbsp;GPU&amp;nbsp;메모리&amp;nbsp;간의&amp;nbsp;데이터를&amp;nbsp;복사할&amp;nbsp;때&amp;nbsp;위치를&amp;nbsp;일일이&amp;nbsp;지정할&amp;nbsp;필요가&amp;nbsp;없습니다. &lt;br /&gt;2. AI 및 딥러닝 가속: vLLM이나 대형 모델(LLM) 학습 시 VRAM 부족을 해결하기 위해 CPU RAM을 공유해 사용할 때(CPU Offloading), 이 기술이 필수적으로 작동해야 합니다.&lt;br /&gt;3.&amp;nbsp;호환성&amp;nbsp;이슈&amp;nbsp;해결:&amp;nbsp;종종&amp;nbsp;WSL&amp;nbsp;환경에서&amp;nbsp;이&amp;nbsp;기능이&amp;nbsp;제대로&amp;nbsp;감지되지&amp;nbsp;않으면&amp;nbsp;메모리&amp;nbsp;오류가&amp;nbsp;발생하거나&amp;nbsp;가속&amp;nbsp;기능이&amp;nbsp;작동하지&amp;nbsp;않을&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1964&quot; data-origin-height=&quot;869&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biEaXt/dJMcagTuImb/mCAb0k12QNjbmVntPZqALk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biEaXt/dJMcagTuImb/mCAb0k12QNjbmVntPZqALk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biEaXt/dJMcagTuImb/mCAb0k12QNjbmVntPZqALk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiEaXt%2FdJMcagTuImb%2FmCAb0k12QNjbmVntPZqALk%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;1964&quot; height=&quot;869&quot; data-origin-width=&quot;1964&quot; data-origin-height=&quot;869&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1964&quot; data-origin-height=&quot;1223&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tdInq/dJMcagFZ10t/7oZkkWDesDKEx5LzpPzb1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tdInq/dJMcagFZ10t/7oZkkWDesDKEx5LzpPzb1K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tdInq/dJMcagFZ10t/7oZkkWDesDKEx5LzpPzb1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtdInq%2FdJMcagFZ10t%2F7oZkkWDesDKEx5LzpPzb1K%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;1964&quot; height=&quot;1223&quot; data-origin-width=&quot;1964&quot; data-origin-height=&quot;1223&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 참고 3&lt;/p&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;675&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNvVm3/dJMcaasdkC2/2CPeBYWmE10oEdPnrkDziK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNvVm3/dJMcaasdkC2/2CPeBYWmE10oEdPnrkDziK/img.png&quot; data-alt=&quot;파일 익스플로러 주소창에 \\wsl$를 입력하면 WSL에 설치된 운영체제의 파일에 접근할 수 있다. 물론 왼쪽 패널에 Linux - Ubuntu-24.04로 접근해도 된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNvVm3/dJMcaasdkC2/2CPeBYWmE10oEdPnrkDziK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNvVm3%2FdJMcaasdkC2%2F2CPeBYWmE10oEdPnrkDziK%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;675&quot; data-origin-width=&quot;1163&quot; data-origin-height=&quot;675&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;파일 익스플로러 주소창에 \\wsl$를 입력하면 WSL에 설치된 운영체제의 파일에 접근할 수 있다. 물론 왼쪽 패널에 Linux - Ubuntu-24.04로 접근해도 된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 참고 4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://docs.vllm.ai/en/stable/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;vLLM Documentation&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://github.com/vllm-project/vllm&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;vLLM GitHub&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI, ML, DL</category>
      <category>face</category>
      <category>hugging</category>
      <category>Linux</category>
      <category>ubuntu</category>
      <category>vllm</category>
      <category>Windows</category>
      <category>WSL</category>
      <category>리눅스</category>
      <category>우분투</category>
      <author>J-sean</author>
      <guid isPermaLink="true">https://s-engineer.tistory.com/720</guid>
      <comments>https://s-engineer.tistory.com/720#entry720comment</comments>
      <pubDate>Fri, 19 Jun 2026 13:29:38 +0900</pubDate>
    </item>
    <item>
      <title>[WPF] Google's Material Design</title>
      <link>https://s-engineer.tistory.com/719</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://github.com/materialdesigninxaml/materialdesigninxamltoolkit&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Google's Material Design&lt;/a&gt;&lt;/span&gt;을 사용해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1815&quot; data-origin-height=&quot;1909&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFxYcX/dJMcaffY4BM/guiaDQxznpNpCpkBNjJeeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFxYcX/dJMcaffY4BM/guiaDQxznpNpCpkBNjJeeK/img.png&quot; data-alt=&quot;MaterialDesignThemes를 설치한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFxYcX/dJMcaffY4BM/guiaDQxznpNpCpkBNjJeeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFxYcX%2FdJMcaffY4BM%2FguiaDQxznpNpCpkBNjJeeK%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;1815&quot; height=&quot;1909&quot; data-origin-width=&quot;1815&quot; data-origin-height=&quot;1909&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;MaterialDesignThemes를 설치한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 약간 수정해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1781767859267&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;Application x:Class=&quot;Test.App&quot;
             xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
             xmlns:local=&quot;clr-namespace:Test&quot;
             StartupUri=&quot;MainWindow.xaml&quot;&amp;gt;
    &amp;lt;Application.Resources&amp;gt;
         
    &amp;lt;/Application.Resources&amp;gt;
&amp;lt;/Application&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래 App.xaml&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1781768259549&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;Application x:Class=&quot;Test.App&quot;
             xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
             xmlns:materialDesign=&quot;http://materialdesigninxaml.net/winfx/xaml/themes&quot;
             StartupUri=&quot;MainWindow.xaml&quot;&amp;gt;
    &amp;lt;Application.Resources&amp;gt;
        &amp;lt;ResourceDictionary&amp;gt;
            &amp;lt;ResourceDictionary.MergedDictionaries&amp;gt;
                &amp;lt;materialDesign:BundledTheme BaseTheme=&quot;Light&quot; PrimaryColor=&quot;DeepPurple&quot; SecondaryColor=&quot;Lime&quot; /&amp;gt;
                &amp;lt;ResourceDictionary Source=&quot;pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesign3.Defaults.xaml&quot; /&amp;gt;
            &amp;lt;/ResourceDictionary.MergedDictionaries&amp;gt;
        &amp;lt;/ResourceDictionary&amp;gt;
    &amp;lt;/Application.Resources&amp;gt;
&amp;lt;/Application&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정된 App.xaml&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1781768325373&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;Window x:Class=&quot;Test.MainWindow&quot;
        xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
        xmlns:d=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;
        xmlns:mc=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
        xmlns:local=&quot;clr-namespace:Test&quot;
        mc:Ignorable=&quot;d&quot;
        Title=&quot;MainWindow&quot; Height=&quot;450&quot; Width=&quot;800&quot;&amp;gt;
    &amp;lt;Grid&amp;gt;

    &amp;lt;/Grid&amp;gt;
&amp;lt;/Window&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래 MainWindow.xaml&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1781768388010&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;Window x:Class=&quot;Test.MainWindow&quot;
        xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
        xmlns:d=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;
        xmlns:mc=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
        xmlns:local=&quot;clr-namespace:Test&quot;
        mc:Ignorable=&quot;d&quot;
        Style=&quot;{StaticResource MaterialDesignWindow}&quot;
        Title=&quot;MainWindow&quot; Height=&quot;450&quot; Width=&quot;800&quot;&amp;gt;
    &amp;lt;Grid&amp;gt;

    &amp;lt;/Grid&amp;gt;
&amp;lt;/Window&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정된 MainWindow.xaml (Style 속성만 추가 되었다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block; text-align: center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-7506419418365672&quot; data-ad-slot=&quot;5217671153&quot;&gt;&lt;/ins&gt;
&lt;script&gt;     (adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&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;1481&quot; data-origin-height=&quot;1909&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qRpjk/dJMcah5WDK0/WIf3XqO1Y97jz3VjY5oWD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qRpjk/dJMcah5WDK0/WIf3XqO1Y97jz3VjY5oWD1/img.png&quot; data-alt=&quot;버튼을 하나 추가한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qRpjk/dJMcah5WDK0/WIf3XqO1Y97jz3VjY5oWD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqRpjk%2FdJMcah5WDK0%2FWIf3XqO1Y97jz3VjY5oWD1%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;1481&quot; height=&quot;1909&quot; data-origin-width=&quot;1481&quot; data-origin-height=&quot;1909&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;버튼을 하나 추가한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;1694&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0POWS/dJMcahEMEP9/b7sKVQdKpDkuZt61Jp8aI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0POWS/dJMcahEMEP9/b7sKVQdKpDkuZt61Jp8aI0/img.png&quot; data-alt=&quot;버튼의 Properties - Miscellaneous - Style을 클릭하고 Local Resource에서 원하는 스타일을 선택할 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0POWS/dJMcahEMEP9/b7sKVQdKpDkuZt61Jp8aI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0POWS%2FdJMcahEMEP9%2Fb7sKVQdKpDkuZt61Jp8aI0%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;1044&quot; height=&quot;1694&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;1694&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;버튼의 Properties - Miscellaneous - Style을 클릭하고 Local Resource에서 원하는 스타일을 선택할 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Material Design을 설치하고 세팅하기 전에는 Style 항목이 비어 있다. Material Design을 설치하고 세팅했기 때문에 선택할 수 있는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1481&quot; data-origin-height=&quot;1909&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AatoT/dJMcag0au6j/RmRmSCkfTe1TtGgVKs6BD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AatoT/dJMcag0au6j/RmRmSCkfTe1TtGgVKs6BD0/img.png&quot; data-alt=&quot;MaterialDesignFloatingActionDarkButton을 선택했다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AatoT/dJMcag0au6j/RmRmSCkfTe1TtGgVKs6BD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAatoT%2FdJMcag0au6j%2FRmRmSCkfTe1TtGgVKs6BD0%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;1481&quot; height=&quot;1909&quot; data-origin-width=&quot;1481&quot; data-origin-height=&quot;1909&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;MaterialDesignFloatingActionDarkButton을 선택했다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1182&quot; data-origin-height=&quot;666&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciHn0a/dJMcafNP8kp/YZxgoZPOkYuyC9EZH5QKCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciHn0a/dJMcafNP8kp/YZxgoZPOkYuyC9EZH5QKCk/img.png&quot; data-alt=&quot;코드를 빌드하고 실행한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciHn0a/dJMcafNP8kp/YZxgoZPOkYuyC9EZH5QKCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FciHn0a%2FdJMcafNP8kp%2FYZxgoZPOkYuyC9EZH5QKCk%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;1182&quot; height=&quot;666&quot; data-origin-width=&quot;1182&quot; data-origin-height=&quot;666&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;코드를 빌드하고 실행한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Material Design&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/wiki/Getting-Started&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Getting Started&lt;/a&gt;&lt;/span&gt;&amp;nbsp;(오른쪽 패널의 Controls, Theming 등도 참고 하자)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>C#</category>
      <category>c#</category>
      <category>DESIGN</category>
      <category>Google</category>
      <category>GUI</category>
      <category>Material</category>
      <category>Windows</category>
      <category>WPF</category>
      <author>J-sean</author>
      <guid isPermaLink="true">https://s-engineer.tistory.com/719</guid>
      <comments>https://s-engineer.tistory.com/719#entry719comment</comments>
      <pubDate>Thu, 18 Jun 2026 17:00:24 +0900</pubDate>
    </item>
  </channel>
</rss>