본문 바로가기
개발~/JAVA

JSON 빈 객체를 단말에 어떻게 내려줄까?(Android,iOS)

by 보배곰 2019. 4. 25.

매번 똑같은 고민을 하기 때문에 정리해봅니다. 

서버에서 결과값을 내려주는데, 데이터가 있으면 괜찮지만 데이터 객체가 null로 내려갈 경우 항상 문제가 생깁니다. 이번에 android, ios 개발자 분들과 얘기해서 나온 결과를 정리해볼까 합니다. 

1. 기능

단계에 대한 설명을 json으로 내려줍니다. 만약, 데이터가 없다면 빈 값으로 보여줍니다.

 

2. 소스

서버는 Spring이고, MyBatis를 이용합니다. 

간단히 자바 소스입니다. 

@RequestMapping(value = "/introduction") 
public Map<String, Object> introduction(@RequestParam Map<String, String> params) {
	
	Map<String, Object> result = new HashMap<String, Object>();
	result.put("resultCode", 200); 
	result.put("data", sqlSession.selectOne("intro.selectIntroduction", params));
		
	return result;
}

간단히 MyBatis 입니다.

<select id="selectIntroduction" resultType="camel">
	SELECT title, content
	FROM introduction
	WHERE id=#{id}
</select>

사실... 클래스 만들어서 객체로 넘겨야하지만.. 일단 이렇게 가도록 합니다! 

이 상태에서 데이터가 있다면 아래처럼 결과가 나옵니다.

{
  "data": {
    "content": "내용입니다.",
    "title": "제목입니다.",
  },
  "resultCode": 200
}

똑같이 이 상태에서 데이터가 없다면 아래처럼 결과가 나옵니다.

{
  "data": null,
  "resultCode": 200
}

여기서 문제 1. !! 

이 상태일 때, 안드로이드(Java)는 받을 수 있지만, 아이폰(Objective-C)의 경우 null을 받을 수 없다고 합니다. 왜?! 두둥! 

아이폰에서 안되는 이유를 물어보니, null을 String으로 인식하고, 값이 아래처럼 들어온다고 합니다. 

{
    data = "<null>";
    resultCode = 200;
}

위에 처럼 받기 위해서 Objective-C에서는 Null 클래스인지를 체크해야 한다고 합니다. 하지만 data가 객체가 아닌 String (data: "안녕" 혹은 data:"")으로 들어오는 API도 있을 수도 있으니 모든 API 같은 소스를 적용할 수는 없고 data가 객체라고 명확히 정해진 부분에만 체크로직을 추가해주어야 합니다.

 

단말에서 수정하지 않고 서버의 결과값을 수정한다면 data에 값이 없을때 data에 빈 스트링("")으로 보내야 한다고 합니다. 아래처럼요! 

{
    "data": "",
    "resultCode": 200
}

 

그래서 서버 소스를 고치고, 결과를 저렇게 보내기로 했습니다.

@RequestMapping(value = "/introduction") 
public Map<String, Object> introduction(@RequestParam Map<String, String> params) {
	
	Map<String, Object> result = new HashMap<String, Object>();
	result.put("resultCode", 200); 
	if(sqlSession.selectOne("intro.selectIntroduction", params) == null) {
		result.put("data", ""); // @@@@ 수정 @@@@
	} else {
		result.put("data", sqlSession.selectOne("intro.selectIntroduction", params));  
	}	
    return result;
}

값이 null이면 result.put("data", ""); 이렇게 보냈죠! 

그런데 여기서 문제 2 !! 

이렇게 보내면, 안드로이드 쪽에서 Exception이 난다고 합니다. Gson을 쓰는데 객체가 String으로 들어와서 에러가 나는 것 같습니다. 

만약 위에처럼 에러가 난다면 android 쪽에서는 api에 try-catch 체크를 해주어야 하는데, 해당 API에만 적용해야하나 모든 API에 적용해야되나 문제가 되었었죠!

 

그래서 android와 iOS 같이 말을 맞춰보시더니, 서버에서 이렇게 보내달라고 하셨습니다.

{
  "data": {
    "content": "",
    "title": "",
  },
  "resultCode": 200
}

여기서 문제 3 !!!

이렇게 보내려면 서버 쪽에서 문제가 생깁니다. 뭐 문제라기 보다는.. 처음 설계할 때 클래스가 없이 sql 결과를 바로 내려주는 식으로 개발을 했기 때문에, data안에 content, title이라는 key로 값을 하드코딩으로 박아주어야 하고, 나중에 sql에 컬럼이 추가될 경우, 하드코딩한 데이터를 다시 손봐야합니다. 그리고 에러를 판단하기 어렵게 되겠죠.

// .... 생략 ....
Map<String, Object> result = new HashMap<>();
if(sqlSession.selectOne("intro.selectIntroduction", params) == null) {

	// @@@@ 수정 @@@@
	Map<String, Object> data = new HashMap<>();
	data.put("title", "");
	data.put("content", "");
    
	result.put("data", data);

} else {
	result.put("data", sqlSession.selectOne("intro.selectIntroduction", params));  
}	
// .... 생략 ....

이렇게 위에처럼 하드코딩하는 건... 정말 좋지 않겠죠. 

 

android는 try-catch를 걸어준다, iOS는 null클래스를 확인해준다는 해결방법이 있기는 하나 모두 너무 일시적인 해결방법이기 때문에 조금 더 고민을 해보기로 합니다.

그리고 해결!

그리고 다시, 빈 객체를 보내는 방법에 대해서 고민하게 됩니다! 하고, 번뜩 든 생각!

// .... 생략 ....
Map<String, Object> result = new HashMap<>();
if(sqlSession.selectOne("intro.selectIntroduction", params) == null) {

	// @@@@ 수정 @@@@
	result.put("data", new HashMap<String, String>());

} else {
	result.put("data", sqlSession.selectOne("intro.selectIntroduction", params));  
}	
// .... 생략 ....

이렇게 보내면, 결과로 아래와 같이 내려갑니다.

{
  "data": {},
  "resultCode": 200
}

그리고 이렇게 보내면 안드로이드, iOS 모두 받을 수 있다고 합니다! 짝짝짝!

만약에 data가 없다면, null이 아니라 서버는 빈 객체를 내려주는 방법인 것이지요!


사실 결과만 놓고보면.. 정말 별거 아니지만, 서버, Android, iOS의 차이를 알 수 있던 경험이었습니다.

그리고 얘기 중에 다양한 다른 해결 방법이 나왔습니다.

1. parameter에 device 플래그 값을 추가한다.

2. resultCode의 값을 추가한다.

3. 객체 유무를 알려주는 boolean 플래그를 추가한다.

4. 안드로이드에서 try-catch를 한다.

5. iOS에서 Null 클래스 체크를 한다.

6. 서버에서 하드코딩을 한다.

7. 적용한 해결 방법 -> 빈 객체를 내려준다. 

사실.. 어떤 방법이 좋은 방법인지 모르겠습니다.. ㅎㅎ 해결한 빈 객체로 내려주는 방법도 좋은 방법인지 잘 모르겠습니다. 뭐가 좋은 방법일까 항상 고민하게 됩니다.

 

3. 결론

'개발~ > JAVA' 카테고리의 다른 글

Kotlin 소개  (0) 2022.12.10
[Spring boot] page 1부터 시작하기  (0) 2020.04.30
Log4j 사용하기  (0) 2019.12.19
주석이쁘게 달기  (0) 2017.06.16
[JAVA] java.util.Date  (0) 2017.03.17