Faits :
A.
Par ordonnance pénale du 23 février 2017, le Ministère public de la République et canton de Genève a condamné A._ pour infraction à l'art. 116 al. 1 let. a LEtr (LEI depuis le 1er janvier 2019).
Ensuite de l'opposition formée par le prénommé contre ladite ordonnance pénale, le ministère public a, par ordonnance du 21 juin 2018, classé la procédure en question, mis les frais de procédure à sa charge et refusé de lui allouer une indemnité à titre de l'<ref-law>.
B.
Par arrêt du 6 mars 2019, la Chambre pénale de recours de la Cour de justice genevoise a rejeté le recours formé par A._ contre l'ordonnance de classement du 21 juin 2018.
La cour cantonale a retenu les faits suivants.
Le 26 janvier 2017, B._ a été interpellé par la police et s'est légitimé au moyen d'un titre de séjour échu depuis 2011. Il a alors expliqué à la police qu'il logeait chez A._. Sur une période d'une année, B._ a été hébergé par A._ pendant plusieurs mois, dont certains consécutifs. Il disposait d'une clé de l'appartement et y était nourri et blanchi. A._ n'a jamais annoncé aux autorités administratives qu'il logeait B._ dans son appartement.
C.
A._ forme un recours en matière pénale au Tribunal fédéral contre l'arrêt du 6 mars 2019, en concluant, avec suite de frais et dépens, à sa réforme en ce sens que les frais de la procédure pénale sont laissés à la charge de l'Etat et que des indemnités à titre de l'<ref-law> lui sont allouées à hauteur de 5'930 fr. 55 pour ses dépens et de 255 fr. pour son dommage économique. Il sollicite par ailleurs le bénéfice de l'assistance judiciaire.
D.
Invités à se déterminer, la cour cantonale s'est référée à l'arrêt du 6 mars 2019, tandis que le ministère public a conclu au rejet du recours.

Considérant en droit :
1.
Le recourant reproche à l'autorité précédente d'avoir violé les art. 426 et 429 CPP en mettant à sa charge les frais de la procédure et en lui refusant toute indemnité.
1.1. Conformément à l'<ref-law>, lorsque la procédure fait l'objet d'une ordonnance de classement ou que le prévenu est acquitté, tout ou partie des frais de procédure peuvent être mis à sa charge s'il a, de manière illicite et fautive, provoqué l'ouverture de la procédure ou rendu plus difficile la conduite de celle-ci.
La condamnation d'un prévenu acquitté à supporter tout ou partie des frais doit respecter la présomption d'innocence, consacrée par les art. 32 al. 1 Cst. et 6 par. 2 CEDH. Celle-ci interdit de rendre une décision défavorable au prévenu libéré en laissant entendre que ce dernier serait néanmoins coupable des infractions qui lui étaient reprochées. Une condamnation aux frais n'est ainsi admissible que si le prévenu a provoqué l'ouverture de la procédure pénale dirigée contre lui ou s'il en a entravé le cours. A cet égard, seul un comportement fautif et contraire à une règle juridique, qui soit en relation de causalité avec les frais imputés, entre en ligne de compte. Pour déterminer si le comportement en cause est propre à justifier l'imputation des frais, le juge peut prendre en considération toute norme de comportement écrite ou non écrite résultant de l'ordre juridique suisse pris dans son ensemble, dans le sens d'une application par analogie des principes découlant de l'<ref-law>. Le fait reproché doit constituer une violation claire de la norme de comportement. Une condamnation aux frais ne peut se justifier que si, en raison du comportement illicite du prévenu, l'autorité était légitimement en droit d'ouvrir une enquête. Elle est en tout cas exclue lorsque l'autorité est intervenue par excès de zèle, ensuite d'une mauvaise analyse de la situation ou par précipitation. La mise des frais à la charge du prévenu en cas d'acquittement ou de classement de la procédure doit en effet rester l'exception (<ref-ruling> consid. 2.2 p. 204 s. et les références citées).
Selon l'<ref-law>, l'autorité pénale peut réduire ou refuser l'indemnité ou la réparation du tort moral prévues par l'<ref-law>, lorsque le prévenu a provoqué illicitement et fautivement l'ouverture de la procédure ou a rendu plus difficile la conduite de celle-ci. L'<ref-law> est le pendant de l'<ref-law> en matière de frais. La question de l'indemnisation (art. 429 à 434 CPP) doit être traitée après celle des frais (arrêts 6B_565/2019 du 12 juin 2019 consid. 5.1; 6B_373/2019 du 4 juin 2019 consid. 1.2). Dans cette mesure, la décision sur les frais préjuge de la question de l'indemnisation (<ref-ruling> consid. 1.8.2 p. 211; <ref-ruling> consid. 2.4.2 p. 357).
1.2. Selon l'art. 5 al. 1 let. b de la loi genevoise d'application de la loi fédérale sur l'harmonisation des registres des habitants et d'autres registres officiels de personnes (LaLHR/GE; RS/GE F 2 25), est tenu de s'annoncer ou de communiquer toute modification de données le concernant au sens de l'article 4 celui qui réside ou séjourne dans le canton. Aux termes de l'art. 7 al. 3 LaLHR/GE, les personnes logeant chez elles, à titre onéreux, des adultes ou des enfants, communiquent gratuitement à l'office, dans un délai de 14 jours, les données des personnes habitant dans leur ménage, au sens de l'art. 6, let. e à k, m et n, de la loi fédérale. Si le logement est mis à disposition à titre gratuit, l'annonce par le logeur n'est obligatoire que si les personnes logées ne l'ont pas déjà fait conformément à l'article 5.
1.3. La cour cantonale a exposé que B._ était établi depuis plusieurs années dans le canton de Genève, ce que savait le recourant qui le connaissait depuis 2009. Ce dernier avait logé le prénommé pendant plusieurs mois - dont certains consécutifs -, sur une période d'une année. Ainsi, B._ avait eu l'obligation de s'annoncer auprès de l'Office cantonal de la population et des migrations (ci-après : OCPM), conformément à l'art. 5 LaLHR/GE. Comme il ne l'avait pas fait, le recourant avait eu, au regard de l'art. 7 al. 3 in fine LaLHR/GE, l'obligation de procéder à cette annonce. Ce dernier avait donc violé une norme de droit administratif et avait ainsi adopté un comportement illicite au sens de l'<ref-law>. Son comportement avait été fautif, puisqu'il n'avait pas agi conformément à ce que l'on pouvait attendre de lui, ce qui relevait à tout le moins de la négligence. Selon l'autorité précédente, même si B._ avait caché son statut illégal à son logeur, les explications nécessaires auraient pu être immédiatement fournies aux autorités pénales et aucune instruction pénale n'aurait été ouverte contre le recourant si ce dernier avait annoncé à l'OCPM qu'il hébergeait le prénommé.
1.4. Au vu des constatations de la cour cantonale, il apparaît que le recourant ne s'est pas conformé à une norme de comportement du droit cantonal genevois, en omettant d'annoncer à l'autorité compétente qu'il logeait B._, étant précisé que le prénommé n'avait pas lui-même procédé à une telle annonce. Contrairement à ce que soutient le recourant, on ne voit pas en quoi l'art. 7 al. 3 LaLHR/GE - qu'il s'agisse ou non d'une règle d'ordre et indépendamment de la question de savoir si cette disposition pourrait placer le logeur dans une position de garant - ne pourrait être pris en compte à titre de norme dont la violation procède d'un comportement illicite pouvant en principe être considéré dans le cadre de l'application de l'<ref-law>.
Le recourant soutient ensuite que, dès lors que les art. 16 LEI et 18 de l'ordonnance relative à l'admission, au séjour et à l'exercice d'une activité lucrative (OASA; RS 142.201) imposent uniquement de procéder à une déclaration auprès de l'autorité cantonale compétente à celui qui loge un étranger à titre lucratif, une disposition plus stricte de droit cantonal ne saurait être prise en compte dans le cadre de l'application de l'<ref-law>, qu'il conviendrait de considérer à l'aune du "curseur fédéral". Ce raisonnement ne saurait être admis. En effet, la disposition précitée implique notamment de déterminer si le prévenu a pu adopter un comportement contraire à une règle juridique, par analogie avec les principes découlant de l'<ref-law>. De ce point de vue, peut s'avérer illicite - au sens de l'<ref-law> - le comportement contraire à une norme de droit tant fédéral que cantonal. Le recourant ne prétend aucunement que l'art. 7 al. 3 LaLHR/GE serait contraire au droit fédéral ni n'explique pour quels motifs il conviendrait d'ignorer une éventuelle violation de cette norme en matière d'application de l'<ref-law>.
1.5. En revanche, force est d'admettre, avec le recourant, que le comportement illicite de ce dernier - indépendamment de la question de savoir si celui-ci était en outre fautif - ne s'est pas trouvé en lien de causalité avec l'ouverture de l'instruction.
Une instruction a été ouverte contre le recourant et l'ordonnance pénale du 23 février 2017 rendue à son encontre car il était reproché à celui-ci d'avoir facilité le séjour illégal de B._, en mettant à sa disposition une chambre dans l'appartement dont il était lui-même locataire. Le comportement visé concernait l'hébergement du prénommé et non les démarches administratives qui auraient été omises par le recourant. Par ailleurs, dès lors que ce dernier a admis - dès l'audition de police du 2 février 2017 - avoir logé B._ dans son appartement, l'aspect déterminant ayant dû être éclairci durant l'instruction a été celui de la connaissance ou de l'ignorance, par l'intéressé, du statut illégal en Suisse du prénommé.
La cour cantonale a indiqué que si le recourant avait annoncé à l'OCPM qu'il logeait B._, "toutes les explications auraient pu être immédiatement fournies à l'autorité et cela aurait évité l'ouverture d'une instruction pénale". On ne voit toutefois pas - et l'autorité précédente ne l'explique aucunement - dans quelle mesure une telle annonce à l'OCPM aurait par la suite permis aux autorités pénales d'exclure d'emblée que le recourant eût logé le prénommé en connaissant son statut illégal en Suisse. Le comportement du recourant ayant déclenché l'instruction pénale a consisté à loger B._ entre l'année 2016 et l'interpellation de ce dernier en janvier 2017, nullement à omettre une annonce à l'OCPM dans le délai légal ayant couru depuis l'installation du prénommé.
Au vu de ce qui précède, la cour cantonale a violé le droit fédéral en mettant les frais de la procédure à la charge du recourant nonobstant le classement dont celui-ci a bénéficié. Le recours doit être admis, l'arrêt attaqué annulé et la cause renvoyée à l'autorité cantonale afin qu'elle rende une nouvelle décision en laissant les frais de la procédure à la charge de l'Etat. Il lui appartiendra en outre, cela fait, de statuer à nouveau sur les prétentions formulées par le recourant à titre de l'<ref-law>.
2.
Le recours doit être admis. Le recourant, qui obtient gain de cause, ne supporte pas de frais judiciaires (<ref-law>). Il peut prétendre à de pleins dépens pour la procédure devant le Tribunal fédéral, à la charge du canton de Genève (<ref-law>). Sa demande d'assistance judiciaire est donc sans objet (<ref-law>).

Par ces motifs, le Tribunal fédéral prononce :
1.
Le recours est admis, l'arrêt attaqué est annulé et la cause est renvoyée à l'autorité cantonale pour nouvelle décision.
2.
Il n'est pas perçu de frais judiciaires.
3.
Le canton de Genève versera au conseil du recourant une indemnité de 3'000 fr. à titre de dépens pour la procédure devant le Tribunal fédéral.
4.
Le présent arrêt est communiqué aux parties et à la Cour de justice de la République et canton de Genève, Chambre pénale de recours.
Lausanne, le 3 octobre 2019
Au nom de la Cour de droit pénal
du Tribunal fédéral suisse
Le Président : Denys
Le Greffier : Graa