규도자 개발 블로그

규칙없는(Not Iterable) 자바스크립트 객체 순회하기 본문

HTML/CSS/JS/JavaScript

규칙없는(Not Iterable) 자바스크립트 객체 순회하기

규도자 (gyudoza) 2019. 4. 10. 23:18

규칙없는(Not Iterable) 자바스크립트 객체 순회하기

무작위하게 적혀있는 자바스크립트 객체 안의 모든 값이 필요할 때가 있다. 그럴 때 쓰기 좋은 함수이다. 아래 소스들은 전부 관리자모드의 console창을 켜서 입력하면 바로바로 실행해볼 수 있다.

var testObj = {
    "id": 1,
    "name": "Leanne Graham",
    "username": "Bret",
    "email": "Sincere@april.biz",
    "address": {
        "street": "Kulas Light",
        "suite": "Apt. 556",
        "city": "Gwenborough",
        "zipcode": "92998-3874",
        "geo": {
            "lat": "-37.3159",
            "lng": "81.1496"
            }
        },
    "phone": "1-770-736-8031 x56442",
    "website": "hildegard.org",
    "company": {
        "name": "Romaguera-Crona",
        "catchPhrase": "Multi-layered client-server neural-net",
        "bs": "harness real-time e-markets"
    }
};

이러한 객체가 있다고 생각해보자. 객체는 내가 좋아하는 https://jsonplaceholder.typicode.com/에서 따왔다. 이 객체는 iterable하지 않다. 해서 일반적인 반복문으로 조회할 수가 없다. 그럴 때 쓰는 방법이다.

Object.keys(testObj).map(function (key) {
    console.log(testObj[key]);
});

를 입력하면 해당 객체의 value값을 전부 뽑아낼 수 있다. 만약에 key : value형태로 정리하고 싶다면 아래와 같은 코드로 쓰면 된다. 근데 결국 이렇게 쓰면 맨 처음에 선언했던 때와 똑같은 모습으로 출력된다. 하지만 아래 방법을 통해 불규칙한 형태를 가진 객체를 순회할 수 있다는 데 의미를 두면 된다.

var testResult = {};
Object.keys(testObj).map(function (key) {
    testResult[key] = testObj[key];
});
console.log(testResult);

아무튼 이렇게 Not Iterable한 객체를 정리하여 key : value형태로 담아봤다. 근데 뭔가 아쉽지 않은가? 여전히 address의 value는 object인 채로 남아있다. 이런 것들도 한번 파고 들어서 1차원 형태로 순회해보자.

function jsonSpliter(object){
    Object.keys(object).map(function (key) {
        if(typeof object[key] === 'object'){
            jsonSpliter(object[key]);
        }else{
            console.log(object[key]);
        }
    });
}

var funcTest = jsonSpliter(testObj);
console.log(funcTest);

Recursive한 형태로 구현하였다. 만약에 이걸 전부 어떤 변수에 담고 싶다면 아래와 같이 쓰면 되겠다.

function jsonSpliter(object, result){
    Object.keys(object).map(function (key) {
        if(typeof object[key] === 'object'){
            jsonSpliter(object[key], result);
        }else{
            result[key] = object[key];
        }
    });
    return result;
}

var funcTest = jsonSpliter(testObj, {});
console.log(funcTest);

제대로 실행됐으면 아래와 같은 결과가 출력된다.

어쩌면 당연한 얘기일수도 있겠지만 2단계, 3단계 깊이에 있는 객체의 key는 출력되지 않는다. 예를 들어 street, city, zipcode등은 address라는 object안에 있었지만 해당 내용은 무시되었다. 개선하려면 개선할 수 있겠지만, 예를 들어 street은 address안에 있었으니 address_street이라는 key로 출력되게. 만약에 이렇게 구현한다손 치면 또 geo안에 있는 lat과 lng이라는 요소는 address_geo_let이라는 드러운 key를 갖게 되고 만약이 이 언더스코어를 기준으로 또 객체들의 계층을 세분화해서 뭔가 작동시킨다고 하면 key자체에 언더스코어가 포함돼있는 경우 또한 고려해야하니 갑자기 머리가 아파져서 여기에서 딱 멈췄다.


주의할 점이라고 해야한다면 말 그대로 계층에 대한 세분화는 구현돼있지 않으니 아무리 계층이 다른 key라고 해도 중복된 key가 온다면 나중에 오는 key : value로 값이 덮어씌워진다는 사실이다. 실험해보고 싶다면 아래 코드를 실행해보면 된다.

var testObj = {
    "id": 1,
    "name": "Leanne Graham",
    "username": "Bret",
    "email": "Sincere@april.biz",
    "address": {
        "street": "Kulas Light",
        "suite": "Apt. 556",
        "city": "Gwenborough",
        "zipcode": "92998-3874",
        "geo": {
            "lat": "-37.3159",
            "lng": "81.1496"
            }
        },
    "phone": "1-770-736-8031 x56442",
    "website": "hildegard.org",
    "company": {
        "name": "Romaguera-Crona",
        "catchPhrase": "Multi-layered client-server neural-net",
        "bs": "harness real-time e-markets"
    },
	"street" : "fighter"
};

address내부의 street는 Kulas Light라고 선언돼있지만 내가 마지막에 street : fighter라고 선언해놨다. 위의 jsonSpliter함수를 통해 이 값을 확인해보면

이렇게 스트리트 파이터가 된 걸 확인할 수 있다. 위 주의사항들만 잘 유의해서 쓴다면 유용할 거라 믿는다. 나도 애초에 필요해서 만든 것이니 말이다.

Comments