Base62에서 표현가능한 값
- ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
가령 어떤 페이지의 원래 주소는 A이며 이 Url이 너무 길어서 base62로 encoding하여 xxx.li/R04R(Shorten url)로 만들었다. 이때 사용자들에게 접속을 유도한 주소는 xxx.li/R04R이고 사용자가 저 주소를 통해 접속하면 서버에서는 R04R을 Decoding하여 6435131(key)를 알아낸다. 그리고 그 key를 DB에서 조회하여 Full Url인 A라는 주소를 찾아낸 후 사용자를 A 주소로 접속하게 한다.
이번 포스팅에서는 C#으로 숏URL을 만들때 사용할 수 있는 base62 인코딩, 디코딩을 구현하고 더 나아가 CLR Obect로 만들어서 DB에서 인코딩/디코딩을 하는 것을 테스트해본다.
자료 링크 : https://github.com/parksuseong/Base62
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public partial class StoredProcedures
{
private static char Base62Digit(int d)
{
if (d < 10){
return (char)('0' + d);
}
else if (d < 36){
return (char)('A' + d - 10);
}
else if (d < 62){
return (char)('a' + d - 36);
}
else{
throw new ArgumentException("d");
}
}
public static void EncodeBase62(SqlString n)
{
int n2 = int.Parse(n.ToString());
var res = "";
while (n2 != 0){
res = Base62Digit(n2 % 62) + res;
n2 /= 62;
}
SqlDataRecord record = new SqlDataRecord(new SqlMetaData("stringcol", SqlDbType.NVarChar, 128));
record.SetSqlString(0, res);
SqlContext.Pipe.Send(record);
}
private static int Base62Decode(char c)
{
if (c >= 'a' && c <= 'z'){
return 36 + c - 'a';
}
else if (c >= 'A' && c <= 'Z'){
return 10 + c - 'A';
}
else if (c >= '0' && c <= '9'){
return c - '0';
}
else{
throw new ArgumentException("c");
}
}
public static void DecodeBase62(SqlString s)
{
SqlString res = "";
string s2 = s.ToString();
res = (s2.Aggregate(0, (current, c) => current * 62 + Base62Decode(c))).ToString();
SqlDataRecord record = new SqlDataRecord(new SqlMetaData("stringcol", SqlDbType.NVarChar, 128));
record.SetSqlString(0, res);
SqlContext.Pipe.Send(record);
}
}
이렇게 만든 프로그램을 실행하여 DLL을 만들었고 그 DLL을 활용하여 MSSQL CLR Object로 만들어보자.
인코딩용/디코딩용 프로시저를 각각 만들기로 한다.
먼저 ASSEMBLY를 생성하하고 각각의 프로시저에서 위에서 생성한 클래스의 알맞은 메서드들을 호출한다.
--drop proc USP_CLR_DECBASE62
--drop proc USP_CLR_ENCBASE62
-- Drop the assembly
IF EXISTS (SELECT * FROM sys.assemblies WHERE name = 'BASE62_CLR')
BEGIN
DROP ASSEMBLY BASE62_CLR
END
GO
-- Create the assembly
CREATE ASSEMBLY BASE62_CLR
FROM 'D:\mssqlClr\BASE62_CLR.dll'
WITH PERMISSION_SET = UNSAFE;
GO
CREATE PROCEDURE USP_CLR_DECBASE62 @STR NVARCHAR(MAX)
WITH EXECUTE AS CALLER AS EXTERNAL NAME BASE62_CLR.StoredProcedures.DecodeBase62
GO
CREATE PROCEDURE USP_CLR_ENCBASE62 @STR NVARCHAR(MAX)
WITH EXECUTE AS CALLER AS EXTERNAL NAME BASE62_CLR.StoredProcedures.EncodeBase62
GO
실제로 잘 동작하는지 확인해보자.
exec USP_CLR_DECBASE62 'R04R'
--exec USP_CLR_ENCBASE62 '6435131'
잘 동작하는 것을 확인할 수 있다.
C# 코드, DB 스크립트, DLL 파일 다운로드 주소
https://github.com/parksuseong/Base62