- .NET 가이드 [.NET] 레퍼런스 프로젝트 리스트 레퍼런스 프로젝트 리스트 .NET Podcasts Github
- 단독주택 집짓기 건축주를 위한 건축 토막 상식 - 현장에서 콘크리트의 품질을 확인하는 방법 건축주를 위한 건축 토막 상식 - 현장에서 콘크리트의 품질을 확인하는 방법 철근콘크리트조를 신축할 때 대규모 건설현장이든 소규모 건설현장이든 콘크리트의 품질이 중요합니다. 따라서 시멘트 공장에서 레미콘 차량으로 운송해온 콘크리트의 품질을 시험해야 하고, 시험할 때 건축주가 참관하는 것을 추천드립니다. 박강현 건축시공기술사의 "100년을 견뎌내는 집 내가 짓는다" 책과 한국건설기술연구원 건설기준코드 중 "KCS 14 20 01:2022 콘크리트공사 일반사항"을 읽어보니 콘크리트 타설 전 품질 검사가 필요함을 깨달았습니다. 소규모 건설현장에서 합리적으로 진행할 수 있는 콘크리트 시험 방법은 아래와 같이 4가지가 있으며 자세한 설명은 국가표준 문서를 참고하시면 되며 현장에서 어떻게 실험하는지는 유튜브 영상으로..
- 단독주택 집짓기 건축주를 위한 건축 토막 상식 - 신재생에너지 설비 건축주를 위한 건축 토막 상식 - 신재생에너지 설비 저는 소프트웨어 개발자입니다. 저는 건축과 관련있는 업무를 일체 해본 적이 없습니다. 하지만 직업 특성상 자료를 조사하고 정리하면서 학습하는 능력이 뛰어나고 이번에 주택을 신축하는 김에 신재생에너지 설비에 관해 건축주 입장에서 정리해봤습니다. 일반적으로 신재생에너지는 환경 친화적인 관점에서 접근하지만, 건축주의 입장에서는 신재생에너지는 정부지원을 받아 건물의 유지관리 비용인 전기를 절약하기 위한 방안으로 고민을 시작하게 됩니다. 특히 일상 생활 속에서 건축주가 신재생에너지에 관심을 갖게 하는건 주변에서 흔하게 볼 수 있는 태양광 발전 설비겠죠. 일단 건축주 입장에서 신재생에너지는 보조금없이 설치하기가 부담스럽습니다. 설비 투자비용이 부담스럽기 보다는 보..
- Frontend 가이드 [Blazor] Blazor WebAssembly + Webpack + TypeScript + Sass 개발 환경 구축 Blazor WebAssembly + Webpack + TypeScript + Sass 개발 환경 구축 Blazor 를 다른 환경과 통합하여 사용하는 예제를 찾을 수 없어, 직접 연구하여 공유합니다. Blazor 와 관련된 자료는 공식 문서 외에 Awesome Blazor 에서 다양하게 찾을 수 있습니다. 1. 프로젝트 생성 위 그림과 같이 Blazor WebAssembly App 프로젝트를 생성합니다. 생성하면 위 그림과 같은 결과를 얻을 수 있습니다. 현재 상태로 빌드해서 실행하면 위 그림과 같은 결과를 얻게 됩니다. 이제 여기서부터 하나하나 환경을 세팅해보도록 합시다. 2. Webpack 추가 node -v npm -v 현재 프로젝트에 Webpack 을 추가하려면 Node.js 를 설치해야 합니다...
- Frontend 가이드 [Blazor] Sass 를 적용하는 방법 Sass 를 적용하는 방법 일단 Sass(Syntactically Awesome Style Sheets) 를 한 문장으로 설명하자면, 스타일을 표현하는 CSS 파일을 프로그래밍 언어처럼 만들 수 있도록 하는 확장 언어입니다. 따라서 Sass 파일을 컴파일하면 결과로 CSS 파일을 얻을 수 있습니다. Sass 는 Node.js 를 바탕으로 npm 으로 패키지를 관리하며 React 로 컴포넌트를 만들고 Webpack 으로 번들링하는 FrontEnd 프로젝트에 빈번하게 사용되며, 번들링할 때 Sass 를 컴파일하여 Css 파일로 만든 뒤 최종 번들에 추가하여 사용합니다. Blazor 에서도 마찬가지로 Sass 를 사용하려면, Sass 를 컴파일하고 최종 결과에 추가하는 과정이 필요합니다. 제일 심플한 방법은 ..
- Frontend 가이드 [FE] webpack 에서 Source Map 이 동작하는 원리 Webpack 에서 Source Map 이 동작하는 원리 Visual Studio Code 에서 디버깅하려고 break point 를 잡으면 break point 가 활성화가 되지 않거나 엉뚱한 코드에서 break 가 되는 경우을 종종 겪게 됩니다. 개발을 하다보면 이게 꽤 거슬립니다. 일단 디버깅을 제대로 할 수 없으니 런타임에 어떤 데이터가 저장되고 어디서 어떤 함수가 호출되는지를 console.log() 로 파악하는데 이게 너무나도 고역입니다. 그래서 저는 Source Map 이 어떻게 구성되고 동작하는지를 조사했고 이를 공유드리고자 합니다. Source Map 은 개발하는 코드와 번들링된 코드 사이의 관계를 표현하는 데이터입니다. 이 Source Map 이 필요한 이유는 webpack 을 사용해서..
- Frontend 가이드 [FE] Web API - WebSocket API Web API - WebSocket API HTTP/1.1 프로토콜은 클라이언트가 TCP 프로토콜로 서버와 연결한 뒤에 요청을 보내고 서버로부터 응답을 받고 나면 연결을 해제하는 프로토콜입니다. 클라이언트가 요청을 보내지 않으면 서버와 연결되지 않기 때문에 서버가 주도적으로 클라이언트와 통신을 시작할 수 없습니다. 그래서 서버가 클라이언트에게 무엇인가 알려주고 싶어도 방법이 없습니다. 서버 내부적인 변경을 감지할 수 없는 클라이언트가 서버가 원하는 걸 눈치채고 요청을 보내는건 불가능합니다. 그래도 이를 해결하고자 여러 방법이 시도되었습니다. 먼저, 클라이언트가 일정 주기로 서버에게 변경사항이 있는지 확인하는 방법이 제일 직관적이고 구현이 간단합니다. 하지만, 이 방법은 현업에서 사용될 수 없는 방법입니다..
- Frontend 가이드 [FE] Web API - Client-side storage : Service Worker API & Cache Web API - Service Worker API & Cache Service Worker 와 Cache 를 활용하면 인터넷 연결이 끊겨도 동작하는 앱을 만들 수 있습니다. Service Worker 는 브라우저에 등록되어, 브라우저와 네트워크 사이에서 프록시 서버의 역할을 수행합니다. 즉, Service Worker 는 서버인 것처럼 브라우저가 서버에게 보내는 요청에 응답할 수 있습니다. Cache 는 브라우저의 Request 와 서버의 Response 를 저장할 수 있습니다. 오프라인에서 동작하는 앱을 만들려면, 먼저 Service Worker 를 등록합니다. 그리고 인터넷이 연결되어 있는 동안, 브라우저가 보내는 Request 와 Response 를 Cache 에 저장합니다. 그리고 인터넷 연결이..
- Frontend 가이드 [FE] Web API - Client-side storage : IndexedDB Web API - Client-side storage 브라우저 환경에서 데이터를 저장하는 방법을 시리즈 글로 소개하고 있습니다. IndexedDB IndexedDB 는 클라이언트에 데이터를 저장하는 방법 중 하나입니다. 따라서 네크워크 연결 여부와 관계없이 데이터를 활용할 수 있어, 모바일 플랫폼의 웹 앱에서 활용하기 좋습니다. IndexedDB 는 Cookie 나 localStorage 와 sessionStorage 와 달리 복잡한 데이터를 저장하기 위한 목적의 저장소입니다. 그래서 원리나 사용하는 방법도 다른 저장소에 비해 복잡합니다. 1. IndexedDB 초기화한다. 쿠키는 서버의 Set-Cookie 헤더에서 설정하고 localStorage 와 sessionStorage 는 사용하는 순간 저절로 ..
- Frontend 가이드 [FE] Web API - Client-side storage : 로컬 스토리지 localStorage 와 세션 스토리지 sessionStorage Web API - Client-side storage 브라우저 환경에서 데이터를 저장하는 방법을 시리즈 글로 소개하고 있습니다. 로컬 스토리지 localStorage 와 세션 스토리지 sessionStorage 로컬 스토리지 localStorage 와 세션 스토리지 sessionStorage 는 쿠키 Cookie 처럼 브라우저 내에서 Key/Value 로 데이터를 저장할 수 있는 저장소입니다. 로컬 스토리지와 세션 스토리지는 쿠키의 한계를 극복하기 위해 HTML5 와 함께 도입되었습니다. 쿠키는 오래동안 함께 했기에 익숙하고 사용하기 편리한 만큼 여러 한계를 가지는데 대표적인 한계로 서버가 허용하는 HTTP 헤더 크기 이상으로 쿠키에 데이터를 저장할 수 없다는 점입니다. HTTP 프로토콜 설계는 헤더의 ..
- Frontend 가이드 [FE] Web API - Client-side storage : 쿠키 Cookie Web API - Client-side storage 브라우저 환경에서 데이터를 저장하는 방법을 시리즈 글로 소개하고 있습니다. 쿠키 Cookie 과거부터 지금까지 사랑받고 있는 방법은 쿠키 Cookie 입니다. 원래 HTTP 프로토콜은 Stateless 한 프로토콜로 과거 통신 상태를 기록하지 않는 프로토콜입니다. 따라서 순수한 HTTP 통신만으로는 클라이언트를 구분하여 반응하거나 클라이언트 상태에 따라 대응할 수 없습니다. 즉 어떤 클라이언트이던지 동일한 요청에 동일한 응답을 합니다. 하지만 현실적으로 클라이언트로부터 오는 요청을 상태에 따라 다르게 처리할 방법이 필요했습니다. 예를 들어, 서버가 클라이언트로 받는 요청이 로그인한 사용자가 보낸 요청인지 아닌지를 판별하거나, 동일한 클라이언트로부터 오..
- 코딩인터뷰 [코딩인터뷰] 백준 15683번 감시 import sys from copy import deepcopy rl = sys.stdin.readline def watch(testbed, sr, sc, direction): direction %= 4 cr = sr + DR[direction] cc = sc + DC[direction] while 0
- Frontend 가이드 [FE] Typescript - Type Guard 타입 가드 TypeScript - Type Guard 타입 가드 TypeScript 에서의 타입은 다른 언어와 의미가 다릅니다. 다른 언어에서 타입은 객체가 반드시 지켜야 하는 계약이라면, TypeScript 에서 타입은 객체에 대한 약속입니다. 다른 언어는 타입에 민감해서 타입이 맞지 않으면 사용할 수 없습니다. 하지만 TypeScript 에서 타입은 약속이고, 약속을 지키지 않는 객체에 접근해도 에러가 발생하지 않을 수 있습니다. 다만 컴파일할 때 개발자에게 문제가 있을 수 있다고 알려줍니다. 이처럼 TypeScript 의 타입은 유연하게 사용할 수 있는 특징이 있습니다. TypeScript 는 타입을 조합하여 사용할 수 있습니다. 그래서 아래와 같이 매개변수의 타입이 number 일수도 있고, string 일..
- 코딩인터뷰 [코딩인터뷰] 백준 16118번 달빛 여우 백준 16118번 달빛 여우 2021.04.15 00:39 기준으로 Python 3 로 통과했는데 시간이 아슬아슬하네요. 새벽이라 서버가 널널해서 통과한 거 같네요. 그래서 다른 코드는 어떻게 통과했나 보려했더니 통과한 코드가 없다? from heapq import heappush, heappop import sys rl = sys.stdin.readline INF = int(1e9) def dik_fox(): dist = [INF for _ in range(N+1)] dist[1] = 0 q = [] heappush(q, (dist[1], 1)) while q: cd, ci = heappop(q) if dist[ci] < cd: continue for vd, vi in G[ci]: nd = cd + v..
- Frontend 가이드 [FE] HTTP/2 - HyperText Transfer Protocol (Version 2) 을 자세히 알아보자 HTTP/2 - HyperText Transfer Protocol (Version 2) 을 자세히 알아보자 HTTP/2 는 HTTP/1.1 보다 성능을 개선한 프로토콜입니다. HTTP/2 는 성능 개선에 집중하여 개발되었으며, 성능을 개선시킬 수 있는 기능들이 추가되었습니다. 기능이 추가되었다 해서 HTTP/1.1 의 URL 이나 Method 와 Header 같은 의미와 연관된 부분은 달라지지 않았습니다. 기존에 사용하던 메서드 (GET, POST 등) 와 헤더 (Content-Type, Authorization 등) 는 HTTP/2 에서도 HTTP/1.1 과 동일하게 사용 가능합니다. HTTP/2 는 클라이언트와 서버 간에 데이터를 주고 받는 과정과 네트워크를 통해 전달할 데이터의 형태를 집중적으로 개..
- 코딩인터뷰 [코딩인터뷰] 2020 카카오 신입 공채 - 문자열 압축 import sys readline = sys.stdin.readline def solution(s): answer = len(s) for step in range(1, len(s)): compressed = '' prev = s[0:step] count = 1 for j in range(step, len(s), step): next = s[j:j+step] if prev == next: count += 1 else: compressed += str(count) + prev if count > 1 else prev prev = next count = 1 compressed += str(count) + prev if count > 1 else prev answer = min(answer, l..
- 코딩인터뷰 [코딩인터뷰] 2020 카카오 신입 공채 - 자물쇠와 열쇠 import sys readline = sys.stdin.readline def rotate(key): return list(list(x)[::-1] for x in zip(*key)) def check(N, M, board): for x in range(M-1, M+N-1): for y in range(M-1, M+N-1): if board[x][y] != 1: return False return True def solution(key, lock): M = len(key) N = len(lock) board = [[0] * ((M-1)+N+(M-1)) for _ in range((M-1)+N+(M-1))] for i in range(N): for j in range(N): board[M-1+i][M-1..
- Frontend 가이드 [FE] JavaScript 완벽 가이드, ECMAScript 를 읽는 방법 (2/2) JavaScript 완벽 가이드, ECMAScript 을 읽는 방법 저번 글 에서는 ECMAScript 를 읽기 위해 알아야 할 개념들을 소개했고, 이번 글에서는 ECMAScript 문서에서 자바스크립트 동작 원리를 파악하는 과정을 소개하도록 하겠습니다. const o1 = { foo: 99 }; const o2 = {}; Object.setPrototypeOf(o2, o1); o2.foo; // → 99 위 코드를 보면 Object.setPrototypeOf(o2, o1) 을 호출해서 o2 의 프로토타입을 o1 으로 설정했습니다. o2 의 프로토타입이 o1 이 되었기 때문에 o2 에 foo 라는 속성이 없어도 o2.foo 는 o1.foo 에 접근하여 값을 얻어 마지막 코드 o2.foo 의 결과가 o1...
- Frontend 가이드 [FE] JavaScript 완벽 가이드, ECMAScript 를 읽는 방법 (1/2) JavaScript 완벽 가이드, ECMAScript 을 읽는 방법 ECMAScript 는 완벽한 자바스크립트 가이드입니다. ECMAScript 가 자바스크립트 언어를 정의한 문서이며 표준이기 때문입니다. 모든 자바스크립트 엔진은 표준인 ECMAScript 에서 요구하는 사항은 반드시 구현해야 합니다. ECMAScript 를 읽고 싶어도 위 그림과 같이 특유의 단어와 문법으로 적혀 있어서 단순하게 읽을 수가 없습니다. 그래서 혹시 잘 정리한 문서가 있나 찾아봤지만 ECMAScript 에 추가된 새로운 기능을 소개하는 글만 있을 뿐, ECMAScript 를 구체적으로 설명하는 글을 찾을 수는 없었습니다. 그래서 제가 ECMAScript 을 읽다보니, 미리 알았으면 읽기 수월했을 개념들을 정리해서 글로 작성..
- Frontend 가이드 [FE] 브라우저 렌더링 Browser rendering - 5단계 변경 'change' 브라우저 렌더링 Browser rendering 브라우저는 'content (콘텐츠)' 를 'rendering (렌더링)' 해서 'pixel image(픽셀 이미지)' 즉 화면을 만듭니다. 브라우저 렌더링 Browser rendering - 0단계 소개 브라우저 렌더링 Browser rendering - 1단계 파싱 'parse' 브라우저 렌더링 Browser rendering - 2단계 스타일링 'style' 브라우저 렌더링 Browser rendering - 3단계 레이아웃 'layout' 브라우저 렌더링 Browser rendering - 4단계 페인팅 'paint' 브라우저 렌더링 Browser r..
- Frontend 가이드 [FE] 브라우저 렌더링 Browser rendering - 4단계 페인팅 'paint' 브라우저 렌더링 Browser rendering 브라우저는 'content (콘텐츠)' 를 'rendering (렌더링)' 해서 'pixel image(픽셀 이미지)' 즉 화면을 만듭니다. 브라우저 렌더링 Browser rendering - 0단계 소개 브라우저 렌더링 Browser rendering - 1단계 파싱 'parse' 브라우저 렌더링 Browser rendering - 2단계 스타일링 'style' 브라우저 렌더링 Browser rendering - 3단계 레이아웃 'layout' 브라우저 렌더링 Browser rendering - 4단계 페인팅 'paint' 브라우저 렌더링 Browser r..
- 코딩인터뷰 [코딩인터뷰] 백준 2110번 공유기 설치 너무 정확하게 문제를 풀려는 습관때문에 쉽게 풀 것도 어렵게 접근하게 되는 나쁜 버릇... import sys rl = sys.stdin.readline N, C = map(int, rl().split()) H = [] for _ in range(N): H.append(int(rl())) H.sort() answer = 0 # 가능한 최소 거리 lo = 1 # 가능한 최대 거리 hi = H[-1] - H[0] while lo = mid: pr = H[i] c += 1 # 설치해야 하는 공유기 수보다 적게 설치했다면, 최대 거리를 좁힌다. if c < C: hi = mid - 1 # 설치해야 하는 공유기 수보다 많이 설치했다면, 최대 거리를 늘린다. else: lo = mid + 1 # 지금 최대 거리를 ..
- 코딩인터뷰 [코딩인터뷰] 백준 10986번 나머지 합 수학적인 추론을 이끌어 내야 풀 수 있는 문제입니다. 'A(i) ~ A(j) = S(j) - S(i-1)' 가 Prefix Sum 의 기본 공식이고 나머지가 0 이어야 한다는 점에 착안해서 새로운 공식을 도출해야 합니다. 'A(1) ~ A(i) = K (K = 정수)' 이고 'A(1) ~ A(j) = K' 라면, 'A(i) ~ A(j) = 0' 이어야 합니다. 왜냐하면 i 부터 j 까지 합으로 인한 변화가 없어야 같은 K 가 나올 수 있기 때문입니다. 그리고 'A(i) ~ A(j) = 0' 이라면 양변에 나머지 연산을 해도 동일해서 '(A(i) ~ A(j)) % M = 0' 입니다. 이점에 착안해서 Prefix Sum ..
- 코딩인터뷰 [코딩인터뷰] 백준 13398번 연속합 2 import sys readline = sys.stdin.readline read = sys.stdin.read N = int(readline()) A = list(map(int, readline().split())) A.insert(0,0) answer = -(10**10) d = [[answer] * (N+1) for _ in range(2)] for k in range(1, N+1): # 일반적인 누적합을 계산하는 부분 # 'd[0][k-1] + A[k]' 는 이전 누적합 중 최대값과 현재 값을 더했을 경우 d[0][k] = max(d[0][k-1] + A[k], A[k]) # 'd[0][k-1]' 는 지금 A[k] 를 누적합 계산에서 제외할 경우 # 'd[1][..
- 코딩인터뷰 [코딩인터뷰] 백준 2616번 소형기관차 DP & 누적 합 처음엔 N 개 중 간격 M 을 두고 3 개를 뽑는 모든 경우의 수를 검토하는 방법으로 풀었더니 '시간 초과' 발생했고 이 글을 참고해서 다시 풀었습니다. 핵심 코드는 dp[x][y] = max(dp[x][y-1], dp[x-1][y-M] + (s[y] - s[y-M])) 로 매 계산마다 이전 최대값과 비교하기 때문에 마지막에 답이 나오게 됩니다. 코드를 바로 이해하기 어려워서 디버거 변수를 노트에 적어가며 해보다 보니 이해하게 되었고 아래 코드로 정답을 맞출 수 있었습니다. import sys readline = sys.stdin.readline read = sys.stdin.read N = int(readline()) T = [0] for t in map(int, rea..
- 코딩인터뷰 [코딩인터뷰] 백준 3020번 개똥벌레 Prefix Sum 누적 합 import sys N, H = map(int, input().split()) MAX = H + 2 top = [0] * MAX bottom = [0] * MAX for k in range(N): v = int(input()) if k % 2 == 1: bottom[v] += 1 else: top[v] += 1 total_top = [0] * MAX total_bottom = [0] * MAX for i in reversed(range(1, H+1)): total_bottom[i] = bottom[i] + total_bottom[i + 1] total_top[i] = top[i] + total_top[i + 1] mini = 200001 count = 1 total = [0]..
- 코딩인터뷰 [코딩인터뷰] 백준 16437번 16437번 양 구출 작전 문제는 "파이썬으로 풀지 말라는게 아닐까" 라는 느낌의 채점 기준이었습니다. 로직이 틀리지 않은거 같은데 왜 통과를 못하고 '메모리 초과' 가 뜰까 싶어서 C++ 정답 코드를 둘러봤는데 로직이 동일한 정답이 있었습니다. 그래서 '어? 환경설정 문젠가?' 싶어서 일단 C++ 정답으로 문제 정답 처리하고 파이썬으로 통과된 코드를 보고 환경설정을 좀 했더니 통과가 되었습니다. 정리하자면, 'PyPy 3' 로 제출하면 '메모리 초과' 가 발생합니다. 'Python 3' 로 제출하면 '시간 초과' 가 발생합니다. PyPy3 메모리 초과는 아무래도 BFS 방식으로 풀어야 해결할 수 있어 보이고, Pyth..
- Frontend 가이드 [FE] 브라우저 렌더링 Browser rendering - 3단계 레이아웃 'layout' 브라우저 렌더링 Browser rendering 브라우저는 'content (콘텐츠)' 를 'rendering (렌더링)' 해서 'pixel image(픽셀 이미지)' 즉 화면을 만듭니다. 브라우저 렌더링 Browser rendering - 0단계 소개 브라우저 렌더링 Browser rendering - 1단계 파싱 'parse' 브라우저 렌더링 Browser rendering - 2단계 스타일링 'style' 브라우저 렌더링 Browser rendering - 3단계 레이아웃 'layout' 브라우저 렌더링 Browser rendering - 4단계 페인팅 'paint' 브라우저 렌더링 Browser r..
- Frontend 가이드 [FE] 브라우저 렌더링 Browser rendering - 2단계 스타일링 'style' 브라우저 렌더링 Browser rendering 브라우저는 'content (콘텐츠)' 를 'rendering (렌더링)' 해서 'pixel image(픽셀 이미지)' 즉 화면을 만듭니다. 브라우저 렌더링 Browser rendering - 0단계 소개 브라우저 렌더링 Browser rendering - 1단계 파싱 'parse' 브라우저 렌더링 Browser rendering - 2단계 스타일링 'style' 브라우저 렌더링 Browser rendering - 3단계 레이아웃 'layout' 브라우저 렌더링 Browser rendering - 4단계 페인팅 'paint' 브라우저 렌더링 Browser r..
- Frontend 가이드 [FE] 브라우저 렌더링 Browser rendering - 1단계 파싱 'parse' 브라우저 렌더링 Browser rendering 브라우저는 'content (콘텐츠)' 를 'rendering (렌더링)' 해서 'pixel image(픽셀 이미지)' 즉 화면을 만듭니다. 브라우저 렌더링 Browser rendering - 0단계 소개 브라우저 렌더링 Browser rendering - 1단계 파싱 'parse' 브라우저 렌더링 Browser rendering - 2단계 스타일링 'style' 브라우저 렌더링 Browser rendering - 3단계 레이아웃 'layout' 브라우저 렌더링 Browser rendering - 4단계 페인팅 'paint' 브라우저 렌더링 Browser r..
- MAUI 가이드 [Xamarin] iOS SafeArea 자연스럽게 반영해주는 CustomEffect iOS SafeArea 자연스럽게 반영해주는 CustomEffect Android 기기와 달리 iOS 기기는 화면 상단에 위치하는 Status bar 가 Application 화면 크기에 포함되어 있어서 UI 를 만들 때 최상단에 위치한 View 의 Padding 에 20 을 추가해야 화면과 Status bar 가 겹치는 불상사를 피할 수 있습니다. 그래서 대체로 아래와 같이 iOS 에서만 따로 Padding 값을 적용하는 코드를 작성하게 됩니다. 기기를 회전하지 않으면 이대로 사용해도 문제가 없었는데, 만약 기기를 회전시키면 Status bar 의 위치가 달라지게 되니Padding 값도 회전에 맞춰서 다시 조정해야 합니다. 따라서 기기의 Orientation 의 변화를 감지해서 Padding 의 어느 ..
- Frontend 가이드 [FE] 브라우저 렌더링 Browser rendering - 0단계 소개 브라우저 렌더링 Browser rendering Rendering (렌더링) 은 여러 데이터를 모아 시각적인 이미지로 만드는 과정입니다. 브라우저는 HTML 과 CSS 같은 데이터를 '렌더링' 해서 픽셀로 구성된 화면을 완성합니다. 이를 브라우저 렌더링 (Browser rendering) 이라고 합니다. 이때 렌더링을 위한 데이터인 HTML / CSS / JavaScript / Media 등 일체를 통틀어서 'content (콘텐츠)' 라고 부릅니다. 브라우저는 'content (콘텐츠)' 를 'rendering (렌더링)' 해서 'pixel image(픽셀 이미지)' 즉 화면을 만듭니다. 웹 프론트 엔드 개발을 크게 보면 '..
- MAUI 가이드 [Xamarin] Renderer 를 만들었더니 BackgroundColor 가 적용되지 않을 때 해결하는 방법 Renderer 를 만들었더니 BackgroundColor 가 적용되지 않을 때 해결하는 방법 Xamarin 으로 개발하다가 특정 Layout 의 CustomRenderer 를 만들었더니 View.BackgroundColor 에 적용한 배경색이 사라지는 버그를 만났고, 해결 과정을 공유합니다. 해결방법은 의외로 간단했습니다. CustomRenderer를 ViewRenderer가 아닌 VisualElementRenderer 로 상속받아 아래와 같이 구현하면됩니다. [assembly: ExportRenderer(typeof(MyView), typeof(MyViewRenderer))] namespace Solution.iOS { public class MyViewRenderer : VisualElementRe..
- 코딩인터뷰 [코딩인터뷰] 백준 1987번 DFS import sys sys.setrecursionlimit(10 ** 5) # 세로 R 가로 C # 같은 알파벳 통과 불가 # (0,0) 포함 시작 def dfs(c, x, y): global answer if answer < c: answer = c for k in range(4): nx = x + dx[k] ny = y + dy[k] if 0
- 코딩인터뷰 [코딩인터뷰] 백준 10026번 BFS from collections import deque # R G B 적록 색약 시 R = G n = int(input()) pic = [] for _ in range(n): pic.append(list(input())) dx = [-1, 0, 1, 0] dy = [0, -1, 0, 1] v_a = [[False] * n for _ in range(n)] v_b = [[False] * n for _ in range(n)] c_a = 0 c_b = 0 for i in range(n): for j in range(n): if not v_a[i][j]: rgb_a = pic[i][j] q_a = deque() q_a.append((i, j)) v_a[i][j] = True c_a += 1 if not v..
- 코딩인터뷰 [코딩인터뷰] 백준 2468번 Python 으로 DFS 전략으로 풀면 'Recursion Error' 나고 '메모리 초과' 나고 난리납니다. 그래서 BFS 로 바꿔서 풀어야 합니다. 전에는 DFS 가능했는데 메모리가 줄었나 봅니다. BFS from collections import deque # 2
- 코딩인터뷰 [코딩인터뷰] 알고리즘 시간 복잡도 분석 방법 알고리즘 시간 복잡도 분석 방법 코딩 테스트는 시간 제한이 있습니다. 이미 구현한 전략이 제한된 실행 시간 안에 풀 수 없다는걸 깨닫고 다른 전략을 시도할 시간은 없습니다. 따라서 문제를 어떻게 풀까 고민하다 떠올린 아이디어가 실행 시간 안에 해결할 수 있는지를 가늠할 줄 알아야, 잘못된 구현을 하는 불상사를 피할 수 있습니다. 내가 구현할 알고리즘 전략이 주어진 실행 시간 안에 동작할 수 있는지를 간단하게라도 가늠할 줄 알아야 합니다. 일반적으로 10의 8승, 1억번 이상 의 연산 시간이 필요한 전략은 코딩 테스트 문제에 일반적으로 주어지는 '1초' 라는 제한된 실행 시간 안에 해결할 수 없습니다. 특히나 Python 는 타 언어에 비해 실행 시간이 더 걸리는 편이라 제한된 실행시간 안에..
- 코딩인터뷰 [코딩인터뷰] 깊이 우선 탐색 Depth first search (DFS) 깊이 우선 탐색 Depth first search (DFS) 깊이 우선 탐색 (DFS) 는 너비 우선 탐색과 함께 코딩 테스트 출제 빈도가 높은 전략입니다. DFS 는 그래프에서 A 노드를 방문하고, 방문한 A 노드와 연결된 B 노드를 방문하고, 방문한 B 노드와 연결된 C 노드를 방문하는 과정을 반복해서 그래프의 모든 노드를 방문합니다. 너비 우선 탐색과 달리 굉장히 직관적인 탐색 방법입니다. DFS 을 사용하여 그래프를 탐색할 때 무한 반복을 조심해야 합니다. 만약 그래프에 사이클이 있다면 무한히 탐색을 반복하게 됩니다. 따라서 이미 방문한 노드를 기록하고 탐색할 때 방문했는지 안했는지를 확인해야 무한 반복을 피할 수 있습니다. DFS 전략으로 푸는 대표적인 문제 유형 노드 사이 간 거리가 다른 최단..
- 코딩인터뷰 [코딩인터뷰] 백준 2638번 from collections import deque # 5
- 코딩인터뷰 [코딩인터뷰] 백준 2146번 from collections import deque import sys sys.setrecursionlimit(10000) def create_island(id, x, y): global sea, islands, iv, dx, dy sea[x][y] = id islands[id].append((x,y, 0)) iv[x][y] = True for i in range(4): nx = x + dx[i] ny = y + dy[i] if 0
- 코딩인터뷰 [코딩인터뷰] 백준 16236번 from collections import deque # 크면 못지나감. 같으면 지나감. 작아야 먹음 # 자기 크기만큼 먹어야 성장 n = int(input()) space = [] for _ in range(n): space.append(list(map(int, input().split()))) # 아기상어 처음 위치 shark_loc = (0, 0) for i in range(n): for j in range(n): if space[i][j] == 9: space[i][j] = 0 shark_loc = (i, j) # 아기 상어 처음 크기 shark_level = 2 shark_eat_count = 0 # 시간 time = 0 # 이동 dx = [-1, 0, 1, 0] dy = [0, -1, 0, 1..
- 코딩인터뷰 [코딩인터뷰] 백준 14502번 백준 14502번 연구소 문제는가능한 경우의 수가 많지 않습니다. 그래서 무식하게 벽을 세울 수 있는 모든 경우의 수를 검토해도 시간 안에 풀 수 있습니다. 만약 이게 문제가 아니었다면 바이러스를 기준으로 탐색해서 벽을 더 효율적인 세울 수 있는 방법을 찾아보고 싶네요. from copy import deepcopy from collections import deque def virus(): global n, m, maps, answer, viruses, dx, dy c_maps = deepcopy(maps) for v in viruses: q = deque() q.append(v) visited = [[False] * m for _ in range(n)] while 0 < len(q): c = q.po..
- 코딩인터뷰 [코딩인터뷰] 너비 우선 탐색 Breadth first search (BFS) 너비 우선 탐색 Breadth first search (BFS) 너비 우선 탐색 (BFS) 는 코딩 테스트 출제 빈도가 높은 전략입니다. 그래서 반드시 알고 있어야 하고 문제에 활용 가능할지 판단할 수 있어야 합니다. BFS 는 이름 그대로 너비를 우선하여 탐색하는 전략입니다. 그래프에서 각 노드를 방문하면서 방문한 노드와 연결된 노드들을 큐에 추가하고 빼면서 각 노드를 한 번씩 탐색하게 됩니다. 각 탐색을 진행하면서 문제가 요구하는 정답 찾아 가게 됩니다. BFS 는 전략 특성상 '노드 방문 여부'를 체크하지 않으면 무한 반복에 빠질 위험이 있습니다. 따라서 BFS 로 문제를 풀 때는 노드의 방문 여부를 체크하는 코드가 반드시 필요합니다. BFS 전략으로 푸는 대표적인 문제 유형 노드 사..
- 코딩인터뷰 [코딩인터뷰] 백준 15686번 def set_min(chicken): global n global city global answer total = 0 for i in range(n): for j in range(n): if city[i][j] == 1: dists = [] for c in chicken: dists.append(abs(c[0] - i) + abs(c[1] - j)) total += min(dists) if total < answer: answer = total def dfs(chicken, x, y): global n global m global city if len(chicken) == m: set_min(chicken) return for i in range(x, n): t = 0 if x != i else y f..
- 코딩인터뷰 [코딩인터뷰] 백준 15684번 def is_completed(): global n global h global ladder for b in range(n): s = b for a in range(h): if 0 < s and ladder[a][s-1]: s -= 1 continue if ladder[a][s]: s += 1 continue if s != b: return False return True def dfs(count, a, b): global n global h global ladder global answer if is_completed(): if count < answer: answer = count return if count == 3: return # 현재 b = 세로선부터 마지막 바로 전 세로선까지만 # i = 세..
- 코딩인터뷰 [코딩인터뷰] 백트래킹 Back tracking 백트래킹 Back tracking 백트래킹 (Back tracking)은 문제 해결 전략 중 하나로, 가능한 모든 경우의 수를 탐색하는 전략인 브루트 포스(Brute force) 전략에서 특정 조건을 만족하지 못하는 경우의 수들을 탐색 범위에서 제외시키며 탐색하는 전략입니다. 브루트 포스 전략은 모든 경우의 수를 전부 탐색하지만 백트래킹 전략은 특정 조건을 만족하지 못하는 경우의 수를 탐색에서 제외하기 때문에 브루트 포스 전략보다 탐색 효율이 좋습니다. 백트래킹 전략은 재귀적으로 조건을 만족하는지 검토하면서 정답을 완성합니다. 정답을 완성하는 과정 중 조건을 만족하지 못하는 경우의 수와 관련된 경우의 수들을 탐색 범위에서 제외시킵니다. 첫 정답이 완성되면 전 상태로 되돌리고 다른 가능한 경우의 수를 탐색..
- 코딩인터뷰 [코딩인터뷰] 백준 14888번 Python3 는 시간초과 가 발생합니다. itertools.permutations 함수가 시간이 오래 걸리기 때문입니다. PyPy3 로 변경하면 통과됩니다. 저는 개인적으로 알고리즘 효율성에 큰 의미를 두지는 않습니다. 효율성이 중요하지 않다는건 아닌데, 실무를 하다보니 주어진 개발 기간을 코드의 효율을 개선하는데 투자하기 보다는 전체 설계를 개선할 수 있는 코드 또는 가독성이 좋아지는 코드를 짜는데 시간을 투자하는게 생산성이 더 높다고 생각합니다. 기간 내에 정확하게 개발해서 출시한 뒤에 효율이 크게 뒤떨어지는 부분부터 제품을 개선해 나가는 재미도 있으니까요. 당연히 효율 높은 코드를 바로바로 구현할 수 있도록 훈련을 지속적으로 하면 생산성과 효율 모두 달성할 수 있으니, 코딩 테스트로 연습할 때는 ..
- 코딩인터뷰 [코딩인터뷰] 백준 14889번 import itertools n = int(input()) score_board = [] for _ in range(n): score_board.append(list(map(lambda i:int(i), input().split()))) team = range(n) min_dist = 10**8 for selected in itertools.combinations(team, n//2): start_team = selected link_team = [] for k in range(n): if k not in selected: link_team.append(k) start_team_score = 0 link_team_score = 0 for m in itertools.combinations(start_te..
- 코딩인터뷰 [코딩인터뷰] 백준 9663번 def solve(n, location, column): c = 0 if column == n: return 1 for row in range(n): if is_possible(n, location, column, row): location.append((column, row)) c += solve(n, location, column + 1) location.pop() return c def is_possible(n, location, column, row): for loc in location: if loc[0] == column: return False if loc[1] == row: return False for k in range(1, min(n - loc[0], n - loc[1])): if c..
- 코딩인터뷰 [코딩인터뷰] 백준 2661번 def is_possible(l): for d in range(1, len(l) // 2 + 1): for s in range(len(l) - (d*2) + 1): a_start = s a_end = s + d a = l[a_start:a_end] b_start = a_end b_end = a_end + d if b_end > len(l): break b = l[b_start:b_end] if a == b: return False return True n = int(input()) l = [] value = (1, 2, 3) pos = [[True, True, True] for _ in range(n)] while len(l) < n: i = len(l) is_appended = False for v i..
- 코딩인터뷰 [코딩인터뷰] 트라이 자료 구조 Trie data structure 트라이 자료 구조 Trie data structure 문자열 검색에 특화된 트리 자료 구조 트라이 자료 구조는 기본적으로 트리 형태로 구성되는데, 언어의 문자가 제한되어 있다는 특징을 활용한 자료 구조입니다. 트라이 자료 구조는 아래 그림과 같이, 단어를 문자의 형태와 순서를 기준으로 트리를 구성하는 자료구조입니다. 예를 들어, tea 라는 단어를 트라이 자료 구조에 추가하게 되면 root 노드부터 시작해서 t, e, a 순서로 트리에 추가합니다. 이렇게 여러 단어가 추가된 트라이 자료 구조에서 tea 로 시작하는 단어를 찾는다면, 모든 단어를 하나 하나 첫 문자부터 비교하며 검색할 필요없이 트라이 자료 구조의 tea 노드의 자식 노드만 탐색하면 됩니다. 특히 영어의 알파벳은 한글과 달리 문자가 나열되는..
- Frontend 가이드 [React] 조건부 렌더링 패턴 Conditional Rendering Pattern 조건부 렌더링 패턴 Conditional Rendering Pattern 리액트의 조건부 렌더링 문서에서 조건에 따라 랜더링할 컴포넌트를 선택하는 방법을 소개하고 있지만 추가적으로 알아두면 유용한 best practices 패턴이 몇 가지 더 있어서, 하나씩 소개드리도록 하겠습니다. 소개드릴 패턴 목록입니다. if else 패턴 : ? 패턴 && 패턴 switch case 패턴 enum 패턴 HOC 패턴 if else 패턴 리액트 공식 문서에서 소개하는 가장 기본적인 패턴입니다. function Greeting(props) { const isLoggedIn = props.isLoggedIn; if (isLoggedIn) { return ; } else { return ; } } if 문 조건에 따라 Us..
- MAUI 가이드 [Xamarin] View 안에 View 를 주입할 수 있는 View 를 작성해보자 View 안에 View 를 주입할 수 있는 View 를 작성해보자 View 안에 여러 View 를 주입하고 속성에 따라 교체하는 ContainerView 를 구현하거나, NavigationBar 의 크기와 모양만 잡아두고 Button 을 추가하는 등 활용하는 방법이 많으니 알아두시면 유용합니다. 예제 코드 ContainerView // ContentView.Content 를 Views 속성으로 연결하는 Attribute [ContentProperty(nameof(Views))] public class ContainerView : ContentView { // 주입된 View 를 배치하는게 사용할 Layout private StackLayout _layout; // 외부에서 주입할 View 를 저장할 자료..
- MAUI 가이드 [Xamarin] BindableProperty 를 Override 해보자 BindableProperty 를 Override 해보자 Xamarin 으로 View 를 개발하다보면 재활용성을 높이기 위해 기존의 View 를 상속받아서 개발하게 됩니다. 특히 특정 스타일의 View 를 반복적으로 사용할 때 아래와 같이 작성하게 됩니다. public class MyFrame : Frame { private readonly Label _title; public string Title { set => _title.Text = value; } public MyFrame() { BackgroundColor = Color.LightPink; _title = new Label { TextColor = Color.Black, FontSize = 16, }; Content = _title; } } ..
- MAUI 가이드 [Xamarin] Item 이 Layout 에 따라 자동으로 배치되도록 해보자 Item 이 Layout 에 따라 자동으로 배치되도록 해보자 ItemsView 개발 배경 ListView 나 CollectionView 는 Xamarin 팀에서 제공하는 Layout 만 사용해야 하는 단점이 있습니다. 저는 이를 극복해보고자 CollectionView.ItemsLayout 에 저만의 레이아웃을 추가해보려고 했지만 실패했고, Custom Layout 을 활용해서 Item 을 배치할 수 있는ItemsView를 만들게 되었습니다. 글 순서는 프로젝트에 바로 사용하실 수 있도록 배치했습니다. 소스코드 활용방법 설명 ItemsView 소스코드 [ContentProperty(nameof(ItemsLayout))] public abstract class ItemsView : ContentView, I..
- MAUI 가이드 [Xamarin] 화면 크기에 따라 변화하는 ResponsiveLayout 을 만들어 보자 화면 크기에 따라 변화하는 ResponsiveLayout 을 만들어 보자 먼저 이 글의 목적은 두 가지입니다. 먼저 공식 문서의 엉성한 번역으로 고생하시는 개발자 분들에게 친절한 설명을 제공하는게 목적입니다. 그리고 추가적으로 이 글 이후에 작성할 ItemsView 에 대한 글을 이해하기 위한 기초 지식을 제공하고자 합니다. Layout 을 직접 구현해야 할까? Xamarin 에서 기본적을 제공하는 Layout 은 아래와 같이 5 가지가 제공됩니다. 각 Layout 마다 특징도 다르고 앱을 만들 때 5 가지 이외 레이아웃이 필요한 상황도 드물기 때문에, Layout 을 직접 구현하게 되는건 드뭅니다. 하지만 Layout 구현에 대한 기초적인 지식을 가지고 있으면 View 의 크기와 배치가 어떻게 결정되는..
- MAUI 가이드 [Xamarin] BindableProperty 구현하고 관리하는 방법 BindableProperty 구현하고 관리하는 방법 마이크로소프트 공식 문서 에서 BindableProperty 를 구현하는 방법을 소개하고 있습니다. 다만 아쉽게도 공식문서엔 BindalbeProperty 코드를 재사용하거나 관리하는 측면에 대한 디테일한 설명이 없어서 글을 작성하게 되었습니다. 먼저 공식 문서대로 하면 BindableProperty 는 기본적으로 아래와 같이 구현하게 됩니다. public class MyContentView : ContentView { public static readonly BindableProperty NameProperty = BindableProperty.Create ("Name", typeof(string), typeof(MyContentView), null..
- 재경관리사 [재경관리사] 세무회계 - 세법적용의 원칙 세무회계 - 세법적용의 원칙 세법적용의 원칙 은 국가가 세법을 해석하고 적용하여 세금을 부과하는 과정 중 국민 모두가 평등하게 대우받으며, 세법의 목적에 맞춰 세금을 징수하고, 국가로부터 납세자인 국민의 재산권이 부당하게 침해되지 않도록 하기 위한 원칙입니다. 세법적용의 원칙과 관련한 법률은 '국세기본법 제2절 세법 적용의 원칙' 중 '제18조(세법 해석의 기준 및 소급과세의 금지)' 와 '제19조(세무공무원의 재량의 한계)', '제20조(기업회계의 존중)' 에 근거하고 있습니다. 국세부과의 원칙 과 함께 재경관리사 시험 세무회계 41번 문제로 출제됩니다. 하지만 국세부과의 원칙의 출제 비중이 더 높은 편이라, 세법적용의 원칙이 출제되는 비중은 낮..
- 재경관리사 [재경관리사] 세무회계 - 국세부과의 원칙 세무회계 - 국세부과의 원칙 국세부과의 원칙 이란 국민에게 세금을 부과하는 과정에 있어서 지켜야 할 원칙들을 말합니다. 국세청은 정부 기관이고 법에 따라 세금을 징수해야 합니다. 그래서 우리나라의 국세기본법 제14조(실질과세), 제15조(신의 성실), 제16조(근거과세), 제17조(조세감면의 사후관리) 를 따라야만 합니다. 재경관리사 시험의 세무 회계 과목에서도 반드시 다루는 부분이지만 기출 문제의 난이도가 쉬워 개념만 익힌다면 쉽게 맞출 수 있습니다. 그리고 세금에 대한 기본이 되는 개념이기 때문에 알아두어야 합니다. 실질과세의 원칙 실질과세의 원칙 이란 세금이 부과되는 행위인 주식의 배당을 받거나, 은행 이자를 받거나, 월급을 받는 등의 행위를 한 당사자에게 세금을 부과한다는 원칙입니다. 이 원칙이 ..
- MAUI 가이드 [Xamarin] Effects 로 Platform-Specific 하게 구현하기 Effects 로 Platform-Specific 하게 구현하기 Xamarin 에서 UI 를 플랫폼 별로 커스터마징할 때는 Effect 와 Custom Renderer 을 사용합니다. 이 글에서는 Effect 를 사용하는 방법을 설명하겠습니다. Effect Effect 는 Custom Renderer 을 단순하게 구현하는 방법이라고 이해하시면 됩니다. Effect 를 구현하는 순서는 아래와 같습니다. 지원하고자 하는 플랫폼 프로젝트마다 PlatformEffect 를 상속받는 클래스를 만듭니다. PlatformEffect 를 상속받은 클래스의 OnAttached, OnDetached 메서드를 오버라이딩합니다. ResolutionGroupName 속성과 ExportEffect 속성을 등록합니다. 공통 프로젝..
- Backend 가이드 [Spring] HTTP Request 를 처리하는 과정 - DispatcherServlet 원리 먼저 이 글은 Spring Web MVC 에 해당되며, Spring WebFlux 는 다른 글을 참고하시길 바랍니다. HTTP Request 를 처리하는 과정 - DispatcherServlet 원리 Spring Web MVC 에서 HTTP Request 를 처리하는 핵심 클래스가 DispatcherServlet 이란 클래스입니다. DispatcherServlet 가 무엇인지 알아야 Spring Web MVC 서버가 어떻게 동작하는지를 알 수 있습니다. 클래스 이름 중 Servlet 단어가 클래스가 어떤 역할을 하는지 설명하는 핵심적인 단어입니다. 왜냐하면 Spring Web MVC 는 Servlet API (javax.servlet) 를 기반으로 만들어진 프레임워크이기 때문입니다. Servlet 일반적..
- MAUI 가이드 [Xamarin] Custom Renderer 로 Platform-Specific 하게 구현하기 Custom Renderer 사용자 지정 렌더러 Renderer 는 Xamarin Forms 로 정의된 뷰를 플랫폼이 제공해주는 컨드롤과 연결하는 역할을 합니다. 예를 들어 Xamarin Forms 의 Entry 는 프레임워크가 기본으로 제공해주는 플랫폼 별 EntryRenderer 를 통해 플랫폼 별 컨트롤로 연결됩니다. 예를 들어, 안드로이드의 EntryRenderer 는 안드로이드 플랫폼의 EditText 컨트롤과 연결하고, iOS의 EntryRenderer는 iOS 플랫폼의 UITextField 컨트롤과 연결합니다. Xamarin Forms 가 기본으로 제공해주는 UI 요소는 모두 Xamarin 개발팀에서 제공해주는 기본 Renderer 가 있습니다. 하지만 어플리케이션을 개발하다보면 가끔 Ren..
- Backend 가이드 [Spring] RDB 에서 계층적인 데이터 구조 관리 전략 - Nested set 관계형 데이터베이스에서 계층적인 데이터 구조 관리 관계형 데이터베이스 (RDB) 는 계층적인 데이터 구조를 표현하기에 적합하지 않은 관계형 모델을 기초로 설계되어 있습니다. 반면에 관계형 데이터베이스를 활용하는 서버는 주로 객체지향 언어로 작성되며 내부적으로 이진트리와 같은 계층적인 데이터 구조를 자주 활용합니다. 따라서 서버에서 그래프 구조의 데이터를 계층적인 데이터 구조 관리에 적합하지 않은 관계형 데이터베이스에 어떻게든 저장하려면 아래와 같은 전략이 필요합니다. 관계형 데이터베이스에 그래프를 표현하는 전략 4 가지 Adjacency list Nested set Path enumeration Closure table 계층적인 데이터 구조를 관계형 데이터베이스에 저장하게 되면 서버가 데이터베이스의 무결..
- Backend 가이드 [Spring] RDB 에서 계층적인 데이터 구조 관리 전략 - Path enumeration 관계형 데이터베이스에서 계층적인 데이터 구조 관리 관계형 데이터베이스 (RDB) 는 계층적인 데이터 구조를 표현하기에 적합하지 않은 관계형 모델을 기초로 설계되어 있습니다. 반면에 관계형 데이터베이스를 활용하는 서버는 주로 객체지향 언어로 작성되며 내부적으로 이진트리와 같은 계층적인 데이터 구조를 자주 활용합니다. 따라서 서버에서 그래프 구조의 데이터를 계층적인 데이터 구조 관리에 적합하지 않은 관계형 데이터베이스에 어떻게든 저장하려면 아래와 같은 전략이 필요합니다. 관계형 데이터베이스에 그래프를 표현하는 전략 4 가지 Adjacency list Nested set Path enumeration Closure table 계층적인 데이터 구조를 관계형 데이터베이스에 저장하게 되면 서버가 데이터베이스의 무결..
- Backend 가이드 [Spring] RDB 에서 계층적인 데이터 구조 관리 전략 - Closure table 관계형 데이터베이스에서 계층적인 데이터 구조 관리 관계형 데이터베이스 (RDB) 는 계층적인 데이터 구조를 표현하기에 적합하지 않은 관계형 모델을 기초로 설계되어 있습니다. 반면에 관계형 데이터베이스를 활용하는 서버는 주로 객체지향 언어로 작성되며 내부적으로 이진트리와 같은 계층적인 데이터 구조를 자주 활용합니다. 따라서 서버에서 그래프 구조의 데이터를 계층적인 데이터 구조 관리에 적합하지 않은 관계형 데이터베이스에 어떻게든 저장하려면 아래와 같은 전략이 필요합니다. 관계형 데이터베이스에 그래프를 표현하는 전략 4 가지 Adjacency list Path enumeration Nested set Closure table 계층적인 데이터 구조를 관계형 데이터베이스에 저장하게 되면 서버가 데이터베이스의 무결..
- Backend 가이드 [Spring] RDB 에서 계층적인 데이터 구조 관리 전략 - Adjacency list 관계형 데이터베이스에서 계층적인 데이터 구조 관리 관계형 데이터베이스 (RDB) 는 계층적인 데이터 구조를 표현하기에 적합하지 않은 관계형 모델을 기초로 설계되어 있습니다. 반면에 관계형 데이터베이스를 활용하는 서버는 주로 객체지향 언어로 작성되며 내부적으로 이진트리와 같은 계층적인 데이터 구조를 자주 활용합니다. 따라서 서버에서 그래프 구조의 데이터를 계층적인 데이터 구조 관리에 적합하지 않은 관계형 데이터베이스에 어떻게든 저장하려면 아래와 같은 전략이 필요합니다. 관계형 데이터베이스에 그래프를 표현하는 전략 4 가지 Adjacency list Nested set Path enumeration Closure table 계층적인 데이터 구조를 관계형 데이터베이스에 저장하게 되면 서버가 데이터베이스의 무결..
- .NET 가이드 [C#] 예외처리 Best Practices 예외처리 Best Practices 1. 리소스를 사용하다가 오류가 발생했을 때 finally 를 활용하자. IDisposable 인터페이스를 구현한 리소스를 사용하다가 오류가 발생했을 때 오류만 잡고 리소스를 해제하는 걸 깜빡하는 경우가 자주 있습니다. 리소스를 사용하다가 오류가 발생할 만한 부분에 finally 문을 정의하고 리소스를 Dispose() 하여 메모리가 누수되지 않도록 합시다. try { var resource = new Resource(); } finally { resource.Dispose(); } 2. 예외를 발생시킬 때와 방지해야 할 때는 발생 빈도로 결정하자. 예외를 반드시 try/catch 문으로 해결할 필요는 없습니다. 예외의 발생 빈도가 높다면 예외가 발생하지 않도록 미연에..
- 단독주택 집짓기 건축주를 위한 건축 토막 상식 - 설계도서 건축주를 위한 건축 토막 상식 건축주가 알아두면 건축가나 시공사와 대화할 때 도움이 될 만한 토막 상식을 끄적여 봤습니다. 읽으시면서 반드시 유의하실 점은 저는 소프트웨어 개발자입니다. 따라서 건축과 일체 관련있는 업무를 해본 적이 없습니다. 따라서 아래 내용은 인터넷과 도서, 잡지 등에서 얻은 단편 정보를 제 임의대로 해석한 내용이니, 참고만 해주시길 바랍니다. 설계도서 건축물을 완성하기 위해 필요한 모든 설계 문서들 설계도서는 단독주택의 디자인과 품질을 정하는 문서입니다. 설계도서는 시공의 품질과 공사비 산정의 기준이 됩니다. 따라서 단독주택을 설계할 때도 당연히 설계도서를 작성해야 합니다. 정말 중요한 문서이기 때문에 국토교통부 건축정책과 (044-201-3763) 에서 행정규칙으로 건축물의 설계도..
- MAUI 가이드 [Xamarin] 픽셀 및 기기 독립 Unit (Device-Independent Units) 픽셀 및 기기 독립 Unit Xamarin 은 크로스 플랫폼, 더 나아가 모든 플랫폼을 지원하려는 야망을 가진 프레임워크입니다. 따라서 기기마다 다른 Unit 기준을 충족시켜야만 합니다. 개발자에게는 이게 무슨 소린지 감이 잡히질 않습니다. 왜냐하면 개발자는 디지털 단위인 픽셀 에 익숙해져 있기 때문입니다. 개발자에게 화면이란 픽셀로 이루어져 있는 장치이며, 픽셀만 맞추면 화면에 잘 표시될 것 같은 헛된 믿음을 가집니다. 하지만 디자이너에게 중요한건 실제 화면에 표현되는 물리적인 비율이 중요합니다. 픽셀만 맞춰서 개발을 하게 되면 화면에 따라 크기가 달라 보입니다! 특히 스마트폰의 화면 크기는 모두 제각각입니다. 심지어 화면마다 표현할 수 있는 픽셀 수도 기기마다 다릅니다. 간단한 실험으로 픽셀을 믿을 ..
- MAUI 가이드 [Xamarin] 성능 개선 - OneTime Binding 성능 개선 - OneTime Binding Compiled Binding 보다 성능을 더 끌어올릴 수 있는 바인딩 방식으로 OneTime Binding 이 있습니다. 이름에서 알 수 있듯이, 최초에 BindingContext가 바뀔 때만 값이 바인딩되고 INotifyPropertyChanged 이벤트를 구독하지 않는 방식입니다. 따라서 이벤트를 구독하고 처리하는 과정이 없어지므로 성능이 개선되는 원리입니다. OneTime Binding 방식이 도움이 되는 때는 UI가 처음 생성될 때만 바인딩하고 이후로는 값이 변경되지 않을 때입니다.OneTime Binding이 유용할 수 있는 사례를 아래에 소개드리도록 하겠습니다. Command를 바인딩할 때 Command 같은 경우 메서드를 바인딩하는데, 런타임에 메..
- MAUI 가이드 [.NET] .NET 통합과 MAUI 란? .NET MAUI 란? .NET MAUI 에 앞서, 마이크로소프트가 .NET 5 에 왜 이렇게 공을 들이는지를 이해하셔야 합니다. .NET 5 는 현재 플랫폼 별로 파편화되어 있는 프레임워크들을 통합하기 위한 노력의 산물입니다. 현재 프레임워크는 크게 플랫폼 별로 아래와 같이 나뉘어 있습니다. 이렇게 파편화된 프레임워크로 인해 지원하는 기능이 프레임워크 별로 달라지기도 하고, 공통으로 사용하고 싶은 기능이 있으면 각 프레임워크마다 지원하는지 확인해야 하는 등의 문제가 끊이지 않았습니다. 그래서 나름 임시 방편으로 제공한 프레임워크가 .NET Standard 프레임워크입니다. 이러한 상황에서 2019년 05월 06일 마이크로소프트 블로그에 .NET 5 를 소개하는 글이 올라오면서 다음과 같이 파편화된 프레..
- MAUI 가이드 [Xamarin] ResourceDictionary 깔끔하게 정리 ResourceDictionary 깔끔하게 정리 아래처럼 View 마다 ResourceDictionary가 있을 경우, 중복되는 XAML 코드도 발생하게 되고 같은 객체를 중복하여 생성하게 되므로, 비효율적입니다. ContentViewA.xaml #FFFFFF 따라서 먼저 아래처럼 ResouceDictionary를 분리된 파일로 만듭니다. ContentViewA.xaml ResourceDictionary.xaml #FFFFFF 하지만 ResourceDictionary.xaml 처럼 모든 리소스를 한 곳에서 관리하게 되면 불필요한 리소스까지 공유하게 되는 문제가 있습니다. 따라서 아래처럼 리소스를 자신만의 기준에 맞춰 분리하도록 합니다. ContentViewA.xaml ResourceDictionary.x..
- MAUI 가이드 [Xamarin] 성능 개선 - Compiled Binding 성능 개선 - Compiled Binding Xamarin 의 핵심 아키텍처는 Model-View-ViewModel 패턴입니다. 따라서 View 와 ViewModel 을 연결할 때 Data Binding을 집중적으로 사용하게 됩니다. 그리고 Data Binding은 View의 속성과 ViewModel의 속성을 연결하고 연결된 속성을 해석하기 위해 Reflection 기술을 사용하는데, Reflection 기술은 런타임에 많은 리소스를 소비합니다. 따라서 컴파일할 때 바인딩될 속성 타입을 명시해서 성능을 개선할 수 있습니다. 이를 Compiled Binding 이라 합니다. Compiled Binding 를 진행하기 위해선 XAML 코드가 컴파일 되어야 합니다. 이 글을 따라 XAML 코드가 컴파일되도록 ..
- MAUI 가이드 [Xamarin] 성능 개선 - XAML 컴파일 성능 개선 - XAML 컴파일 XAML 코드는 View 의 디자인을 위해 사용하는 마크업 언어라, 컴파일하여 배포하는 언어가 아닙니다. 그래서 Xamarin 앱을 배포하면 XAML 코드는 .xaml 파일 그대로 배포되고, 런타임에 동적으로 해석해서 View 를 만듭니다. 개발자 입장에서 런타임에 동적으로 XAML 코드를 해석하는건 Hot Reload 같이 디버깅을 하는 경우를 제외하고는 성능을 희생해서 얻는 메리트가 없습니다. 따라서 XAML 코드를 CLR 이 해석할 수 있는 IL (Intermediate Language) 코드로 변환하도록 설정하여 간단하게 성능을 개선하여 봅시다. Assembly 단위로 XAML 코드를 컴파일하도록 설정 [assembly: XamlCompilation (XamlComp..
- MAUI 가이드 [Xamarin] TypedDataTemplateSelector TypedDataTempalteSelector WPF 프로그램을 개발하면 ItemsControl.ItemTemplate 에 DataTemplate 을 등록해서 ItemsControl.ItemSource 에 ViewModel 이 추가될 때마다 ViewModel 타입에 맞는 View가 추가되는데, Xamarin 는 WPF 처럼 DataTemplate.DataType을 지원하지 않아 반드시 DataTemplateSelector를 사용해야만 합니다. 문제는 DataTemplateSelector 를 ViewModel 타입에 따라 선택하게 구현하려면 아래와 같이 클린하지 않은 코드를 만들 수 밖에 없습니다. public class MyDataTemplateSelector : DataTemplateSelector {..
- Frontend 가이드 [React] 이벤트 이벤트 합성 이벤트 (SyntheticEvent) 브라우저마다 이벤트 이름부터 시작해서 이벤트 종류나 이벤트가 처리되는 방식이 다릅니다. 이를 동일하게 처리하기 위해 React 는 Synthetic 이벤트로 브라우저마다 다른 Native 이벤트를 묶어서 처리합니다. 따라서 React 개발자는 브라우저마다 다른 Native 이벤트를 신경쓰지 않고, React 가 제공하는 이벤트만 신경쓰면 됩니다.f React 이벤트는 합성 이벤트라서, false 를 반환하더라도 이벤트 전파가 멈추지 않습니다. 반드시 e.stopPropagation() 또는 e.preventDefault() 를 호출해야 합니다. 이벤트 등록하기 React JSX 에서 이벤트를 등록할 때 조심해야 하는건 일반적인 HTML에서 이벤트를 등록하..
- Frontend 가이드 [React] Lifecycle 이벤트 Lifecycle 이벤트 React 컴포넌트는 Lifecycle 을 가지고 있으며, 발생한 이벤트에 따라 정해진 순서로 특정 메서드들을 실행합니다. 이벤트에 따라 발생하는 함수의 순서를 알고 있어야 어떤 순서에 어떤 코드를 실행시켜야 할지 판단할 수 있고, 실행 결과를 예측할 수 있습니다. 여기서는 React 16.13.0 버전 이후 Lifecycle 만 설명드리도록 하겠습니다. React 팀에서 Async Rendering 을 위해 Lifecycle 설계를 변경하기로 결정하였으며, 17.0 버전 이후로는 componentWillMount 메서드와 componentWillReceiveProps 메서드, 그리고 componentWillUpdate 함수가 지원되지 않습니다. Lifecycle 지도 그림 출처..
- Frontend 가이드 [React] Stateful 컴포넌트보다 Stateless 컴포넌트로 작성하자 React에서 컴포넌트(Component) 란? React는 아래와 같이 컴포넌트(Component)를 만들고, 컴포넌트를 조합해서 UI를 구현합니다. class Welcome extends React.Component { render() { return Hello, {this.props.name}; } } Sateful 컴포넌트와 Stateless 컴포넌트 위와 같이 작성하는 React 컴포넌트 중 state 를 사용하는 경우를 Stateful 컴포넌트라 하고, state 를 사용하지 않는 컴포넌트를 Stateless 컴포넌트 라 합니다. 만약 state를 사용하지 않는 Stateless 컴포넌트로 작성할 수 있다면 최대한 state를 사용하지 않도록 컴포넌트를 구현해야 이해하기 쉽습니다. 이해하기 쉬..
- 재경관리사 [재경관리사] 개발자가 독학으로 재경관리사 합격한 이야기 개발자가 독학으로 재경관리사 합격한 이야기 한마디로, 정말 힘들었습니다... 일단 합격은 했는데, 제 점수가 높은 편은 아닙니다. 재경관리사는 3 과목을 보며 재무회계, 세무회계, 원가관리회계 입니다. 합격은 모든 과목에서 70점 이상의 점수를 받아야 합격할 수 있으며, 평균 점수는 합격 여부와 상관이 없습니다. 저는 재무회계 77.5점, 세무회계 75점, 원가관리회계 95점을 받아 합격하였습니다. 재경관리사를 보기 전에, 저는 전산회계 1급을 취득했던 경험이 있습니다. 이외에 회계와 관련된 경험은 투자와 관련한 책을 읽다가 재무제표에 흥미가 생겨 도서관에서 책을 읽어 본 정도입니다. 취득한 연도는 2019년으로 제가 군복무를 하면서, 컴퓨터 과학 독학사와 정보처리기사를 준비하면서 재경관리사 공부를 병행..
- .NET 가이드 [C#] 리플렉션 Reflection (4) : 복잡한 if 문 대신 리플렉션으로 생성 함수 호출하기 복잡한 if 문 대신 리플렉션으로 객체 생성하기 프로젝트를 진행하면서 아래 예제 코드와 같이 형타입에 따라 다른 객체를 생성해야 하는 경우가 있었습니다. if( data is DataTypeA a) { var model = new DataModelA(a); list.Add(model); } else if( data is DataTypeB b) { var model = new DataModelB(b); list.Add(model); } // 엄청 긴 if 문~ 위 예제 코드와 같은 구조로 개발을 하게 되면 데이터 타입이 추가될 때마다, if 문은 계속 길어질 수 밖에 없고 데이터 타입에 따라 DataModel을 생성하는 논리가 달라지면서 if 문 내부도 복잡해져갔습니다. 이러한 구조로 인해 점점 코드는 더..
- .NET 가이드 [C#] 리플렉션 Reflection (3) : PropertyDescriptor.SetValue에 TypeConverter 로 데이터 형변환하기 PropertyDescriptor.SetValue에 TypeConverter 활용하기 리플렉션 Reflection (2) : 타입에 따라 동적으로 객체 생성하기 글에서 TagFactory를 통해 Tag 클래스에 속성 값을 입력할 때, XML 파일의 string을 읽어 string으로 객체에 저장하기 때문에 형변환 문제가 발생하지는 않았습니다. 기본 데이터 타입으로 변환할 때는 문제가 발생하지 않았지만, 만약 개발자가 정의한 클래스로 저장해야 한다면 문제가 발생하게 됩니다. 이러한 데이터 변환 문제를 해결하는 방법을 알려드리도록 하겠습니다. propertyDescriptor.SetValue(tag, propertyDescriptor.Converter.ConvertFromInvariantString(attr..
- .NET 가이드 [C#] 리플렉션 Reflection (2) : 타입에 따라 동적으로 객체 생성하기 타입에 따라 동적으로 객체 생성하기 바로 사용할 수 있는 예제로 리플렉션(Reflection) 기술을 설명드리도록 하겠습니다. 먼저 예제를 사용하는 상황을 설명드리자면, XML 파일을 Parse 해서 태그별로 객체를 생성하려는 상황입니다. 제가 맨 처음 도입한 방식은 누구나 쉽게 떠올릴 수 있는 방법인 태그 이름에 따라 switch 문을 사용한 방법입니다. var tags = new List(); while (xmlReader.Read()) { if (xmlReader.NodeType == XmlNodeType.Element) { switch (xmlReader.Name) { case "A": // A 태그를 해석하여 객체를 만들고 저장합니다. var a = new TagA(xmlReader.GetAtt..
- .NET 가이드 [C#] 리플렉션 Reflection (1) : 왜 알아야 할까? 리플렉션 Reflection 리플렉션 (Reflection) 은 프로그램이 동적으로 소스 코드를 해석할 수 있게 하는 기술입니다. Activity나 Service 같이 특정 이름 규칙으로 클래스를 작성하면 개발자가 코드로 객체를 생성하거나 연결하지 않아도, 프로그램 내에 등록되고 사용할 수 있었던 마법의 원리는 프레임워크가 리플렉션 기술을 사용해 클래스의 이름을 바탕으로 클래스를 생성/관리/제거해주기 때문입니다. 객체를 프레임워크가 관리해주니까, 개발자는 프레임워크에게 요청하면 언제 어디서나 안정적으로 원하는 클래스를 얻을 수 있습니다. 즉 개발자는 클래스로 객체를 생성하는 거나, 객체를 사용할 수 있게 준비하는 일정 부분을 프레임워크에게 믿고 맡길 수 있게 됩니다. 예제 코드를 보여드리자면, 아래와 같..
- MAUI 가이드 [Xamarin] MvvmCross 데이터 바인딩 MvvmCross 데이터 바인딩 데이터 바인딩은 MVVM 패턴에서 제일 핵심적인 기능입니다. 데이터 바인딩을 통해 View와 ViewModel 이 서로의 참조 변수를 가지지 않는 형태로 느슨한 결합을 유지할 수 있습니다. MVVM 패턴을 의도했지만 데이터 바인딩을 사용하지 않는다면 MVVM 패턴을 활용하지 못하는 겁니다. MvvmCross에서 데이터 바인딩을 구현하는 순서는 아래와 같습니다. ViewModel에 속성이 변경될 때마다 이벤트를 발생시키도록 구현한다. View에 ViewModel을 연결한다. View 속성에 ViewModel 속성을 Binding 한다. 1. ViewModel에 속성이 변경될 때마다 이벤트를 발생시키도록 구현한다. 데이터 바인딩의 핵심은 ViewModel이 INotifyPro..
- MAUI 가이드 [Xamarin] Xamarin 프로젝트에서 MvvmCross 사용하기 Xamarin 프로젝트에서 MvvmCross 사용하기 MvvmCross 공식 문서 나름 Xamarin.Forms 에서 사용하는 방법을 알려주고 있지만 부족한 점이 많아 추가로 설명드리도록 하겠습니다. MvvmCross 샘플 중 [MvxForms] 를 참고해보시면 많은 도움이 되실 겁니다. 이 샘플을 기반으로 설명을 드리도록 하겠습니다. 1. MvxApplication 생성 제일 먼저해야 할 일은 MvxApplication 을 상속받아 Serivce 를 등록하고, 시작 ViewModel을 등록하는 작업입니다. public class CoreApp : MvxApplication { public override void Initialize() { // 모든 클래스 중 이름이 "Service" 로 끝나는 클래스..
- MAUI 가이드 [Xamarin] MvvmCross 소개 MvvmCross MvvmCross 는 Platform 에 상관없이 MVVM 패턴을 적용할 수 있도록 만들어진 Nuget 패키지입니다. 즉 MVVM 에서 ViewModel 을 플랫폼 독립적으로 만들 수 있게 지원해줍니다. MvvmCross를 사용하면 플랫폼에 상관없이 비지니스 로직을 만들고 플랫폼 별로 View 만 작성하면 됩니다. .NET Standard 기반을 작성되었기 때문에 모든 .NET 프로젝트에서도 사용할 수 있습니다. Xamarin WPF UWP MvvmCross 이전에는 MvvmLight이 대표적인 패키지였습니다. 하지만 시간이 흐르면서 .NET Framework 기반으로 작성된 MvvmLight 보다는 .NET Standard로 작성된 MVVM 패키지가 필요하게 되었고, MvvmCross..
- MAUI 가이드 [Xamarin] ResourceDictionary 관리 ResourceDictionary Xamarin 개발에서 Resource Dictionary는 반드시 사용하게 되는 클래스입니다. 특히 XAML 에서 Style 이나 IValueConverter, ContentTemplate, DataTemplate 등을 사용할 때 Resource Dictionary 를 사용하면 다른 XAML에서 공유하여 사용할 수 있습니다. 문제는 ResourceDictionary 를 분리하거나 합치는 방법을 모르면 하나의 파일 안에 모든 XAML 리소스를 관리해야 해서 Resoucre Dictionary가 매우 복잡해집니다. 이를 해결하기 위해 Resource Dictionary 가 다른 Resource Dictionary 를 참조하는 방법을 알려드리도록 하겠습니다. 아래 코드 한 ..
- UX 디자인 특강 [UX 디자인 특강] 4장 사회적인 디자인과 사용자 경험 디자인 사회적인 디자인: 사용자를 돕는 디자인 제품을 개발할 때 모든 부품이 문제없이 작동하고 있을거라 생각하는건 너무나 순진한 생각이며, 사용자가 언제나 예상한대로 행동하지도 않습니다. 따라서 디자인은 예기치 않은 상황 속에서도 사용자와 상호작용하며 문제를 극복해야만 합니다. 따라서 디자인은 사용자와 상호작용할 수 있도록 설계되어야 합니다. 그래야 문제가 발생해도 차분히 해결할 수 있기 때문입니다. 디자인으로 사용자와 원활히 의사소통하기 위해서는 제품이 현재 어떠한 상태인지 그리고 앞으로 무엇을 해야 하는지를 사용자에게 명확히 전달해야만 합니다. 특히 사용자가 제품에 온전히 집중할 수 없을 때가 많습니다. 제품을 사용하다가 주변으로부터 간섭을 받을 수도 있고, 사용자가 제품에 집중하지 않는 상태일수도 있다는걸..
- MAUI 가이드 [Xamarin] 플랫폼 종속 코드 작성하는 방법 플랫폼에 종속적인 코드 작성하는 방법 Xamarin 은 플랫폼에 독립적인 UI를 만들 수 있도록 도와주기는 하지만, 플랫폼 별로 다른 이미지나 코드를 적용해야 하는 순간이 있습니다. 이때 플랫폼 별로 다른 값을 적용할 수 있는 방법을 알려드리도록 하겠습니다. 플랫폼 별 Code if (Device.RuntimePlatform == Device.iOS) { Padding = new Thickness(0, 20, 0, 0); } Devce.RuntimePlatform 을 활용해서 플랫폼 별로 다른 코드를 실행시킬 수 있습니다. Device 가 구분할 수 있는 플랫폼은 아래 목록과 같습니다. Device.Android Device.iOS Device.macOS Device.WPF Device.UWP Devic..
- UX 디자인 특강 [UX 디자인 특강] 3장 디자인 기술 디자인 기술 이번 장에서는 좋은 디자인을 위해 사용할 수 있는 기술들을 설명해드리도록 하겠습니다. 첫째, 정보 노출 사용자가 제품을 사용하기 위해 사전에 외워야 하는 정보가 있다면 제품 디자인을 통해 정보를 외울 필요가 없도록 노출하는 것도 하나의 방법입니다. 다만 정보를 광고하듯이 노출시키는게 아니라, 어떤 방법으로 노출시킬지에 대한 고민이 필요합니다. 일상 생활에 자주 노출되는 정보 중 하나는 "와이파이 비밀번호" 입니다. 공개된 장소에서 와이파이에 접속하려면 비밀번호가 필요합니다. 하지만 어떤 곳은 비밀번호가 아예 없기도 하고, 대부분의 카페는 결제하는 곳에 붙혀둡니다. 또 영수증에만 공개하는 사업장도 있고, 와이파이를 사용하려면 회원가입을 해야하는 경우도 있습니다. "공공 와이파이" 를 하나의 제..
- UX 디자인 특강 [UX 디자인 특강] 2장 단순한 디자인 단순한 디자인 개념 모델 (Conceptual Model) 이란 제품이 어떠한 원리나 방식으로 작동하는지에 대한 이해 입니다. 1장에서 설명드렸듯이 사용자가 제품을 단순하며 사용하기 쉽다고 느끼는데 필요한 건 작동 방식에 대한 이해 입니다. 이렇게 사용자가 머릿속에 개념적으로 가지고 있는 작동 방식에 대한 이해를 개념 모델 이라 합니다. 디자이너가 복잡함을 다스리기 위해 하는 작업은 시각적으로 단순한 디자인을 만드는게 아니라 사용자에게 알맞은 개념 모델, 즉 작동 방식에 대한 이해를 전달하는 작업입니다. 사용자가 제품의 작동방식을 얼마나 체계적으로 이해하느냐에 따라, 좋은 디자인인지 또는 나쁜 디자인인지를 판단할 수 있습니다. 특히 제품 개발 초기에 자주하는 실수가 쉽고 그럴듯해 보이지만 잘못된 해결책 ..
- UX 디자인 특강 [UX 디자인 특강] 1장 복잡함을 다스리는 디자인 UX 디자인 특강 '복잡함'과 '혼란스러움'은 다르다. 일상 생활에서 경험하는 제품은 굉장히 복잡한 체계를 갖추고 있습니다. 스마트폰과 컴퓨터만 해도 너무 복잡해서, 새로운 앱이라도 설치하면 어떻게 사용해야 하는지 머리가 아픕니다. 그리고 일상에서 잘 의식하지 못하는 사회 시스템도 굉장히 복잡합니다. 매일 출퇴근할 때 이용하는 버스나 지하철은 우리가 익숙해져서 복잡함을 느끼지 못하지만, 해외 여행이라도 가면 그 나라 교통 시스템을 어떻게 이용해야 하는지 혼란스럽습니다. 사용자는 제품의 사용 방법을 배우는 일이 필요하다고 생각하면 복잡함에 대해 별로 신경 쓰지 않습니다. 예를 들어 엑셀을 처음 접하는 사용자에게 굉장히 혼란스러운 프로그램입니다. 워드나 파워포인트만큼 직관적이지 ..
- Backend 가이드 [Spring] JPA Mapping - @ManyToMany @ManyToMany @ManyToMany 관계는 두 Entity 가 서로를 Collection 으로 가지게 되는 관계입니다. @Entity class Student { @ManyToMany(targetEntity=Course.class) Set selectedCources; } @Entity class Course { @ManyToMany(targetEntity=Student.class) Set registeredStudents; @ManyToMany 는 다른 형태로 변형할 수 있는 여지가 많은 관계입니다. @JoinTable 로 @ManyToMany 관계를 지정할 수도 있고, @ManyToOne 두 개로 관계를 변화시킬 수도 있습니다.
- Backend 가이드 [Spring] JPA Mapping - @OneToMany / @ManyToOne @OneToMany / @ManyToOne @OneToMany 는 지정하는 객체는 하나이고, 연결되는 객체가 여러 개일 때 사용합니다. 연결할 때 mappedBy 속성으로 연결할 속성을 지정할 수도 있고, targetEntity 속성으로 연결할 Entity를 지정할 수도 있습니다. mappedBy 방식 @Entity @Table(name="CUSTOMER") public class Customer { @Id @GeneratedValue @Column(name="ID") public int id; // mappedBy 속성에 customer 속성을 연결한다. @OneToMany(mappedBy="customer") public Set orders; } @ManyToOne @JoinColumn(name="C..
- Backend 가이드 [Spring] JPA Mapping - @OneToOne @OneToOne @OneToOne 관계를 정의하는 방법은 여러가지가 있습니다. Foreign Key 를 등록하는 방법 // Customer class @OneToOne // Foreign Key 를 참조할 곳을 지정합니다. @JoinColumn(name="record_id") public Record record; // Record class // Foreign Key 를 제공하는 속성을 지정합니다. @OneToOne(mappedBy="record") public Customer customer; Foreign Key를 제공하는 Entity와 제공받는 Entity로 생성됩니다. 제공받는 Entity는 반드시 @JoinColumn 으로 참조할 곳을 지정해줘야 하고, 제공하는 Entity는 제공받는 Ent..
- Backend 가이드 [Spring] JPA Mapping JPA Mapping JPA Mapping 은 관계형 데이터베이스에서 테이블 간의 관계를 Java 언어로 표현하는 방법입니다. 관계형 데이터베이스라는 이름에서도 알 수 있듯이, 관계를 어떻게 표현하느냐에 따라 데이터베이스 전체 구조가 결정될 정도로 중요한 기능입니다. 데이터베이스에서 사용하는 관계는 아래 3가지 입니다. 일대일 One-to-One (1:1) 관계 일대다 One-to-Many (1:N) 관계 다대다 Many-to-Many (N:M) 관계 데이터베이스에 맞춰서, JPA 에서 제공하는 관계는 아래 4가지 입니다. @OneToOne @OneToMany @ManyToOne @ManyToMany
- Backend 가이드 [Spring] @NotNull, @NotEmpty, @NotBlank 차이 결론 String text 값에 따라 @Notnull / @NotEmpty / @NotBlank 결과가 어떻게 달라지는지 표로 정리했습니다. String text = null; AnnotationBoolean@NotNullfalse@NotEmptyfalse@NotBlankfalse String text = ""; AnnotationBoolean@NotNulltrue@NotEmptyfalse@NotBlankfalse String text = " "; AnnotationBoolean@NotNulltrue@NotEmptytrue@NotBlankfalse String text = "Hello, World!"; AnnotationBoolean@NotNulltrue@NotEmptytrue@NotBlanktrue @..
- Backend 가이드 [Spring] Spring Security 설계 구조 들어가며... 저는 "프레임워크의 설계를 이해하고 있느냐 아니냐" 에 따라, 개발을 진행하면서 얻는 경험의 깊이가 다르다고 생각합니다. 프레임워크의 설계를 이해하고 있으면 프레임워크를 설계한 의도에 맞게 사용하고자 노력하게 되며, 이는 곧 좋은 코드를 만들려는 습관으로 이어지게 됩니다. 개발자는 레퍼런스 문서를 전부 읽고 개발을 시작하지 않습니다. 검색을 통해 여러 샘플 코드를 적용해보면서 프레임워크를 어떻게 사용해야 하는지 경험하게 됩니다. 이때 얻는 경험이 단편적인 지식으로 그치는게 아니라, 축적되는 지혜가 되기 위해서는 프레임워크 설계에 대한 이해가 필요하다 생각합니다. Spring Security (Servlet Application) Spring Security Overview는 Spring S..
- Backend 가이드 [Spring] VSCode에서 DevTools & LiveReload 사용하기 1. VScode Extension 설치 Spring Boot Extension Pack 2. DevTools dependency 추가 Maven org.springframework.boot spring-boot-devtools true Gradle compileOnly "org.springframework.boot:spring-boot-devtools" 3. Chrome Extension 설치 RemoteLiveReload LiveReload 가 아니라 RemoteLiveReload 를 설치해야 제대로 작동 4. SPRING-BOOT DASHBOARD 에서 Debug 시작 5. DevTools 와 LiveReload 작동 확인 DevTools 확인 RestartedMain 이 나오면 DevTools 이..
- 코딩인터뷰 [코딩인터뷰] 문제 8.5
꾸준히 노력하는 개발자 "김예건" 입니다.