Coding Memo

Http에서의 Json Convert - nullable 본문

Language/C#

Http에서의 Json Convert - nullable

minttea25 2024. 2. 5. 15:02

Summary

 
Web 상에서의 Http, Https를 이용한 req/res의 body의 text를 직렬화/역직렬화할 때, 타입에 유의하자.
nullable 타입과 그렇지 않은 타입은 다르게 직렬화/역직렬화 된다.
(예를 들어 int? 타입은 "null"값으로 파싱하지만, 단순 int 타입은 0(default) 값이 될 것이다.)
 
nullable 타입은 아예 text로 `null`이라는 값으로 들어온다.
 
반드시 서버와 클라이언트에서 같은 데이터에 대한 클래스의 멤버 타입들은 특별한 이유가 없다면 동일하게 해주자.


C# 8.0 부터 nullable 기능이 도입되었다.
이 Nullable Reference Types를 사용하면 null이 될 수 있는 참조형 변수와 될 수 없는 참조형 변수를 구분할 수 있다.
 
즉, 다른 타입으로 취급된다는 것이다!
 
Web 서버에서 로그인 요청을 처리하고 클라이언트에 응답을 해주는 기능이 있었는데, 로그인 실패 시 (Id가 없거나 비밀번호가 일치하지 않을 때) 클라이언트에서 Res의 text를 json 형식으로 파싱하는데, 문제가 발생하면서 알게 되었다.
 
로그인 성공 시에는 Res 클래스의 모든 멤버들이 null 값 없이, 모든 값이 유효하게 text에 들어오지만, 실패 시에는 대부분의 값들이 null로 처리되어 클라이언트로 전송이 된다. 
서버에서는 다음과 같은 Res 클래스를 사용하고 있었다.

[Serializable]
public class AccountLoginWebRes
{
    public int Res { get; set; }
    public string? AuthToken { get; set; }
    public long AccountDbId { get; set; }
    public string? ServerName { get; set; }
    public string? ServerIp { get; set; }
    public int? ServerPort { get; set; }
}

바이트 배열을 파싱하는 것과는 달리, 만약 ServerIp 값이 null이라면 `"ServerIp": "null"`로 파싱이 된다. 
 
이에 반해, 클라이언트에서는 위와 같은 구조를 그대로 사용하고 있었지만, 단지 nullable 타입이 아닌, 단순히 string, int 등의 타입을 사용하고 있었기에, 서버로 부터 받은 text를 그 클래스로 파싱하는데 예외가 발생했던 것이었다.
 

[Server] AccountLoginWebRes의 값

 

[Client] AccountLoginWebRes의 값(text)