url은 https://www.google.com 과 같은 형식의 문자열이다.

사실 우리는 https와 www를 생략하고 브라우저에 입력해도

알아서 찾아가주지만

프로그램에서는 전체를 입력받는 것이 좋다.

 

http와 www를 생략해도 처리되게 하려면

정규표현식을 사용해야 한다.

 

하지만 전체 url 문자열의 유효성을 검사하려면 모듈을 사용하면 된다.

 

validators 문자열은 url 뿐만 아니라 email주소, ip 주소 등 다양한 문자열의

유효성을 검사해준다.

 

참고 : https://pypi.org/project/validators/

 

validators

Python Data Validation for Humans™.

pypi.org

 

pip install validators
import validators

if validators.url('http://google.com'):
    print('참')
else:
    print('거짓')

 

맞으면 True

아니면 ValidationFailure를 반환하기 때문에 if를 활용한다.

IP는 v4와 v6가 존재한다.

 

v4 형식 :

1.12.123.1

v6 형식 : 

2001:0DB8:0000:0000:0000:0000:1428:57ab
2001:0DB8:0000:0000:0000::1428:57ab
2001:0DB8:0:0:0:0:1428:57ab
2001:0DB8:0::0:1428:57ab
2001:0DB8::1428:57ab

 

IP 유효성 검사 1. ipaddress 활용

 

IP를 입력값으로 받을 때 제대로 입력했는지 확인을 꼭 해야한다.

정규표현식으로 처리할 수도 있지만

ipaddress 모듈을 활용하여 편하게 검사할 수 있다.

 

참고 : https://pypi.org/project/ipaddress/

 

ipaddress

IPv4/IPv6 manipulation library

pypi.org

pip install ipaddress
import ipaddress

try:
    ipaddress.ip_address('1.1.1.1')
    print('ip 형식입니다.')
except:
    print('ip 형식이 아닙니다.')

ipaddress는 사실 ip 주소를 편하게 다룰 수 있게 도와주는 모듈로

ip 형식을 체크하는 모듈은 아니지만

ip를 다룬다면 어차피 사용하는 모듈이니

이렇게 활용해보자

 

참과 거짓을 반환하지 않고 ipaddress 객체를 반환하거나 에러가 나기 때문에

try / except를 활용한다.

 

import ipaddress

try:
    ipaddress.ip_address('2001:0DB8::1428:57ab')
    print('ip 형식입니다.')
except:
    print('ip 형식이 아닙니다.')

ipv6도 되니 얼마나 좋은가!!

 

 

IP 유효성 검사 2. validators 활용

 

validators 모듈은 다양한 문자열의 유효성을 검사해주는 모듈이다.

 

https://pypi.org/project/validators/

 

validators

Python Data Validation for Humans™.

pypi.org

pip install validators
import validators

if validators.ipv4('1.1.1.1'):
    print('참')
else:
    print('거짓')

validators는 참과 ValidationFailure를 반환하기 때문에

if를 활용한다.

'Application Language > Python' 카테고리의 다른 글

[python] 파이썬 url 유효성 검사 방법  (0) 2022.09.06

Thread 사용하면서 자원공유는 쉬운 문제가 아니다.

예를 들어 txt를 많은 Thread가 동시에 사용한다면 충돌을 피하기 어렵다. 

 

일반적인 파일 입출력 예

using (FileStream Fs = new FileStream(filePath, FileMode.Append))

                { 

                    StreamWriter streamWriter = new StreamWriter(Fs, Encoding.UTF8); 

                    streamWriter.Write("Something...\n"); 

                    streamWriter.Close(); 

                    emailResertFs.Close(); 

                } 

Thread가 아니면 문제가 되지 않는 코드이지만 Thread면 문제가 달라진다.

 

저 코드가 일반적인 상황이 아닌 Thread를 사용하면서  Thread가 위의 코드를 처리한다고 가정하자. 

 

운이 좋으면 지나가겠지만 그렇지 않으면 위와 같은 에러를 만나게 된다. 

원인은 두개 이상의 Thread가 동시에 txt파일에 액세스 하려고 하면서 발생하는 문제이다. 

 

이 문제를 간단히 해결해보자 

 

해결책 - lock 사용 

 

위의 예제를 이렇게 바꿔보자 

 

private object locker = new object(); //맴버변수로 위에서 따로 정의한다. 




 lock (locker) 

            { 

                using (FileStream Fs = new FileStream(filePath, FileMode.Append))

                { 

                    StreamWriter streamWriter = new StreamWriter(Fs, Encoding.UTF8); 

                    streamWriter.Write("Something...\n"); 

                    streamWriter.Close(); 

                    emailResertFs.Close(); 

                } 

            } 

lock 키워드는 블록 안에 있는 코드를 한 Thread에서만 사용할 수 있게 해주는 키워드이다.

블록에 있는 코드가 끝나기 전까지는 다른 Thread가 들어오지 못한다.

lock()의 파라미터는 임의의 객체를 사용할  있지만 일반적으로 private object 형태로 만든다. 

 

Lock(obj) 

{ 

	Do Something; 

} 

특별한 상황이 아니라면 이렇게 만들자.

 

참고

여기에서 만약에 클래스 객체인 this를 사용하여 lock(this)라고 하면 의도치 않게 데드락이 발생될 수 있기 때문에 this는 사용하지 않는 것이 좋다. 

 

this를 사용하면 집을 잠그는 개념이고 obj를 사용하면 방문을 잠그는 개념. 

집을 lock해야 하는 경우도 있기 때문에 무조건 사용하지 않는 것은 아니지만 일반적으로는 방만 lock하자! 

 

마지막으로 코드 블록 ( { } 사이 코드 )  범위는 최대한 작게 하는 것이 좋다. 

 

결론 

 

대소문자 구분 

EndsWith(".png");

 

대소문자 구분 안함 

EndsWith(".jpg", true, null);

 

2번째 인자가 true이면 구분 안함, false이면 구분함.

 

설명 

 

c#에서 확장자를 다룰 때 EndsWith() 사용하는 경우가 있다. 

 

Directory.GetFiles(_rootPath, "*.*", SearchOption.AllDirectories).Where(s => s.EndsWith(".jpg", true, null) || s.EndsWith(".png"));

Directory.GetFiles(_rootPath, "*.*", SearchOption.AllDirectories).Where(s => s.EndsWith(".jpg", true, null) || s.EndsWith(".png")); 

 

이런식으로.. 

RootPath에서부터 하위 폴더까지 파일을 검색할 때 위와 같이 많이 사용하는데 

모든 파일을 보는 것이 아니라 특정 확장자만 봐야 하는 경우가 일반적이다. 

 

이럴 때 Where와 EndsWith를 함께 사용하는데 이럴 때 확장자가 대소문자 구분을 하지 말아야 할 때가 많은데 예제와 같이 작성하면 확장자를 구분한다. 

 

 

참고 : https://docs.microsoft.com/ko-kr/dotnet/api/system.string.endswith?view=netcore-3.1#System_String_EndsWith_System_String_ 

 

EndsWith를 사용하는 방식은 총 4 가지이다. 

이 중 4번째 방식을 사용하면 된다. 

 

 

 

필자 환경

OS : Windows 10

IDE : Visual Studio 2019

 

Blazor는 Visual Studio 2019에서 개발할 수 있다.

템플릿도 존재한다.

 

Blazor 앱을 선택한다.

 

저장 위치를 설정하고 나면 갑자기 둘 중 하나를 선택해야 하는 창이 나온다.

이게 뭔가...

 

참고로 만약 Blazor WebAssembly App 나오지 않는다면 Visual Studio를 최신버전으로 업데이터 해야 한다.

Blazor Server App은 2019버전부터 지원하는데, Blazor WASM은 2020년 5월에 추가되었다.

 

자.. 우리는 Blazor Server 와 Blazor WebAssembly app 중 하나를 선택해야 한다.

차이점을 알아야 선택할 수 있지 않을까?

 

차이점

아주 쉽고 간단하게 결론부터 말하면 Blazor Server App은 Server Side 개념, Blazor WebAssembly App은 Client Side 개념으로 이해하면 된다.

다시 말해, 우리가 만든 C# 코드가 서버에서 실행되냐 클라이언트에서 실행되냐 의 차이이다.

 

좀더 자세히 설명을 하자면 다음과 같다.

 

Server Model

1. C#코드가 서버에서 실행된다.

2. Javascript hooks는 DOM에 액세스하는데 사용한다.

3. SignalIR을 사용하여 브라우저와 서버 간에 정보를 바이너리로 주고받는다.

4. 만약 무언가가 변경되면 서버는 DOM 업데이트 메시지를 다시 보낸다.

 

WebAssembly Model

1. 클라이언트의 부러우저에서 실행된다.

2. 웹 요청 중 첫 번째 요청은 CLR, 어셈블리, JavaScript, CSS를 다운로드하는 요청이다.

3. 보안 WASM 샌드박스에서 실행된다.

4. Blazor Javascript 핸들러는 Dom에 액세스한다.

 

참고 SignalIR ??

SignalIR은 Blazor의 필수 부분이기 때문에 꼭 알아야 하며, 다음 기능을 제공한다.

1. 무료 오픈 소스이다.

2. 지속적으로 연결되어 비동기 메시지를 보낸다.

3. 연결은 양방향

 

SignalR 웹 소켓은 포트 80을 사용하며, 이는 서버에서 Azure SignalR Service로 오프로드 될 수 있으며,이를 통해 하루에 10 만 명의 동시 사용자와 1 억 개의 메시지가 허용된다. 무료 오퍼링은 하루에 20 명의 동시 사용자와 20,000 개의 메시지를 허용한다.

 

 

그래서 뭘 선택해야 하나? 장단점을 보자!

Blazor Sever App

장점

로딩이 WASM보다 빠르다.

데이터베이스 또는 클라우드 기반 서비스와 같은 보안 리소스에 대한 엑세스가 가능하다.

클라이언트에서는 IE11처럼 WASM을 지원하지 않는 브라우저에서도 상관없이 돌아간다.

C#코드가 클라이언트쪽으로 전송되지 않기 때문에 보안에 유리하다.

 

단점

데이터 전송으로 인한 추가 대기 시간이 있다.

오프라인 지원이 안된다.

확장성이 어렵다.

서버가 필요하다.

 

 

Blazor WebAssembly App

장점

UI코드가 빠르게 처리된다.

오프라인을 지원한다.

CDN을 통해 배포가 가능하고 서버가 불필요하다. (API 제외)

모든 .net 표준 2.0 C#을 실행할 수 있다.

 

단점

보안 리소스에 액세스 하려면 API레이어가 필요하다.

디버깅이 어렵다.

 

그래서 결론은...

많은 수의 사용자를 상대해야 하고 보안이 중요하지 않고 성능이 중요하다면 WASM

조금 느려도 보안이 중요하다면 Server!!

 

 

아직 이해가 다 안됬다면.. 몇 가지 테스트를 해보자!

 

테스트는 Github에 있는 데모 코드를 가지고 테스트를 한다.

 

-Github Url

https://github.com/WolfgangOfner/Blazor-ServervsClient

 

 

4개의 프로젝트가 있다.

 

참고로 템플릿을 선택할 때 만약 blazor Server를 선택했다면 첫번째 프로젝트처럼 하나의 프로젝트가 만들어질 것이고, Blazor WASM을 선택했다면 2-4 프로젝트 3개(Client, Server, Shared)의 프로젝트가 자동 생성된다.

 

 

솔루션 - 속성에서 실행할 프로젝트를 설정하고 실행하면 BlazorServer 프로젝트가 실행된다.

 

 

 

1. Blazor Server Test

 

먼저 Server를 실행한다.

 

 

브라우저의 디버그의 네트워크를 보면 서버와 브라우저 간의 SignalIR 메시지를 확인할 수 있다.

브라우저가 서버에게 요청하는 형태이다.

 

 

2. Blazor WASM Test

 

다음은 WASM을 실행해본다.

 

Visual Studio에서 실행 프로젝트를 변경하고 실행하면 된다.

 

 

마찬가지로 디버깅을 해서 Console을 보면 클라이언트에서 실행될 수 있도록 많은 dll 파일이 전송된 것을 볼 수 있다.

데모코드에서는 6.15M 가 전송되었다.

 

참고로 릴리즈 모드로 하면 약 2.3M의 파일이 전송된다. 릴리스모드에서는 링커가 켜져서 필요한 파일만 전송되기 때문이다.

 

그리고 동시 연결 지원은 다음과 같다.

- CPU가 1 개이고 램이 3.5GB 인 서버는 5k 동시 연결 지원

- CPU가 4 개이고 RAM이 14GB 인 서버는 2 만 개의 동시 연결 지원

 

 

 

 이해가 되었는지....??

코드를 작성하다 보면 문자열에 공백문자가 들어갈 때가 있다. 

C#에서는 간단히 제거할  있고 Trim이  역할을 해준다. 

<코드>

string st = "\r\n \t 문자열 입니다 \n ";
Console.WriteLine(st);
Console.WriteLine("===================");
Console.WriteLine("|" + st.Trim() + "|");

 

<결과>

 

위와 같이 문자열의 앞/뒤 공백문자를 제거해준다. 

 

Trim() - 문자열의 앞 뒤 공백문자 제거

TrimStart() - 문자열의 앞 공백문자 제거

TrimEnd() - 문자열의 뒤 공백문자 제거

 

참고로 중간에 있는 공백문자는 제거하지 않는다. 

제거하고 싶다면 Replace나 정규식의 치환 등을 이용하면 된다. 

 

+ Recent posts