진정한 남자는 DB를 쓰지 않습니다.

아래 영상에 감명을 받아서,…

// .razor.cs
    [Parameter]
    [SupplyParameterFromQuery]
    public string? Data { get; set; }

    [Inject]
    public NavigationManager NavMan { get; set; } = null!;

    [Inject]
    public IJSRuntime JS { get; set; } = null!;

    private DataDto _dto = new(); 

    protected override void OnParametersSet()
    {
       if(Data != null)
       {
           _dto = DataDto.FromJson64(Data);
       }
    }

    private async Task OnSaveClickedAsync()
    {
       var url = NavMan.GetUriWithQueryParameter(nameof(Data), _dto.ToJson64());
       await JS.InvokeVoidAsync("navigator.clipboard.writeText", url);
       await JS.InvokeVoidAsync("alert", "데이터가 복사되었습니다.");
       NavMan.NavigateTo(url);
    }
    
class DataDto
{

   // properties..

    public static DataDto? FromJson64(string json64)
    {
        var bytes = Convert.FromBase64String(json64);
        var utf8String = Encoding.UTF8.GetString(bytes);
        var dto = JsonSerializer.Deserialize<DataDto>(utf8String);
        return dto;
    }

    public string ToJson64()
    {
        var jsonString = JsonSerializer.Serialize(this);
        var bytes = Encoding.UTF8.GetBytes(jsonString);
        var json64 = Convert.ToBase64String(bytes);
        return json64;
    }  
}

근데, DataDto 에 배열이 들어가니, URL이 몇 천자가 쉽게 넘어갑니다.
영상과는 다르게, 414 (URL 너무 김) 에러가 납니다.

진정한 남자는 여기에서 멈추지 않고, 압축해서 구겨 넣어 봅니다.

static class Ziper
{
    public static void CopyTo(Stream src, Stream dest)
    {
        byte[] bytes = new byte[4096];

        int cnt;

        while ((cnt = src.Read(bytes, 0, bytes.Length)) != 0)
        {
            dest.Write(bytes, 0, cnt);
        }
    }

    public static byte[] Zip(string str)
    {
        var utf8Bytes = Encoding.UTF8.GetBytes(str);

        using var inStream = new MemoryStream(utf8Bytes);
        using var outStream = new MemoryStream();
        using (var gs = new GZipStream(outStream, CompressionMode.Compress))
        {
            CopyTo(inStream, gs);
        }

        return outStream.ToArray();
    }

    public static string Unzip(byte[] bytes)
    {
        using var inStream = new MemoryStream(bytes);
        using var outStream = new MemoryStream();
        using (var gs = new GZipStream(inStream, CompressionMode.Decompress))
        {
            CopyTo(gs, outStream);
        }

        return Encoding.UTF8.GetString(outStream.ToArray());
    }
}

DataDto 도 바꿔줍니다.

class DataDto
{
   // properties..

    public static DataDto? FromJson64(string json64)
    {
        var bytes = Convert.FromBase64String(json64);
        //var utf8String = Encoding.UTF8.GetString(bytes);
        var utf8String = Ziper.Unzip(bytes);
        var dto = JsonSerializer.Deserialize<DataDto>(utf8String);
        return dto;
    }

    public string ToJson64()
    {
        var jsonString = JsonSerializer.Serialize(this);
        // var bytes = Encoding.UTF8.GetBytes(jsonString));
        var bytes = Ziper.Zip(jsonString);
        var json64 = Convert.ToBase64String(bytes);
        return json64;
    }  
}

이제 URL이 반 이하로 줄어 414에러가 없어집니다… 는 뻥이고, Json 문자열을 줄이기 위해, 온갖 뻘짓을 하고 난 후에야 에러가 없어졌습니다.

로컬 저장소 또는 DB에 저장하는 하남자로 돌아 왔습니다.

6 Likes

저도 저영상을 봤습니다 url 에 데이타를 저장한다는 개념 가능했구나 하며 놀랐는데
막상 실무에서 저같은 SI 쪽은 활용하기 좀 그렇지만 언제가 써먹을 수단 같긴 하니다

3 Likes

서버 설정에 url 길이 제한에 대한 설정이 있었던거 같아요

3 Likes

남성 호르몬이 넘치다 보니 구겨 넣을 생각만 했지, 그런 것까지 생각을 못했군요. ㅋㅋ

5 Likes

저도 지금 서비스중인 blazor에 쿼리 스트링을 많이 활용하는 편인데
긴 데이터를 압축해서 넣는다니… 진정 상남자시군요??

2 Likes

뭐 이런 시도가 처음은 아닌 것이, 과거에 ASP.NET Web Form에서는 View State라고 하는 BASE64로 폼 상태 데이터를 인코딩해서 데이터 뭉치로 만들어 놓고 전송때마다 태그에 얹어서 보내는 만행(?)을 저지르던 때도 있었습니다. 복잡한 비즈니스 애플리케이션들은 이 뷰스테이트 데이터 한 방에 1~2MB 이상의 트래픽을 주고 받게끔 덩치를 키우는 경우도 있었죠. :thinking: (URL에 query string을 넣든, 폼 태그에 데이터를 넣든 사용자 인터페이스에만 차이가 생길 뿐이지 본질적으로는 같습니다.)

그리고 URL을 받아서 해석하는 브라우저나 서버가 무엇이냐에 따라서 해석 방법이 제각기 모두 다르기 때문에, 말씀하신것처럼 URL이 잘리거나 414 오류가 발생할 수 있는데, 문제는 URL 최대 길이라는 것이 표준화된 적이 한 번도 없기 때문에 "상식선의 상한선"을 정의해서 알아서 관리해야 하는 어려움도 있겠습니다.

URL length: how long can a URL be? - SISTRIX

5 Likes