WPF 애플리케이션 UI 디자인 실전 가이드

CSharp
WPF(Windows Presentation Foundation)는 강력한 데스크톱 애플리케이션 UI 개발 플랫폼입니다. 이번 글에서는 WPF에서 효과적이고 아름다운 UI를 만드는 방법을 단계별로 안내하겠습니다. 1. WPF와 XAML의 이해 WPF는 XAML 기반의 UI 디자인을 사용하여, 깔끔하고 직관적인 UI를 쉽게 만들 수 있도록 돕습니다. XAML의 기본 문법과 구조 소개 주요 레이아웃 컨트롤 (Grid, StackPanel, DockPanel 등) 2. 간단한 화면 설계하기 XAML을 사용한 레이아웃 구성 방법: <Grid> <StackPanel Orientation="Vertical" Margin="20"> <TextBlock Text="WPF UI 실습 예제" FontSize="24" FontWeight="Bold"/> <Button Content="버튼 클릭" Margin="10"/> </StackPanel></Grid> 3. 스타일과 테마 관리하기 XAML의 Style과 ResourceDictionary를 활용한 스타일 재사용법 애플리케이션 전체에 적용되는 테마 관리하기 예시 코드: <Window.Resources> <Style TargetType="Button"> <Setter Property="FontSize" Value="16"/> <Setter Property="Background" Value="#FF007ACC"/> <Setter Property="Foreground" Value="White"/> </Style></Window.Resources> 4. 데이터 바인딩과 MVVM 패턴 활용 MVVM(Model-View-ViewModel) 구조의 장점 설명 데이터 바인딩으로 View와 ViewModel 연동하기 간단한 예제 코드: <TextBlock Text="{Binding UserName}" /> 5. 커스텀 컨트롤 제작…
Read More

안드로이드 앱에서 Retrofit을 활용한 API 통신 완벽 가이드

Android
Retrofit은 안드로이드 앱에서 서버와 쉽게 통신할 수 있는 가장 널리 사용되는 라이브러리입니다. 이번 포스트에서는 Retrofit을 활용하여 API 통신하는 방법을 기초부터 상세히 소개합니다. 1. Retrofit이란? Retrofit은 Square에서 만든 타입 안전(type-safe)의 REST 클라이언트로, HTTP 통신을 쉽게 해주는 라이브러리입니다. 코드 간결화 및 가독성 향상 비동기 처리 지원 2. 프로젝트에 Retrofit 추가하기 build.gradle(:app)에 의존성 추가: implementation 'com.squareup.retrofit2:retrofit:2.11.0'implementation 'com.squareup.retrofit2:converter-gson:2.11.0' 3. Retrofit 기본 구조 이해하기 기본 API 인터페이스 정의 예시: public interface ApiService { @GET("users/{id}") Call<User> getUser(@Path("id") int userId);} 4. Retrofit을 이용한 API 요청 구현 레트로핏 객체 생성 예제: Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.example.com/") .addConverterFactory(GsonConverterFactory.create()) .build();ApiService apiService = retrofit.create(ApiService.class); API 요청 및 응답 처리 예제: apiService.getUser(1).enqueue(new Callback<User>() { @Override public void onResponse(Call<User> call, Response<User> response) { if(response.isSuccessful()) { User user = response.body(); // 성공적으로 응답받은 데이터 처리 } } @Override public void onFailure(Call<User> call, Throwable…
Read More

MySQL 성능 최적화를 위한 기초 가이드

Database
MySQL을 사용하는 프로젝트가 많아지면서 데이터베이스 성능은 개발자의 중요한 고민 중 하나입니다. 이번 포스트에서는 MySQL의 성능을 기초적으로 최적화하는 방법을 소개합니다. 1. 인덱스(Index) 설정과 최적화 인덱스는 데이터 조회 속도를 현저히 높여줍니다. 자주 조회하는 컬럼에 인덱스를 설정합니다. 인덱스는 과도하게 생성하면 삽입, 수정, 삭제 성능이 떨어지므로 적정 수준을 유지합니다. 예시: CREATE INDEX idx_user_email ON users(email); 2. 느린 쿼리(Slow Query) 확인 및 개선하기 느린 쿼리는 성능 저하의 주범입니다. MySQL에서는 이를 쉽게 확인할 수 있습니다. MySQL의 Slow Query Log 활성화: [mysqld]slow_query_log = 1slow_query_log_file = /var/log/mysql/mysql-slow.loglong_query_time = 2 느린 쿼리 최적화 전략: 서브쿼리를 JOIN으로 변경 WHERE절에 인덱스 적용 여부 확인 LIMIT를 활용하여 반환 데이터를 최소화 3. 쿼리 최적화 팁 성능을 높이기 위해 쿼리 작성 시 다음 사항을 참고하세요. SELECT 문에서 꼭 필요한 컬럼만 지정하여 불필요한 데이터 전송을 줄입니다. LIKE 검색 시 % 앞부분 사용을 자제합니다. ORDER BY를…
Read More

안드로이드 앱 출시 방법과 필수 체크리스트

Android
안드로이드 개발자로서 앱을 구글 플레이스토어에 출시하는 것은 매우 중요한 단계입니다. 본 포스팅에서는 앱을 성공적으로 출시하기 위한 방법과 필수 체크리스트를 안내합니다. 1. 구글 개발자 계정 생성하기 Google Play Console에 가입하고 개발자 등록비($25)를 결제합니다. 2. 앱 패키지 이름 결정 및 생성 고유하고 명확한 패키지 이름(예: com.company.appname)을 선택합니다. 3. 앱 콘텐츠 준비 스크린샷, 앱 아이콘, 설명 등 스토어 등록에 필요한 모든 콘텐츠를 준비합니다. 4. APK/AAB 파일 빌드 및 서명 Android Studio에서 앱을 빌드하고 디지털 서명을 하여 릴리즈 파일을 생성합니다. APK나 권장하는 AAB(Android App Bundle) 파일 형식으로 준비합니다. 5. 스토어 등록 및 정책 점검 플레이 콘솔에서 앱 등록 시 모든 세부사항(개인정보 처리방침, 등급, 타겟층)을 명확히 설정합니다. 앱 정책 위반 여부를 꼼꼼히 검토합니다. 6. 앱 출시 전 최종 점검 체크리스트 필수 권한 설정 확인 테스트 기기에서 앱 실행 테스트 앱 설명 및 스크린샷 정확성 검증…
Read More

모든다해 IP66 금속 검출기

CSharp
IP66 금속 검출기, TCP 통신으로 불량품 자동 추적 시스템 구축 현장에서 사용 중인 모든다해 IP66 금속 검출기는 식품이나 산업 라인의 제품 중 금속 이물질을 검출하는 장비입니다. 이번 작업에서는 해당 금속검출기의 TCP 통신 기능을 활용하여 불량품 수집 및 로그 분석 시스템을 구현하였습니다. 장비에 부착된 컨베이어 벨트 상에서 제품이 검출되면, 시스템은 양품/불량 판정 데이터를 실시간으로 전송합니다. 이 데이터를 TCP를 통해 수집하여 생산 라인 불량률, 구간별 이상 통계, 추적 정보까지 저장할 수 있도록 자동화 시스템을 구성하였습니다. 🛠 사용한 장비는 IP66 등급으로, 물과 먼지에 강한 밀폐 설계를 갖추고 있어 습한 환경이나 세척이 필요한 식품 공정에 최적화되어 있습니다. 주요 작업 내용 금속 검출기와 TCP 소켓 기반 통신 구현 불량 판정 시 자동 로그 기록 및 시각화 처리 특정 라인에서 불량률 상승 감지 시 알람 시스템과 연동 해당 장비는 실제 운영 중인 업체에서 사용되며, 보안상 업체명은…
Read More

Keithley 계측기 TCP 통신: C#을 활용한 제어 가이드

CSharp
Keithley 계측기는 정밀한 전류, 전압 측정을 지원하는 장비로, LAN을 통한 TCP/IP 통신으로 원격 제어가 가능합니다. 본 글에서는 C#으로 Keithley 장비에 SCPI 명령어를 전송하고 응답을 받는 기본 통신 구조를 소개합니다. 1. Keithley TCP 통신 기본 개념 장비는 TCP 서버 역할, PC는 클라이언트 기본 포트는 5025 통신 방식은 소켓 기반, 명령어는 SCPI (IEEE488.2) 사용 2. 장비 설정 확인 사항 장비의 IP 주소 확인 (고정 IP 또는 DHCP) 포트 번호: 기본은 5025, 다르면 설정 메뉴에서 변경 가능 Ping 테스트로 네트워크 연결 확인 방화벽에서 포트가 열려 있는지 확인 3. C# 예제: TCP 클라이언트로 SCPI 명령어 전송 csharp복사편집using System; using System.Net.Sockets; using System.Text; class Program { static void Main() { string ip = "192.168.0.10"; // Keithley 장비 IP int port = 5025; try { using (TcpClient client = new TcpClient(ip, port)) using (NetworkStream stream =…
Read More

웹 Context 메뉴

JavaScript, WWW
// Context Menu List 렌더링 function renderContextMenuList( list ){ // List Element 생성 const ctxMenuList = document.createElement('ul'); // List Item 생성 list.forEach(function( item ){ // Item Element 생성 const ctxMenuItem = document.createElement('li'); const ctxMenuItem_a = document.createElement('a'); const ctxMenuItem_a_text = document.createTextNode(item.label); // 클릭 이벤트 설정 if( item.onClick ){ ctxMenuItem.addEventListener( 'click', item.onClick, false ); } // Item 추가 ctxMenuItem_a.appendChild( ctxMenuItem_a_text ); ctxMenuItem.appendChild( ctxMenuItem_a ); ctxMenuList.appendChild( ctxMenuItem ); }); // List Element 반환 return ctxMenuList; } // Context Menu 생성 function handleCreateContextMenu(event){ // 기본 Context Menu가 나오지 않게 차단 event.preventDefault(); // Context Menu Element 생성 const ctxMenuId = 'dochi_context_menu'; const ctxMenu = document.createElement('div'); // Context Menu Element 옵션 설정 ctxMenu.id = ctxMenuId; ctxMenu.className = 'custom-context-menu'; // 위치 설정 ctxMenu.style.top = event.pageY+'px'; ctxMenu.style.left = event.pageX+'px'; // 메뉴 목록 생성 ctxMenu.appendChild(renderContextMenuList([ { label: "메뉴1", onClick:…
Read More

회사 동일 다수 DB 관리

CSharp, Windows, 프로그램
DB 가 분리되어 있지만 모두 동일한 DB 일 경우에 컬럼을 동일하게 변경하기 위해서 필요함.먼저 대상이 되는 DB를 수집후 테이블 명을 보고 컬럼을 변경을 할수 있습니다. 각 DB에서 테이블 정보를 수집도 가능합니다. 테이블을 추가 할 경우 다수의 DB에서 동일한 작업이 필요할 경우에 추가를 진행하면은 동시에 다수를 작업을 합니다. 테이블을 한곳에 만들어 두거나 혹은 특정 DB에서 필요한 테이블을 복사 혹은 삭제 처리 할수 있습니다. 테이블 내의 컬럼을 추가 하거나 삭제 변경 할수 있습니다. 컬럼의 형식이나 값을 변경할 경우에 나오는 화면입니다. 테이블에 컬럼을 추가 할 경우에 입력 하는 화면 입니다. 데이터를 볼때 정렬이 필요하면은 정렬 기능을 이용해서 정렬을 해서 전체 테이블에 동일 컬럼이나 값이 일치 하지 않는 것을 확인할때 필요합니다. DB 명세서를 만들때 엑셀 파일로 출력이 가능 합니다. 실제 엑셀로 출력 할 때 테스트나 불필요한 테이블을 제외 하고 저장 할 수 있도록 설정을…
Read More

Groupby 에 대해서 Count 하기

Database
MySQL에서 Count를 하다 보니 SELECT에서 GroupBy 를 하면은 정확한 Count가 나오지 않는 문제가 있어서 찾아 보니 찾은 SQL 입니다. SELECT IFNULL(COUNT(S.컬럼), ' ') AS cnt FROM ( SELECT 컬럼 FROM 테이블 WHERE 컬럼='1' GROUP BY 컬럼) AS S; 별다른 형태가 없이 보통 사용하는 SELECT에서 한번 더 SELECT 를 감싸니 쉽게 해결이 되었습니다. 기록을 하지 않으면은 잊어 버릴것 같아서 작성해 둡니다. 결과 화면은 별도로 없습니다.
Read More

폰터 어썸 유료를 내 서버에서 서비스하자

Linux, WWW
※ 자기 서버가 있어야 가능한 기능 입니다. (트래픽주의) 홈페이지를 만들다 보면 사용자에게 주기가 애매한 소스들이 있습니다. 웹이라는 한계성 때문에 어떻게는 사용자가 내용을 알수가 있지만 최대한 주기 싫은 소스에 대해서 내 서버에서 운영을 할 수 있도록 만들어야 하는데 CrossDomain 위반으로 URL Domain이 다를경우에 문제가 생길때가 있습니다. AddType application/font-woff2 .woff2 일단 폰터어썸이 woff2 확장자를 처리를 해야 합니다. 위에 처럼 MIME 을 추가를 해서 처리가 가능하도록 해줘야지만 WEB 서버가 작동을 하게 됩니다. <FilesMatch "\.(ttf|otf|eot|woff|woff2)$"> Header set Access-Control-Allow-Origin "*" </FilesMatch> 위에 처럼 처리를 해줘서 어디서든 불러가서 사용할수 있도록 해주면 일단은 마무리 입니다. 일단 이렇게 사용을 하면은 자기 서버에서 서비스를 할 수 있는것으로 판단은 되지만 잘 작동하지 않을 수도 있지만 저의 입장에서는 현재 그대로 사용을 할 수 있습니다. 이 뿐만 아니라... Javascript를 고객 사이트에 두지 않아도 작동하도록 하는 기능도 작동을 합니다. 원래 이렇게 사용을 하면…
Read More

WebServer에서 사용률 체크하기

CSharp, Database
홈페이지를 만들고 나서 사용률이 저조하면은 상당히 힘이 빠지는 일입니다. 더욱이 정부에서 사용을 하라고 하는데 제작을 할때는 사람들이 요구사항이 상당히 많이 발생하고 좀 더 자기에게 유리하게 만들기 위해서 시간과 노력을 투자 하지만 일단 정부에서 대금이 지급되고 나서는 시들해지기 마련입니다. 하지만 정부도 바보가 아닌 이상 몇년간 사용을 해야 하는데 사람들이 일이 늘어나서 사용하지 않는다는것을 알고 있어서 조금은 강제로 사용 현황을 수집하고 있습니다. 정부 사이트에 현황을 볼 수 있는 사이트가 있지만 매일 들어가서 보기 힘들고 어차피 우리가 만들어준 시스템에서 자료를 가지고 통계를 전송하기에 해당 부분에 착안해서 먼저 우리가 시스템에서 데이터를 통계를 내서 메일을 발송하기로 하였습니다. 상태 표시 화면 이렇게 매일 실행을 해서 상태를 확인 후 우리가 정한 상한선 보다 낮을 경우에 메일을 발송을 해서 경각심을 가지고 해야 합니다. 정부는 몇달간 모았다가 갑자기 감사를 나오기 때문에 미리 미리 해 놓아야 합니다. 메일 발송 내역…
Read More

HTML를 PDF로 만들기

WWW
웹브라우저에서 HTML를 그대로 PDF로 만들기 위해서 찾아 보게 되었습니다. 위 사진은 웹페이지 그대로 화면은 캡쳐한 부분입니다. 해당 화면을 가지고 그대로 PDF로 만들어야 하는 상태 입니다. background로 제작을 하면 되지만 고객이 일단 화면에 먼저 보여지기를 원해서 View를 만들고 그다음에 PDF로 제작을 해야 되는 조건이 붙었습니다. 이렇게 VIew 에서 PDF로 다운 받아서 그대로 확인을 할 수 있도록 만들기 위해서 html2pdf 라이브러리를 사용을 하여서 제작을 하게 되었습니다. 일단든 보여지는 그대로 나오기 때문에 그다지 어렵지는 않았습니다. // Get the element. var element = document.getElementById('PDFROOT'); // Generate the PDF. // orientation는 출력 방항 ( 가로 세로 ), // scale 는 확대 html2pdf().from(element).set({ filename: '<?=$mainResData['reportNo'];?>', html2canvas: { scale: 1 }, jsPDF: {orientation: 'portrait', unit: 'mm', format: 'A4', compressPDF: true} }).save(); Javascript 코드는 위와 같이 처리를 하면은 됩니다. 좀 더 자세한 사항은 html2pdf 옵션을 찾아 보면은 자세하게…
Read More

1년동안 주차와 전년도 주차와 비교하기

PHP
고객이 검색한 년도의 1년동안의 매월 주를 계산을 하고 나서 기간에 따른 Row 갯수를 그래프에 표현을 하고 싶어 하기에 작성하게 된 것입니다. 조금은 난해하게 보이지만은 조건 검사가 많은 편이지 그다지 복잡한 코드는 아닙니다. $end_yearmonthday = date("Y-m-d", strtotime($_GET['end_year'].'-'.$_GET['end_month'].'-'.$_GET['end_day'])); // 이전년도 $agoTime = date('Y-m-d', strtotime(date('Y-01-01', strtotime($end_yearmonthday)).' -1 years')); $agoMaxWeek = date('W', strtotime(date('Y-12-31', strtotime($end_yearmonthday)).' -1 years')); $monthCnt = 0; $historyMonth = 0; for($w = 0; $w <= $agoMaxWeek; $w++) { $thisWeek = date('W', strtotime( $agoTime .' +'.$w.' week') ); $thisYear = date('Y', strtotime( $agoTime .' +'.$w.' week') ); $thisMonth = date('m', strtotime( $agoTime .' +'.$w.' week') ); $thisDay = date('d', strtotime( $agoTime .' +'.$w.' week') ); $dayOfTheWeek = date('w',mktime(0,0,0,$thisMonth,$thisDay,$thisYear)); // 해당주차의 시작 날짜 $today_week_sday1 = mktime(0,0,0,$thisMonth,$thisDay-$dayOfTheWeek,$thisYear); $today_week_sday2 = date("Y-m-d",$today_week_sday1); // 해당주차의 종료 날짜 $today_week_eday1 = mktime(23,59,59,$thisMonth,$thisDay+(6-$dayOfTheWeek),$thisYear); $today_week_eday2 = date("Y-m-d",$today_week_eday1); // if( $historyMonth == $thisMonth)…
Read More

MySQL 정렬 특정 단어를 우선순위에 두기

Database
MySQL을 이용할 경우에 정렬을 사용할때가 있습니다. 문자를 숫자로 변형해서 하기도 하고 Abc순으로 할 수도 있고 가나다 방법등 다양하게 사용을 할 수 있습니다. 보통의 방법으로 오름차순, 내림차순 정렬을 사용하면은 원하는 결과물에 대해서 정렬을 해서 목록을 만들수 있습니다. 하지만, 특정 단어가 목록중에서 가장 최상단에 와야 하는 경우라는 보통의 방법으로는 할 경우에는 WHERE 조건후에 다른것까지 붙이다 보면은 원하는 정렬이 되지 않아서 고생을 하게 됩니다. ORDER BY CASE WHEN 정렬컬럼명 = '정렬단어A' THEN 1 WHEN 정렬컬럼명 = '정렬단어B' THEN 2 WHEN 정렬컬럼명 = '정렬단어C' THEN 3 WHEN 정렬컬럼명 = '정렬단어D' THEN 4 ELSE 10 END , 정렬컬럼명2 ASC 위에 예제를 이용 할 경우에는 1차적으로 정렬컬럼명을 통해서 정렬을 시도하고 정렬컬럼명2를 통해서 정렬을 하기 때문에 원하는 단어를 문저 올려서 처리를 할 수 있습니다. 잘 사용을 하지 않지만은 꼭 필요할때 유용하게 사용을 할 수 있을것 같아서 글을…
Read More