일반적으로 파일을 생성하거나 수정 할 때 등은 권한이 필요하다.

근데 운영체제를 너무 따라가는...

그저 한숨만 나온다!!

하지만 뚫을 수 있다!!

먼저 솔루션의 속성에 들어가 보안 탭을 열고 난 다음!!ClickOnce 보안 설정을 클릭 했다가 다시 취소하고 저장한다!!

그러면 Manifest 파일이 생성이 되는데

<requestedExecutionLevel  level="asInvoker" uiAccess="false" />
<requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel  level="highestAvailable" uiAccess="false" />

이런 항목이 보일 것이다!!

저걸 이용해서 보안을 뚫을 수 있다!!

현재 저 부분은 주석으로 되어 있지만 아래 쪽에 보면

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

요런 놈이 주석이 풀려 있는데 level에 저 3개 중 하나 적절한걸 넣으면 된다.

사실 오늘 이 포스팅을 하는건... -_-... 해놓고 까먹고 삽질하고 댕겨서... ㅠ_ㅠ

제길.. 바보다 바보 ㅠ_ㅠ

Picture Box 컴포넌트 관련해서 작업을 하다가 마지막에 이미지를 끝까지!!

잡고 있는 문제가 있었다.

급하게 퇴근하느라.. 부사수에게 넘겼는데 null 처리를 하고 Dispose를 해도 안된다는 연락..

그래서 아침에 와서

그냥 컨테이너->컴포넌트니까 해당 속성에 대해서 Dispose를 걸었다...

잘된다..

쉽게 생각하면 그거다.

로컬에 있는 파일에 접근해서 데이터를 처리 할 경우에는 그 속성에 대해서 리소스 해제를 하지 않는 한..

메모리 상에 남아 꽉!! 쥐고 놓지를 않는다.

부사수에게 그렇게 설명을 하긴 했는데..

-_-a 내가 잘못 알고 있는건 아닌가.. 싶기도 하지만 -_- 난 맞다고 알고 있다!!

어떤 파일이 프로세스에 의해 작업 중이라고 되어 있다면..

당황하지 말고 순차적으로 올린 것에 대해서 리소스 해제를 하기를 바란다.

별 다른 내용이 없는 포스팅이긴 하지만..

한번씩 실수를 할 수 있는 문제이기도 하기에 다시 한번 생각해보자는 의미로 포스팅을 해 본다.
[C#] WebClient C# 2011. 11. 2. 17:51

WebClient 이용해서 일단 데이터 날리는 방법과 파일 업/다운로드 방식이다.

귀찮아서 창고용으로 하핫~

물론 데이터 전송과 파일 업로드는 웹 구현이 필요하다.

[데이터 전송]

Encoding encode = System.Text.Encoding.GetEncoding("euc-kr");
byte[] result = encode.GetBytes(웹으로 날릴 인자 값);
Uri uri = new Uri(처리 해 줄 웹);
HttpWebRequest wReqFirst = (HttpWebRequest)WebRequest.Create(uri);
wReqFirst.Method = "POST";
wReqFirst.Accept = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 2.0.50727; .NET CLR 3.0.04506.590; .NET CLR 3.5.20706; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)";
wReqFirst.Method = "POST";
wReqFirst.UserAgent = "웹에 설정한 인증자";
wReqFirst.Headers.Add("trans-user", "");
wReqFirst.ContentType = "application/x-www-form-urlencoded";
wReqFirst.ContentLength = result.Length;
wReqFirst.Headers.Add("trans-key", "");
wReqFirst.Headers.Add("Cookie: 세션="세션값";");//요건 선택 사항 하고 싶은 사람은 하면 됨 ``/ 세션 유지 할 때 이용시 유용 한 느낌~
Stream postDataStream = wReqFirst.GetRequestStream();
postDataStream.Write(result, 0, result.Length);
postDataStream.Close();
HttpWebResponse wRespFirst = (HttpWebResponse)wReqFirst.GetResponse();
Stream respPostStream = wRespFirst.GetResponseStream();
StreamReader readerPost = new StreamReader(respPostStream, encode);
string resultPost = readerPost.ReadToEnd();

[파일 업로드]

HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(uri);
webrequest.Accept = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 2.0.50727; .NET CLR 3.0.04506.590; .NET CLR 3.5.20706; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)";
webrequest.UserAgent = "웹에 설정한 인증자";
webrequest.ContentType = "multipart/form-data; boundary=" + boundary;
webrequest.Method = "POST";

헤더  값에 업로드 할 파일 명 등 추가~ 웹에서 구현하기 나름이다.

string postHeader = sb.ToString();
byte[] postHeaderBytes = Encoding.UTF8.GetBytes(postHeader);
byte[] boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
FileStream fileStream = new FileStream(filepath, FileMode.Open, FileAccess.Read);
long length = postHeaderBytes.Length + fileStream.Length + boundaryBytes.Length;
webrequest.ContentLength = length;
Stream requestStream = webrequest.GetRequestStream();
requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);
byte[] buffer = new Byte[checked((uint)Math.Min(4096, (int)fileStream.Length))];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
          requestStream.Write(buffer, 0, bytesRead);
}
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
WebResponse responce = webrequest.GetResponse();
Stream s = responce.GetResponseStream();

[파일 다운로드]

WebClient webclient = new WebClient();
Uri uri = new Uri(서버 주소 + 다운로드 할 파일 명);
webclient.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 2.0.50727; .NET CLR 3.0.04506.590; .NET CLR 3.5.20706; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729;)");
webclient.Credentials = new NetworkCredential("sitemgr", "S2_.T8UJ");
webclient.UseDefaultCredentials = true;
webclient.DownloadFileAsync(uri, 올릴 파일 전체 경로);
while (webclient.IsBusy) { System.Windows.Forms.Application.DoEvents(); System.Threading.Thread.Sleep(1); };

뭐.. 대략 이 정도 인듯?

창고는 쌓아두는게 제맛!!

제때 제때 잘 찾음 MSDN 부럽지 않다 ㅋㅋ

[C#] stdole.dll C# 2011. 11. 2. 17:41
뭐라 해야하나.. 좀 황당하긴 했는 경험..

여지껏 배포하고 했을 때

stdole.dll 이란 파일은 한번도 넣은 적이 없다.

근데 이번에 프로젝트 하면서..

저녀석이 없으니...

컴포넌트부터 해서 말썽이네? 흠냐;;

뭐 무튼 stdole.dll 명심해두기.
[C#] FTP 이용 C# 2011. 9. 1. 13:14

만들어 놓은걸 귀찮게 왔다 갔다 하기 싫어서..

포스팅을 하긴 하는데.. 흠.. 심플하다 역시. 모두들 다 아는 방법 일 것이고

1. Upload

            Uri ftpUri = new Uri("ftp경로 + 파일 이름");
            FtpWebRequest reqFtp = (FtpWebRequest)WebRequest.Create(ftpUri);
            reqFtp.Credentials = new NetworkCredential("id", "password");
            reqFtp.UseBinary = true;
            reqFtp.UsePassive = true;
            reqFtp.KeepAlive = false;
            reqFtp.Timeout = 10000;
            reqFtp.Method = WebRequestMethods.Ftp.UploadFile;
            FileInfo fileinfo = new FileInfo(@"C:\Result110830.txt");
            FileStream fstream = fileinfo.OpenRead();
            byte[] buffer = new byte[2048];
            int curroffset = 0;            try
            {
                Stream stream = reqFtp.GetRequestStream();
                curroffset = fstream.Read(buffer, 0, 2048);
                while (curroffset != 0)
                {
                    stream.Write(buffer, 0, curroffset);
                    curroffset = fstream.Read(buffer, 0, 2048);
                }
            }
            catch (Exception ex)
            {
            }

2. Download

            Uri ftpUri = new Uri("ftp경로 + 파일 이름");
            FtpWebRequest reqFtp = (FtpWebRequest)WebRequest.Create(ftpUri);
            reqFtp.Credentials = new NetworkCredential("id", "password");
            reqFtp.Timeout = 10000;
            reqFtp.Method = WebRequestMethods.Ftp.ListDirectory;
            FtpWebResponse resFtp = (FtpWebResponse)reqFtp.GetResponse();
            StreamReader reader = new StreamReader(resFtp.GetResponseStream());
            string strData = reader.ReadToEnd();
            //ftp 경로 내의 파일 정보 읽어 오는 부분
            string[] filesInDirectory = strData.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            resFtp.Close();
            try
            {
                foreach (string _str in filesInDirectory)//파일명  
                {
                    //이미 윗 부분에서 권한을 가져 왔기 때문에 다시 권한을 지정 해 줄 필요가 없다.
                    WebClient wclient = new WebClient();
                    wclient.Credentials = new NetworkCredential();
                    wclient.DownloadFileAsync(ftpUri, @"C:\dsneat\" + _str);
                }
            }
            catch (Exception exx)
            {               
            }

두가지 방법으로 왔다 갔다 하면 그냥 왠만한건 다 되는거 같다.

기억상에 폴더 채로 해 봤던 적이 있었던거 같은데.. 기억이 잘 안난다 ㅠ_ㅠ

누가 알면.. 간단히 리뷰 해 주면 좋겠는데 ㅠ_ㅠ

그럼 오늘도 열심히 화이팅!!

자동 업데이트 만들다가 살짝 만들었다.

데몬을 안띄우고 하면 이게 제일 효율적이다 싶어서 한건데.. 흠..

기능 적으론 나쁘지 않았다.

using System.Runtime.InteropServices;

처리 한 후,

WebClient m_webclient = new WebClient();
m_webclient.Credentials = new System.Net.NetworkCredential("계정", "비번");

처리를 해 준다.

downloader.DownloadFile(new Url("http://해당 경로/해당파일"),"복사 할 파일 경로");

하면 끝!!

항시 서비스하는 웹 사이트가 있다거나 도메인이 있다면 간결하게 하고 좋은 듯 하다!!

그럼 오늘의 포스팅은 여기까지~ 텨~

[C#] Web 통신 C# 2011. 8. 19. 17:23

일단 급하게 필요해서 짰는데 누군가 웹 서버 형태를 MIME 규칙에 따닥 하고 맞춰놔서

조금 고생 했다 -_-;;

샘플은 다음과 같다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Web;
namespace WebSocket
{
    class Program
    {
        static void Main()
        {
            try
            {
                Encoding encoding = Encoding.UTF8;
               
                byte[] result = encoding.GetBytes("msg=메세지");
               
                Uri uri = new Uri("url/경로/웹파일");

여기서 부터가 이제 시작이다.
각각의 타입에 맞게 지정하고

                HttpWebRequest wReqFirst = (HttpWebRequest)WebRequest.Create(uri);
                wReqFirst.Method = "POST";
이놈은 PHP에서 해당하는 내용 때문에 맞춘 내역이다.

$_SERVER["HTTP_USER_AGENT"]
$_SERVER["HTTP_TRANS_USER"]
$_SERVER["SCRIPT_FILENAME"]
$_SERVER["HTTP_TRANS_USER"]
$_POST["msg"]
base64_decode($_POST["msg"]
$_SERVER["HTTP_TRANS_KEY"]

이런 내용이 PHP에 적용이 되어 있었다.

처음엔 아무것도 모르고 그냥 Header 형태만 만들어서 날리면 되는 줄 알았는데..

그냥 단순 무식하게 생각한게 잘못이었다.

C#에서는 Header 자체를 자동적으로 만들어서 날리기 때문에 세부 사항만 맞춰서 처리 해 주면 된다.

그 예가 다음이다.

                wReqFirst.UserAgent = "해당 사항";
                wReqFirst.Headers.Add("trans-user", "해당 사항");
                wReqFirst.ContentType = "application/x-www-form-urlencoded";
                wReqFirst.ContentLength = result.Length;
                wReqFirst.Headers.Add("trans-key", "MD5=md5규칙");

여기까지 해 주면 스트림을 열고 날려주면 된다.

                Stream postDataStream = wReqFirst.GetRequestStream();
                postDataStream.Write(result, 0, result.Length);
                postDataStream.Close();

                HttpWebResponse wRespFirst = (HttpWebResponse)wReqFirst.GetResponse();
                Stream respPostStream = wRespFirst.GetResponseStream();
                StreamReader readerPost = new StreamReader(respPostStream, Encoding.UTF8);
                string resultPost = readerPost.ReadToEnd();

여기까지가 웹 서버에 요청한 내용을 담아두고 이 다음은 base64 처리를 해서 나타낸 것이다.

                byte[] conv = Convert.FromBase64String(resultPost);
                UTF8Encoding utf8 = new UTF8Encoding();
                Console.WriteLine(utf8.GetString(conv));
            }
            catch (WebException ex)
            {
            }
        }
    }
}

나름 상큼하게 고민 좀 한거 같다;;

웹 서버 자체에 대해서 차근이 하다보면 다른 방법도 많을 거 같다.

어떻게 구성하냐 그 차이 일 수도 있겠지만..

그럼 간만에 블로깅은 여기까지!!

[C#] Linq 기본 정리 C# 2010. 12. 22. 16:14


Linq 부분을 보면서 코드로 기본 적인 부분에 대해서 정리를 해 봤다.

class info
    {
        public int num;
        public string name;
        public info(int num, string name)
        {
            this.num = num;
            this.name = name;
        }
    }

    class info1
    {
        public int num;
        public string name;
        public info1(int num, string name)
        {
            this.num = num;
            this.name = name;
        }
    }

    class Program
    {
        static bool method(int num)
        {
            return 200 < num * 100;
        }

        static void Main(string[] args)
        {
            //기본 표현식
           
            //from 변수명 in 컬렉션 (where | orderby | let) select {select | group}

            //string[] msg = { "Hello", "Hi", "World", "Korea" };           
            //IEnumerable<string> query = from str in msg select str;
            //foreach (string temp in query)
            //{
            //    Console.WriteLine(temp);
            //}

            //string path = @"C:\";
            //var Files = from file in Directory.GetDirectories(path) select file;
            //foreach (var temp in Files)
            //{
            //    Console.WriteLine(temp);
            //}

            //info[] data = { new info(1, "1"), new info(2, "2"), new info(3, "3") };
            //IEnumerable<info> result = from temp in data select temp;
            //foreach (info temp in result)
            //{
            //    Console.WriteLine(temp.num + "  :  " + temp.name);
            //}

            //where 이용
            //List<int> data = new List<int> { 1, 2, 3, 4, 5, 6 };
            //IEnumerable<int> result = from int temp in data where (temp > 2) select temp;
            //foreach (int temp in result)
            //{
            //    Console.WriteLine(temp);
            //}

            //select 에서 데이터 가공
            //List<int> data = new List<int> { 1, 2, 3, 4, 5, 6 };
            //IEnumerable<int> result = from int temp in data where (temp > 1) select (temp + 3);
            //foreach (int temp in result)
            //{
            //    Console.WriteLine(temp);
            //}

            //두개 이상 select, 클래스를 그때 그때 생성 할 수도 있지만 부담스러움에 다음과 같이 처리
            //info[] data = { new info(1, "1"), new info(2, "2"), new info(3, "3") };
            //var result = from temp in data select new { num = temp.num, name = temp.name };
            //foreach (var temp in result)
            //{
            //    Console.WriteLine(temp.num + " : " + temp.name);
            //}

            //메서드 이용
            //List<int> data = new List<int> { 200, 300, 400 };
            //IEnumerable<int> result = data.Where(method);
            //foreach (int temp in result)
            //{
            //    Console.WriteLine(temp);
            //}
           
            //람다식 이용
            //List<int> data = new List<int> { 1000, 2000, 3000, 4000, 5000, 6000 };
            ////인자값 => (비교 판단)
            //var result = data.Where(x => (x * 12 >= 20000));
            //foreach (int temp in result)
            //{
            //    Console.WriteLine(temp);
            //}

            //data 합계
            //List<int> data = new List<int> { 1, 2, 3, 4, 5, 6 };
            //var result = (from int temp in data where temp > 2 select temp).Sum();
            //Console.WriteLine(result);

            //data 합집합
            //List<int> data1 = new List<int> { 1, 2, 3, 4, 6, 7 };
            //List<int> data2 = new List<int> { 5, 8 };
            //var result = (from temp in data1 select temp).Union(from temp in data2 select temp);
            //foreach (var temp in result)
            //{
            //    Console.WriteLine(temp);
            //}

            //정렬
            //info[] data = { new info(1, "31"), new info(2, "21"), new info(3, "13") };
            //IEnumerable<info> result = from temp in data orderby temp.name select temp;
            //IEnumerable<info> result = from temp in data orderby  temp.name descending select temp;
            //foreach (info temp in result)
            //{
            //    Console.WriteLine(temp.num + " : " + temp.name);
            //}

            //let 특정 데이터에 별칭 붙여서 이용
            //info[] data = { new info(1, "31"), new info(2, "21"), new info(3, "13") };
            //IEnumerable<info> result = from temp in data let num1 = temp.num where num1 > 1 select temp;
            //foreach (info temp in result)
            //{
            //    Console.WriteLine(temp.num + " : " + temp.name);
            //}

            //group by
            //info[] data = { new info(1, "31"), new info(2, "13"), new info(3, "13"), new info(3, "14") };
            //IEnumerable<IGrouping<string, info>> result = from temp in data group temp by temp.name;
            //foreach (IGrouping<string, info> temp in result)
            //{
            //    Console.WriteLine(temp.Key);
            //    foreach (info tem in temp)
            //    {
            //        Console.WriteLine(tem.num + " : " + tem.name);
            //    }
            //}

            //into let과 비슷하지만 그룹화, 조인 쿼리에 대해 별칭 부여, 그룹화 결과에 대한 정렬 또는 필터링시 이용
            //info[] data = { new info(1, "31"), new info(2, "13"), new info(3, "13"), new info(3, "14") };
            //var result = from temp in data group temp by temp.name into it where it.Key == "13" select it;
            //foreach (var tem in result)
            //{
            //    Console.WriteLine(tem.Key);
            //    foreach(info tem1 in tem)
            //    {
            //        Console.WriteLine(tem1.num);
            //    }
            //}

            //Sub Query
            //info[] data = { new info(1, "31"), new info(2, "13"), new info(3, "13"), new info(3, "14") };
            //var result = from temp in data where temp.num == ((from temp1 in data select temp1.num).Max()) select temp.name;
            //foreach (var temp in result)
            //{
            //    Console.WriteLine(temp);
            //}

            //Join
            info[] data = { new info(1, "31"), new info(2, "13"), new info(0, "13"), new info(3, "14") };
            info[] data1 = { new info(4, "31"), new info(2, "13"), new info(9, "13"), new info(3, "14") };
            var result = from temp in data join temp1 in data1 on temp.num equals temp1.num select new {temp.num,temp1.name};
            foreach(var temp in result)
            {
                Console.WriteLine(temp.num + " : " +temp.name);
            }

            Console.ReadLine();
        }
    }

매번 루프를 돌려서 처릴 했는데.. Linq를 왜 소홀히 했을까 싶은 생각이 드는 공부..

좀 더 깊게 봐야지 ㅠ_ㅠ

요새 포스팅도 안하고 해서 반성의 시작으로 한번 해 본 코드..

좀 간단하게;;

서버는 Java로 구성해봤는데.. ㅠㅠ

단지 테스팅용으로..  한거니까 다른 분들 들어오시면 돌 던지지마세요 ㅠㅠ

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;

namespace JavaServerTest
{
    public partial class Form1 : Form
    {
        IPEndPoint ipEP;
        Socket socket = null;
        IPHostEntry ipHE;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            System.Console.WriteLine("프로그램 시작 윈도우 폼 활성화");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Encoding encString = Encoding.GetEncoding(949);
            byte[] d_byte = new byte[1024];
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //ipHE = Dns.GetHostByName("127.0.0.1");
            ipEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8520);
            socket.Connect(ipEP);
            string s_data = "Client Start";

            d_byte = encoding.GetBytes(s_data);
            System.Console.WriteLine("보낼 준비");
            socket.Send(d_byte);

            byte[] R_byte = new byte[1024];
            System.Console.WriteLine("받을 준비");
            int size = socket.Receive(R_byte);
            System.Console.WriteLine(encString.GetString(R_byte, 0, size));
            socket.Close();
        }
    }
}

여기까지가 클라이언트!!

말 그대로 간단하다;;

요새 공부를 안했더니.. 좀 더 발전해야하는데...

[C#] 엑셀 조작법 추가!! C# 2010. 7. 27. 18:45

C#에서 챠트를 직접적으로 생성 할 때는 다음과 같이 한다.

먼저 챠트 객체를 생성한 후
Excel.ChartObjects chartObjs = (Excel.ChartObjects)worksheet.ChartObjects(Type.Missing);               
챠트 포지션을 정해준다.
Excel.ChartObject chartObj = chartObjs.Add(270, 10, 200, 100);
그 다음 챠트 할당한 후
Excel.Chart xlChart = chartObj.Chart;
데이터를 넣어준다.
여기서 chartRange는 셀의 범위를 말한다.(Range)
xlChart.SetSourceData(chartRange, Type.Missing);
다음은 챠트 형태를 구하고
xlChart.ChartType = Excel.XlChartType.xlLineMarkers;
X,Y축에 대한 설정을 한다.
Excel.Axis xAxis = (Excel.Axis)xlChart.Axes(Excel.XlAxisType.xlValue,Excel.XlAxisGroup.xlPrimary);
xAxis.MajorUnit = 20;
Excel.Axis yAxis = (Excel.Axis)xlChart.Axes(Excel.XlAxisType.xlValue,Excel.XlAxisGroup.xlPrimary);
yAxis.MaximumScale = 100;
다음은 챠트 외부의 색을 정하는 것이고
xAxis.Border.Color = ColorTranslator.ToWin32(Color.Black);
이번 것은 챠트 내부의 색을 정한다.
xlChart.PlotArea.Interior.Color = ColorTranslator.ToWin32(Color.White);
범례를 쓰고 싶지 않다면 다음과 같이 Legend를 설정하면 된다.
Excel.Legend legend = xlChart.Legend;
legend.Delete();
셀만으로 접근하기가 힘들 경우는 TextBox를 쓰면 된다.
필자의 경우도 그러한 적이 있어 TextBox를 써봤다. 직접 생성해서 붙일 수도 있지만
엑셀 문서의 TextBox에 접근하는 것은 다음과 같다.
Excel.TextBox box = _worksheet.TextBoxes(엑셀에서 생성한 텍스트 박스 순서) as Excel.TextBox;
txt_HowTo.Text = String형 데이터;

흠냐.. 은근.. 접근 할 수 있는 것이 많지만..
셀 경우 ADO.NET에서 XML로 넘겨 속도가 빠르게 할 수 있지만..

이와 같이 객체에 접근하는 것에는 속도가 많이 떨어진다..

방법이 없을까 ㅠㅠ