<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>chyan_e_.log</title>
        <link>https://velog.io/</link>
        <description>찬과장의 Daily Reflection</description>
        <lastBuildDate>Mon, 19 May 2025 03:48:29 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>chyan_e_.log</title>
            <url>https://velog.velcdn.com/images/chyan_e_log/profile/99dcd589-6f8a-4be6-8278-3e4415a1c231/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. chyan_e_.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/chyan_e_log" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[3] Cloud]]></title>
            <link>https://velog.io/@chyan_e_log/Cloud</link>
            <guid>https://velog.io/@chyan_e_log/Cloud</guid>
            <pubDate>Mon, 19 May 2025 03:48:29 GMT</pubDate>
            <description><![CDATA[<h3 id="git-clone-연결">git clone 연결</h3>
<h4 id="저번까지-한거-확인하는-코드">저번까지 한거 확인하는 코드</h4>
<blockquote>
</blockquote>
<pre><code>echo $JAVA_HOME</code></pre><ul>
<li>java-21-openjdk-amd64가 뜨면 완료</li>
</ul>
<h4 id="home으로-이동">home으로 이동</h4>
<pre><code>cd ../</code></pre><h4 id="git-colne-연결">git colne 연결</h4>
<pre><code>git clone 깃허브링크</code></pre><h4 id="프로젝트-파일로-이동">프로젝트 파일로 이동</h4>
<pre><code>cd SpringMVC6</code></pre><h4 id="maven-다운">maven 다운</h4>
<blockquote>
<p>/home/git/클라우드/SpringMVC06</p>
</blockquote>
<pre><code>apt install maven</code></pre><h4 id="상위-폴더로-이동">상위 폴더로 이동</h4>
<pre><code>cd ../</code></pre><h4 id="클라우드-폴더로-이동">클라우드 폴더로 이동</h4>
<blockquote>
<p>/home/git/</p>
</blockquote>
<pre><code>cd 클라우드 이름</code></pre><h4 id="pull">pull</h4>
<blockquote>
<p>/home/git/클라우드</p>
</blockquote>
<pre><code>git pull</code></pre><h4 id="프로젝트-파일로-이동-1">프로젝트 파일로 이동</h4>
<pre><code>cd SpringMVC06</code></pre><h4 id="mvn">mvn</h4>
<blockquote>
<p>/home/git/lgdx6_cloud/SpringMVC06</p>
</blockquote>
<pre><code>mvn clean pakage</code></pre><h4 id="서버실행">서버실행</h4>
<blockquote>
<p>home/git/lgdx_cloud/SpringMVC06</p>
</blockquote>
<pre><code>cd target</code></pre><blockquote>
<p>home/git/lgdx_cloud/SpringMVC06/target</p>
</blockquote>
<pre><code>java -jar SpringMVC06-0.0.1 자동완성</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[22] Flutter Camera]]></title>
            <link>https://velog.io/@chyan_e_log/Flutter-Camera</link>
            <guid>https://velog.io/@chyan_e_log/Flutter-Camera</guid>
            <pubDate>Fri, 16 May 2025 08:30:38 GMT</pubDate>
            <description><![CDATA[<h3 id="라이브러리-다운로드">라이브러리 다운로드</h3>
<ul>
<li><p><a href="https://pub.dev/packages/image_picker/install">https://pub.dev/packages/image_picker/install</a></p>
<pre><code>import &#39;package:flutter/material.dart&#39;;
import &#39;package:image_picker/image_picker.dart&#39;;
final ImagePicker picker = ImagePicker();
class ExImage extends StatelessWidget {
const ExImage({super.key});

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: SafeArea(child: Column(
      children: [
        ElevatedButton(
          onPressed: () async {
            // Pick an image.
            final XFile? image = await picker.pickImage(source: ImageSource.gallery);
        },
          child: Text(&quot;갤러리 접근&quot;),
        ),
        ElevatedButton(onPressed: () async {
          // Capture a photo.
          final XFile? photo = await picker.pickImage(source: ImageSource.camera);
        },
            child: Text(&quot;카메라 접근&quot;)),
      ],
    )),
  );
}
}
</code></pre></li>
</ul>
<p>```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[21] Flutter DB연동2]]></title>
            <link>https://velog.io/@chyan_e_log/Flutter-DB%EC%97%B0%EB%8F%992</link>
            <guid>https://velog.io/@chyan_e_log/Flutter-DB%EC%97%B0%EB%8F%992</guid>
            <pubDate>Fri, 16 May 2025 07:45:34 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/chyan_e_log/post/d88398d1-ef08-4a17-8deb-9a1e810de6e2/image.png" alt=""></p>
<h2 id="내장-데이터-베이스-연동해보기">내장 데이터 베이스 연동해보기</h2>
<h3 id="라이브러리-다운로드">라이브러리 다운로드</h3>
<ol>
<li><p>pub.dev 접속
<img src="https://velog.velcdn.com/images/chyan_e_log/post/011d171f-4e51-4fa9-95ec-2ffe23eb6488/image.png" alt=""></p>
</li>
<li><p>대충 사용법
<img src="https://velog.velcdn.com/images/chyan_e_log/post/236ef364-9066-4645-bcd4-607eef1c56a4/image.png" alt=""></p>
</li>
<li><p>pubspec.yaml에 추가 후 저장 및 pub get
<img src="https://velog.velcdn.com/images/chyan_e_log/post/0181088d-870c-4290-b52e-d4e921759e4e/image.png" alt=""></p>
</li>
</ol>
<h3 id="라이브러리-전체-프로세스">라이브러리 전체 프로세스</h3>
<ol>
<li>로그인 시 storage에 저장</li>
<li>앱을 실행시켜서 storage에 저장 되어 있는 값 확인</li>
<li>1 값이 있으면 바로 LoginSuccessPage로 이동</li>
<li>2 값이 없으면 LoginPage로 이동</li>
<li>로그아웃 storage값 삭제 -&gt; LiginPage로 이동</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[2] Cloud VPC 생성]]></title>
            <link>https://velog.io/@chyan_e_log/Cloud-VPC-%EC%83%9D%EC%84%B1</link>
            <guid>https://velog.io/@chyan_e_log/Cloud-VPC-%EC%83%9D%EC%84%B1</guid>
            <pubDate>Fri, 16 May 2025 03:11:12 GMT</pubDate>
            <description><![CDATA[<h3 id="1-네이버-클라우드-접속-후-로그인">1. 네이버 클라우드 접속 후 로그인</h3>
<h3 id="2-vpc-생성">2. VPC 생성</h3>
<p><img src="https://velog.velcdn.com/images/chyan_e_log/post/30565d89-f68b-4291-a313-ec63c3c91791/image.png" alt=""></p>
<h3 id="3-생성중-화면">3. 생성중 화면</h3>
<p><img src="https://velog.velcdn.com/images/chyan_e_log/post/931ced10-1370-4f98-b15e-40afd07a9a0d/image.png" alt=""></p>
<h3 id="4-생성완료-화면">4. 생성완료 화면</h3>
<p><img src="https://velog.velcdn.com/images/chyan_e_log/post/8d7ca33a-10da-438b-8088-14a7778788c5/image.png" alt=""></p>
<h3 id="5-github-레파지포리-생성">5. GitHub 레파지포리 생성</h3>
<p><img src="https://velog.velcdn.com/images/chyan_e_log/post/7880c2b5-4336-415e-9241-65ec6f1b9e6a/image.png" alt=""></p>
<h3 id="6-전자정부-프레임워크-git-공유하기">6. 전자정부 프레임워크 Git 공유하기</h3>
<ol>
<li>application.properties
<img src="https://velog.velcdn.com/images/chyan_e_log/post/dc616c9b-659a-475e-8c62-003a42718898/image.png" alt=""></li>
</ol>
<p>2.
<img src="https://velog.velcdn.com/images/chyan_e_log/post/90106fb8-ba4c-4e71-ad9b-80d25625f70b/image.png" alt=""></p>
<p>3.
<img src="https://velog.velcdn.com/images/chyan_e_log/post/d2cc5675-7b01-49c1-a357-12ff039f22ed/image.png" alt=""></p>
<p>4.
<img src="https://velog.velcdn.com/images/chyan_e_log/post/6767f39a-7c32-4813-92c9-8d8bd1ab52e4/image.png" alt=""></p>
<p>5.
<img src="https://velog.velcdn.com/images/chyan_e_log/post/37b3ff7a-2855-4459-ac3f-6be0f8e6b910/image.png" alt="">
<img src="https://velog.velcdn.com/images/chyan_e_log/post/3fbbe745-a62b-4193-b37a-60ce1880744f/image.png" alt=""></p>
<p>6.
<img src="https://velog.velcdn.com/images/chyan_e_log/post/5331695c-e92c-4891-9313-6583cb38870e/image.png" alt=""></p>
<p>7.
<img src="https://velog.velcdn.com/images/chyan_e_log/post/dcea2397-2c95-4a6c-a7d5-5bd07c45234a/image.png" alt=""></p>
<p>8.
<img src="https://velog.velcdn.com/images/chyan_e_log/post/a58a9b16-47ee-4c40-8be8-3c1ef460939c/image.png" alt=""></p>
<p>9.
<img src="https://velog.velcdn.com/images/chyan_e_log/post/e14c8c5d-3a86-41e8-a55b-c436c8a45139/image.png" alt=""></p>
<ol start="10">
<li><p>초록색 창에 토큰 복사
<img src="https://velog.velcdn.com/images/chyan_e_log/post/cc7345a4-b76b-45a7-bcdf-e94185cb4475/image.png" alt=""></p>
</li>
<li><p>아이디 입력후 비밀번호 창에 토큰값 붙여넣기 하고. preview---finish
<img src="https://velog.velcdn.com/images/chyan_e_log/post/5e1800a5-4590-45e7-b7a8-96feedd51b78/image.png" alt=""></p>
</li>
</ol>
<h3 id="7-서브넷-생성">7. 서브넷 생성</h3>
<p><img src="https://velog.velcdn.com/images/chyan_e_log/post/7802eea9-56b7-427d-a909-2128ded7f6ec/image.png" alt=""></p>
<h3 id="8-서버-생성">8. 서버 생성</h3>
<ol>
<li>3세대 서버 생성 후 신규 서버로 선택
<img src="https://velog.velcdn.com/images/chyan_e_log/post/df9790bf-358b-41a8-878f-7afb94fcec96/image.png" alt=""></li>
</ol>
<p>2.
<img src="https://velog.velcdn.com/images/chyan_e_log/post/67f5d4c5-6ddc-4bb0-98db-836bb772647e/image.png" alt=""></p>
<p>3.
<img src="https://velog.velcdn.com/images/chyan_e_log/post/22caa1ee-e182-430f-bca1-f0f07f0b3082/image.png" alt=""></p>
<p>4.
<img src="https://velog.velcdn.com/images/chyan_e_log/post/dfcffb79-bf22-4fb7-9cb9-8ea0d3749582/image.png" alt=""></p>
<p>5.
<img src="https://velog.velcdn.com/images/chyan_e_log/post/2e90df5d-ebe1-414b-83f7-7441e03eb48a/image.png" alt=""></p>
<p>6.
<img src="https://velog.velcdn.com/images/chyan_e_log/post/f33e75ce-52a6-43a1-bb05-4350b318c8de/image.png" alt=""></p>
<ol start="7">
<li>서버 생성 버튼</li>
</ol>
<h3 id="9">9.</h3>
<ol>
<li>다운로드 후 실행파일 실행
<img src="https://velog.velcdn.com/images/chyan_e_log/post/b03a5f4b-2fbc-472b-8d0a-0a3bfe6b8bd7/image.png" alt=""></li>
</ol>
<ol start="2">
<li>비밀번호 확인 후 복사
<img src="https://velog.velcdn.com/images/chyan_e_log/post/908532b3-7471-49fb-b6af-96d0ace4e6c8/image.png" alt=""></li>
</ol>
<p>3.
<img src="https://velog.velcdn.com/images/chyan_e_log/post/4d1f9118-842a-4730-b6cc-5b0a9e0f4e61/image.png" alt=""></p>
<ol start="4">
<li><p>생성된 ssh 창 선택후 프롬프트 실행되면 root입력. 입력후 password입력 명령어에 마우스 우클릭 딱 한번만 하고 엔터</p>
</li>
<li><p>실행 완료
<img src="https://velog.velcdn.com/images/chyan_e_log/post/19098b59-4b4b-4c08-80f0-42398de49dc2/image.png" alt=""></p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[20] Flutter DB연동]]></title>
            <link>https://velog.io/@chyan_e_log/Flutter-DB%EC%97%B0%EB%8F%99</link>
            <guid>https://velog.io/@chyan_e_log/Flutter-DB%EC%97%B0%EB%8F%99</guid>
            <pubDate>Thu, 15 May 2025 08:51:14 GMT</pubDate>
            <description><![CDATA[<h2 id="db-연동">DB 연동</h2>
<h3 id="db-sql문-포매팅-방법">DB-sql문 포매팅 방법</h3>
<p><img src="https://velog.velcdn.com/images/chyan_e_log/post/4d1e0909-f04e-491f-a39a-7e716431c9b8/image.png" alt=""></p>
<blockquote>
<p>VsCode(app.py)</p>
</blockquote>
<pre><code>from flask import Flask, request,Blueprint
# 파일 관리를 위해 Blueprint
# 해당 파일 명을 import 진행
# from 파일명  import 변수명
from dbConnect import member
app = Flask(__name__)
# register_blueprint() 사용해서 연결
app.register_blueprint(member, url_prefix=&quot;/member&quot;) # prefix 별칭
@app.route(&#39;/&#39;)
def test():
    # return타입에 html 띄울 수 있는 함수 혹은 문자열 혹은 json이 반환
    return &#39;hello&#39;
@app.route(&#39;/send&#39;)
def send():
    # 데이터 받는법
    # request.args.get(&#39;보내준 곳에서의 key값&#39;)
    test = request.args.get(&#39;test&#39;)
    print(test)
    return &quot;hello234&quot;
if __name__ == &#39;__main__&#39;:
    app.debug = True #저장 하면 즉시 반영
    app.run(&#39;192.168.219.102&#39;, port = 8086)</code></pre><blockquote>
<p>VsCode(dbConnect.py)</p>
</blockquote>
<pre><code># python - mysql 연결 라이브러리
import pymysql
from flask import Blueprint, request
import json
# 1. Blueprint 설정
member = Blueprint(&quot;member&quot;, __name__, template_folder=&quot;templates&quot;)
@member.route(&#39;/&#39;)
def test():
    return &#39;hello member&#39;
@member.route(&#39;/insert&#39;)
def insert():
    #0. 클라이언트 값 받기
    email = request.args.get(&#39;email&#39;)
    password = request.args.get(&#39;password&#39;)
    age = int(request.args.get(&#39;age&#39;)) # request의 경우 str 타임으로 받아오기 때문에 DB와 타입 일치 위해 형변환!
    name = request.args.get(&#39;name&#39;)
    print(email,password,age,name)
    # 1. db 연결 - host, user, password,schema, encoding
    db = pymysql.connect(host=&#39;localhost&#39;, user=&#39;root&#39;, password=&#39;1234&#39;, db=&#39;flutter_db&#39;, charset = &#39;utf8&#39;)
    # 2. 데이터 접근 객 체(cursor 객체 생성)
    # db 연결한 변수 안에 cursor가 존재
    cursor = db.cursor()
    # 3. sql문 작성
    # sql = &quot;insert into member values(&#39;test2&#39;,&#39;1234&#39;,&#39;test2&#39;,20)&quot;
    # pymysql의 포맷팅
    # %(변수명)s
    sql = &quot;insert into member values(%(email)s, %(password)s, %(name)s, %(age)s)&quot;
    # 4. 실행 cursor.excute(sql)
    cursor.execute(sql,{&quot;email&quot;: email, &quot;password&quot; : password, &quot;age&quot; : age, &quot;name&quot; : name})
    # 필수는 아니나 유용한 변수 insert, update, delete 성공한 행의 개수를 파악
    row = cursor.rowcount
    # 5. 저장 후 db 닫기
    db.commit()
    db.close()
    # 데이터 insert 성공시 row라는 변수에 양수가 들어가 예정(성공한 행의 개수)
    if row &gt; 0:
        return &quot;success&quot;
    else :
        return &quot;fail&quot;
@member.route(&quot;/login&quot;)
def login():
    # 0. 데이터 받기
    id = request.args.get(&quot;id&quot;)
    password = request.args.get(&quot;pw&quot;)
    # 1. db 연결
    db = pymysql.connect(host = &quot;localhost&quot;,  user =&quot;root&quot;, password = &quot;1234&quot;, db= &quot;flutter_db&quot;, charset = &quot;utf8&quot;)
    # 2. 데이터 접근 객체 생성
    cursor = db.cursor()
    # 3.sql 작성
    sql = &quot;select * from member where id = %(id)s and pw = %(password)s&quot;
    # sql = &quot;select * from member&quot;
    # 4. 실행
    cursor.execute(sql, {&#39;id&#39;: id, &#39;password&#39; : password})
    # 5. 결과 받아오기
    result = cursor.fetchall() # 모든 행에 데이터 가져오기
    # cursor.fetchone() # 한개의 행만 가져오기
    # cursor.fetchmany(2) # ()안의 숫자 행 만큼 가져오기
    print(result)  # select 결과값은 튜플로 가져옴
    # 튜플은 Flask 내에서 reurtn되지 않습니다!!(return이 가능 한 타입은 json혹은 문자열)
    # 튜플은 json타입으로 변환
    row_headers = [x[0] for x in cursor.description] #db table의 name, type code, size~~
    print(row_headers) # table의 컬럼명
    json_data = [] # dict 구조들이 들어갈 예정
    for rv in result:
        json_data.append(dict(zip(row_headers, rv)))
        #zip 함수 사용해 다른 2개를 묶는 역할 -&gt; 튜플
        #튜플 -&gt; dict로 형변환
    #dict 가 있는 list를 json으로 변환 --&gt; json 라이브러리 사용
    # json.dumps()
    data = json.dumps(json_data)
    # 마지막 db 저장 close
    db.commit()
    db.close()
    return data</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[1] Cloud 네이버 클라우드]]></title>
            <link>https://velog.io/@chyan_e_log/Cloud-%EB%84%A4%EC%9D%B4%EB%B2%84-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C</link>
            <guid>https://velog.io/@chyan_e_log/Cloud-%EB%84%A4%EC%9D%B4%EB%B2%84-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C</guid>
            <pubDate>Thu, 15 May 2025 03:13:04 GMT</pubDate>
            <description><![CDATA[<h1 클라우드 노션 수업 url 숨김처리  https://sue019522.notion.site/LGDX3-1ee505eec7f1807e8674c54f58324620 >

<h2 id="클라우드-서비스란">클라우드 서비스란?</h2>
<ul>
<li>게시글 수정 눌러서 확인하기</li>
</ul>
<h2 id="네이버-클라우드">네이버 클라우드</h2>
<h3 id="콘솔">콘솔</h3>
<ul>
<li>로그인 후 콘솔 대시보드로 들어가기</li>
<li>지역(region 바꾸기)</li>
<li>플랫폼 VPC로 변경</li>
<li>서비스에서 server랑 VPC 즐겨찾기(별표) 누르기</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[2] GitHub & Git 공유하기]]></title>
            <link>https://velog.io/@chyan_e_log/GitHub-Git-%EA%B3%B5%EC%9C%A0%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@chyan_e_log/GitHub-Git-%EA%B3%B5%EC%9C%A0%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 13 May 2025 08:14:02 GMT</pubDate>
            <description><![CDATA[<h2 id="공유하기">공유하기</h2>
<h3 id="commit">Commit</h3>
<blockquote>
<ul>
<li>gitTest.html</li>
</ul>
</blockquote>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;Document&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;첫 번째 커밋&lt;/h1&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre><h4 id="gitbash">GitBash</h4>
<ol start="0">
<li><p>cd로 작업 폴더로 이동</p>
<ul>
<li>pwd로 현재 작업 폴더 확인 가능 </li>
</ul>
</li>
<li><p>git init</p>
</li>
</ol>
<ul>
<li>현재 경로에서 git 명령(commit,pull,push)을 사용할 수 있게끔 초기화</li>
<li>로컬레퍼지토리 생성</li>
<li>폴더 옆에 master가 뜨면 완료</li>
</ul>
<ol start="2">
<li><p>git config --global user.name &quot;이름&quot;
git config --global user.email &quot;이메일&quot;</p>
<ul>
<li>사용자 정보 등록</li>
</ul>
</li>
<li><p>커밋(내 로컬에서 커밋할때),(다른 주소를 커밋할때는 4번을 먼저)
3-1. git add 커밋할 프로젝트 =&gt; 커밋 활성화 단계
3-2. git commit -m &quot;커밋 메시지&quot; =&gt; 커밋 진행 단계(의무사항)</p>
</li>
<li><p>git remote add origin 주소</p>
<ul>
<li>원격 저장소 연결 </li>
</ul>
</li>
<li><p>git push origin master</p>
<ul>
<li>푸쉬 명령</li>
</ul>
</li>
<li><p>git pull origin master</p>
<ul>
<li>풀 명령</li>
</ul>
</li>
</ol>
<hr>
<ol>
<li>로컬 레퍼지토리 삭제(내역)</li>
</ol>
<ul>
<li>rm -rf .git</li>
<li>폴더 옆에 master가 사라진다.</li>
</ul>
<ol start="2">
<li>사용자 정보 확인</li>
</ol>
<ul>
<li>git config --global --list</li>
</ul>
<ol start="3">
<li>등록된 원격 저장소 확인</li>
</ol>
<ul>
<li>git remote -v</li>
</ul>
<ol start="4">
<li>등록된 원격 저장소 삭제</li>
</ol>
<ul>
<li>git remote rm 원격저장소 이름</li>
</ul>
<p>참고)
<a href="https://verdant-structure-e78.notion.site/Git-a9eefbccbc89495397d196172b8bcf85">https://verdant-structure-e78.notion.site/Git-a9eefbccbc89495397d196172b8bcf85</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[1] GitHub & Git]]></title>
            <link>https://velog.io/@chyan_e_log/Git</link>
            <guid>https://velog.io/@chyan_e_log/Git</guid>
            <pubDate>Tue, 13 May 2025 05:23:40 GMT</pubDate>
            <description><![CDATA[<h2 id="github를-활용한-프로젝트-환경-구축하기">GitHub를 활용한 프로젝트 환경 구축하기</h2>
<h3 id="git이란">Git이란?</h3>
<ul>
<li>Git 저장소 호스팅을 지원하는 웹 서비스로 온라인 상에서 여러 사용자들이 컴퓨터 파일을 공유하도록 도와준다</li>
</ul>
<h3 id="git의-장점">Git의 장점</h3>
<ul>
<li>소스코드를 주고 받을 필요 없이, 같은 파일을 여러명이 동시에 작업하는 병렬개발이 가능</li>
<li>프로젝트 관리, 배포, 이슈 추적 기능등 프로젝트 진행에 있어 편리한 기능들을 지원</li>
</ul>
<h3 id="github의-원리">GitHub의 원리</h3>
<p><img src="https://velog.velcdn.com/images/chyan_e_log/post/0d9a51ee-2f73-480b-aa37-e42f2a380ea6/image.png" alt=""></p>
<ul>
<li>🌟🌟중요한 순서🌟🌟<ul>
<li>Commit을 하기전 다른 팀원이 했던 내용을 먼저 pull 하고</li>
<li>자신의 코드를 Commit -&gt; Push를 통해 올려주어야 한다.</li>
</ul>
</li>
</ul>
<h3 id="github의-필요성">GitHub의 필요성</h3>
<ul>
<li>재택근무, 비대면 작업이 활성화 되는 요즘 온라인 협업도구의 필요성 증가</li>
<li>GitHub에 남겨진 프로젝트 결과물들이 포트폴리오 역할을 하고 동시에 그 사람의 작업 능력을 증명</li>
<li>협업 능력을 중요시 하는 요즘 GitHub 사용 경험은 필수</li>
</ul>
<h3 id="github-활용시-지켜야-하는-규칙">GitHub 활용시 지켜야 하는 규칙</h3>
<ul>
<li>수정할 때 같은 파일을 동시에 수정하지 않기!</li>
<li>pull,push 작업을 할때 꼭 commit을 통해서 local repository최신화 시켜주기!</li>
<li>개발을 한 후 commit -&gt; push 할때 꼭! 팀원들에게 알려주기
EX)
<img src="https://velog.velcdn.com/images/chyan_e_log/post/b36e6fbb-b87b-4260-b4bd-49dd6216ae53/image.png" alt=""></li>
</ul>
<h3 id="git-설치">Git 설치</h3>
<ul>
<li><a href="https://git-scm.com/downloads/win">https://git-scm.com/downloads/win</a> 들어가서 설치 </li>
<li>실행 후 싹다 Next -----&gt; Finish</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[19] Flutter 로그인 구성하기]]></title>
            <link>https://velog.io/@chyan_e_log/Flutter-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B5%AC%EC%84%B1%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@chyan_e_log/Flutter-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B5%AC%EC%84%B1%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 13 May 2025 03:41:33 GMT</pubDate>
            <description><![CDATA[<h3 id="login_page">login_page</h3>
<pre><code>import &#39;package:flutter/material.dart&#39;;
import &#39;package:flutter_http/screen/join_page.dart&#39;;

TextEditingController emailCon = TextEditingController();
TextEditingController pwCon = TextEditingController();

class LoginPage extends StatelessWidget {
  const LoginPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(&#39;로그인 페이지&#39;),
      ),
      body: SafeArea(
        child: SingleChildScrollView(
          child: Container(
            margin: EdgeInsets.all(12),
            padding: EdgeInsets.all(12),
            child: Column(
              children: [
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: TextField(
                    controller: emailCon,
                    decoration: InputDecoration(
                        label: Row(
                          children: [
                            Icon(Icons.account_circle),
                            Text(&quot;email 입력 &quot;),
                          ],
                        ),
                        hintText: &quot;example@example.com&quot;,
                        hintStyle: TextStyle(color: Colors.grey[300])),
                    keyboardType: TextInputType.emailAddress,
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: TextField(
                      obscureText: true,
                      controller: pwCon,
                      decoration: InputDecoration(
                        label: Row(
                          children: [
                            Icon(Icons.key),
                            Text(&quot;pw 입력 &quot;),
                          ],
                        ),
                      )),
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    ElevatedButton(
                        style: ElevatedButton.styleFrom(
                            backgroundColor: Colors.blueAccent),
                        onPressed: () {

                        },
                        child: Text(&#39;로그인하기&#39;)),
                    ElevatedButton(
                        style: ElevatedButton.styleFrom(
                            backgroundColor: Colors.grey),
                        onPressed: () {
                          Navigator.push(context, MaterialPageRoute(builder: (
                              _) =&gt; JoinPage()));
                        },
                        child: Text(&#39;회원가입하기&#39;))
                  ],
                ),
                SizedBox(
                  height: 40,
                ),
                Container(
                  color: Colors.grey[200],
                  width: double.infinity,
                  height: 2,
                ),
                SizedBox(
                  height: 40,
                ),

              ],
            ),
          ),
        ),
      ),
    );
  }
}
</code></pre><h3 id="join_page">join_page</h3>
<pre><code>import &#39;package:flutter/material.dart&#39;;

class JoinPage extends StatelessWidget {
  const JoinPage({super.key});

  @override
  Widget build(BuildContext context) {
    TextEditingController input_id = TextEditingController();
    TextEditingController input_pw = TextEditingController();
    TextEditingController input_age = TextEditingController();
    TextEditingController input_name = TextEditingController();

    return Scaffold(
      appBar: AppBar(
        title: Text(&#39;회원가입 페이지&#39;),
      ),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: TextField(
              decoration: InputDecoration(
                  label: Row(
                    children: [
                      Icon(Icons.account_circle),
                      Text(&quot;email 입력 &quot;),
                    ],
                  ),
                  hintText: &quot;example@example.com&quot;,
                  hintStyle: TextStyle(color: Colors.grey[300])),
              keyboardType: TextInputType.emailAddress,
              controller: input_id,
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: TextField(
              decoration: InputDecoration(
                label: Row(
                  children: [
                    Icon(Icons.key),
                    Text(&quot;비밀번호 입력 &quot;),
                  ],
                ),

              ),
              keyboardType: TextInputType.text,
              obscureText: true,
              controller: input_pw,
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: TextField(
              decoration: InputDecoration(
                  label: Text(&quot;나이 입력 &quot;),
                  hintText: &quot;20&quot;,
                  hintStyle: TextStyle(color: Colors.grey[300])),
              keyboardType: TextInputType.number,
              controller: input_age,
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: TextField(
              decoration: InputDecoration(
                  label: Text(&quot;이름 입력 &quot;),
                  hintText: &quot;플러터&quot;,
                  hintStyle: TextStyle(color: Colors.grey[300])),
              keyboardType: TextInputType.text,
              controller: input_name,
            ),
          ),

          ElevatedButton(onPressed: (){

          }, child: Text(&#39;회원 가입&#39;))
        ],
      ),
    );
  }
}</code></pre><h3 id="mysql연동하고-데이터-강제로-넣어보기">MySQL연동하고 데이터 강제로 넣어보기</h3>
<ul>
<li>dbConnect.py<pre><code># python - mysql 연결 라이브러리
import pymysql
from flask import Blueprint
</code></pre></li>
</ul>
<h1 id="1-blueprint-설정">1. Blueprint 설정</h1>
<p>member = Blueprint(&quot;member&quot;, <strong>name</strong>, template_folder=&quot;templates&quot;)</p>
<p>@member.route(&#39;/&#39;)
def test():
    return &#39;hello member&#39;</p>
<p>@member.route(&#39;/insert&#39;)
def insert():
    # 1. db 연결 - host, user, password,schema, encoding
    db = pymysql.connect(host=&#39;localhost&#39;, user=&#39;root&#39;, password=&#39;1234&#39;, db=&#39;flutter_db&#39;, charset = &#39;utf8&#39;)</p>
<pre><code># 2. 데이터 접근 객 체(cursor 객체 생성)
# db 연결한 변수 안에 cursor가 존재
cursor = db.cursor()

# 3. sql문 작성
sql = &quot;insert into member values(&#39;test2&#39;,&#39;1234&#39;,&#39;test2&#39;,20)&quot;

# 4. 실행 cursor.excute(sql)
cursor.execute(sql)

# 필수는 아니나 유용한 변수 insert, update, delete 성공한 행의 개수를 파악
row = cursor.rowcount

# 5. 저장 후 db 닫기
db.commit()
db.close()

# 데이터 insert 성공시 row라는 변수에 양수가 들어가 예정(성공한 행의 개수)
if row &gt; 0:
    return &quot;success&quot;
else :
    return &quot;fail&quot;</code></pre><pre><code>
- app.py</code></pre><p>from flask import Flask, request,Blueprint</p>
<h1 id="파일-관리를-위해-blueprint">파일 관리를 위해 Blueprint</h1>
<h1 id="해당-파일-명을-import-진행">해당 파일 명을 import 진행</h1>
<h1 id="from-파일명--import-변수명">from 파일명  import 변수명</h1>
<p>from dbConnect import member</p>
<p>app = Flask(<strong>name</strong>)</p>
<h1 id="register_blueprint-사용해서-연결">register_blueprint() 사용해서 연결</h1>
<p>app.register_blueprint(member, url_prefix=&quot;/member&quot;) # prefix 별칭</p>
<p>@app.route(&#39;/&#39;)
def test():
    # return타입에 html 띄울 수 있는 함수 혹은 문자열 혹은 json이 반환
    return &#39;hello&#39;</p>
<p>@app.route(&#39;/send&#39;)
def send():
    # 데이터 받는법
    # request.args.get(&#39;보내준 곳에서의 key값&#39;)
    test = request.args.get(&#39;test&#39;)
    print(test)
    return &quot;hello234&quot;</p>
<p>if <strong>name</strong> == &#39;<strong>main</strong>&#39;:
    app.debug = True #저장 하면 즉시 반영
    app.run(&#39;192.168.219.179&#39;, port = 8086)</p>
<p>```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[18] Flutter Flask서버 연결하기]]></title>
            <link>https://velog.io/@chyan_e_log/Flutter-Flask%EC%84%9C%EB%B2%84-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@chyan_e_log/Flutter-Flask%EC%84%9C%EB%B2%84-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 13 May 2025 02:29:52 GMT</pubDate>
            <description><![CDATA[<h3 id="vscode에서-서버-생성하기">VsCode에서 서버 생성하기</h3>
<blockquote>
<p>app.py</p>
</blockquote>
<pre><code>from flask import Flask, request
app = Flask(__name__)
@app.route(&#39;/&#39;)
def test():
    # return타입에 html 띄울 수 있는 함수 혹은 문자열 혹은 json이 반환
    return &#39;hello&#39;
@app.route(&#39;/send&#39;)
def send():
    # 데이터 받는법
    # request.args.get(&#39;보내준 곳에서의 key값&#39;)
    test = request.args.get(&#39;test&#39;)
    print(test)
    return &quot;hello234&quot;
if __name__ == &#39;__main__&#39;:
    app.debug = True #저장 하면 즉시 반영
    app.run(&#39;192.168.219.179&#39;, port = 8086)</code></pre><h3 id="안드로이드-스튜디오-돌아와서-서버-연결">안드로이드 스튜디오 돌아와서 서버 연결</h3>
<blockquote>
</blockquote>
<ul>
<li>ex_flask<pre><code>import &#39;package:dio/dio.dart&#39;;
import &#39;package:flutter/material.dart&#39;;
// tf 컨트롤러
TextEditingController testCon  = TextEditingController();
final dio = Dio();
class ExFlask extends StatelessWidget {
const ExFlask({super.key});
@override
Widget build(BuildContext context) {
  return Scaffold(
    body: SafeArea(
      child: Column(
        children: [
          TextField(
            controller: testCon,
          ),
          ElevatedButton(onPressed: () async{
            String test = testCon.text;
            // 1. url 작성
            String url = &#39;http://192.168.219.179:8086/send&#39;;
            // 핸드폰도 작은 컴퓨터 입니다.
            // 즉 핸드폰도 서버가 될 수 있습니다.!
            // 코드에 작성한 localhost는 flutter 쪽에선 핸드폰
            // vscode쪽(python)에서는 컴퓨터
            // cmd 창 ipconfig 통해서 ip 주소 알아낸 다음 코드 수정
            // 2. 통신 라이브러리 - dio 라이브러리
            // dio 객체 생성했는지 확인(없으면 객체 생성코드 작성)
            // 3. 통신(get/post)
            // get(url,(queryParameters{map구조로 작성}))
            Response res = await dio.get(
                url,
                queryParameters:{&#39;test&#39; : test}
            );
            print(res);
          },
            child: Text(&quot;보내기&quot;),
          ),
        ],
      ),
    ),
  );
}
}</code></pre></li>
</ul>
<blockquote>
<p>통신 라이브러리 dio사용</p>
</blockquote>
<ul>
<li>pubspec.yaml<pre><code>dependencies:
dio: ^5.8.0+1</code></pre></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[17] Flutter MySQL WorkBench다운 및 세팅]]></title>
            <link>https://velog.io/@chyan_e_log/Flutter-MySQL-WorkBench%EB%8B%A4%EC%9A%B4-%EB%B0%8F-%EC%84%B8%ED%8C%85</link>
            <guid>https://velog.io/@chyan_e_log/Flutter-MySQL-WorkBench%EB%8B%A4%EC%9A%B4-%EB%B0%8F-%EC%84%B8%ED%8C%85</guid>
            <pubDate>Tue, 13 May 2025 00:49:51 GMT</pubDate>
            <description><![CDATA[<h2 id="mysql및-workbench-다운">MySQl및 workbench 다운</h2>
<h3 id="mysql-다운로드">MySQL 다운로드</h3>
<ul>
<li>들어가서 두번째꺼 다운로드, 로그인 안하고 아래쪽에 다운로드 시작버튼
<a href="https://dev.mysql.com/downloads/installer/">https://dev.mysql.com/downloads/installer/</a></li>
<li>실행 후 다 NEXT----Finish</li>
</ul>
<h3 id="workbench-다운로드">WorkBench 다운로드</h3>
<ul>
<li>들어가서 같은 방법으로 다운로드
<a href="https://dev.mysql.com/downloads/workbench/">https://dev.mysql.com/downloads/workbench/</a></li>
</ul>
<h3 id="스키마-생성">스키마 생성</h3>
<ul>
<li>workbench 들어가서 왼쪽 가운데 회색창 클릭</li>
<li>status누르고 우클릭 후 Create Schema</li>
<li>이름 지정하고 Apply</li>
<li>생성된 스키마에 우클릭 후 Set as Default Schema 하면 자동으로 스키마를 찾아간다.</li>
</ul>
<h3 id="테이블-생성">테이블 생성</h3>
<ul>
<li>스키마 드롭다운 내리고 테이블 우클릭 후 Create Table</li>
<li>이름 지정, 컬럼, 타입 지정 후 Apply후 창 뜨면 Finish</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[16] Flutter]]></title>
            <link>https://velog.io/@chyan_e_log/Flutter-u7f5un4k</link>
            <guid>https://velog.io/@chyan_e_log/Flutter-u7f5un4k</guid>
            <pubDate>Tue, 13 May 2025 00:24:41 GMT</pubDate>
            <description><![CDATA[<p>임시</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[15] Flutter 통신]]></title>
            <link>https://velog.io/@chyan_e_log/Flutter-%ED%86%B5%EC%8B%A0</link>
            <guid>https://velog.io/@chyan_e_log/Flutter-%ED%86%B5%EC%8B%A0</guid>
            <pubDate>Fri, 09 May 2025 03:18:49 GMT</pubDate>
            <description><![CDATA[<h2 id="학습목표">학습목표</h2>
<ul>
<li>json파싱을 이해한다.</li>
<li>Dart언어의 Future와 await를 이해한다.</li>
<li>API를 사용하여 http 통신과 json파싱을 구현한다.</li>
</ul>
<h3 id="동기-vs-비동기">동기 vs 비동기</h3>
<p><img src="https://velog.velcdn.com/images/chyan_e_log/post/ee9cc28b-216c-4f19-b456-3bf7c4ae8408/image.png" alt=""></p>
<h3 id="future-예시">Future 예시</h3>
<ul>
<li>궁극적으로 원하는 물건은 음식!</li>
<li>영수증은 추후 음식으로 변경 예정!</li>
<li><blockquote>
<p>영수증 == Future 객체
<img src="blob:https://velog.io/315efc7f-7771-4db8-bb7e-0d0c7d2e87c9" alt="업로드중.."></p>
</blockquote>
</li>
</ul>
<h3 id="dart-언어--future-async-await-이론">Dart 언어 – future, async, await 이론</h3>
<ul>
<li>Futuer 객체는 추후 어떠한 타입으로 변형 될지 대기 하는 객체</li>
<li>&lt;&gt;제네릭으로 타입으로 어떤 결과물이 올 지 알고 있다.</li>
<li>Future클래스는 비동기 작업시 사용</li>
<li>일정 소요시간 후에 실제 데이터나 에러를 반환</li>
<li>async클래스는 await메서드를 가지고 있음</li>
<li>await 로 선언된 메서드는 응답이 처리 될 때까지 대기</li>
</ul>
<h3 id="json">JSON</h3>
<ul>
<li><p>XML : eXtensible Markup Language</p>
</li>
<li><p>HTML은 정해진 태그만 사용 가능 하지만 Extendible하게 XML은 내가 만든 태그를 사용 가능</p>
</li>
<li><p>하지만 이러한 태그들은 개발에 있어 공유하기 어려움</p>
</li>
<li><p>Json : jacascript objext Notation
k:v 값으로 설정 된 값으로 데이터를 더 편하게 보기</p>
</li>
<li><p>Json viewer 설치하여 조금 더 편하게 보기!</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[14] Flutter 이미지 넣기]]></title>
            <link>https://velog.io/@chyan_e_log/Flutter-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EB%84%A3%EA%B8%B0</link>
            <guid>https://velog.io/@chyan_e_log/Flutter-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EB%84%A3%EA%B8%B0</guid>
            <pubDate>Fri, 09 May 2025 03:05:17 GMT</pubDate>
            <description><![CDATA[<p>image_listview.dart</p>
<p>var 타입은 List <code>&lt;String&gt;</code> 을 대신할 수 있다.</p>
<h3 id="코드">코드</h3>
<blockquote>
<ul>
<li>image_listview</li>
</ul>
</blockquote>
<pre><code>import &#39;package:flutter/material.dart&#39;;
import &#39;package:fluuter_listview/model/image_model.dart&#39;;
import &#39;image_detail.page.dart&#39;;
var ryanName = [
  &#39;리틀 라이언&#39;,
  &#39;반짝 라이언&#39;,
  &#39;하트하트 라이언&#39;,
  &#39;춘식이와의 만남&#39;,
  &#39;룸메는 춘식이&#39;,
  &#39;좋아요&#39;
];
var imgList = [
  &#39;image/ryan1.jpg&#39;,
  &#39;image/ryan2.png&#39;,
  &#39;image/ryan3.jpg&#39;,
  &#39;image/ryan4.png&#39;,
  &#39;image/ryan5.png&#39;,
  &#39;image/ryan6.jpg&#39;,
];
class ImageListview extends StatefulWidget {
  const ImageListview({super.key});
  @override
  State&lt;ImageListview&gt; createState() =&gt; _ImageListviewState();
}
class _ImageListviewState extends State&lt;ImageListview&gt; {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        child: const Icon(Icons.add),
        onPressed: () {
          setState(() {
            imgList.add(&quot;image/ryan1.jpg&quot;);
            ryanName.add(&quot;리틀라이언&quot;);
          });
        },
      ),
      body: SafeArea(
        child: ListView.builder(
          itemCount: imgList.length,
          itemBuilder: (context, index) {
            // 하위 위젯에게 클릭과 같은 이벤트를 부여하는 위젯 - GestureDetector
            return GestureDetector(
              onTap: () {
                print(&quot;hello $index&quot;);
                //img_model 객체생성(new생략 가능)
                ImgModel im = ImgModel(index, imgList[index], ryanName[index]);
                // 상세 페이지 이동 (예시로 만들어 둔 ImageDetailPage)
                Navigator.push(context, MaterialPageRoute(
                    builder: (_) =&gt; ImageDetailPage(imgModel:im,)),
                );
                // 팝업창 띄우기
                // 내장함수 showDialog
                showDialog(
                  context: context,
                  builder: (_) {
                    // 위젯을 리턴하는 이유 : Dialog 창 디자인
                    return Dialog(
                      child: Container(
                        width: MediaQuery.of(context).size.width * 0.7,
                        height: 380,
                        decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(10),
                          color: Colors.white,
                        ),
                        child: Column(
                          children: [
                            const SizedBox(height: 32),
                            ClipRRect(
                              borderRadius: BorderRadius.circular(10),
                              child: Image.asset(
                                imgList[index],
                                width: 200,
                                height: 200,
                              ),
                            ),
                            const SizedBox(height: 10),
                            Text(
                              ryanName[index],
                              style: const TextStyle(
                                fontSize: 25,
                                fontWeight: FontWeight.bold,
                                color: Colors.grey,
                              ),
                            ),
                            Padding(
                              padding: const EdgeInsets.all(8.0),
                              child: Row(
                                mainAxisAlignment: MainAxisAlignment.center,
                                children: [
                                  ElevatedButton.icon(
                                    onPressed: () {
                                      setState(() {
                                        ryanName.removeAt(index);
                                        imgList.removeAt(index);
                                      });
                                      // dialog도 하나의 페이지로 인식 --&gt; 이전
                                      Navigator.pop(context);
                                    },
                                    icon: const Icon(Icons.close),
                                    label: const Text(&#39;삭제하기&#39;),
                                    style: ElevatedButton.styleFrom(
                                      backgroundColor: Colors.grey,
                                    ),
                                  ),
                                  const SizedBox(width: 10),
                                  ElevatedButton.icon(
                                    onPressed: () {
                                      Navigator.pop(context);
                                    },
                                    icon: const Icon(Icons.close),
                                    label: const Text(&#39;close&#39;),
                                  ),
                                ],
                              ),
                            ),
                          ],
                        ),
                      ),
                    );
                  },
                );
              },
              child: Card(
                child: Row(
                  children: [
                    Expanded(child: Image.asset(imgList[index])),
                    Expanded(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(ryanName[index]),
                          Text(&quot;${index + 1}번째 라이언&quot;),
                        ],
                      ),
                    ),
                  ],
                ),
              ),
            );
          },
        ),
      ),
    );
  }
}</code></pre><blockquote>
<ul>
<li>image_detail_page</li>
</ul>
</blockquote>
<pre><code>import &#39;package:flutter/material.dart&#39;;
import &#39;package:fluuter_listview/model/image_model.dart&#39;;
// class ImageDetailPage extends StatelessWidget {
//   const ImageDetailPage({
//     super.key,
//     required this.ryanName,
//     required this.imgPath,
//     required this.index,
//   });
class ImageDetailPage extends StatelessWidget {
  const ImageDetailPage({super.key, required this.imgModel,
  });
  // index, ryanName정보, 이미지 경로
  // final int index;
  // final String ryanName;
  // final String imgPath;
  final ImgModel imgModel;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          title: Text(&quot;${imgModel.index} 번째 라이언&quot;)),
      body: Center(
        child: Column(
            children: [
              Image.asset(imgModel.imgPath),
              Text(&#39;world&#39;)
            ]),
      ),
    );
  }
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[13] Flutter ListView]]></title>
            <link>https://velog.io/@chyan_e_log/Flutter-ListView</link>
            <guid>https://velog.io/@chyan_e_log/Flutter-ListView</guid>
            <pubDate>Thu, 08 May 2025 03:45:28 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>flutter_listview
lib.zip
└── lib/
    ├── main.dart
    ├── grid_listview.dart
    ├── HorizontalListview.dart
    └── vertical_listview.dart</p>
</blockquote>
<h2 id="list-view--스크롤이-가능한-배열형-위젯">List View : 스크롤이 가능한 배열형 위젯</h2>
<p><img src="https://velog.velcdn.com/images/chyan_e_log/post/825c615d-5465-4ead-896e-e702b8c93284/image.png" alt=""></p>
<h3 id="코드">코드</h3>
<blockquote>
<ul>
<li>HorizontalListview</li>
</ul>
</blockquote>
<pre><code>import &#39;package:flutter/material.dart&#39;;
import &#39;package:fluuter_listview/vertical_listview.dart&#39;;
class Horizontallistview extends StatelessWidget {
  const Horizontallistview({super.key});
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: ListView.builder(
          // 가로 리스트뷰로 변경 코드
          // scrollDirection을 미작성시 vertical이 기본
          scrollDirection: Axis.horizontal,
          itemBuilder: (context,index) {
            return Container(
              margin: EdgeInsets.all(4),
              height: 50,
              color: Colors.lightBlueAccent,
              child: Text(&quot;${intList[index]}번째&quot;),
            );
          }
        ),
      ),
    );
  }
}</code></pre><blockquote>
<ul>
<li>verticalListview</li>
</ul>
</blockquote>
<pre><code>import &#39;package:flutter/material.dart&#39;;
// 1~100 있는 리스트 생성
// 리스트 안에 있는 내장 메소드
// generate(몇개 만들지, 한개 만든 후 실핼될 코드)
List&lt;int&gt; intList = List&lt;int&gt;.generate(100,(index) =&gt; index++);
class VerticalListview extends StatelessWidget {
  const VerticalListview({super.key});
  @override
  Widget build(BuildContext context) {
    print(intList);
    return Scaffold(
      body: SafeArea(
          child: ListView.builder(
            itemCount: intList.length,
              itemBuilder: (context,index){ // builder의 매개변수 context _로 수정가능
                // 매개변수 buildContext, int
                // ListView의 한 칸(item)에는 index가 존재
                // return 위젯
                // 디자인
                return Container(
                  // 회색줄 : lint 줄(hint)
                  // 의미  : 에러 x, 경고 x
                  // --&gt; 추천
                  margin: EdgeInsets.all(8),
                  color: Colors.greenAccent,
                  height: 50,
                  child: Text(&quot;${intList[index]}번째 아이템&quot;),
                );
              }
              )),
    );
  }
}</code></pre><blockquote>
<ul>
<li>gird_listview</li>
</ul>
</blockquote>
<pre><code>import &#39;package:flutter/material.dart&#39;;
import &#39;package:flutter/rendering.dart&#39;;
// 1.count
List&lt;int&gt; intList = List&lt;int&gt;.generate(100,(index) =&gt; index++);
class GridListviewCount extends StatelessWidget {
  const GridListviewCount({super.key});
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: GridView.builder(
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 4,
          childAspectRatio: 1/2
          ),
          itemBuilder: (_,index){
            return Container(
              margin: EdgeInsets.all(4),
              height: 50,
              color: Colors.purple,
              child: Text(&quot;${intList[index]}번째&quot;),
            );
          },
        ),
      ),
    );
  }
}
// 2. extend -- 비율
class GridListviewExtend extends StatelessWidget {
  const GridListviewExtend({super.key});
  @override
  Widget build(BuildContext context) {
    // 디바이스 가로길이를 구하는 코드
    print(MediaQuery.of(context).size.width);
    return Scaffold(
      body: SafeArea(
        child: GridView.builder(
            gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
                maxCrossAxisExtent: 100,
                  // 디바이스의 가로길이 ~/ maxCrossAxisExtend에 작성한 숫자 +1 개수 출력
            ),
            itemBuilder: (_, index){
              return Container(
                margin: EdgeInsets.all(4),
                height: 50,
                color: Colors.pinkAccent,
                child: Text(&#39;${intList[index]}번쩨&#39;),
              );
            }),
      ),
    );
  }
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[12] Flutter 페이지 이동2]]></title>
            <link>https://velog.io/@chyan_e_log/Flutter-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%9D%B4%EB%8F%992</link>
            <guid>https://velog.io/@chyan_e_log/Flutter-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%9D%B4%EB%8F%992</guid>
            <pubDate>Thu, 08 May 2025 01:37:01 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>flutter_pagemove
lib/
├── main.dart
└── screen/
    ├── bluepage.dart
    ├── color_page.dart
    ├── login_page.dart
    ├── login_success_page.dart
    └── red_page.dart</p>
</blockquote>
<h3 id="화면이동--로그인-페이지">화면이동- 로그인 페이지</h3>
<ul>
<li>const클래스 에서는 상수가 아닌 값을 선언할 수 없다는 뜻<ul>
<li>해결방안1. 클래스 앞에 const지워주기</li>
<li>해결방안2. 변수명에 final작성해주기</li>
</ul>
</li>
<li><blockquote>
<p>가급적 해결방안2로 해결하기 : const같은 경우는 컴파일시 값이 결정되기 때문에 앱을 생성할 때 한번만 생성하게됨.
특정 화면 rerendering될 경우 재생성을 막을 수 있어 내부 리소스 낭비를 막을 수 있다.</p>
</blockquote>
</li>
</ul>
<h3 id="dart언어-클래스-생성자">dart언어 클래스, 생성자</h3>
<h4 id="생성자-생성">생성자 생성</h4>
<ul>
<li>this키워드는 클래스 나 자신을 뜻함<pre><code>Animal(String name, int age){
  this.name = name;
  this..age = age;
}</code></pre></li>
<li>한줄로 요약 가능 이때 반드시 name, age 값이 있어야 하므로 Late,?연산사 생략 가능!<pre><code>Animal(this.name, this.age);</code></pre></li>
</ul>
<h4 id="함수-메소드-추가-설명">함수/ 메소드 추가 설명</h4>
<ul>
<li>선택적 매개변수, 위치적 매개변수, Function 타입 등
함수/ 메소드에 대한 지식이 더 존재하나 추후 등장시 설명(예시코드만)
<img src="https://velog.velcdn.com/images/chyan_e_log/post/fb38f350-506f-4434-9b65-89ad9036ef73/image.png" alt=""></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[17] Spring JPA]]></title>
            <link>https://velog.io/@chyan_e_log/Spring-JPA</link>
            <guid>https://velog.io/@chyan_e_log/Spring-JPA</guid>
            <pubDate>Fri, 02 May 2025 08:30:55 GMT</pubDate>
            <description><![CDATA[<ul>
<li><a href="https://docs.spring.io/spring-data/jpa/reference/index.html">https://docs.spring.io/spring-data/jpa/reference/index.html</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[11] Flutter 페이지 이동(화면이동)]]></title>
            <link>https://velog.io/@chyan_e_log/Flutter-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%9D%B4%EB%8F%99%ED%99%94%EB%A9%B4%EC%9D%B4%EB%8F%99</link>
            <guid>https://velog.io/@chyan_e_log/Flutter-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%9D%B4%EB%8F%99%ED%99%94%EB%A9%B4%EC%9D%B4%EB%8F%99</guid>
            <pubDate>Fri, 02 May 2025 03:21:53 GMT</pubDate>
            <description><![CDATA[<h2 id="페이지-이동-학습-목표">페이지 이동 학습 목표</h2>
<ul>
<li>Navigator를 활용하여 페이지를 이동할 수 있다.</li>
<li>Push, Pop의 차이를 이해한다</li>
<li>페이지 이동에 대한 예제를 풀 수 있다.</li>
<li><a href="https://grow-grow.tistory.com/7">https://grow-grow.tistory.com/7</a></li>
<li>수정하기</li>
</ul>
<h3 id="화면이동-이론">화면이동 이론</h3>
<ul>
<li>Flutter에서 화면 간 이동 처리를 위해 Navigator 사용!</li>
<li>Navigator 내 push(), pop(), replace() 메소드를 이용해서 페이지 이동</li>
<li>Navigator는 전환 애니메이션을 사용하여 화면을 Stack으로 관리,</li>
<li>BuildContext를 이용해서 어떠한 페이지로 이동할지 Routing하여 페이지 이동</li>
</ul>
<h4 id="stack-구조란">Stack 구조란?</h4>
<ul>
<li>데이터를 차례대로 쌓아 데이터를 관리 : FILO구조</li>
<li>데이터 삽입은 push</li>
<li>데이터 삭제는 pop로 구성</li>
<li>참고) 들어온 순서대로 나가는 FIFO Queue 구조 있음
<img src="https://velog.velcdn.com/images/chyan_e_log/post/47b5ec4b-1e93-4919-bff2-33acc4aec428/image.png" alt=""></li>
</ul>
<h4 id="buildcontext란">BuildContext란?</h4>
<ul>
<li>Flutter의 모든 Widget은 build 라는 메소드를 가지고 있음</li>
<li>안드로이드의 Context가 있듯이 Flutter에 BuildContext가 존재</li>
<li>SnackBar를 보여주거나 화면이동 등 buildContext를 사용하여 호출</li>
<li>Flutter는 위젯으로 시작해서 위젯으로 끝난다</li>
<li>Flutter UI의 가장 작은 단위는 위젯이다</li>
<li>BuildContext는 현재 빌드에 대한 정보를 저장하는 객체(위젯의 모양, 환경, 동작 등
<img src="https://velog.velcdn.com/images/chyan_e_log/post/edbb8151-69f7-4435-b2f2-108821dc62e5/image.png" alt=""></li>
</ul>
<h4 id="route란">route란?</h4>
<ul>
<li>기본적인 프로그래밍 관점의 의미<ul>
<li>디바이스와 네트워크를 다른 네트워크를 연결하는 네트워킹 디바이스
경로 결정, 데이터 전달 등을 담당</li>
</ul>
</li>
</ul>
<ul>
<li>Routing이란?<ul>
<li>네트워크에서 경로, 링크를 선택하는 프로세스
=&gt; 결국 flutter의 route도 유사
    어느 화면으로 이동할지 경로 결정하고 해당 페이지로 데이터 전달하는 기능</li>
</ul>
</li>
</ul>
<h4 id="코드-구조">코드 구조</h4>
<p><img src="https://velog.velcdn.com/images/chyan_e_log/post/5eda277e-0f8e-4a73-999b-289417e04371/image.png" alt=""></p>
<h4 id="메소드-종류">메소드 종류</h4>
<ul>
<li><p>Flutter에서 화면 간 이동 처리를 위해 Navigator 내 메소드 종류</p>
</li>
<li><p>push(), pushNamed(), pushAndRemoveUntil(), pop(), canPop(), pushReplacement() 등</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[10] Flutter 라이브러리(toast)]]></title>
            <link>https://velog.io/@chyan_e_log/Flutter-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC</link>
            <guid>https://velog.io/@chyan_e_log/Flutter-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC</guid>
            <pubDate>Fri, 02 May 2025 03:03:04 GMT</pubDate>
            <description><![CDATA[<h3 id="flutter-라이브러리-다운로드-사이트">Flutter 라이브러리 다운로드 사이트</h3>
<ul>
<li><a href="https://pub.dev/">https://pub.dev/</a></li>
</ul>
<h3 id="fluttertoast-8212">fluttertoast: ^8.2.12</h3>
<ul>
<li><p>fluttertoast 검색</p>
</li>
<li><p>installing탭 들어가기</p>
</li>
<li><p>pubspec.yaml 파일에</p>
<pre><code>dependencies:
fluttertoast: ^8.2.12</code></pre><p>추가
<img src="https://velog.velcdn.com/images/chyan_e_log/post/ed7261c7-6548-4637-b69e-2fc3ade6eb6a/image.png" alt=""></p>
</li>
<li><p>저장하고 오른쪽 위에 pub get클릭</p>
</li>
<li><p>코드 0뜨면 설치 성공</p>
</li>
</ul>
<h3 id="실습간단하게-띄워보기">실습(간단하게 띄워보기)</h3>
<blockquote>
<p>ex20</p>
</blockquote>
<pre><code>import &#39;package:flutter/material.dart&#39;;
import &#39;package:fluttertoast/fluttertoast.dart&#39;;
class Ex20Lib extends StatelessWidget {
  const Ex20Lib({super.key});
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(child: 
      Center(
        child: ElevatedButton(onPressed: (){
            Fluttertoast.showToast(
              msg: &quot;안녕하세요!&quot;,
              toastLength: Toast.LENGTH_SHORT,
              gravity: ToastGravity.BOTTOM,
              timeInSecForIosWeb: 1,
              backgroundColor: Colors.blue,
              textColor: Colors.white,
              fontSize: 16.0
          );
        },
            child: Text(&quot;토스트 띄우기&quot;)),
      )),
    );
  }
}</code></pre><ul>
<li>실행화면
<img src="https://velog.velcdn.com/images/chyan_e_log/post/8672baba-4fca-4a1c-863f-ad287b66b71c/image.png" alt=""></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[9] Flutter CheckBox, RadioButton]]></title>
            <link>https://velog.io/@chyan_e_log/Flutter-CheckBox-RadioButton</link>
            <guid>https://velog.io/@chyan_e_log/Flutter-CheckBox-RadioButton</guid>
            <pubDate>Fri, 02 May 2025 01:33:09 GMT</pubDate>
            <description><![CDATA[<h3 id="flutter-flow">Flutter Flow</h3>
<ul>
<li>템플릿 선택해서 드래그 앤 드랍으로 화면을 구성하고 코드를 만들어 주는 사이트
<a href="https://app.flutterflow.io/">https://app.flutterflow.io/</a></li>
</ul>
<h3 id="figma-to-flutter">Figma to Flutter</h3>
<ul>
<li>Figma로 구성한 화면을 실제 Flutter에 적용할 수 있게 해주는 Figma사이트
<a href="https://www.figma.com/community/plugin/1236863310201087089/figma-to-flutter">https://www.figma.com/community/plugin/1236863310201087089/figma-to-flutter</a></li>
</ul>
<h3 id="firebase-studio">Firebase Studio</h3>
<ul>
<li>온라인 웹상에서 앱개발을 할 수 있는 사이트</li>
<li>전혀 설치같은게 필요없다.
<a href="https://firebase.studio/">https://firebase.studio/</a></li>
</ul>
<blockquote>
<h4 id="ex18_stateful">ex18_stateful</h4>
</blockquote>
<pre><code>import &#39;package:flutter/material.dart&#39;;
// stl -&gt; stateless 단축키
// stf -&gt; stateful 단축키
class ExStateful extends StatefulWidget {
  const ExStateful({super.key});
  // 클래스 내부에서 변수를 사용하지 못하므로 반드시 final키워드를 사용하여 진행
  final int data1 = 5;
  @override
  State&lt;ExStateful&gt; createState() =&gt; _ExStatefulState();
}
class _ExStatefulState extends State&lt;ExStateful&gt; {
  // 일반 변수 지정이 가능! -&gt; 해당하는 클래스는 상태를 체크하기 위한 기능을 물려받아
  // 생성되므로, 데이터 값이 언제든 바뀔 수 있다!
  bool isChecked1 = false;
  bool isChecked2 = false;
  bool isChecked3 = false;
  @override
  Widget build(BuildContext context) {
    // build 메소드는 화면을 설계하기 위해서 확정되어 있는 내용들만 사용할 수 있다!
    // 즉, 변수는 값이 바뀌므로 사용할 수 없다! =&gt; 문제점 완화! set state()
    // set state() : 상태가 바뀌거나 변수의 데이터가 바뀜을 감지할 수 있는 메소드
    // =&gt; 값이 바뀌면 바뀐 내용을 활용하여 build 메소드에게 화면 재구성을 자동적으로 요청 할 수 있다!
    return Scaffold(
      body: SafeArea(
          child: Column(
            children: [
              // value 값 : true(체크 0), flase(체크x)
              Row(
                children: [
                  Checkbox(value: false, onChanged: (vlaue){
                    // 상태가 바뀌면 어떤 작업을 할지 로직을 세울 수 있는 영역!
                    setState(() {
                      isChecked1 = vlaue!;
                    });
                  }),
                  Text(&#39;data1&#39;),
                ],
              ),
              Row(
                children: [
                  Checkbox(value: false, onChanged: (vlaue){
                    // 상태가 바뀌면 어떤 작업을 할지 로직을 세울 수 있는 영역!
                    setState(() {
                      isChecked2 = vlaue!;
                    });
                  }),
                  Text(&#39;data2&#39;),
                ],
              ),
              // 사용자의 편의성을 위한 위젯
              // CheckboxListTile
              CheckboxListTile(
                title: Text(&#39;data3&#39;),
                  controlAffinity: ListTileControlAffinity.leading,
                  value: isChecked3 , onChanged: (v){
                  setState(() {
                    isChecked3 = v!;
                  });
              })
            ],
          )
      ),
    );
  }
}
//////////////////////////
class ExStateless extends StatelessWidget {
  const ExStateless({super.key});
  @override
  Widget build(BuildContext context) {
    return const Placeholder();
  }
}</code></pre><blockquote>
<h4 id="ex19_radio">ex19_radio</h4>
</blockquote>
<pre><code>import &#39;package:flutter/material.dart&#39;;
class Ex19Radio extends StatefulWidget {
  const Ex19Radio({super.key});
  @override
  State&lt;Ex19Radio&gt; createState() =&gt; _Ex19RadioState();
}
enum Gender { man, woman }
class _Ex19RadioState extends State&lt;Ex19Radio&gt; {
  Gender g = Gender.woman; // 기준이 되는 변수
  bool isChecked = false;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Column(
          children: [
            // 객체타입
            // value는 radio의 버튼의 고유 값
            // groupValue를 바탕으로 value값과 같으며 true, 다르면 false
            RadioListTile(
              title: Text(&quot;남성&quot;),
              value: Gender.man, groupValue: g, onChanged: (v) {
                print(v);
                setState(() {
                  g = v!;
                });
              },
            ),
            RadioListTile(
              title: Text(&quot;여성&quot;),
              value: Gender.woman, groupValue: g, onChanged: (v) {
                print(v);
                setState(() {
                  g = v!;
                });
              },
            ),
            Switch(activeColor: Colors.red, value: isChecked, onChanged: (v){
              setState(() {
                isChecked = v;
              });
            })
          ],
        ),
      ),
    );
  }
}</code></pre>]]></description>
        </item>
    </channel>
</rss>